Commit 6d2d91b3 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'usb-4.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB fixes from Greg KH:
 "Here are a number of USB fixes and new device ids for 4.4-rc2.  All
  have been in linux-next and the details are in the shortlog"

* tag 'usb-4.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (28 commits)
  usblp: do not set TASK_INTERRUPTIBLE before lock
  USB: MAINTAINERS: cxacru
  usb: kconfig: fix warning of select USB_OTG
  USB: option: add XS Stick W100-2 from 4G Systems
  xhci: Fix a race in usb2 LPM resume, blocking U3 for usb2 devices
  usb: xhci: fix checking ep busy for CFC
  xhci: Workaround to get Intel xHCI reset working more reliably
  usb: chipidea: imx: fix a possible NULL dereference
  usb: chipidea: usbmisc_imx: fix a possible NULL dereference
  usb: chipidea: otg: gadget module load and unload support
  usb: chipidea: debug: disable usb irq while role switch
  ARM: dts: imx27.dtsi: change the clock information for usb
  usb: chipidea: imx: refine clock operations to adapt for all platforms
  usb: gadget: atmel_usba_udc: Expose correct device speed
  usb: musb: enable usb_dma parameter
  usb: phy: phy-mxs-usb: fix a possible NULL dereference
  usb: dwc3: gadget: let us set lower max_speed
  usb: musb: fix tx fifo flush handling
  usb: gadget: f_loopback: fix the warning during the enumeration
  usb: dwc2: host: Fix remote wakeup when not in DWC2_L2
  ...
parents 0ec7dc8d 19cd80a2
...@@ -2931,10 +2931,9 @@ S: Maintained ...@@ -2931,10 +2931,9 @@ S: Maintained
F: drivers/platform/x86/compal-laptop.c F: drivers/platform/x86/compal-laptop.c
CONEXANT ACCESSRUNNER USB DRIVER CONEXANT ACCESSRUNNER USB DRIVER
M: Simon Arlott <cxacru@fire.lp0.eu>
L: accessrunner-general@lists.sourceforge.net L: accessrunner-general@lists.sourceforge.net
W: http://accessrunner.sourceforge.net/ W: http://accessrunner.sourceforge.net/
S: Maintained S: Orphan
F: drivers/usb/atm/cxacru.c F: drivers/usb/atm/cxacru.c
CONFIGFS CONFIGFS
......
...@@ -486,7 +486,10 @@ ...@@ -486,7 +486,10 @@
compatible = "fsl,imx27-usb"; compatible = "fsl,imx27-usb";
reg = <0x10024000 0x200>; reg = <0x10024000 0x200>;
interrupts = <56>; interrupts = <56>;
clocks = <&clks IMX27_CLK_USB_IPG_GATE>; clocks = <&clks IMX27_CLK_USB_IPG_GATE>,
<&clks IMX27_CLK_USB_AHB_GATE>,
<&clks IMX27_CLK_USB_DIV>;
clock-names = "ipg", "ahb", "per";
fsl,usbmisc = <&usbmisc 0>; fsl,usbmisc = <&usbmisc 0>;
status = "disabled"; status = "disabled";
}; };
...@@ -495,7 +498,10 @@ ...@@ -495,7 +498,10 @@
compatible = "fsl,imx27-usb"; compatible = "fsl,imx27-usb";
reg = <0x10024200 0x200>; reg = <0x10024200 0x200>;
interrupts = <54>; interrupts = <54>;
clocks = <&clks IMX27_CLK_USB_IPG_GATE>; clocks = <&clks IMX27_CLK_USB_IPG_GATE>,
<&clks IMX27_CLK_USB_AHB_GATE>,
<&clks IMX27_CLK_USB_DIV>;
clock-names = "ipg", "ahb", "per";
fsl,usbmisc = <&usbmisc 1>; fsl,usbmisc = <&usbmisc 1>;
dr_mode = "host"; dr_mode = "host";
status = "disabled"; status = "disabled";
...@@ -505,7 +511,10 @@ ...@@ -505,7 +511,10 @@
compatible = "fsl,imx27-usb"; compatible = "fsl,imx27-usb";
reg = <0x10024400 0x200>; reg = <0x10024400 0x200>;
interrupts = <55>; interrupts = <55>;
clocks = <&clks IMX27_CLK_USB_IPG_GATE>; clocks = <&clks IMX27_CLK_USB_IPG_GATE>,
<&clks IMX27_CLK_USB_AHB_GATE>,
<&clks IMX27_CLK_USB_DIV>;
clock-names = "ipg", "ahb", "per";
fsl,usbmisc = <&usbmisc 2>; fsl,usbmisc = <&usbmisc 2>;
dr_mode = "host"; dr_mode = "host";
status = "disabled"; status = "disabled";
...@@ -515,7 +524,6 @@ ...@@ -515,7 +524,6 @@
#index-cells = <1>; #index-cells = <1>;
compatible = "fsl,imx27-usbmisc"; compatible = "fsl,imx27-usbmisc";
reg = <0x10024600 0x200>; reg = <0x10024600 0x200>;
clocks = <&clks IMX27_CLK_USB_AHB_GATE>;
}; };
sahara2: sahara@10025000 { sahara2: sahara@10025000 {
......
...@@ -84,6 +84,12 @@ struct ci_hdrc_imx_data { ...@@ -84,6 +84,12 @@ struct ci_hdrc_imx_data {
struct imx_usbmisc_data *usbmisc_data; struct imx_usbmisc_data *usbmisc_data;
bool supports_runtime_pm; bool supports_runtime_pm;
bool in_lpm; bool in_lpm;
/* SoC before i.mx6 (except imx23/imx28) needs three clks */
bool need_three_clks;
struct clk *clk_ipg;
struct clk *clk_ahb;
struct clk *clk_per;
/* --------------------------------- */
}; };
/* Common functions shared by usbmisc drivers */ /* Common functions shared by usbmisc drivers */
...@@ -135,6 +141,102 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev) ...@@ -135,6 +141,102 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
} }
/* End of common functions shared by usbmisc drivers*/ /* End of common functions shared by usbmisc drivers*/
static int imx_get_clks(struct device *dev)
{
struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
int ret = 0;
data->clk_ipg = devm_clk_get(dev, "ipg");
if (IS_ERR(data->clk_ipg)) {
/* If the platform only needs one clocks */
data->clk = devm_clk_get(dev, NULL);
if (IS_ERR(data->clk)) {
ret = PTR_ERR(data->clk);
dev_err(dev,
"Failed to get clks, err=%ld,%ld\n",
PTR_ERR(data->clk), PTR_ERR(data->clk_ipg));
return ret;
}
return ret;
}
data->clk_ahb = devm_clk_get(dev, "ahb");
if (IS_ERR(data->clk_ahb)) {
ret = PTR_ERR(data->clk_ahb);
dev_err(dev,
"Failed to get ahb clock, err=%d\n", ret);
return ret;
}
data->clk_per = devm_clk_get(dev, "per");
if (IS_ERR(data->clk_per)) {
ret = PTR_ERR(data->clk_per);
dev_err(dev,
"Failed to get per clock, err=%d\n", ret);
return ret;
}
data->need_three_clks = true;
return ret;
}
static int imx_prepare_enable_clks(struct device *dev)
{
struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
int ret = 0;
if (data->need_three_clks) {
ret = clk_prepare_enable(data->clk_ipg);
if (ret) {
dev_err(dev,
"Failed to prepare/enable ipg clk, err=%d\n",
ret);
return ret;
}
ret = clk_prepare_enable(data->clk_ahb);
if (ret) {
dev_err(dev,
"Failed to prepare/enable ahb clk, err=%d\n",
ret);
clk_disable_unprepare(data->clk_ipg);
return ret;
}
ret = clk_prepare_enable(data->clk_per);
if (ret) {
dev_err(dev,
"Failed to prepare/enable per clk, err=%d\n",
ret);
clk_disable_unprepare(data->clk_ahb);
clk_disable_unprepare(data->clk_ipg);
return ret;
}
} else {
ret = clk_prepare_enable(data->clk);
if (ret) {
dev_err(dev,
"Failed to prepare/enable clk, err=%d\n",
ret);
return ret;
}
}
return ret;
}
static void imx_disable_unprepare_clks(struct device *dev)
{
struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
if (data->need_three_clks) {
clk_disable_unprepare(data->clk_per);
clk_disable_unprepare(data->clk_ahb);
clk_disable_unprepare(data->clk_ipg);
} else {
clk_disable_unprepare(data->clk);
}
}
static int ci_hdrc_imx_probe(struct platform_device *pdev) static int ci_hdrc_imx_probe(struct platform_device *pdev)
{ {
...@@ -145,31 +247,31 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) ...@@ -145,31 +247,31 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
.flags = CI_HDRC_SET_NON_ZERO_TTHA, .flags = CI_HDRC_SET_NON_ZERO_TTHA,
}; };
int ret; int ret;
const struct of_device_id *of_id = const struct of_device_id *of_id;
of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev); const struct ci_hdrc_imx_platform_flag *imx_platform_flag;
const struct ci_hdrc_imx_platform_flag *imx_platform_flag = of_id->data;
of_id = of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev);
if (!of_id)
return -ENODEV;
imx_platform_flag = of_id->data;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(pdev, data);
data->usbmisc_data = usbmisc_get_init_data(&pdev->dev); data->usbmisc_data = usbmisc_get_init_data(&pdev->dev);
if (IS_ERR(data->usbmisc_data)) if (IS_ERR(data->usbmisc_data))
return PTR_ERR(data->usbmisc_data); return PTR_ERR(data->usbmisc_data);
data->clk = devm_clk_get(&pdev->dev, NULL); ret = imx_get_clks(&pdev->dev);
if (IS_ERR(data->clk)) { if (ret)
dev_err(&pdev->dev, return ret;
"Failed to get clock, err=%ld\n", PTR_ERR(data->clk));
return PTR_ERR(data->clk);
}
ret = clk_prepare_enable(data->clk); ret = imx_prepare_enable_clks(&pdev->dev);
if (ret) { if (ret)
dev_err(&pdev->dev,
"Failed to prepare or enable clock, err=%d\n", ret);
return ret; return ret;
}
data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0); data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0);
if (IS_ERR(data->phy)) { if (IS_ERR(data->phy)) {
...@@ -212,8 +314,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) ...@@ -212,8 +314,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
goto disable_device; goto disable_device;
} }
platform_set_drvdata(pdev, data);
if (data->supports_runtime_pm) { if (data->supports_runtime_pm) {
pm_runtime_set_active(&pdev->dev); pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
...@@ -226,7 +326,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) ...@@ -226,7 +326,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
disable_device: disable_device:
ci_hdrc_remove_device(data->ci_pdev); ci_hdrc_remove_device(data->ci_pdev);
err_clk: err_clk:
clk_disable_unprepare(data->clk); imx_disable_unprepare_clks(&pdev->dev);
return ret; return ret;
} }
...@@ -240,7 +340,7 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev) ...@@ -240,7 +340,7 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
pm_runtime_put_noidle(&pdev->dev); pm_runtime_put_noidle(&pdev->dev);
} }
ci_hdrc_remove_device(data->ci_pdev); ci_hdrc_remove_device(data->ci_pdev);
clk_disable_unprepare(data->clk); imx_disable_unprepare_clks(&pdev->dev);
return 0; return 0;
} }
...@@ -252,7 +352,7 @@ static int imx_controller_suspend(struct device *dev) ...@@ -252,7 +352,7 @@ static int imx_controller_suspend(struct device *dev)
dev_dbg(dev, "at %s\n", __func__); dev_dbg(dev, "at %s\n", __func__);
clk_disable_unprepare(data->clk); imx_disable_unprepare_clks(dev);
data->in_lpm = true; data->in_lpm = true;
return 0; return 0;
...@@ -270,7 +370,7 @@ static int imx_controller_resume(struct device *dev) ...@@ -270,7 +370,7 @@ static int imx_controller_resume(struct device *dev)
return 0; return 0;
} }
ret = clk_prepare_enable(data->clk); ret = imx_prepare_enable_clks(dev);
if (ret) if (ret)
return ret; return ret;
...@@ -285,7 +385,7 @@ static int imx_controller_resume(struct device *dev) ...@@ -285,7 +385,7 @@ static int imx_controller_resume(struct device *dev)
return 0; return 0;
clk_disable: clk_disable:
clk_disable_unprepare(data->clk); imx_disable_unprepare_clks(dev);
return ret; return ret;
} }
......
...@@ -322,8 +322,10 @@ static ssize_t ci_role_write(struct file *file, const char __user *ubuf, ...@@ -322,8 +322,10 @@ static ssize_t ci_role_write(struct file *file, const char __user *ubuf,
return -EINVAL; return -EINVAL;
pm_runtime_get_sync(ci->dev); pm_runtime_get_sync(ci->dev);
disable_irq(ci->irq);
ci_role_stop(ci); ci_role_stop(ci);
ret = ci_role_start(ci, role); ret = ci_role_start(ci, role);
enable_irq(ci->irq);
pm_runtime_put_sync(ci->dev); pm_runtime_put_sync(ci->dev);
return ret ? ret : count; return ret ? ret : count;
......
...@@ -1751,6 +1751,22 @@ static int ci_udc_start(struct usb_gadget *gadget, ...@@ -1751,6 +1751,22 @@ static int ci_udc_start(struct usb_gadget *gadget,
return retval; return retval;
} }
static void ci_udc_stop_for_otg_fsm(struct ci_hdrc *ci)
{
if (!ci_otg_is_fsm_mode(ci))
return;
mutex_lock(&ci->fsm.lock);
if (ci->fsm.otg->state == OTG_STATE_A_PERIPHERAL) {
ci->fsm.a_bidl_adis_tmout = 1;
ci_hdrc_otg_fsm_start(ci);
} else if (ci->fsm.otg->state == OTG_STATE_B_PERIPHERAL) {
ci->fsm.protocol = PROTO_UNDEF;
ci->fsm.otg->state = OTG_STATE_UNDEFINED;
}
mutex_unlock(&ci->fsm.lock);
}
/** /**
* ci_udc_stop: unregister a gadget driver * ci_udc_stop: unregister a gadget driver
*/ */
...@@ -1775,6 +1791,7 @@ static int ci_udc_stop(struct usb_gadget *gadget) ...@@ -1775,6 +1791,7 @@ static int ci_udc_stop(struct usb_gadget *gadget)
ci->driver = NULL; ci->driver = NULL;
spin_unlock_irqrestore(&ci->lock, flags); spin_unlock_irqrestore(&ci->lock, flags);
ci_udc_stop_for_otg_fsm(ci);
return 0; return 0;
} }
......
...@@ -500,7 +500,11 @@ static int usbmisc_imx_probe(struct platform_device *pdev) ...@@ -500,7 +500,11 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
struct imx_usbmisc *data; struct imx_usbmisc *data;
struct of_device_id *tmp_dev; const struct of_device_id *of_id;
of_id = of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
if (!of_id)
return -ENODEV;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data) if (!data)
...@@ -513,9 +517,7 @@ static int usbmisc_imx_probe(struct platform_device *pdev) ...@@ -513,9 +517,7 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
if (IS_ERR(data->base)) if (IS_ERR(data->base))
return PTR_ERR(data->base); return PTR_ERR(data->base);
tmp_dev = (struct of_device_id *) data->ops = (const struct usbmisc_ops *)of_id->data;
of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
data->ops = (const struct usbmisc_ops *)tmp_dev->data;
platform_set_drvdata(pdev, data); platform_set_drvdata(pdev, data);
return 0; return 0;
......
...@@ -884,11 +884,11 @@ static int usblp_wwait(struct usblp *usblp, int nonblock) ...@@ -884,11 +884,11 @@ static int usblp_wwait(struct usblp *usblp, int nonblock)
add_wait_queue(&usblp->wwait, &waita); add_wait_queue(&usblp->wwait, &waita);
for (;;) { for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
if (mutex_lock_interruptible(&usblp->mut)) { if (mutex_lock_interruptible(&usblp->mut)) {
rc = -EINTR; rc = -EINTR;
break; break;
} }
set_current_state(TASK_INTERRUPTIBLE);
rc = usblp_wtest(usblp, nonblock); rc = usblp_wtest(usblp, nonblock);
mutex_unlock(&usblp->mut); mutex_unlock(&usblp->mut);
if (rc <= 0) if (rc <= 0)
......
...@@ -77,8 +77,7 @@ config USB_OTG_BLACKLIST_HUB ...@@ -77,8 +77,7 @@ config USB_OTG_BLACKLIST_HUB
config USB_OTG_FSM config USB_OTG_FSM
tristate "USB 2.0 OTG FSM implementation" tristate "USB 2.0 OTG FSM implementation"
depends on USB depends on USB && USB_OTG
select USB_OTG
select USB_PHY select USB_PHY
help help
Implements OTG Finite State Machine as specified in On-The-Go Implements OTG Finite State Machine as specified in On-The-Go
......
...@@ -324,12 +324,13 @@ void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg) ...@@ -324,12 +324,13 @@ void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg)
*/ */
static void dwc2_hcd_rem_wakeup(struct dwc2_hsotg *hsotg) static void dwc2_hcd_rem_wakeup(struct dwc2_hsotg *hsotg)
{ {
if (hsotg->lx_state == DWC2_L2) { if (hsotg->bus_suspended) {
hsotg->flags.b.port_suspend_change = 1; hsotg->flags.b.port_suspend_change = 1;
usb_hcd_resume_root_hub(hsotg->priv); usb_hcd_resume_root_hub(hsotg->priv);
} else {
hsotg->flags.b.port_l1_change = 1;
} }
if (hsotg->lx_state == DWC2_L1)
hsotg->flags.b.port_l1_change = 1;
} }
/** /**
...@@ -1428,8 +1429,8 @@ static void dwc2_wakeup_detected(unsigned long data) ...@@ -1428,8 +1429,8 @@ static void dwc2_wakeup_detected(unsigned long data)
dev_dbg(hsotg->dev, "Clear Resume: HPRT0=%0x\n", dev_dbg(hsotg->dev, "Clear Resume: HPRT0=%0x\n",
dwc2_readl(hsotg->regs + HPRT0)); dwc2_readl(hsotg->regs + HPRT0));
hsotg->bus_suspended = 0;
dwc2_hcd_rem_wakeup(hsotg); dwc2_hcd_rem_wakeup(hsotg);
hsotg->bus_suspended = 0;
/* Change to L0 state */ /* Change to L0 state */
hsotg->lx_state = DWC2_L0; hsotg->lx_state = DWC2_L0;
......
...@@ -108,7 +108,8 @@ static const struct dwc2_core_params params_rk3066 = { ...@@ -108,7 +108,8 @@ static const struct dwc2_core_params params_rk3066 = {
.host_ls_low_power_phy_clk = -1, .host_ls_low_power_phy_clk = -1,
.ts_dline = -1, .ts_dline = -1,
.reload_ctl = -1, .reload_ctl = -1,
.ahbcfg = 0x7, /* INCR16 */ .ahbcfg = GAHBCFG_HBSTLEN_INCR16 <<
GAHBCFG_HBSTLEN_SHIFT,
.uframe_sched = -1, .uframe_sched = -1,
.external_id_pin_ctl = -1, .external_id_pin_ctl = -1,
.hibernation = -1, .hibernation = -1,
......
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
#define PCI_DEVICE_ID_INTEL_BSW 0x22b7 #define PCI_DEVICE_ID_INTEL_BSW 0x22b7
#define PCI_DEVICE_ID_INTEL_SPTLP 0x9d30 #define PCI_DEVICE_ID_INTEL_SPTLP 0x9d30
#define PCI_DEVICE_ID_INTEL_SPTH 0xa130 #define PCI_DEVICE_ID_INTEL_SPTH 0xa130
#define PCI_DEVICE_ID_INTEL_BXT 0x0aaa
#define PCI_DEVICE_ID_INTEL_APL 0x5aaa
static const struct acpi_gpio_params reset_gpios = { 0, 0, false }; static const struct acpi_gpio_params reset_gpios = { 0, 0, false };
static const struct acpi_gpio_params cs_gpios = { 1, 0, false }; static const struct acpi_gpio_params cs_gpios = { 1, 0, false };
...@@ -210,6 +212,8 @@ static const struct pci_device_id dwc3_pci_id_table[] = { ...@@ -210,6 +212,8 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTLP), }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTLP), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTH), }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTH), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL), },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB), }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB), },
{ } /* Terminating Entry */ { } /* Terminating Entry */
}; };
......
...@@ -2744,11 +2744,33 @@ int dwc3_gadget_init(struct dwc3 *dwc) ...@@ -2744,11 +2744,33 @@ int dwc3_gadget_init(struct dwc3 *dwc)
} }
dwc->gadget.ops = &dwc3_gadget_ops; dwc->gadget.ops = &dwc3_gadget_ops;
dwc->gadget.max_speed = USB_SPEED_SUPER;
dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->gadget.speed = USB_SPEED_UNKNOWN;
dwc->gadget.sg_supported = true; dwc->gadget.sg_supported = true;
dwc->gadget.name = "dwc3-gadget"; dwc->gadget.name = "dwc3-gadget";
/*
* FIXME We might be setting max_speed to <SUPER, however versions
* <2.20a of dwc3 have an issue with metastability (documented
* elsewhere in this driver) which tells us we can't set max speed to
* anything lower than SUPER.
*
* Because gadget.max_speed is only used by composite.c and function
* drivers (i.e. it won't go into dwc3's registers) we are allowing this
* to happen so we avoid sending SuperSpeed Capability descriptor
* together with our BOS descriptor as that could confuse host into
* thinking we can handle super speed.
*
* Note that, in fact, we won't even support GetBOS requests when speed
* is less than super speed because we don't have means, yet, to tell
* composite.c that we are USB 2.0 + LPM ECN.
*/
if (dwc->revision < DWC3_REVISION_220A)
dwc3_trace(trace_dwc3_gadget,
"Changing max_speed on rev %08x\n",
dwc->revision);
dwc->gadget.max_speed = dwc->maximum_speed;
/* /*
* Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize * Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize
* on ep out. * on ep out.
......
...@@ -329,7 +329,7 @@ static int alloc_requests(struct usb_composite_dev *cdev, ...@@ -329,7 +329,7 @@ static int alloc_requests(struct usb_composite_dev *cdev,
for (i = 0; i < loop->qlen && result == 0; i++) { for (i = 0; i < loop->qlen && result == 0; i++) {
result = -ENOMEM; result = -ENOMEM;
in_req = usb_ep_alloc_request(loop->in_ep, GFP_KERNEL); in_req = usb_ep_alloc_request(loop->in_ep, GFP_ATOMIC);
if (!in_req) if (!in_req)
goto fail; goto fail;
......
...@@ -1633,7 +1633,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) ...@@ -1633,7 +1633,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
spin_lock(&udc->lock); spin_lock(&udc->lock);
int_enb = usba_int_enb_get(udc); int_enb = usba_int_enb_get(udc);
status = usba_readl(udc, INT_STA) & int_enb; status = usba_readl(udc, INT_STA) & (int_enb | USBA_HIGH_SPEED);
DBG(DBG_INT, "irq, status=%#08x\n", status); DBG(DBG_INT, "irq, status=%#08x\n", status);
if (status & USBA_DET_SUSPEND) { if (status & USBA_DET_SUSPEND) {
......
...@@ -782,12 +782,15 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, ...@@ -782,12 +782,15 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
status |= USB_PORT_STAT_SUSPEND; status |= USB_PORT_STAT_SUSPEND;
} }
} }
if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0 if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0 &&
&& (raw_port_status & PORT_POWER) (raw_port_status & PORT_POWER)) {
&& (bus_state->suspended_ports & (1 << wIndex))) { if (bus_state->suspended_ports & (1 << wIndex)) {
bus_state->suspended_ports &= ~(1 << wIndex); bus_state->suspended_ports &= ~(1 << wIndex);
if (hcd->speed < HCD_USB3) if (hcd->speed < HCD_USB3)
bus_state->port_c_suspend |= 1 << wIndex; bus_state->port_c_suspend |= 1 << wIndex;
}
bus_state->resume_done[wIndex] = 0;
clear_bit(wIndex, &bus_state->resuming_ports);
} }
if (raw_port_status & PORT_CONNECT) { if (raw_port_status & PORT_CONNECT) {
status |= USB_PORT_STAT_CONNECTION; status |= USB_PORT_STAT_CONNECTION;
......
...@@ -3896,28 +3896,6 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, ...@@ -3896,28 +3896,6 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
return ret; return ret;
} }
static int ep_ring_is_processing(struct xhci_hcd *xhci,
int slot_id, unsigned int ep_index)
{
struct xhci_virt_device *xdev;
struct xhci_ring *ep_ring;
struct xhci_ep_ctx *ep_ctx;
struct xhci_virt_ep *xep;
dma_addr_t hw_deq;
xdev = xhci->devs[slot_id];
xep = &xhci->devs[slot_id]->eps[ep_index];
ep_ring = xep->ring;
ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) != EP_STATE_RUNNING)
return 0;
hw_deq = le64_to_cpu(ep_ctx->deq) & ~EP_CTX_CYCLE_MASK;
return (hw_deq !=
xhci_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue));
}
/* /*
* Check transfer ring to guarantee there is enough room for the urb. * Check transfer ring to guarantee there is enough room for the urb.
* Update ISO URB start_frame and interval. * Update ISO URB start_frame and interval.
...@@ -3983,10 +3961,12 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, ...@@ -3983,10 +3961,12 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
} }
/* Calculate the start frame and put it in urb->start_frame. */ /* Calculate the start frame and put it in urb->start_frame. */
if (HCC_CFC(xhci->hcc_params) && if (HCC_CFC(xhci->hcc_params) && !list_empty(&ep_ring->td_list)) {
ep_ring_is_processing(xhci, slot_id, ep_index)) { if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) ==
urb->start_frame = xep->next_frame_id; EP_STATE_RUNNING) {
goto skip_start_over; urb->start_frame = xep->next_frame_id;
goto skip_start_over;
}
} }
start_frame = readl(&xhci->run_regs->microframe_index); start_frame = readl(&xhci->run_regs->microframe_index);
......
...@@ -175,6 +175,16 @@ int xhci_reset(struct xhci_hcd *xhci) ...@@ -175,6 +175,16 @@ int xhci_reset(struct xhci_hcd *xhci)
command |= CMD_RESET; command |= CMD_RESET;