[PATCH] USB: sl811-hcd fixes

Various fixes to the sl811-hcd driver:

* Fix small glitches that crept in during recent evolution of usbcore's hcd
glue layer, coupling endpoint state records to usbcore and active urbs.
(As noted by folk whose boards weren't stuck on 2.6.9 kernels...)

* Cope with various system-specific issues:
- Some configurations (e.g. a CF-card uses this chip) have iospace
addresses for the two registers, rather than memory mapped ones.
- Some configurations do interesting things with IRQs; maybe the
line is shared, or it doesn't support level triggering.
- Not all boards can drive the chip reset line in software.

* Address a potential race during unlinking.

* Tweak probe/remove section info to handle the case where this segment
of a platform bus is hotpluggable (e.g. CF card). (The basic problem
is that CONFIG_HOTPLUG is global, which is wrong since not all busses
can hotplug even on hotplug-friendly systems...) Also export the
driver, so that the CF driver can depend on it.

Also removed some annoying end-of-line whitespace.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

David Brownell and committed by
Greg KH
1e9a47b6 2e3e80c2

+82 -66
+82 -66
drivers/usb/host/sl811-hcd.c
··· 2 * SL811HS HCD (Host Controller Driver) for USB. 3 * 4 * Copyright (C) 2004 Psion Teklogix (for NetBook PRO) 5 - * Copyright (C) 2004 David Brownell 6 - * 7 * Periodic scheduling is based on Roman's OHCI code 8 * Copyright (C) 1999 Roman Weissgaerber 9 * ··· 15 * For documentation, see the SL811HS spec and the "SL811HS Embedded Host" 16 * document (providing significant pieces missing from that spec); plus 17 * the SL811S spec if you want peripheral side info. 18 - */ 19 20 /* 21 * Status: Passed basic stress testing, works with hubs, mice, keyboards, ··· 67 MODULE_DESCRIPTION("SL811HS USB Host Controller Driver"); 68 MODULE_LICENSE("GPL"); 69 70 - #define DRIVER_VERSION "15 Dec 2004" 71 72 73 #ifndef DEBUG ··· 121 /* reset as thoroughly as we can */ 122 if (sl811->board && sl811->board->reset) 123 sl811->board->reset(hcd->self.controller); 124 125 sl811_write(sl811, SL11H_IRQ_ENABLE, 0); 126 sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); ··· 447 spin_lock(&urb->lock); 448 if (urb->status == -EINPROGRESS) 449 urb->status = status; 450 spin_unlock(&urb->lock); 451 452 spin_unlock(&sl811->lock); ··· 477 if (*prev) 478 *prev = ep->next; 479 sl811->load[i] -= ep->load; 480 - } 481 ep->branch = PERIODIC_SIZE; 482 sl811->periodic_count--; 483 sl811_to_hcd(sl811)->self.bandwidth_allocated ··· 666 667 #ifdef QUIRK2 668 /* this may no longer be necessary ... */ 669 - if (irqstat == 0 && ret == IRQ_NONE) { 670 irqstat = checkdone(sl811); 671 - if (irqstat /* && irq != ~0 */ ) 672 sl811->stat_lost++; 673 } 674 #endif ··· 727 if (sl811->active_a) { 728 sl811_write(sl811, SL811_EP_A(SL11H_HOSTCTLREG), 0); 729 finish_request(sl811, sl811->active_a, 730 - container_of(sl811->active_a->hep->urb_list.next, 731 struct urb, urb_list), 732 NULL, -ESHUTDOWN); 733 sl811->active_a = NULL; ··· 737 if (sl811->active_b) { 738 sl811_write(sl811, SL811_EP_B(SL11H_HOSTCTLREG), 0); 739 finish_request(sl811, sl811->active_b, 740 - container_of(sl811->active_b->hep->urb_list.next, 741 struct urb, urb_list), 742 NULL, -ESHUTDOWN); 743 sl811->active_b = NULL; ··· 768 goto retry; 769 } 770 771 - if (sl811->periodic_count == 0 && list_empty(&sl811->async)) 772 sofirq_off(sl811); 773 sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable); 774 ··· 803 } 804 if (j < PERIODIC_SIZE) 805 continue; 806 - branch = i; 807 } 808 } 809 return branch; ··· 897 break; 898 } 899 900 hep->hcpriv = ep; 901 } 902 ··· 969 static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) 970 { 971 struct sl811 *sl811 = hcd_to_sl811(hcd); 972 - struct usb_host_endpoint *hep = urb->hcpriv; 973 unsigned long flags; 974 struct sl811h_ep *ep; 975 int retval = 0; 976 977 - if (!hep) 978 - return -EINVAL; 979 - 980 spin_lock_irqsave(&sl811->lock, flags); 981 ep = hep->hcpriv; 982 if (ep) { 983 /* finish right away if this urb can't be active ... ··· 1026 VDBG("dequeue, urb %p active %s; wait4irq\n", urb, 1027 (sl811->active_a == ep) ? "A" : "B"); 1028 } else 1029 retval = -EINVAL; 1030 spin_unlock_irqrestore(&sl811->lock, flags); 1031 return retval; ··· 1586 if (sl811->board && sl811->board->power) 1587 hub_set_power_budget(udev, sl811->board->power * 2); 1588 1589 return 0; 1590 } 1591 ··· 1631 1632 /*-------------------------------------------------------------------------*/ 1633 1634 - static int __init_or_module 1635 sl811h_remove(struct device *dev) 1636 { 1637 struct usb_hcd *hcd = dev_get_drvdata(dev); ··· 1644 remove_debug_file(sl811); 1645 usb_remove_hcd(hcd); 1646 1647 - iounmap(sl811->data_reg); 1648 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 1649 - release_mem_region(res->start, 1); 1650 1651 - iounmap(sl811->addr_reg); 1652 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1653 - release_mem_region(res->start, 1); 1654 1655 usb_put_hcd(hcd); 1656 return 0; 1657 } 1658 1659 - #define resource_len(r) (((r)->end - (r)->start) + 1) 1660 - 1661 - static int __init 1662 sl811h_probe(struct device *dev) 1663 { 1664 struct usb_hcd *hcd; ··· 1668 void __iomem *addr_reg; 1669 void __iomem *data_reg; 1670 int retval; 1671 - u8 tmp; 1672 1673 /* basic sanity checks first. board-specific init logic should 1674 * have initialized these three resources and probably board ··· 1676 * minimal sanity checking. 1677 */ 1678 pdev = container_of(dev, struct platform_device, dev); 1679 - if (pdev->num_resources < 3) 1680 - return -ENODEV; 1681 - 1682 - addr = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1683 - data = platform_get_resource(pdev, IORESOURCE_MEM, 1); 1684 irq = platform_get_irq(pdev, 0); 1685 - if (!addr || !data || irq < 0) 1686 return -ENODEV; 1687 1688 /* refuse to confuse usbcore */ ··· 1686 return -EINVAL; 1687 } 1688 1689 - if (!request_mem_region(addr->start, 1, hcd_name)) { 1690 - retval = -EBUSY; 1691 - goto err1; 1692 - } 1693 - addr_reg = ioremap(addr->start, resource_len(addr)); 1694 - if (addr_reg == NULL) { 1695 - retval = -ENOMEM; 1696 - goto err2; 1697 - } 1698 1699 - if (!request_mem_region(data->start, 1, hcd_name)) { 1700 - retval = -EBUSY; 1701 - goto err3; 1702 - } 1703 - data_reg = ioremap(data->start, resource_len(addr)); 1704 - if (data_reg == NULL) { 1705 - retval = -ENOMEM; 1706 - goto err4; 1707 } 1708 1709 /* allocate and initialize hcd */ ··· 1751 goto err6; 1752 } 1753 1754 - /* sl811s would need a different handler for this irq */ 1755 - #ifdef CONFIG_ARM 1756 - /* Cypress docs say the IRQ is IRQT_HIGH ... */ 1757 - set_irq_type(irq, IRQT_RISING); 1758 - #endif 1759 - retval = usb_add_hcd(hcd, irq, SA_INTERRUPT); 1760 if (retval != 0) 1761 goto err6; 1762 ··· 1768 err6: 1769 usb_put_hcd(hcd); 1770 err5: 1771 - iounmap(data_reg); 1772 err4: 1773 - release_mem_region(data->start, 1); 1774 - err3: 1775 - iounmap(addr_reg); 1776 err2: 1777 - release_mem_region(addr->start, 1); 1778 - err1: 1779 DBG("init error, %d\n", retval); 1780 return retval; 1781 } ··· 1781 #ifdef CONFIG_PM 1782 1783 /* for this device there's no useful distinction between the controller 1784 - * and its root hub, except that the root hub only gets direct PM calls 1785 * when CONFIG_USB_SUSPEND is enabled. 1786 */ 1787 ··· 1835 #endif 1836 1837 1838 - static struct device_driver sl811h_driver = { 1839 .name = (char *) hcd_name, 1840 .bus = &platform_bus_type, 1841 1842 .probe = sl811h_probe, 1843 - .remove = sl811h_remove, 1844 1845 .suspend = sl811h_suspend, 1846 .resume = sl811h_resume, 1847 }; 1848 1849 /*-------------------------------------------------------------------------*/ 1850 - 1851 - static int __init sl811h_init(void) 1852 { 1853 if (usb_disabled()) 1854 return -ENODEV; ··· 1860 } 1861 module_init(sl811h_init); 1862 1863 - static void __exit sl811h_cleanup(void) 1864 - { 1865 driver_unregister(&sl811h_driver); 1866 } 1867 module_exit(sl811h_cleanup);
··· 2 * SL811HS HCD (Host Controller Driver) for USB. 3 * 4 * Copyright (C) 2004 Psion Teklogix (for NetBook PRO) 5 + * Copyright (C) 2004-2005 David Brownell 6 + * 7 * Periodic scheduling is based on Roman's OHCI code 8 * Copyright (C) 1999 Roman Weissgaerber 9 * ··· 15 * For documentation, see the SL811HS spec and the "SL811HS Embedded Host" 16 * document (providing significant pieces missing from that spec); plus 17 * the SL811S spec if you want peripheral side info. 18 + */ 19 20 /* 21 * Status: Passed basic stress testing, works with hubs, mice, keyboards, ··· 67 MODULE_DESCRIPTION("SL811HS USB Host Controller Driver"); 68 MODULE_LICENSE("GPL"); 69 70 + #define DRIVER_VERSION "19 May 2005" 71 72 73 #ifndef DEBUG ··· 121 /* reset as thoroughly as we can */ 122 if (sl811->board && sl811->board->reset) 123 sl811->board->reset(hcd->self.controller); 124 + else { 125 + sl811_write(sl811, SL11H_CTLREG1, SL11H_CTL1MASK_SE0); 126 + mdelay(20); 127 + } 128 129 sl811_write(sl811, SL11H_IRQ_ENABLE, 0); 130 sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); ··· 443 spin_lock(&urb->lock); 444 if (urb->status == -EINPROGRESS) 445 urb->status = status; 446 + urb->hcpriv = NULL; 447 spin_unlock(&urb->lock); 448 449 spin_unlock(&sl811->lock); ··· 472 if (*prev) 473 *prev = ep->next; 474 sl811->load[i] -= ep->load; 475 + } 476 ep->branch = PERIODIC_SIZE; 477 sl811->periodic_count--; 478 sl811_to_hcd(sl811)->self.bandwidth_allocated ··· 661 662 #ifdef QUIRK2 663 /* this may no longer be necessary ... */ 664 + if (irqstat == 0) { 665 irqstat = checkdone(sl811); 666 + if (irqstat) 667 sl811->stat_lost++; 668 } 669 #endif ··· 722 if (sl811->active_a) { 723 sl811_write(sl811, SL811_EP_A(SL11H_HOSTCTLREG), 0); 724 finish_request(sl811, sl811->active_a, 725 + container_of(sl811->active_a 726 + ->hep->urb_list.next, 727 struct urb, urb_list), 728 NULL, -ESHUTDOWN); 729 sl811->active_a = NULL; ··· 731 if (sl811->active_b) { 732 sl811_write(sl811, SL811_EP_B(SL11H_HOSTCTLREG), 0); 733 finish_request(sl811, sl811->active_b, 734 + container_of(sl811->active_b 735 + ->hep->urb_list.next, 736 struct urb, urb_list), 737 NULL, -ESHUTDOWN); 738 sl811->active_b = NULL; ··· 761 goto retry; 762 } 763 764 + if (sl811->periodic_count == 0 && list_empty(&sl811->async)) 765 sofirq_off(sl811); 766 sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable); 767 ··· 796 } 797 if (j < PERIODIC_SIZE) 798 continue; 799 + branch = i; 800 } 801 } 802 return branch; ··· 890 break; 891 } 892 893 + ep->hep = hep; 894 hep->hcpriv = ep; 895 } 896 ··· 961 static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) 962 { 963 struct sl811 *sl811 = hcd_to_sl811(hcd); 964 + struct usb_host_endpoint *hep; 965 unsigned long flags; 966 struct sl811h_ep *ep; 967 int retval = 0; 968 969 spin_lock_irqsave(&sl811->lock, flags); 970 + hep = urb->hcpriv; 971 + if (!hep) 972 + goto fail; 973 + 974 ep = hep->hcpriv; 975 if (ep) { 976 /* finish right away if this urb can't be active ... ··· 1017 VDBG("dequeue, urb %p active %s; wait4irq\n", urb, 1018 (sl811->active_a == ep) ? "A" : "B"); 1019 } else 1020 + fail: 1021 retval = -EINVAL; 1022 spin_unlock_irqrestore(&sl811->lock, flags); 1023 return retval; ··· 1576 if (sl811->board && sl811->board->power) 1577 hub_set_power_budget(udev, sl811->board->power * 2); 1578 1579 + /* enable power and interupts */ 1580 + port_power(sl811, 1); 1581 + 1582 return 0; 1583 } 1584 ··· 1618 1619 /*-------------------------------------------------------------------------*/ 1620 1621 + static int __devexit 1622 sl811h_remove(struct device *dev) 1623 { 1624 struct usb_hcd *hcd = dev_get_drvdata(dev); ··· 1631 remove_debug_file(sl811); 1632 usb_remove_hcd(hcd); 1633 1634 + /* some platforms may use IORESOURCE_IO */ 1635 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 1636 + if (res) 1637 + iounmap(sl811->data_reg); 1638 1639 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1640 + if (res) 1641 + iounmap(sl811->addr_reg); 1642 1643 usb_put_hcd(hcd); 1644 return 0; 1645 } 1646 1647 + static int __devinit 1648 sl811h_probe(struct device *dev) 1649 { 1650 struct usb_hcd *hcd; ··· 1656 void __iomem *addr_reg; 1657 void __iomem *data_reg; 1658 int retval; 1659 + u8 tmp, ioaddr = 0; 1660 1661 /* basic sanity checks first. board-specific init logic should 1662 * have initialized these three resources and probably board ··· 1664 * minimal sanity checking. 1665 */ 1666 pdev = container_of(dev, struct platform_device, dev); 1667 irq = platform_get_irq(pdev, 0); 1668 + if (pdev->num_resources < 3 || irq < 0) 1669 return -ENODEV; 1670 1671 /* refuse to confuse usbcore */ ··· 1679 return -EINVAL; 1680 } 1681 1682 + /* the chip may be wired for either kind of addressing */ 1683 + addr = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1684 + data = platform_get_resource(pdev, IORESOURCE_MEM, 1); 1685 + retval = -EBUSY; 1686 + if (!addr || !data) { 1687 + addr = platform_get_resource(pdev, IORESOURCE_IO, 0); 1688 + data = platform_get_resource(pdev, IORESOURCE_IO, 1); 1689 + if (!addr || !data) 1690 + return -ENODEV; 1691 + ioaddr = 1; 1692 1693 + addr_reg = (void __iomem *) addr->start; 1694 + data_reg = (void __iomem *) data->start; 1695 + } else { 1696 + addr_reg = ioremap(addr->start, 1); 1697 + if (addr_reg == NULL) { 1698 + retval = -ENOMEM; 1699 + goto err2; 1700 + } 1701 + 1702 + data_reg = ioremap(data->start, 1); 1703 + if (data_reg == NULL) { 1704 + retval = -ENOMEM; 1705 + goto err4; 1706 + } 1707 } 1708 1709 /* allocate and initialize hcd */ ··· 1737 goto err6; 1738 } 1739 1740 + /* The chip's IRQ is level triggered, active high. A requirement 1741 + * for platform device setup is to cope with things like signal 1742 + * inverters (e.g. CF is active low) or working only with edge 1743 + * triggers (e.g. most ARM CPUs). Initial driver stress testing 1744 + * was on a system with single edge triggering, so most sorts of 1745 + * triggering arrangement should work. 1746 + */ 1747 + retval = usb_add_hcd(hcd, irq, SA_INTERRUPT | SA_SHIRQ); 1748 if (retval != 0) 1749 goto err6; 1750 ··· 1752 err6: 1753 usb_put_hcd(hcd); 1754 err5: 1755 + if (!ioaddr) 1756 + iounmap(data_reg); 1757 err4: 1758 + if (!ioaddr) 1759 + iounmap(addr_reg); 1760 err2: 1761 DBG("init error, %d\n", retval); 1762 return retval; 1763 } ··· 1767 #ifdef CONFIG_PM 1768 1769 /* for this device there's no useful distinction between the controller 1770 + * and its root hub, except that the root hub only gets direct PM calls 1771 * when CONFIG_USB_SUSPEND is enabled. 1772 */ 1773 ··· 1821 #endif 1822 1823 1824 + /* this driver is exported so sl811_cs can depend on it */ 1825 + struct device_driver sl811h_driver = { 1826 .name = (char *) hcd_name, 1827 .bus = &platform_bus_type, 1828 1829 .probe = sl811h_probe, 1830 + .remove = __devexit_p(sl811h_remove), 1831 1832 .suspend = sl811h_suspend, 1833 .resume = sl811h_resume, 1834 }; 1835 + EXPORT_SYMBOL(sl811h_driver); 1836 1837 /*-------------------------------------------------------------------------*/ 1838 + 1839 + static int __init sl811h_init(void) 1840 { 1841 if (usb_disabled()) 1842 return -ENODEV; ··· 1844 } 1845 module_init(sl811h_init); 1846 1847 + static void __exit sl811h_cleanup(void) 1848 + { 1849 driver_unregister(&sl811h_driver); 1850 } 1851 module_exit(sl811h_cleanup);