aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2008-05-11 01:46:38 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-05-14 13:00:30 -0400
commit405177070614f35133304d4daa1332afeb83ffa2 (patch)
tree5e021454bd6027ad7289b6a7cc206ee95386f3e5
parent5a59bc544d00923ff715e2fe68ea537153f52dda (diff)
USB: atmel_usba_udc fixes, mostly disconnect()
Various fixes to Atmel's high speed UDC driver. * Issue some missing disconnect() calls. Currently they are only made when VBUS power goes away (on boards where the driver can sense such changes), but that's not enough for gadget drivers to clean out all the state that's needed. Missing calls were: - After USB reset, before starting enumeration. - When unregistering a gadget driver, before unbind(). * Don't assume gadget drivers provide disconnect callbacks; make sure to not call through a null pointer! * When the driver doesn't provide an unbind() callback, refuse to unregister it. Also remove two bogus "error" messages: * Related to mis-handling of disconnect() ... don't emit error messages for disconnect() handlers that disable endpoints. All of them should be doing that; the problem is (unfixed) oddness in atmel_usba_udc. * Don't emit a diagnostic for a curious and transient nonfatal error that shows up sometimes with EP0. Those messages spammed syslog, for no good reason. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Acked-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.c48
1 files changed, 38 insertions, 10 deletions
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index e756023362c2..07e5a0b5dcda 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -649,7 +649,13 @@ static int usba_ep_disable(struct usb_ep *_ep)
649 649
650 if (!ep->desc) { 650 if (!ep->desc) {
651 spin_unlock_irqrestore(&udc->lock, flags); 651 spin_unlock_irqrestore(&udc->lock, flags);
652 DBG(DBG_ERR, "ep_disable: %s not enabled\n", ep->ep.name); 652 /* REVISIT because this driver disables endpoints in
653 * reset_all_endpoints() before calling disconnect(),
654 * most gadget drivers would trigger this non-error ...
655 */
656 if (udc->gadget.speed != USB_SPEED_UNKNOWN)
657 DBG(DBG_ERR, "ep_disable: %s not enabled\n",
658 ep->ep.name);
653 return -EINVAL; 659 return -EINVAL;
654 } 660 }
655 ep->desc = NULL; 661 ep->desc = NULL;
@@ -1032,8 +1038,6 @@ static struct usba_udc the_udc = {
1032 .release = nop_release, 1038 .release = nop_release,
1033 }, 1039 },
1034 }, 1040 },
1035
1036 .lock = SPIN_LOCK_UNLOCKED,
1037}; 1041};
1038 1042
1039/* 1043/*
@@ -1052,6 +1056,12 @@ static void reset_all_endpoints(struct usba_udc *udc)
1052 request_complete(ep, req, -ECONNRESET); 1056 request_complete(ep, req, -ECONNRESET);
1053 } 1057 }
1054 1058
1059 /* NOTE: normally, the next call to the gadget driver is in
1060 * charge of disabling endpoints... usually disconnect().
1061 * The exception would be entering a high speed test mode.
1062 *
1063 * FIXME remove this code ... and retest thoroughly.
1064 */
1055 list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { 1065 list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
1056 if (ep->desc) { 1066 if (ep->desc) {
1057 spin_unlock(&udc->lock); 1067 spin_unlock(&udc->lock);
@@ -1219,7 +1229,7 @@ static inline bool feature_is_ep_halt(struct usb_ctrlrequest *crq)
1219static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, 1229static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep,
1220 struct usb_ctrlrequest *crq) 1230 struct usb_ctrlrequest *crq)
1221{ 1231{
1222 int retval = 0;; 1232 int retval = 0;
1223 1233
1224 switch (crq->bRequest) { 1234 switch (crq->bRequest) {
1225 case USB_REQ_GET_STATUS: { 1235 case USB_REQ_GET_STATUS: {
@@ -1693,6 +1703,14 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
1693 usba_writel(udc, INT_CLR, USBA_END_OF_RESET); 1703 usba_writel(udc, INT_CLR, USBA_END_OF_RESET);
1694 reset_all_endpoints(udc); 1704 reset_all_endpoints(udc);
1695 1705
1706 if (udc->gadget.speed != USB_SPEED_UNKNOWN
1707 && udc->driver->disconnect) {
1708 udc->gadget.speed = USB_SPEED_UNKNOWN;
1709 spin_unlock(&udc->lock);
1710 udc->driver->disconnect(&udc->gadget);
1711 spin_lock(&udc->lock);
1712 }
1713
1696 if (status & USBA_HIGH_SPEED) { 1714 if (status & USBA_HIGH_SPEED) {
1697 DBG(DBG_BUS, "High-speed bus reset detected\n"); 1715 DBG(DBG_BUS, "High-speed bus reset detected\n");
1698 udc->gadget.speed = USB_SPEED_HIGH; 1716 udc->gadget.speed = USB_SPEED_HIGH;
@@ -1716,9 +1734,13 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
1716 | USBA_DET_SUSPEND 1734 | USBA_DET_SUSPEND
1717 | USBA_END_OF_RESUME)); 1735 | USBA_END_OF_RESUME));
1718 1736
1737 /*
1738 * Unclear why we hit this irregularly, e.g. in usbtest,
1739 * but it's clearly harmless...
1740 */
1719 if (!(usba_ep_readl(ep0, CFG) & USBA_EPT_MAPPED)) 1741 if (!(usba_ep_readl(ep0, CFG) & USBA_EPT_MAPPED))
1720 dev_warn(&udc->pdev->dev, 1742 dev_dbg(&udc->pdev->dev,
1721 "WARNING: EP0 configuration is invalid!\n"); 1743 "ODD: EP0 configuration is invalid!\n");
1722 } 1744 }
1723 1745
1724 spin_unlock(&udc->lock); 1746 spin_unlock(&udc->lock);
@@ -1751,9 +1773,11 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid)
1751 reset_all_endpoints(udc); 1773 reset_all_endpoints(udc);
1752 toggle_bias(0); 1774 toggle_bias(0);
1753 usba_writel(udc, CTRL, USBA_DISABLE_MASK); 1775 usba_writel(udc, CTRL, USBA_DISABLE_MASK);
1754 spin_unlock(&udc->lock); 1776 if (udc->driver->disconnect) {
1755 udc->driver->disconnect(&udc->gadget); 1777 spin_unlock(&udc->lock);
1756 spin_lock(&udc->lock); 1778 udc->driver->disconnect(&udc->gadget);
1779 spin_lock(&udc->lock);
1780 }
1757 } 1781 }
1758 udc->vbus_prev = vbus; 1782 udc->vbus_prev = vbus;
1759 } 1783 }
@@ -1825,7 +1849,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
1825 1849
1826 if (!udc->pdev) 1850 if (!udc->pdev)
1827 return -ENODEV; 1851 return -ENODEV;
1828 if (driver != udc->driver) 1852 if (driver != udc->driver || !driver->unbind)
1829 return -EINVAL; 1853 return -EINVAL;
1830 1854
1831 if (udc->vbus_pin != -1) 1855 if (udc->vbus_pin != -1)
@@ -1840,6 +1864,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
1840 toggle_bias(0); 1864 toggle_bias(0);
1841 usba_writel(udc, CTRL, USBA_DISABLE_MASK); 1865 usba_writel(udc, CTRL, USBA_DISABLE_MASK);
1842 1866
1867 if (udc->driver->disconnect)
1868 udc->driver->disconnect(&udc->gadget);
1869
1843 driver->unbind(&udc->gadget); 1870 driver->unbind(&udc->gadget);
1844 udc->gadget.dev.driver = NULL; 1871 udc->gadget.dev.driver = NULL;
1845 udc->driver = NULL; 1872 udc->driver = NULL;
@@ -1879,6 +1906,7 @@ static int __init usba_udc_probe(struct platform_device *pdev)
1879 goto err_get_hclk; 1906 goto err_get_hclk;
1880 } 1907 }
1881 1908
1909 spin_lock_init(&udc->lock);
1882 udc->pdev = pdev; 1910 udc->pdev = pdev;
1883 udc->pclk = pclk; 1911 udc->pclk = pclk;
1884 udc->hclk = hclk; 1912 udc->hclk = hclk;