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