aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2005-04-09 17:26:00 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-06-27 17:43:43 -0400
commitf5946f8220a866dcdb8edc6abe23c1443e252425 (patch)
tree3984d5eb8382d3bc694168e90957206d97fd7d1c /drivers/usb/host
parent014e73c99aa408f3766afe8d11a1caa3a708b736 (diff)
[PATCH] USB UHCI: Minor improvements
This patch makes a few small improvements in the UHCI driver. Some code is moved between different source files and a more useful pointer is passed to a callback routine. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/uhci-hcd.c69
-rw-r--r--drivers/usb/host/uhci-hub.c16
-rw-r--r--drivers/usb/host/uhci-q.c23
3 files changed, 55 insertions, 53 deletions
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 8b6c87ef486b..c17bd7ebc021 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -100,22 +100,15 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
100/* to make sure it doesn't hog all of the bandwidth */ 100/* to make sure it doesn't hog all of the bandwidth */
101#define DEPTH_INTERVAL 5 101#define DEPTH_INTERVAL 5
102 102
103static inline void restart_timer(struct uhci_hcd *uhci)
104{
105 mod_timer(&uhci->stall_timer, jiffies + msecs_to_jiffies(100));
106}
107
103#include "uhci-hub.c" 108#include "uhci-hub.c"
104#include "uhci-debug.c" 109#include "uhci-debug.c"
105#include "uhci-q.c" 110#include "uhci-q.c"
106 111
107static int ports_active(struct uhci_hcd *uhci)
108{
109 unsigned long io_addr = uhci->io_addr;
110 int connection = 0;
111 int i;
112
113 for (i = 0; i < uhci->rh_numports; i++)
114 connection |= (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_CCS);
115
116 return connection;
117}
118
119static int suspend_allowed(struct uhci_hcd *uhci) 112static int suspend_allowed(struct uhci_hcd *uhci)
120{ 113{
121 unsigned long io_addr = uhci->io_addr; 114 unsigned long io_addr = uhci->io_addr;
@@ -270,14 +263,14 @@ static void hc_state_transitions(struct uhci_hcd *uhci)
270 case UHCI_RUNNING: 263 case UHCI_RUNNING:
271 264
272 /* global suspend if nothing connected for 1 second */ 265 /* global suspend if nothing connected for 1 second */
273 if (!ports_active(uhci) && suspend_allowed(uhci)) { 266 if (!any_ports_active(uhci) && suspend_allowed(uhci)) {
274 uhci->state = UHCI_SUSPENDING_GRACE; 267 uhci->state = UHCI_SUSPENDING_GRACE;
275 uhci->state_end = jiffies + HZ; 268 uhci->state_end = jiffies + HZ;
276 } 269 }
277 break; 270 break;
278 271
279 case UHCI_SUSPENDING_GRACE: 272 case UHCI_SUSPENDING_GRACE:
280 if (ports_active(uhci)) 273 if (any_ports_active(uhci))
281 uhci->state = UHCI_RUNNING; 274 uhci->state = UHCI_RUNNING;
282 else if (time_after_eq(jiffies, uhci->state_end)) 275 else if (time_after_eq(jiffies, uhci->state_end))
283 suspend_hc(uhci); 276 suspend_hc(uhci);
@@ -302,58 +295,24 @@ static void hc_state_transitions(struct uhci_hcd *uhci)
302 } 295 }
303} 296}
304 297
305static int init_stall_timer(struct usb_hcd *hcd); 298static void stall_callback(unsigned long _uhci)
306
307static void stall_callback(unsigned long ptr)
308{ 299{
309 struct usb_hcd *hcd = (struct usb_hcd *)ptr; 300 struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci;
310 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
311 struct urb_priv *up;
312 unsigned long flags; 301 unsigned long flags;
313 302
314 spin_lock_irqsave(&uhci->lock, flags); 303 spin_lock_irqsave(&uhci->lock, flags);
315 uhci_scan_schedule(uhci, NULL); 304 uhci_scan_schedule(uhci, NULL);
316 305 check_fsbr(uhci);
317 list_for_each_entry(up, &uhci->urb_list, urb_list) {
318 struct urb *u = up->urb;
319
320 spin_lock(&u->lock);
321
322 /* Check if the FSBR timed out */
323 if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT))
324 uhci_fsbr_timeout(uhci, u);
325
326 spin_unlock(&u->lock);
327 }
328
329 /* Really disable FSBR */
330 if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
331 uhci->fsbrtimeout = 0;
332 uhci->skel_term_qh->link = UHCI_PTR_TERM;
333 }
334 306
335 /* Poll for and perform state transitions */ 307 /* Poll for and perform state transitions */
336 hc_state_transitions(uhci); 308 hc_state_transitions(uhci);
337 if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED)) 309 if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED))
338 uhci_check_ports(uhci); 310 uhci_check_ports(uhci);
339 311
340 init_stall_timer(hcd); 312 restart_timer(uhci);
341 spin_unlock_irqrestore(&uhci->lock, flags); 313 spin_unlock_irqrestore(&uhci->lock, flags);
342} 314}
343 315
344static int init_stall_timer(struct usb_hcd *hcd)
345{
346 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
347
348 init_timer(&uhci->stall_timer);
349 uhci->stall_timer.function = stall_callback;
350 uhci->stall_timer.data = (unsigned long)hcd;
351 uhci->stall_timer.expires = jiffies + msecs_to_jiffies(100);
352 add_timer(&uhci->stall_timer);
353
354 return 0;
355}
356
357static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) 316static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
358{ 317{
359 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 318 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
@@ -509,6 +468,10 @@ static int uhci_start(struct usb_hcd *hcd)
509 468
510 init_waitqueue_head(&uhci->waitqh); 469 init_waitqueue_head(&uhci->waitqh);
511 470
471 init_timer(&uhci->stall_timer);
472 uhci->stall_timer.function = stall_callback;
473 uhci->stall_timer.data = (unsigned long) uhci;
474
512 uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), 475 uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
513 &dma_handle, 0); 476 &dma_handle, 0);
514 if (!uhci->fl) { 477 if (!uhci->fl) {
@@ -646,7 +609,7 @@ static int uhci_start(struct usb_hcd *hcd)
646 if ((retval = start_hc(uhci)) != 0) 609 if ((retval = start_hc(uhci)) != 0)
647 goto err_alloc_skelqh; 610 goto err_alloc_skelqh;
648 611
649 init_stall_timer(hcd); 612 restart_timer(uhci);
650 613
651 udev->speed = USB_SPEED_FULL; 614 udev->speed = USB_SPEED_FULL;
652 615
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 4c45ba8390f8..ddb19cbf4b75 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -33,6 +33,22 @@ static __u8 root_hub_hub_des[] =
33/* status change bits: nonzero writes will clear */ 33/* status change bits: nonzero writes will clear */
34#define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC) 34#define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC)
35 35
36/* A port that either is connected or has a changed-bit set will prevent
37 * us from AUTO_STOPPING.
38 */
39static int any_ports_active(struct uhci_hcd *uhci)
40{
41 int port;
42
43 for (port = 0; port < uhci->rh_numports; ++port) {
44 if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) &
45 (USBPORTSC_CCS | RWC_BITS)) ||
46 test_bit(port, &uhci->port_c_suspend))
47 return 1;
48 }
49 return 0;
50}
51
36static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) 52static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
37{ 53{
38 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 54 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 2a7c19501f24..f5c75885f7be 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -1537,3 +1537,26 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
1537 /* Wake up anyone waiting for an URB to complete */ 1537 /* Wake up anyone waiting for an URB to complete */
1538 wake_up_all(&uhci->waitqh); 1538 wake_up_all(&uhci->waitqh);
1539} 1539}
1540
1541static void check_fsbr(struct uhci_hcd *uhci)
1542{
1543 struct urb_priv *up;
1544
1545 list_for_each_entry(up, &uhci->urb_list, urb_list) {
1546 struct urb *u = up->urb;
1547
1548 spin_lock(&u->lock);
1549
1550 /* Check if the FSBR timed out */
1551 if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT))
1552 uhci_fsbr_timeout(uhci, u);
1553
1554 spin_unlock(&u->lock);
1555 }
1556
1557 /* Really disable FSBR */
1558 if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
1559 uhci->fsbrtimeout = 0;
1560 uhci->skel_term_qh->link = UHCI_PTR_TERM;
1561 }
1562}