aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlav Kongas <ok@artecdesign.ee>2005-08-05 07:23:35 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-09-08 19:22:48 -0400
commit9a57116bc9e36c9accc869f666e1d25c5e2cdcbf (patch)
tree64cd816ac2f9e119d8c1afd330e8f737ab643617
parentf8d23d309809ae69c763520dababb7e845938272 (diff)
[PATCH] USB: Switch isp116x-hcd over to root hub interrupt
Switch isp116x-hcd over from root hub polling to interrupt. This change closes also a race that was present with the old polling scheme: status polling could happen in a time window, where root hub status bits were not stable. Signed-off-by: Olav Kongas <ok@artecdesign.ee> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/host/isp116x-hcd.c35
1 files changed, 22 insertions, 13 deletions
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 1ed2abac8d17..41bbae83fc71 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -83,7 +83,7 @@
83#include "../core/hcd.h" 83#include "../core/hcd.h"
84#include "isp116x.h" 84#include "isp116x.h"
85 85
86#define DRIVER_VERSION "08 Apr 2005" 86#define DRIVER_VERSION "05 Aug 2005"
87#define DRIVER_DESC "ISP116x USB Host Controller Driver" 87#define DRIVER_DESC "ISP116x USB Host Controller Driver"
88 88
89MODULE_DESCRIPTION(DRIVER_DESC); 89MODULE_DESCRIPTION(DRIVER_DESC);
@@ -629,14 +629,12 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
629 ERR("Unrecoverable error\n"); 629 ERR("Unrecoverable error\n");
630 /* What should we do here? Reset? */ 630 /* What should we do here? Reset? */
631 } 631 }
632 if (intstat & HCINT_RHSC) { 632 if (intstat & HCINT_RHSC)
633 isp116x->rhstatus = 633 /* When root hub or any of its ports is going
634 isp116x_read_reg32(isp116x, HCRHSTATUS); 634 to come out of suspend, it may take more
635 isp116x->rhport[0] = 635 than 10ms for status bits to stabilize. */
636 isp116x_read_reg32(isp116x, HCRHPORT1); 636 mod_timer(&hcd->rh_timer, jiffies
637 isp116x->rhport[1] = 637 + msecs_to_jiffies(20) + 1);
638 isp116x_read_reg32(isp116x, HCRHPORT2);
639 }
640 if (intstat & HCINT_RD) { 638 if (intstat & HCINT_RD) {
641 DBG("---- remote wakeup\n"); 639 DBG("---- remote wakeup\n");
642 schedule_work(&isp116x->rh_resume); 640 schedule_work(&isp116x->rh_resume);
@@ -925,20 +923,27 @@ static int isp116x_hub_status_data(struct usb_hcd *hcd, char *buf)
925{ 923{
926 struct isp116x *isp116x = hcd_to_isp116x(hcd); 924 struct isp116x *isp116x = hcd_to_isp116x(hcd);
927 int ports, i, changed = 0; 925 int ports, i, changed = 0;
926 unsigned long flags;
928 927
929 if (!HC_IS_RUNNING(hcd->state)) 928 if (!HC_IS_RUNNING(hcd->state))
930 return -ESHUTDOWN; 929 return -ESHUTDOWN;
931 930
932 ports = isp116x->rhdesca & RH_A_NDP; 931 /* Report no status change now, if we are scheduled to be
932 called later */
933 if (timer_pending(&hcd->rh_timer))
934 return 0;
933 935
934 /* init status */ 936 ports = isp116x->rhdesca & RH_A_NDP;
937 spin_lock_irqsave(&isp116x->lock, flags);
938 isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS);
935 if (isp116x->rhstatus & (RH_HS_LPSC | RH_HS_OCIC)) 939 if (isp116x->rhstatus & (RH_HS_LPSC | RH_HS_OCIC))
936 buf[0] = changed = 1; 940 buf[0] = changed = 1;
937 else 941 else
938 buf[0] = 0; 942 buf[0] = 0;
939 943
940 for (i = 0; i < ports; i++) { 944 for (i = 0; i < ports; i++) {
941 u32 status = isp116x->rhport[i]; 945 u32 status = isp116x->rhport[i] =
946 isp116x_read_reg32(isp116x, i ? HCRHPORT2 : HCRHPORT1);
942 947
943 if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC 948 if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
944 | RH_PS_OCIC | RH_PS_PRSC)) { 949 | RH_PS_OCIC | RH_PS_PRSC)) {
@@ -947,6 +952,7 @@ static int isp116x_hub_status_data(struct usb_hcd *hcd, char *buf)
947 continue; 952 continue;
948 } 953 }
949 } 954 }
955 spin_unlock_irqrestore(&isp116x->lock, flags);
950 return changed; 956 return changed;
951} 957}
952 958
@@ -1536,6 +1542,9 @@ static int isp116x_start(struct usb_hcd *hcd)
1536 return -ENODEV; 1542 return -ENODEV;
1537 } 1543 }
1538 1544
1545 /* To be removed in future */
1546 hcd->uses_new_polling = 1;
1547
1539 isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE); 1548 isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE);
1540 isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE); 1549 isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE);
1541 1550
@@ -1639,7 +1648,7 @@ static int __init_or_module isp116x_remove(struct device *dev)
1639 struct platform_device *pdev; 1648 struct platform_device *pdev;
1640 struct resource *res; 1649 struct resource *res;
1641 1650
1642 if(!hcd) 1651 if (!hcd)
1643 return 0; 1652 return 0;
1644 isp116x = hcd_to_isp116x(hcd); 1653 isp116x = hcd_to_isp116x(hcd);
1645 pdev = container_of(dev, struct platform_device, dev); 1654 pdev = container_of(dev, struct platform_device, dev);