Commit 90a3c48f authored by Linus Torvalds's avatar Linus Torvalds

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

Pull USB fixes from Greg KH:
 "Here are some USB and PHY fixes for 3.17-rc5.

  Nothing major here, just a number of tiny fixes for reported issues,
  and some new device ids as well.

  All have been tested in linux-next"

* tag 'usb-3.17-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (46 commits)
  xhci: fix oops when xhci resumes from hibernate with hw lpm capable devices
  usb: xhci: Fix OOPS in xhci error handling code
  xhci: Fix null pointer dereference if xhci initialization fails
  storage: Add single-LUN quirk for Jaz USB Adapter
  uas: Add missing le16_to_cpu calls to asm1051 / asm1053 usb-id check
  usb: chipidea: msm: Initialize PHY on reset event
  usb: chipidea: msm: Use USB PHY API to control PHY state
  usb: hub: take hub->hdev reference when processing from eventlist
  uas: Disable uas on ASM1051 devices
  usb: dwc2/gadget: avoid disabling ep0
  usb: dwc2/gadget: delay enabling irq once hardware is configured properly
  usb: dwc2/gadget: do not call disconnect method in pullup
  usb: dwc2/gadget: break infinite loop in endpoint disable code
  usb: dwc2/gadget: fix phy initialization sequence
  usb: dwc2/gadget: fix phy disable sequence
  uwb: init beacon cache entry before registering uwb device
  USB: ftdi_sio: Add support for GE Healthcare Nemo Tracker device
  USB: document the 'u' flag for usb-storage quirks parameter
  usb: host: xhci: fix compliance mode workaround
  usb: dwc3: fix TRB completion when multiple TRBs are started
  ...
parents 602b5366 e2c60989
...@@ -5,6 +5,7 @@ Required properties: ...@@ -5,6 +5,7 @@ Required properties:
* "fsl,imx23-usbphy" for imx23 and imx28 * "fsl,imx23-usbphy" for imx23 and imx28
* "fsl,imx6q-usbphy" for imx6dq and imx6dl * "fsl,imx6q-usbphy" for imx6dq and imx6dl
* "fsl,imx6sl-usbphy" for imx6sl * "fsl,imx6sl-usbphy" for imx6sl
* "fsl,imx6sx-usbphy" for imx6sx
"fsl,imx23-usbphy" is still a fallback for other strings "fsl,imx23-usbphy" is still a fallback for other strings
- reg: Should contain registers location and length - reg: Should contain registers location and length
- interrupts: Should contain phy interrupt - interrupts: Should contain phy interrupt
......
...@@ -3541,6 +3541,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ...@@ -3541,6 +3541,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
bogus residue values); bogus residue values);
s = SINGLE_LUN (the device has only one s = SINGLE_LUN (the device has only one
Logical Unit); Logical Unit);
u = IGNORE_UAS (don't bind to the uas driver);
w = NO_WP_DETECT (don't test whether the w = NO_WP_DETECT (don't test whether the
medium is write-protected). medium is write-protected).
Example: quirks=0419:aaf5:rl,0421:0433:rc Example: quirks=0419:aaf5:rl,0421:0433:rc
......
...@@ -7913,6 +7913,19 @@ S: Supported ...@@ -7913,6 +7913,19 @@ S: Supported
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
F: drivers/net/ethernet/samsung/sxgbe/ F: drivers/net/ethernet/samsung/sxgbe/
SAMSUNG USB2 PHY DRIVER
M: Kamil Debski <k.debski@samsung.com>
L: linux-kernel@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/phy/samsung-phy.txt
F: Documentation/phy/samsung-usb2.txt
F: drivers/phy/phy-exynos4210-usb2.c
F: drivers/phy/phy-exynos4x12-usb2.c
F: drivers/phy/phy-exynos5250-usb2.c
F: drivers/phy/phy-s5pv210-usb2.c
F: drivers/phy/phy-samsung-usb2.c
F: drivers/phy/phy-samsung-usb2.h
SERIAL DRIVERS SERIAL DRIVERS
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-serial@vger.kernel.org L: linux-serial@vger.kernel.org
......
...@@ -41,9 +41,9 @@ config PHY_MVEBU_SATA ...@@ -41,9 +41,9 @@ config PHY_MVEBU_SATA
config PHY_MIPHY365X config PHY_MIPHY365X
tristate "STMicroelectronics MIPHY365X PHY driver for STiH41x series" tristate "STMicroelectronics MIPHY365X PHY driver for STiH41x series"
depends on ARCH_STI depends on ARCH_STI
depends on GENERIC_PHY
depends on HAS_IOMEM depends on HAS_IOMEM
depends on OF depends on OF
select GENERIC_PHY
help help
Enable this to support the miphy transceiver (for SATA/PCIE) Enable this to support the miphy transceiver (for SATA/PCIE)
that is part of STMicroelectronics STiH41x SoC series. that is part of STMicroelectronics STiH41x SoC series.
......
...@@ -542,6 +542,7 @@ static const struct of_device_id exynos5_usbdrd_phy_of_match[] = { ...@@ -542,6 +542,7 @@ static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
}, },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, exynos5_usbdrd_phy_of_match);
static int exynos5_usbdrd_phy_probe(struct platform_device *pdev) static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
{ {
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/usb/otg.h> #include <linux/usb/otg.h>
#include <linux/phy/phy.h> #include <linux/phy/phy.h>
#include <linux/pm_runtime.h>
#include <linux/usb/musb-omap.h> #include <linux/usb/musb-omap.h>
#include <linux/usb/ulpi.h> #include <linux/usb/ulpi.h>
#include <linux/i2c/twl.h> #include <linux/i2c/twl.h>
...@@ -422,37 +423,55 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) ...@@ -422,37 +423,55 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on)
} }
} }
static int twl4030_phy_power_off(struct phy *phy) static int twl4030_usb_runtime_suspend(struct device *dev)
{ {
struct twl4030_usb *twl = phy_get_drvdata(phy); struct twl4030_usb *twl = dev_get_drvdata(dev);
dev_dbg(twl->dev, "%s\n", __func__);
if (twl->asleep) if (twl->asleep)
return 0; return 0;
twl4030_phy_power(twl, 0); twl4030_phy_power(twl, 0);
twl->asleep = 1; twl->asleep = 1;
dev_dbg(twl->dev, "%s\n", __func__);
return 0; return 0;
} }
static void __twl4030_phy_power_on(struct twl4030_usb *twl) static int twl4030_usb_runtime_resume(struct device *dev)
{ {
struct twl4030_usb *twl = dev_get_drvdata(dev);
dev_dbg(twl->dev, "%s\n", __func__);
if (!twl->asleep)
return 0;
twl4030_phy_power(twl, 1); twl4030_phy_power(twl, 1);
twl4030_i2c_access(twl, 1); twl->asleep = 0;
twl4030_usb_set_mode(twl, twl->usb_mode);
if (twl->usb_mode == T2_USB_MODE_ULPI) return 0;
twl4030_i2c_access(twl, 0); }
static int twl4030_phy_power_off(struct phy *phy)
{
struct twl4030_usb *twl = phy_get_drvdata(phy);
dev_dbg(twl->dev, "%s\n", __func__);
pm_runtime_mark_last_busy(twl->dev);
pm_runtime_put_autosuspend(twl->dev);
return 0;
} }
static int twl4030_phy_power_on(struct phy *phy) static int twl4030_phy_power_on(struct phy *phy)
{ {
struct twl4030_usb *twl = phy_get_drvdata(phy); struct twl4030_usb *twl = phy_get_drvdata(phy);
if (!twl->asleep)
return 0;
__twl4030_phy_power_on(twl);
twl->asleep = 0;
dev_dbg(twl->dev, "%s\n", __func__); dev_dbg(twl->dev, "%s\n", __func__);
pm_runtime_get_sync(twl->dev);
twl4030_i2c_access(twl, 1);
twl4030_usb_set_mode(twl, twl->usb_mode);
if (twl->usb_mode == T2_USB_MODE_ULPI)
twl4030_i2c_access(twl, 0);
/* /*
* XXX When VBUS gets driven after musb goes to A mode, * XXX When VBUS gets driven after musb goes to A mode,
...@@ -558,9 +577,27 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) ...@@ -558,9 +577,27 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
* USB_LINK_VBUS state. musb_hdrc won't care until it * USB_LINK_VBUS state. musb_hdrc won't care until it
* starts to handle softconnect right. * starts to handle softconnect right.
*/ */
if ((status == OMAP_MUSB_VBUS_VALID) ||
(status == OMAP_MUSB_ID_GROUND)) {
if (twl->asleep)
pm_runtime_get_sync(twl->dev);
} else {
if (!twl->asleep) {
pm_runtime_mark_last_busy(twl->dev);
pm_runtime_put_autosuspend(twl->dev);
}
}
omap_musb_mailbox(status); omap_musb_mailbox(status);
} }
sysfs_notify(&twl->dev->kobj, NULL, "vbus");
/* don't schedule during sleep - irq works right then */
if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) {
cancel_delayed_work(&twl->id_workaround_work);
schedule_delayed_work(&twl->id_workaround_work, HZ);
}
if (irq)
sysfs_notify(&twl->dev->kobj, NULL, "vbus");
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -569,29 +606,8 @@ static void twl4030_id_workaround_work(struct work_struct *work) ...@@ -569,29 +606,8 @@ static void twl4030_id_workaround_work(struct work_struct *work)
{ {
struct twl4030_usb *twl = container_of(work, struct twl4030_usb, struct twl4030_usb *twl = container_of(work, struct twl4030_usb,
id_workaround_work.work); id_workaround_work.work);
enum omap_musb_vbus_id_status status;
bool status_changed = false;
status = twl4030_usb_linkstat(twl);
spin_lock_irq(&twl->lock);
if (status >= 0 && status != twl->linkstat) {
twl->linkstat = status;
status_changed = true;
}
spin_unlock_irq(&twl->lock);
if (status_changed) {
dev_dbg(twl->dev, "handle missing status change to %d\n",
status);
omap_musb_mailbox(status);
}
/* don't schedule during sleep - irq works right then */ twl4030_usb_irq(0, twl);
if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) {
cancel_delayed_work(&twl->id_workaround_work);
schedule_delayed_work(&twl->id_workaround_work, HZ);
}
} }
static int twl4030_phy_init(struct phy *phy) static int twl4030_phy_init(struct phy *phy)
...@@ -599,22 +615,17 @@ static int twl4030_phy_init(struct phy *phy) ...@@ -599,22 +615,17 @@ static int twl4030_phy_init(struct phy *phy)
struct twl4030_usb *twl = phy_get_drvdata(phy); struct twl4030_usb *twl = phy_get_drvdata(phy);
enum omap_musb_vbus_id_status status; enum omap_musb_vbus_id_status status;
/* pm_runtime_get_sync(twl->dev);
* Start in sleep state, we'll get called through set_suspend()
* callback when musb is runtime resumed and it's time to start.
*/
__twl4030_phy_power(twl, 0);
twl->asleep = 1;
status = twl4030_usb_linkstat(twl); status = twl4030_usb_linkstat(twl);
twl->linkstat = status; twl->linkstat = status;
if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) { if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID)
omap_musb_mailbox(twl->linkstat); omap_musb_mailbox(twl->linkstat);
twl4030_phy_power_on(phy);
}
sysfs_notify(&twl->dev->kobj, NULL, "vbus"); sysfs_notify(&twl->dev->kobj, NULL, "vbus");
pm_runtime_mark_last_busy(twl->dev);
pm_runtime_put_autosuspend(twl->dev);
return 0; return 0;
} }
...@@ -650,6 +661,11 @@ static const struct phy_ops ops = { ...@@ -650,6 +661,11 @@ static const struct phy_ops ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
static const struct dev_pm_ops twl4030_usb_pm_ops = {
SET_RUNTIME_PM_OPS(twl4030_usb_runtime_suspend,
twl4030_usb_runtime_resume, NULL)
};
static int twl4030_usb_probe(struct platform_device *pdev) static int twl4030_usb_probe(struct platform_device *pdev)
{ {
struct twl4030_usb_data *pdata = dev_get_platdata(&pdev->dev); struct twl4030_usb_data *pdata = dev_get_platdata(&pdev->dev);
...@@ -726,6 +742,11 @@ static int twl4030_usb_probe(struct platform_device *pdev) ...@@ -726,6 +742,11 @@ static int twl4030_usb_probe(struct platform_device *pdev)
ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier); ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, 2000);
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
/* Our job is to use irqs and status from the power module /* Our job is to use irqs and status from the power module
* to keep the transceiver disabled when nothing's connected. * to keep the transceiver disabled when nothing's connected.
* *
...@@ -744,6 +765,9 @@ static int twl4030_usb_probe(struct platform_device *pdev) ...@@ -744,6 +765,9 @@ static int twl4030_usb_probe(struct platform_device *pdev)
return status; return status;
} }
pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(twl->dev);
dev_info(&pdev->dev, "Initialized TWL4030 USB module\n"); dev_info(&pdev->dev, "Initialized TWL4030 USB module\n");
return 0; return 0;
} }
...@@ -753,6 +777,7 @@ static int twl4030_usb_remove(struct platform_device *pdev) ...@@ -753,6 +777,7 @@ static int twl4030_usb_remove(struct platform_device *pdev)
struct twl4030_usb *twl = platform_get_drvdata(pdev); struct twl4030_usb *twl = platform_get_drvdata(pdev);
int val; int val;
pm_runtime_get_sync(twl->dev);
cancel_delayed_work(&twl->id_workaround_work); cancel_delayed_work(&twl->id_workaround_work);
device_remove_file(twl->dev, &dev_attr_vbus); device_remove_file(twl->dev, &dev_attr_vbus);
...@@ -772,9 +797,8 @@ static int twl4030_usb_remove(struct platform_device *pdev) ...@@ -772,9 +797,8 @@ static int twl4030_usb_remove(struct platform_device *pdev)
/* disable complete OTG block */ /* disable complete OTG block */
twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
pm_runtime_mark_last_busy(twl->dev);
if (!twl->asleep) pm_runtime_put(twl->dev);
twl4030_phy_power(twl, 0);
return 0; return 0;
} }
...@@ -792,6 +816,7 @@ static struct platform_driver twl4030_usb_driver = { ...@@ -792,6 +816,7 @@ static struct platform_driver twl4030_usb_driver = {
.remove = twl4030_usb_remove, .remove = twl4030_usb_remove,
.driver = { .driver = {
.name = "twl4030_usb", .name = "twl4030_usb",
.pm = &twl4030_usb_pm_ops,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = of_match_ptr(twl4030_usb_id_table), .of_match_table = of_match_ptr(twl4030_usb_id_table),
}, },
......
...@@ -20,13 +20,13 @@ ...@@ -20,13 +20,13 @@
static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event) static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
{ {
struct device *dev = ci->gadget.dev.parent; struct device *dev = ci->gadget.dev.parent;
int val;
switch (event) { switch (event) {
case CI_HDRC_CONTROLLER_RESET_EVENT: case CI_HDRC_CONTROLLER_RESET_EVENT:
dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n"); dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
writel(0, USB_AHBBURST); writel(0, USB_AHBBURST);
writel(0, USB_AHBMODE); writel(0, USB_AHBMODE);
usb_phy_init(ci->transceiver);
break; break;
case CI_HDRC_CONTROLLER_STOPPED_EVENT: case CI_HDRC_CONTROLLER_STOPPED_EVENT:
dev_dbg(dev, "CI_HDRC_CONTROLLER_STOPPED_EVENT received\n"); dev_dbg(dev, "CI_HDRC_CONTROLLER_STOPPED_EVENT received\n");
...@@ -34,10 +34,7 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event) ...@@ -34,10 +34,7 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
* Put the transceiver in non-driving mode. Otherwise host * Put the transceiver in non-driving mode. Otherwise host
* may not detect soft-disconnection. * may not detect soft-disconnection.
*/ */
val = usb_phy_io_read(ci->transceiver, ULPI_FUNC_CTRL); usb_phy_notify_disconnect(ci->transceiver, USB_SPEED_UNKNOWN);
val &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
usb_phy_io_write(ci->transceiver, val, ULPI_FUNC_CTRL);
break; break;
default: default:
dev_dbg(dev, "unknown ci_hdrc event\n"); dev_dbg(dev, "unknown ci_hdrc event\n");
......
...@@ -5024,9 +5024,10 @@ static void hub_events(void) ...@@ -5024,9 +5024,10 @@ static void hub_events(void)
hub = list_entry(tmp, struct usb_hub, event_list); hub = list_entry(tmp, struct usb_hub, event_list);
kref_get(&hub->kref); kref_get(&hub->kref);
hdev = hub->hdev;
usb_get_dev(hdev);
spin_unlock_irq(&hub_event_lock); spin_unlock_irq(&hub_event_lock);
hdev = hub->hdev;
hub_dev = hub->intfdev; hub_dev = hub->intfdev;
intf = to_usb_interface(hub_dev); intf = to_usb_interface(hub_dev);
dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n", dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
...@@ -5139,6 +5140,7 @@ static void hub_events(void) ...@@ -5139,6 +5140,7 @@ static void hub_events(void)
usb_autopm_put_interface(intf); usb_autopm_put_interface(intf);
loop_disconnected: loop_disconnected:
usb_unlock_device(hdev); usb_unlock_device(hdev);
usb_put_dev(hdev);
kref_put(&hub->kref, hub_release); kref_put(&hub->kref, hub_release);
} /* end while (1) */ } /* end while (1) */
......
...@@ -1649,6 +1649,7 @@ static void s3c_hsotg_txfifo_flush(struct s3c_hsotg *hsotg, unsigned int idx) ...@@ -1649,6 +1649,7 @@ static void s3c_hsotg_txfifo_flush(struct s3c_hsotg *hsotg, unsigned int idx)
dev_err(hsotg->dev, dev_err(hsotg->dev,
"%s: timeout flushing fifo (GRSTCTL=%08x)\n", "%s: timeout flushing fifo (GRSTCTL=%08x)\n",
__func__, val); __func__, val);
break;
} }
udelay(1); udelay(1);
...@@ -2747,13 +2748,14 @@ static void s3c_hsotg_phy_enable(struct s3c_hsotg *hsotg) ...@@ -2747,13 +2748,14 @@ static void s3c_hsotg_phy_enable(struct s3c_hsotg *hsotg)
dev_dbg(hsotg->dev, "pdev 0x%p\n", pdev); dev_dbg(hsotg->dev, "pdev 0x%p\n", pdev);
if (hsotg->phy) { if (hsotg->uphy)
phy_init(hsotg->phy);
phy_power_on(hsotg->phy);
} else if (hsotg->uphy)
usb_phy_init(hsotg->uphy); usb_phy_init(hsotg->uphy);
else if (hsotg->plat->phy_init) else if (hsotg->plat && hsotg->plat->phy_init)
hsotg->plat->phy_init(pdev, hsotg->plat->phy_type); hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
else {
phy_init(hsotg->phy);
phy_power_on(hsotg->phy);
}
} }
/** /**
...@@ -2767,13 +2769,14 @@ static void s3c_hsotg_phy_disable(struct s3c_hsotg *hsotg) ...@@ -2767,13 +2769,14 @@ static void s3c_hsotg_phy_disable(struct s3c_hsotg *hsotg)
{ {
struct platform_device *pdev = to_platform_device(hsotg->dev); struct platform_device *pdev = to_platform_device(hsotg->dev);
if (hsotg->phy) { if (hsotg->uphy)
phy_power_off(hsotg->phy);
phy_exit(hsotg->phy);
} else if (hsotg->uphy)
usb_phy_shutdown(hsotg->uphy); usb_phy_shutdown(hsotg->uphy);
else if (hsotg->plat->phy_exit) else if (hsotg->plat && hsotg->plat->phy_exit)
hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type); hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
else {
phy_power_off(hsotg->phy);
phy_exit(hsotg->phy);
}
} }
/** /**
...@@ -2892,13 +2895,11 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget, ...@@ -2892,13 +2895,11 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,
return -ENODEV; return -ENODEV;
/* all endpoints should be shutdown */ /* all endpoints should be shutdown */
for (ep = 0; ep < hsotg->num_of_eps; ep++) for (ep = 1; ep < hsotg->num_of_eps; ep++)
s3c_hsotg_ep_disable(&hsotg->eps[ep].ep); s3c_hsotg_ep_disable(&hsotg->eps[ep].ep);
spin_lock_irqsave(&hsotg->lock, flags); spin_lock_irqsave(&hsotg->lock, flags);
s3c_hsotg_phy_disable(hsotg);
if (!driver) if (!driver)
hsotg->driver = NULL; hsotg->driver = NULL;
...@@ -2941,7 +2942,6 @@ static int s3c_hsotg_pullup(struct usb_gadget *gadget, int is_on) ...@@ -2941,7 +2942,6 @@ static int s3c_hsotg_pullup(struct usb_gadget *gadget, int is_on)
s3c_hsotg_phy_enable(hsotg); s3c_hsotg_phy_enable(hsotg);
s3c_hsotg_core_init(hsotg); s3c_hsotg_core_init(hsotg);
} else { } else {
s3c_hsotg_disconnect(hsotg);
s3c_hsotg_phy_disable(hsotg); s3c_hsotg_phy_disable(hsotg);
} }
...@@ -3441,13 +3441,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev) ...@@ -3441,13 +3441,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
hsotg->irq = ret; hsotg->irq = ret;
ret = devm_request_irq(&pdev->dev, hsotg->irq, s3c_hsotg_irq, 0,
dev_name(dev), hsotg);
if (ret < 0) {
dev_err(dev, "cannot claim IRQ\n");
goto err_clk;
}
dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq); dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq);
hsotg->gadget.max_speed = USB_SPEED_HIGH; hsotg->gadget.max_speed = USB_SPEED_HIGH;
...@@ -3488,9 +3481,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev) ...@@ -3488,9 +3481,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
if (hsotg->phy && (phy_get_bus_width(phy) == 8)) if (hsotg->phy && (phy_get_bus_width(phy) == 8))
hsotg->phyif = GUSBCFG_PHYIF8; hsotg->phyif = GUSBCFG_PHYIF8;
if (hsotg->phy)
phy_init(hsotg->phy);
/* usb phy enable */ /* usb phy enable */
s3c_hsotg_phy_enable(hsotg); s3c_hsotg_phy_enable(hsotg);
...@@ -3498,6 +3488,17 @@ static int s3c_hsotg_probe(struct platform_device *pdev) ...@@ -3498,6 +3488,17 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
s3c_hsotg_init(hsotg); s3c_hsotg_init(hsotg);
s3c_hsotg_hw_cfg(hsotg); s3c_hsotg_hw_cfg(hsotg);
ret = devm_request_irq(&pdev->dev, hsotg->irq, s3c_hsotg_irq, 0,
dev_name(dev), hsotg);
if (ret < 0) {
s3c_hsotg_phy_disable(hsotg);
clk_disable_unprepare(hsotg->clk);
regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
hsotg->supplies);
dev_err(dev, "cannot claim IRQ\n");
goto err_clk;
}
/* hsotg->num_of_eps holds number of EPs other than ep0 */ /* hsotg->num_of_eps holds number of EPs other than ep0 */
if (hsotg->num_of_eps == 0) { if (hsotg->num_of_eps == 0) {
...@@ -3582,9 +3583,6 @@ static int s3c_hsotg_remove(struct platform_device *pdev) ...@@ -3582,9 +3583,6 @@ static int s3c_hsotg_remove(struct platform_device *pdev)
usb_gadget_unregister_driver(hsotg->driver); usb_gadget_unregister_driver(hsotg->driver);
} }
s3c_hsotg_phy_disable(hsotg);
if (hsotg->phy)
phy_exit(hsotg->phy);
clk_disable_unprepare(hsotg->clk); clk_disable_unprepare(hsotg->clk);
return 0; return 0;
......
...@@ -799,20 +799,21 @@ static int dwc3_remove(struct platform_device *pdev) ...@@ -799,20 +799,21 @@ static int dwc3_remove(struct platform_device *pdev)
{ {
struct dwc3 *dwc = platform_get_drvdata(pdev); struct dwc3 *dwc = platform_get_drvdata(pdev);
dwc3_debugfs_exit(dwc);
dwc3_core_exit_mode(dwc);
dwc3_event_buffers_cleanup(dwc);
dwc3_free_event_buffers(dwc);
usb_phy_set_suspend(dwc->usb2_phy, 1); usb_phy_set_suspend(dwc->usb2_phy, 1);
usb_phy_set_suspend(dwc->usb3_phy, 1); usb_phy_set_suspend(dwc->usb3_phy, 1);
phy_power_off(dwc->usb2_generic_phy); phy_power_off(dwc->usb2_generic_phy);
phy_power_off(dwc->usb3_generic_phy); phy_power_off(dwc->usb3_generic_phy);
dwc3_core_exit(dwc);
pm_runtime_put_sync(&pdev->dev); pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
dwc3_debugfs_exit(dwc);
dwc3_core_exit_mode(dwc);
dwc3_event_buffers_cleanup(dwc);
dwc3_free_event_buffers(dwc);
dwc3_core_exit(dwc);
return 0; return 0;
} }
......
...@@ -576,9 +576,9 @@ static int dwc3_omap_remove(struct platform_device *pdev) ...@@ -576,9 +576,9 @@ static int dwc3_omap_remove(struct platform_device *pdev)
if (omap->extcon_id_dev.edev) if (omap->extcon_id_dev.edev)
extcon_unregister_interest(&omap->extcon_id_dev); extcon_unregister_interest(&omap->extcon_id_dev);
dwc3_omap_disable_irqs(omap); dwc3_omap_disable_irqs(omap);
device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
pm_runtime_put_sync(&pdev->dev); pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
return 0; return 0;
} }
......
...@@ -527,7 +527,7 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, ...@@ -527,7 +527,7 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep,
dep->stream_capable = true; dep->stream_capable = true;
} }
if (usb_endpoint_xfer_isoc(desc)) if (!usb_endpoint_xfer_control(desc))
params.param1 |= DWC3_DEPCFG_XFER_IN_PROGRESS_EN; params.param1 |= DWC3_DEPCFG_XFER_IN_PROGRESS_EN;
/* /*
...@@ -1225,16 +1225,17 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, ...@@ -1225,16 +1225,17 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
int ret; int ret;
spin_lock_irqsave(&dwc->lock, flags);
if (!dep->endpoint.desc) { if (!dep->endpoint.desc) {
dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n", dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n",
request, ep->name); request, ep->name);
spin_unlock_irqrestore(&dwc->lock, flags);
return -ESHUTDOWN; return -ESHUTDOWN;
} }
dev_vdbg(dwc->dev, "queing request %p to %s length %d\n", dev_vdbg(dwc->dev, "queing request %p to %s length %d\n",
request, ep->name, request->length); request, ep->name, request->length);
spin_lock_irqsave(&dwc->lock, flags);
ret = __dwc3_gadget_ep_queue(dep, req); ret = __dwc3_gadget_ep_queue(dep, req);
spin_unlock_irqrestore(&dwc->lock, flags); spin_unlock_irqrestore(&dwc->lock, flags);
...@@ -2041,12 +2042,6 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, ...@@ -2041,12 +2042,6 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
dwc3_endpoint_transfer_complete(dwc, dep, event); dwc3_endpoint_transfer_complete(dwc, dep, event);
break; break;
case DWC3_DEPEVT_XFERINPROGRESS: case DWC3_DEPEVT_XFERINPROGRESS:
if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
dev_dbg(dwc->dev, "%s is not an Isochronous endpoint\n",
dep->name);
return;
}
dwc3_endpoint_transfer_complete(dwc, dep, event); dwc3_endpoint_transfer_complete(dwc, dep, event);
break; break;
case DWC3_DEPEVT_XFERNOTREADY: case DWC3_DEPEVT_XFERNOTREADY:
......
...@@ -155,6 +155,12 @@ struct ffs_io_data { ...@@ -155,6 +155,12 @@ struct ffs_io_data {
struct usb_request *req; struct usb_request *req;
}; };
struct ffs_desc_helper {
struct ffs_data *ffs;
unsigned interfaces_count;
unsigned eps_count;
};
static int __must_check ffs_epfiles_create(struct ffs_data *ffs); static int __must_check ffs_epfiles_create(struct ffs_data *ffs);
static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count); static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count);
...@@ -1830,7 +1836,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type, ...@@ -1830,7 +1836,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
u8 *valuep, struct usb_descriptor_header *desc, u8 *valuep, struct usb_descriptor_header *desc,
void *priv) void *priv)
{ {
struct ffs_data *ffs = priv; struct ffs_desc_helper *helper = priv;
struct usb_endpoint_descriptor *d;
ENTER(); ENTER();
...@@ -1844,8 +1851,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type, ...@@ -1844,8 +1851,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
* encountered interface "n" then there are at least * encountered interface "n" then there are at least
* "n+1" interfaces. * "n+1" interfaces.
*/ */
if (*valuep >= ffs->interfaces_count) if (*valuep >= helper->interfaces_count)
ffs->interfaces_count = *valuep + 1; helper->interfaces_count = *valuep + 1;
break; break;
case FFS_STRING: case FFS_STRING:
...@@ -1853,14 +1860,22 @@ static int __ffs_data_do_entity(enum ffs_entity_type type, ...@@ -1853,14 +1860,22 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
* Strings are indexed from 1 (0 is magic ;) reserved * Strings are indexed from 1 (0 is magic ;) reserved
* for languages list or some such) * for languages list or some such)
*/ */
if (*valuep > ffs->strings_count) if (*valuep > helper->ffs->strings_count)
ffs->strings_count = *valuep; helper->ffs->strings_count = *valuep;
break; break;
case FFS_ENDPOINT: case FFS_ENDPOINT:
/* Endpoints are indexed from 1 as well. */ d = (void *)desc;
if ((*valuep & USB_ENDPOINT_NUMBER_MASK) > ffs->eps_count) helper->eps_count++;
ffs->eps_count = (*valuep & USB_ENDPOINT_NUMBER_MASK); if (helper->eps_count >= 15)
return -EINVAL;
/* Check if descriptors for any speed were already parsed */
if (!helper->ffs->eps_count && !helper->ffs->interfaces_count)
helper->ffs->eps_addrmap[helper->eps_count] =
d->bEndpointAddress;
else if (helper->ffs->eps_addrmap[helper->eps_count] !=
d->bEndpointAddress)
return -EINVAL;
break; break;
} }
...@@ -2053,6 +2068,7 @@ static int __ffs_data_got_descs(struct ffs_data *ffs, ...@@ -2053,6 +2068,7 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
char *data = _data, *raw_descs; char *data = _data, *raw_descs;
unsigned os_descs_count = 0, counts[3], flags; unsigned os_descs_count = 0, counts[3], flags;
int ret = -EINVAL, i; int ret = -EINVAL, i;
struct ffs_desc_helper helper;
ENTER(); ENTER();
...@@ -2101,13 +2117,29 @@ static int __ffs_data_got_descs(struct ffs_data *ffs, ...@@ -2101,13 +2117,29 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
/* Read descriptors */ /* Read descriptors */
raw_descs = data; raw_descs = data;
helper.ffs = ffs;
for (i = 0; i < 3; ++i) { for (i = 0; i < 3; ++i) {
if (!counts[i]) if (!counts[i])
continue; continue;
helper.interfaces_count = 0;
helper.eps_count = 0;
ret = ffs_do_descs(counts[i], data, len, ret = ffs_do_descs(counts[i], data, len,
__ffs_data_do_entity, ffs); __ffs_data_do_entity, &helper);
if (ret < 0) if (ret < 0)
goto error; goto error;
if (!ffs->eps_count && !ffs->interfaces_count) {
ffs->eps_count = helper.eps_count;
ffs->interfaces_count = helper.interfaces_count;
} else {
if (ffs->eps_count != helper.eps_count) {
ret = -EINVAL;
goto error;
}
if (ffs->interfaces_count != helper.interfaces_count) {
ret = -EINVAL;
goto error;
}
}
data += ret; data += ret;
len -= ret; len -= ret;
} }
...@@ -2342,9 +2374,18 @@ static void ffs_event_add(struct ffs_data *ffs, ...@@ -2342,9 +2374,18 @@ static void ffs_event_add(struct ffs_data *ffs,
spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags); spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
} }
/* Bind/unbind USB function hooks *******************************************/ /* Bind/unbind USB function hooks *******************************************/
static int ffs_ep_addr2idx(struct ffs_data *ffs, u8 endpoint_address)
{
int i;
for (i = 1; i < ARRAY_SIZE(ffs->eps_addrmap); ++i)
if (ffs->eps_addrmap[i] == endpoint_address)
return i;
return -ENOENT;
}
static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep, static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
struct usb_descriptor_header *desc, struct usb_descriptor_header *desc,
void *priv) void *priv)
...@@ -2378,7 +2419,10 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep, ...@@ -2378,7 +2419,10 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT) if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT)
return 0; return 0;
idx = (ds->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) - 1; idx = ffs_ep_addr2idx(func->ffs, ds->bEndpointAddress) - 1;
if (idx < 0)
return idx;
ffs_ep = func->eps + idx; ffs_ep = func->eps + idx;
if (unlikely(ffs_ep->descs[ep_desc_id])) { if (unlikely(ffs_ep->descs[ep_desc_id])) {
......
...@@ -224,6 +224,8 @@ struct ffs_data { ...@@ -224,6 +224,8 @@ struct ffs_data {
void *ms_os_descs_ext_prop_name_avail; void *ms_os_descs_ext_prop_name_avail;
void *ms_os_descs_ext_prop_data_avail; void *ms_os_descs_ext_prop_data_avail;
u8 eps_addrmap[15];
unsigned short strings_count; unsigned short strings_count;
unsigned short interfaces_count; unsigned short interfaces_count;
unsigned short eps_count; unsigned short eps_count;
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#ifndef __FUSB300_UDC_H__ #ifndef __FUSB300_UDC_H__
#define __FUSB300_UDC_H_ #define __FUSB300_UDC_H__
#include <linux/kernel.h> #include <linux/kernel.h>
......
...@@ -3320,7 +3320,7 @@ static void handle_stat1_irqs(struct net2280 *dev, u32 stat) ...@@ -3320,7 +3320,7 @@ static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
if (stat & tmp) { if (stat & tmp) {
writel(tmp, &dev->regs->irqstat1); writel(tmp, &dev->regs->irqstat1);
if ((((stat & BIT(ROOT_PORT_RESET_INTERRUPT)) && if ((((stat & BIT(ROOT_PORT_RESET_INTERRUPT)) &&
(readl(&dev->usb->usbstat) & mask)) || ((readl(&dev->usb->usbstat) & mask) == 0)) ||
((readl(&dev->usb->usbctl) & ((readl(&dev->usb->usbctl) &
BIT(VBUS_PIN)) == 0)) && BIT(VBUS_PIN)) == 0)) &&
(dev->gadget.speed != USB_SPEED_UNKNOWN)) { (dev->gadget.speed != USB_SPEED_UNKNOWN)) {
......
...@@ -468,7 +468,8 @@ static void xhci_hub_report_usb2_link_state(u32 *status, u32 status_reg) ...@@ -468,7 +468,8 @@ static void xhci_hub_report_usb2_link_state(u32 *status, u32 status_reg)
} }
/* Updates Link Status for super Speed port */ /* Updates Link Status for super Speed port */
static void xhci_hub_report_usb3_link_state(u32 *status, u32 status_reg) static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci,
u32 *status, u32 status_reg)
{ {
u32 pls = status_reg & PORT_PLS_MASK; u32 pls = status_reg & PORT_PLS_MASK;
...@@ -507,7 +508,8 @@ static void xhci_hub_report_usb3_link_state(u32 *status, u32 status_reg) ...@@ -507,7 +508,8 @@ static void xhci_hub_report_usb3_link_state(u32 *status, u32 status_reg)
* in which sometimes the port enters compliance mode * in which sometimes the port enters compliance mode
* caused by a delay on the host-device negotiation. * caused by a delay on the host-device negotiation.
*/ */
if (pls == USB_SS_PORT_LS_COMP_MOD) if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
(pls == USB_SS_PORT_LS_COMP_MOD))
pls |= USB_PORT_STAT_CONNECTION; pls |= USB_PORT_STAT_CONNECTION;
} }
...@@ -666,7 +668,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, ...@@ -666,7 +668,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
} }
/* Update Port Link State */ /* Update Port Link State */
if (hcd->speed == HCD_USB3) { if (hcd->speed == HCD_USB3) {
xhci_hub_report_usb3_link_state(&status, raw_port_status); xhci_hub_report_usb3_link_state(xhci, &status, raw_port_status);
/* /*
* Verify if all USB3 Ports Have entered U0 already. * Verify if all USB3 Ports Have entered U0 already.
* Delete Compliance Mode Timer if so. * Delete Compliance Mode Timer if so.
......
...@@ -1812,6 +1812,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) ...@@ -1812,6 +1812,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
if (xhci->lpm_command) if (xhci->lpm_command)
xhci_free_command(xhci, xhci->lpm_command); xhci_free_command(xhci, xhci->lpm_command);
xhci->lpm_command = NULL;
if (xhci->cmd_ring) if (xhci->cmd_ring)
xhci_ring_free(xhci, xhci->cmd_ring); xhci_ring_free(xhci, xhci->cmd_ring);
xhci->cmd_ring = NULL; xhci->cmd_ring = NULL;
...@@ -1819,7 +1820,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) ...@@ -1819,7 +1820,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
xhci_cleanup_command_queue(xhci); xhci_cleanup_command_queue(xhci);
num_ports = HCS_MAX_PORTS(xhci->hcs_params1); num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
for (i = 0; i < num_ports; i++) { for (i = 0; i < num_ports && xhci->rh_bw; i++) {
struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table; struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table;
for (j = 0; j < XHCI_MAX_INTERVAL; j++) { for (j = 0; j < XHCI_MAX_INTERVAL; j++) {
struct list_head *ep = &bwt->interval_bw[j].endpoints; struct list_head *ep = &bwt->interval_bw[j].endpoints;
......
...@@ -3971,13 +3971,21 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci, ...@@ -3971,13 +3971,21 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci,
int ret; int ret;
spin_lock_irqsave(&xhci->lock, flags); spin_lock_irqsave(&xhci->lock, flags);
if (max_exit_latency == xhci->devs[udev->slot_id]->current_mel) {
virt_dev = xhci->devs[udev->slot_id];
/*
* virt_dev might not exists yet if xHC resumed from hibernate (S4) and
* xHC was re-initialized. Exit latency will be set later after
* hub_port_finish_reset() is done and xhci->devs[] are re-allocated
*/
if (!virt_dev || max_exit_latency == virt_dev->current_mel) {
spin_unlock_irqrestore(&xhci->lock, flags); spin_unlock_irqrestore(&xhci->lock, flags);
return 0; return 0;
} }
/* Attempt to issue an Evaluate Context command to change the MEL. */ /* Attempt to issue an Evaluate Context command to change the MEL. */
virt_dev = xhci->devs[udev->slot_id];
command = xhci->lpm_command; command = xhci->lpm_command;
ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx); ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx);
if (!ctrl_ctx) { if (!ctrl_ctx) {
......
...@@ -39,6 +39,7 @@ struct cppi41_dma_channel { ...@@ -39,6 +39,7 @@ struct cppi41_dma_channel {
u32 transferred; u32 transferred;
u32 packet_sz; u32 packet_sz;
struct list_head tx_check; struct list_head tx_check;
int tx_zlp;
}; };
#define MUSB_DMA_NUM_CHANNELS 15 #define MUSB_DMA_NUM_CHANNELS 15
...@@ -122,6 +123,8 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel) ...@@ -122,6 +123,8 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
{ {
struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep; struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
struct musb *musb = hw_ep->musb; struct musb *musb = hw_ep->musb;
void __iomem *epio = hw_ep->regs;
u16 csr;
if (!cppi41_channel->prog_len || if (!cppi41_channel->prog_len ||
(cppi41_channel->channel.status == MUSB_DMA_STATUS_FREE)) { (cppi41_channel->channel.status == MUSB_DMA_STATUS_FREE)) {
...@@ -131,15 +134,24 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel) ...@@ -131,15 +134,24 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
cppi41_channel->transferred; cppi41_channel->transferred;
cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE; cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE;
cppi41_channel->channel.rx_packet_done = true; cppi41_channel->channel.rx_packet_done = true;
/*
* transmit ZLP using PIO mode for transfers which size is
* multiple of EP packet size.
*/
if (cppi41_channel->tx_zlp && (cppi41_channel->transferred %
cppi41_channel->packet_sz) == 0) {
musb_ep_select(musb->mregs, hw_ep->epnum);
csr = MUSB_TXCSR_MODE | MUSB_TXCSR_TXPKTRDY;
musb_writew(epio, MUSB_TXCSR, csr);
}
musb_dma_completion(musb, hw_ep->epnum, cppi41_channel->is_tx); musb_dma_completion(musb, hw_ep->epnum, cppi41_channel->is_tx);
} else { } else {
/* next iteration, reload */ /* next iteration, reload */
struct dma_chan *dc = cppi41_channel->dc; struct dma_chan *dc = cppi41_channel->dc;
struct dma_async_tx_descriptor *dma_desc; struct dma_async_tx_descriptor *dma_desc;
enum dma_transfer_direction direction; enum dma_transfer_direction direction;
u16 csr;
u32 remain_bytes; u32 remain_bytes;
void __iomem *epio = cppi41_channel->hw_ep->regs;
cppi41_channel->buf_addr += cppi41_channel->packet_sz; cppi41_channel->buf_addr += cppi41_channel->packet_sz;
...@@ -363,6 +375,7 @@ static bool cppi41_configure_channel(struct dma_channel *channel, ...@@ -363,6 +375,7 @@ static bool cppi41_configure_channel(struct dma_channel *channel,
cppi41_channel->total_len = len; cppi41_channel->total_len = len;
cppi41_channel->transferred = 0; cppi41_channel->transferred = 0;
cppi41_channel->packet_sz = packet_sz; cppi41_channel->packet_sz = packet_sz;
cppi41_channel->tx_zlp = (cppi41_channel->is_tx && mode) ? 1 : 0;
/* /*
* Due to AM335x' Advisory 1.0.13 we are not allowed to transfer more * Due to AM335x' Advisory 1.0.13 we are not allowed to transfer more
......
/* /*
* Copyright 2012-2013 Freescale Semiconductor, Inc. * Copyright 2012-2014 Freescale Semiconductor, Inc.
* Copyright (C) 2012 Marek Vasut <marex@denx.de> * Copyright (C) 2012 Marek Vasut <marex@denx.de>
* on behalf of DENX Software Engineering GmbH * on behalf of DENX Software Engineering GmbH
* *
...@@ -125,7 +125,13 @@ static const struct mxs_phy_data imx6sl_phy_data = { ...@@ -125,7 +125,13 @@ static const struct mxs_phy_data imx6sl_phy_data = {
MXS_PHY_NEED_IP_FIX, MXS_PHY_NEED_IP_FIX,
}; };
static const struct mxs_phy_data imx6sx_phy_data = {
.flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
MXS_PHY_NEED_IP_FIX,
};
static const struct of_device_id mxs_phy_dt_ids[] = { static const struct of_device_id mxs_phy_dt_ids[] = {
{ .compatible = "fsl,imx6sx-usbphy", .data = &imx6sx_phy_data, },
{ .compatible = "fsl,imx6sl-usbphy", .data = &imx6sl_phy_data, }, { .compatible = "fsl,imx6sl-usbphy", .data = &imx6sl_phy_data, },
{ .compatible = "fsl,imx6q-usbphy", .data = &imx6q_phy_data, }, { .compatible = "fsl,imx6q-usbphy", .data = &imx6q_phy_data, },
{ .compatible = "fsl,imx23-usbphy", .data = &imx23_phy_data, }, { .compatible = "fsl,imx23-usbphy", .data = &imx23_phy_data, },
......
...@@ -878,8 +878,8 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy, ...@@ -878,8 +878,8 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
return -ENOMEM; return -ENOMEM;
} }
tegra_phy->config = devm_kzalloc(&pdev->dev, tegra_phy->config = devm_kzalloc(&pdev->dev, sizeof(*config),
sizeof(*tegra_phy->config), GFP_KERNEL); GFP_KERNEL);
if (!tegra_phy->config) { if (!tegra_phy->config) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"unable to allocate memory for USB UTMIP config\n"); "unable to allocate memory for USB UTMIP config\n");
......
...@@ -108,19 +108,45 @@ static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe) ...@@ -108,19 +108,45 @@ static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe)
return list_first_entry(&pipe->list, struct usbhs_pkt, node); return list_first_entry(&pipe->list, struct usbhs_pkt, node);
} }
static void usbhsf_fifo_clear(struct usbhs_pipe *pipe,
struct usbhs_fifo *fifo);
static void usbhsf_fifo_unselect(struct usbhs_pipe *pipe,
struct usbhs_fifo *fifo);
static struct dma_chan *usbhsf_dma_chan_get(struct usbhs_fifo *fifo,
struct usbhs_pkt *pkt);
#define usbhsf_dma_map(p) __usbhsf_dma_map_ctrl(p, 1)
#define usbhsf_dma_unmap(p) __usbhsf_dma_map_ctrl(p, 0)
static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map);
struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt)
{ {
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe);
unsigned long flags; unsigned long flags;
/******************** spin lock ********************/ /******************** spin lock ********************/
usbhs_lock(priv, flags); usbhs_lock(priv, flags);
usbhs_pipe_disable(pipe);
if (!pkt) if (!pkt)
pkt = __usbhsf_pkt_get(pipe); pkt = __usbhsf_pkt_get(pipe);
if (pkt) if (pkt) {
struct dma_chan *chan = NULL;
if (fifo)
chan = usbhsf_dma_chan_get(fifo, pkt);
if (chan) {
dmaengine_terminate_all(chan);
usbhsf_fifo_clear(pipe, fifo);
usbhsf_dma_unmap(pkt);
}
__usbhsf_pkt_del(pkt); __usbhsf_pkt_del(pkt);
}
if (fifo)
usbhsf_fifo_unselect(pipe, fifo);
usbhs_unlock(priv, flags); usbhs_unlock(priv, flags);
/******************** spin unlock ******************/ /******************** spin unlock ******************/
...@@ -544,6 +570,7 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done) ...@@ -544,6 +570,7 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done)
usbhsf_send_terminator(pipe, fifo); usbhsf_send_terminator(pipe, fifo);
usbhsf_tx_irq_ctrl(pipe, !*is_done); usbhsf_tx_irq_ctrl(pipe, !*is_done);
usbhs_pipe_running(pipe, !*is_done);
usbhs_pipe_enable(pipe); usbhs_pipe_enable(pipe);
dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n", dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n",
...@@ -570,12 +597,21 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done) ...@@ -570,12 +597,21 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done)
* retry in interrupt * retry in interrupt
*/ */
usbhsf_tx_irq_ctrl(pipe, 1); usbhsf_tx_irq_ctrl(pipe, 1);
usbhs_pipe_running(pipe, 1);
return ret; return ret;
} }
static int usbhsf_pio_prepare_push(struct usbhs_pkt *pkt, int *is_done)
{
if (usbhs_pipe_is_running(pkt->pipe))
return 0;
return usbhsf_pio_try_push(pkt, is_done);
}
struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = { struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = {
.prepare = usbhsf_pio_try_push, .prepare = usbhsf_pio_prepare_push,
.try_run = usbhsf_pio_try_push, .try_run = usbhsf_pio_try_push,
}; };
...@@ -589,6 +625,9 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done) ...@@ -589,6 +625,9 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done)
if (usbhs_pipe_is_busy(pipe)) if (usbhs_pipe_is_busy(pipe))
return 0; return 0;
if (usbhs_pipe_is_running(pipe))
return 0;
/* /*
* pipe enable to prepare packet receive * pipe enable to prepare packet receive
*/ */
...@@ -597,6 +636,7 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done) ...@@ -597,6 +636,7 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done)
usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length); usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length);
usbhs_pipe_enable(pipe); usbhs_pipe_enable(pipe);
usbhs_pipe_running(pipe, 1);
usbhsf_rx_irq_ctrl(pipe, 1); usbhsf_rx_irq_ctrl(pipe, 1);
return 0; return 0;
...@@ -642,6 +682,7 @@ static int usbhsf_pio_try_pop(struct usbhs_pkt *pkt, int *is_done) ...@@ -642,6 +682,7 @@ static int usbhsf_pio_try_pop(struct usbhs_pkt *pkt, int *is_done)
(total_len < maxp)) { /* short packet */ (total_len < maxp)) { /* short packet */
*is_done = 1; *is_done = 1;
usbhsf_rx_irq_ctrl(pipe, 0); usbhsf_rx_irq_ctrl(pipe, 0);
usbhs_pipe_running(pipe, 0);
usbhs_pipe_disable(pipe); /* disable pipe first */ usbhs_pipe_disable(pipe); /* disable pipe first */
} }
...@@ -763,8 +804,6 @@ static void __usbhsf_dma_ctrl(struct usbhs_pipe *pipe, ...@@ -763,8 +804,6 @@ static void __usbhsf_dma_ctrl(struct usbhs_pipe *pipe,
usbhs_bset(priv, fifo->sel, DREQE, dreqe); usbhs_bset(priv, fifo->sel, DREQE, dreqe);
} }
#define usbhsf_dma_map(p) __usbhsf_dma_map_ctrl(p, 1)
#define usbhsf_dma_unmap(p) __usbhsf_dma_map_ctrl(p, 0)
static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map) static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
{ {
struct usbhs_pipe *pipe = pkt->pipe; struct usbhs_pipe *pipe = pkt->pipe;
...@@ -805,6 +844,7 @@ static void xfer_work(struct work_struct *work) ...@@ -805,6 +844,7 @@ static void xfer_work(struct work_struct *work)
dev_dbg(dev, " %s %d (%d/ %d)\n", dev_dbg(dev, " %s %d (%d/ %d)\n",
fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero); fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero);
usbhs_pipe_running(pipe, 1);
usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans); usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans);
usbhs_pipe_enable(pipe); usbhs_pipe_enable(pipe);
usbhsf_dma_start(pipe, fifo); usbhsf_dma_start(pipe, fifo);
...@@ -836,6 +876,10 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) ...@@ -836,6 +876,10 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */
goto usbhsf_pio_prepare_push; goto usbhsf_pio_prepare_push;
/* return at this time if the pipe is running */
if (usbhs_pipe_is_running(pipe))
return 0;
/* get enable DMA fifo */ /* get enable DMA fifo */
fifo = usbhsf_get_dma_fifo(priv, pkt); fifo = usbhsf_get_dma_fifo(priv, pkt);
if (!fifo) if (!fifo)
...@@ -869,15 +913,29 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) ...@@ -869,15 +913,29 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
static int usbhsf_dma_push_done(struct usbhs_pkt *pkt, int *is_done) static int usbhsf_dma_push_done(struct usbhs_pkt *pkt, int *is_done)
{ {
struct usbhs_pipe *pipe = pkt->pipe; struct usbhs_pipe *pipe = pkt->pipe;
int is_short = pkt->trans % usbhs_pipe_get_maxpacket(pipe);
pkt->actual += pkt->trans;
pkt->actual = pkt->trans; if (pkt->actual < pkt->length)
*is_done = 0; /* there are remainder data */
else if (is_short)
*is_done = 1; /* short packet */
else
*is_done = !pkt->zero; /* send zero packet? */
*is_done = !pkt->zero; /* send zero packet ? */ usbhs_pipe_running(pipe, !*is_done);
usbhsf_dma_stop(pipe, pipe->fifo); usbhsf_dma_stop(pipe, pipe->fifo);
usbhsf_dma_unmap(pkt); usbhsf_dma_unmap(pkt);
usbhsf_fifo_unselect(pipe, pipe->fifo); usbhsf_fifo_unselect(pipe, pipe->fifo);
if (!*is_done) {
/* change handler to PIO */
pkt->handler = &usbhs_fifo_pio_push_handler;
return pkt->handler->try_run(pkt, is_done);
}
return 0; return 0;
} }
...@@ -972,8 +1030,10 @@ static int usbhsf_dma_pop_done(struct usbhs_pkt *pkt, int *is_done) ...@@ -972,8 +1030,10 @@ static int usbhsf_dma_pop_done(struct usbhs_pkt *pkt, int *is_done)
if ((pkt->actual == pkt->length) || /* receive all data */ if ((pkt->actual == pkt->length) || /* receive all data */
(pkt->trans < maxp)) { /* short packet */ (pkt->trans < maxp)) { /* short packet */
*is_done = 1; *is_done = 1;
usbhs_pipe_running(pipe, 0);
} else { } else {
/* re-enable */ /* re-enable */
usbhs_pipe_running(pipe, 0);
usbhsf_prepare_pop(pkt, is_done); usbhsf_prepare_pop(pkt, is_done);
} }
......
...@@ -213,7 +213,10 @@ static int usbhs_status_get_each_irq(struct usbhs_priv *priv, ...@@ -213,7 +213,10 @@ static int usbhs_status_get_each_irq(struct usbhs_priv *priv,
{ {
struct usbhs_mod *mod = usbhs_mod_get_current(priv); struct usbhs_mod *mod = usbhs_mod_get_current(priv);
u16 intenb0, intenb1; u16 intenb0, intenb1;
unsigned long flags;
/******************** spin lock ********************/
usbhs_lock(priv, flags);
state->intsts0 = usbhs_read(priv, INTSTS0); state->intsts0 = usbhs_read(priv, INTSTS0);
state->intsts1 = usbhs_read(priv, INTSTS1); state->intsts1 = usbhs_read(priv, INTSTS1);
...@@ -229,6 +232,8 @@ static int usbhs_status_get_each_irq(struct usbhs_priv *priv, ...@@ -229,6 +232,8 @@ static int usbhs_status_get_each_irq(struct usbhs_priv *priv,
state->bempsts &= mod->irq_bempsts; state->bempsts &= mod->irq_bempsts;
state->brdysts &= mod->irq_brdysts; state->brdysts &= mod->irq_brdysts;
} }
usbhs_unlock(priv, flags);
/******************** spin unlock ******************/
/* /*
* Check whether the irq enable registers and the irq status are set * Check whether the irq enable registers and the irq status are set
......
...@@ -578,6 +578,19 @@ int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe) ...@@ -578,6 +578,19 @@ int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe)
return usbhsp_flags_has(pipe, IS_DIR_HOST); return usbhsp_flags_has(pipe, IS_DIR_HOST);
} }
int usbhs_pipe_is_running(struct usbhs_pipe *pipe)
{
return usbhsp_flags_has(pipe, IS_RUNNING);
}
void usbhs_pipe_running(struct usbhs_pipe *pipe, int running)
{
if (running)
usbhsp_flags_set(pipe, IS_RUNNING);
else
usbhsp_flags_clr(pipe, IS_RUNNING);
}
void usbhs_pipe_data_sequence(struct usbhs_pipe *pipe, int sequence) void usbhs_pipe_data_sequence(struct usbhs_pipe *pipe, int sequence)
{ {
u16 mask = (SQCLR | SQSET); u16 mask = (SQCLR | SQSET);
......
...@@ -36,6 +36,7 @@ struct usbhs_pipe { ...@@ -36,6 +36,7 @@ struct usbhs_pipe {
#define USBHS_PIPE_FLAGS_IS_USED (1 << 0) #define USBHS_PIPE_FLAGS_IS_USED (1 << 0)
#define USBHS_PIPE_FLAGS_IS_DIR_IN (1 << 1) #define USBHS_PIPE_FLAGS_IS_DIR_IN (1 << 1)
#define USBHS_PIPE_FLAGS_IS_DIR_HOST (1 << 2) #define USBHS_PIPE_FLAGS_IS_DIR_HOST (1 << 2)
#define USBHS_PIPE_FLAGS_IS_RUNNING (1 << 3)
struct usbhs_pkt_handle *handler; struct usbhs_pkt_handle *handler;
...@@ -80,6 +81,9 @@ int usbhs_pipe_probe(struct usbhs_priv *priv); ...@@ -80,6 +81,9 @@ int usbhs_pipe_probe(struct usbhs_priv *priv);
void usbhs_pipe_remove(struct usbhs_priv *priv); void usbhs_pipe_remove(struct usbhs_priv *priv);
int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe); int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe);
int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe); int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe);
int usbhs_pipe_is_running(struct usbhs_pipe *pipe);
void usbhs_pipe_running(struct usbhs_pipe *pipe, int running);
void usbhs_pipe_init(struct usbhs_priv *priv, void usbhs_pipe_init(struct usbhs_priv *priv,
int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map)); int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map));
int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe); int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe);
......
...@@ -728,6 +728,7 @@ static const struct usb_device_id id_table_combined[] = { ...@@ -728,6 +728,7 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID), { USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID),
.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
{ USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
{ USB_DEVICE(NOVITUS_VID, NOVITUS_BONO_E_PID) },
{ USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S03_PID) }, { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S03_PID) },
{ USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_59_PID) }, { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_59_PID) },
{ USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_57A_PID) }, { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_57A_PID) },
...@@ -939,6 +940,8 @@ static const struct usb_device_id id_table_combined[] = { ...@@ -939,6 +940,8 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(FTDI_VID, FTDI_EKEY_CONV_USB_PID) }, { USB_DEVICE(FTDI_VID, FTDI_EKEY_CONV_USB_PID) },
/* Infineon Devices */ /* Infineon Devices */
{ USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) }, { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) },
/* GE Healthcare devices */
{ USB_DEVICE(GE_HEALTHCARE_VID, GE_HEALTHCARE_NEMO_TRACKER_PID) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
......
...@@ -836,6 +836,12 @@ ...@@ -836,6 +836,12 @@
#define TELLDUS_VID 0x1781 /* Vendor ID */ #define TELLDUS_VID 0x1781 /* Vendor ID */
#define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */ #define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */
/*
* NOVITUS printers
*/
#define NOVITUS_VID 0x1a28
#define NOVITUS_BONO_E_PID 0x6010
/* /*
* RT Systems programming cables for various ham radios * RT Systems programming cables for various ham radios
*/ */
...@@ -1385,3 +1391,9 @@ ...@@ -1385,3 +1391,9 @@
* ekey biometric systems GmbH (http://ekey.net/) * ekey biometric systems GmbH (http://ekey.net/)
*/ */
#define FTDI_EKEY_CONV_USB_PID 0xCB08 /* Converter USB */ #define FTDI_EKEY_CONV_USB_PID 0xCB08 /* Converter USB */
/*
* GE Healthcare devices
*/
#define GE_HEALTHCARE_VID 0x1901
#define GE_HEALTHCARE_NEMO_TRACKER_PID 0x0015
...@@ -282,14 +282,19 @@ static const struct usb_device_id id_table[] = { ...@@ -282,14 +282,19 @@ static const struct usb_device_id id_table[] = {
/* Sierra Wireless HSPA Non-Composite Device */ /* Sierra Wireless HSPA Non-Composite Device */
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)}, { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)},
{ USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */ { USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */
{ USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */ /* Sierra Wireless Direct IP modems */
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68A3, 0xFF, 0xFF, 0xFF),
.driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
},
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68AA, 0xFF, 0xFF, 0xFF),
.driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
}, },
/* AT&T Direct IP LTE modems */ /* AT&T Direct IP LTE modems */
{ USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF), { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF),
.driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
}, },
{ USB_DEVICE(0x0f3d, 0x68A3), /* Airprime/Sierra Wireless Direct IP modems */ /* Airprime/Sierra Wireless Direct IP modems */
{ USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68A3, 0xFF, 0xFF, 0xFF),
.driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
}, },
......
...@@ -272,6 +272,14 @@ static void zte_ev_usb_serial_close(struct usb_serial_port *port) ...@@ -272,6 +272,14 @@ static void zte_ev_usb_serial_close(struct usb_serial_port *port)
} }
static const struct usb_device_id id_table[] = { static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x19d2, 0xffec) },
{ USB_DEVICE(0x19d2, 0xffee) },
{ USB_DEVICE(0x19d2, 0xfff6) },
{ USB_DEVICE(0x19d2, 0xfff7) },
{ USB_DEVICE(0x19d2, 0xfff8) },
{ USB_DEVICE(0x19d2, 0xfff9) },
{ USB_DEVICE(0x19d2, 0xfffb) },
{ USB_DEVICE(0x19d2, 0xfffc) },
/* MG880 */ /* MG880 */
{ USB_DEVICE(0x19d2, 0xfffd) }, { USB_DEVICE(0x19d2, 0xfffd) },
{ }, { },
......
...@@ -59,10 +59,6 @@ static int uas_use_uas_driver(struct usb_interface *intf, ...@@ -59,10 +59,6 @@ static int uas_use_uas_driver(struct usb_interface *intf,
unsigned long flags = id->driver_info; unsigned long flags = id->driver_info;
int r, alt; int r, alt;
usb_stor_adjust_quirks(udev, &flags);
if (flags & US_FL_IGNORE_UAS)
return 0;
alt = uas_find_uas_alt_setting(intf); alt = uas_find_uas_alt_setting(intf);
if (alt < 0) if (alt < 0)
...@@ -72,6 +68,29 @@ static int uas_use_uas_driver(struct usb_interface *intf, ...@@ -72,6 +68,29 @@ static int uas_use_uas_driver(struct usb_interface *intf,
if (r < 0) if (r < 0)
return 0; return 0;
/*
* ASM1051 and older ASM1053 devices have the same usb-id, and UAS is
* broken on the ASM1051, use the number of streams to differentiate.
* New ASM1053-s also support 32 streams, but have a different prod-id.
*/
if (le16_to_cpu(udev->descriptor.idVendor) == 0x174c &&
le16_to_cpu(udev->descriptor.idProduct) == 0x55aa) {
if (udev->speed < USB_SPEED_SUPER) {
/* No streams info, assume ASM1051 */
flags |= US_FL_IGNORE_UAS;
} else if (usb_ss_max_streams(&eps[1]->ss_ep_comp) == 32) {
flags |= US_FL_IGNORE_UAS;
}
}
usb_stor_adjust_quirks(udev, &flags);
if (flags & US_FL_IGNORE_UAS) {
dev_warn(&udev->dev,
"UAS is blacklisted for this device, using usb-storage instead\n");
return 0;
}
if (udev->bus->sg_tablesize == 0) { if (udev->bus->sg_tablesize == 0) {
dev_warn(&udev->dev, dev_warn(&udev->dev,
"The driver for the USB controller %s does not support scatter-gather which is\n", "The driver for the USB controller %s does not support scatter-gather which is\n",
......
...@@ -741,6 +741,12 @@ UNUSUAL_DEV( 0x059b, 0x0001, 0x0100, 0x0100, ...@@ -741,6 +741,12 @@ UNUSUAL_DEV( 0x059b, 0x0001, 0x0100, 0x0100,
USB_SC_DEVICE, USB_PR_DEVICE, NULL, USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_SINGLE_LUN ), US_FL_SINGLE_LUN ),
UNUSUAL_DEV( 0x059b, 0x0040, 0x0100, 0x0100,
"Iomega",
"Jaz USB Adapter",
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_SINGLE_LUN ),
/* Reported by <Hendryk.Pfeiffer@gmx.de> */ /* Reported by <Hendryk.Pfeiffer@gmx.de> */
UNUSUAL_DEV( 0x059f, 0x0643, 0x0000, 0x0000, UNUSUAL_DEV( 0x059f, 0x0643, 0x0000, 0x0000,
"LaCie", "LaCie",
......
...@@ -431,16 +431,19 @@ void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e *bce) ...@@ -431,16 +431,19 @@ void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e *bce)
uwb_dev->mac_addr = *bce->mac_addr; uwb_dev->mac_addr = *bce->mac_addr;
uwb_dev->dev_addr = bce->dev_addr; uwb_dev->dev_addr = bce->dev_addr;
dev_set_name(&uwb_dev->dev, "%s", macbuf); dev_set_name(&uwb_dev->dev, "%s", macbuf);
/* plug the beacon cache */
bce->uwb_dev = uwb_dev;
uwb_dev->bce = bce;
uwb_bce_get(bce); /* released in uwb_dev_sys_release() */
result = uwb_dev_add(uwb_dev, &rc->uwb_dev.dev, rc); result = uwb_dev_add(uwb_dev, &rc->uwb_dev.dev, rc);
if (result < 0) { if (result < 0) {
dev_err(dev, "new device %s: cannot instantiate device\n", dev_err(dev, "new device %s: cannot instantiate device\n",
macbuf); macbuf);
goto error_dev_add; goto error_dev_add;
} }
/* plug the beacon cache */
bce->uwb_dev = uwb_dev;
uwb_dev->bce = bce;
uwb_bce_get(bce); /* released in uwb_dev_sys_release() */
dev_info(dev, "uwb device (mac %s dev %s) connected to %s %s\n", dev_info(dev, "uwb device (mac %s dev %s) connected to %s %s\n",
macbuf, devbuf, rc->uwb_dev.dev.parent->bus->name, macbuf, devbuf, rc->uwb_dev.dev.parent->bus->name,
dev_name(rc->uwb_dev.dev.parent)); dev_name(rc->uwb_dev.dev.parent));
...@@ -448,6 +451,8 @@ void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e *bce) ...@@ -448,6 +451,8 @@ void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e *bce)
return; return;
error_dev_add: error_dev_add:
bce->uwb_dev = NULL;
uwb_bce_put(bce);
kfree(uwb_dev); kfree(uwb_dev);
return; return;
} }
......
...@@ -396,6 +396,7 @@ header-y += un.h ...@@ -396,6 +396,7 @@ header-y += un.h
header-y += unistd.h header-y += unistd.h
header-y += unix_diag.h header-y += unix_diag.h
header-y += usbdevice_fs.h header-y += usbdevice_fs.h
header-y += usbip.h
header-y += utime.h header-y += utime.h
header-y += utsname.h header-y += utsname.h
header-y += uuid.h header-y += uuid.h
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include <syslog.h> #include <syslog.h>
#include <unistd.h> #include <unistd.h>
#include <linux/usb/ch9.h> #include <linux/usb/ch9.h>
#include "../../uapi/usbip.h" #include <linux/usbip.h>
#ifndef USBIDS_FILE #ifndef USBIDS_FILE
#define USBIDS_FILE "/usr/share/hwdata/usb.ids" #define USBIDS_FILE "/usr/share/hwdata/usb.ids"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment