diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2005-04-09 17:26:00 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-06-27 17:43:43 -0400 |
commit | f5946f8220a866dcdb8edc6abe23c1443e252425 (patch) | |
tree | 3984d5eb8382d3bc694168e90957206d97fd7d1c /drivers | |
parent | 014e73c99aa408f3766afe8d11a1caa3a708b736 (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')
-rw-r--r-- | drivers/usb/host/uhci-hcd.c | 69 | ||||
-rw-r--r-- | drivers/usb/host/uhci-hub.c | 16 | ||||
-rw-r--r-- | drivers/usb/host/uhci-q.c | 23 |
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 | ||
103 | static 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 | ||
107 | static 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 | |||
119 | static int suspend_allowed(struct uhci_hcd *uhci) | 112 | static 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 | ||
305 | static int init_stall_timer(struct usb_hcd *hcd); | 298 | static void stall_callback(unsigned long _uhci) |
306 | |||
307 | static 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 | ||
344 | static 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 | |||
357 | static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | 316 | static 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 | */ | ||
39 | static 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 | |||
36 | static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) | 52 | static 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 | |||
1541 | static 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 | } | ||