diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/uhci-hcd.c | 62 | ||||
-rw-r--r-- | drivers/usb/host/uhci-hcd.h | 11 | ||||
-rw-r--r-- | drivers/usb/host/uhci-hub.c | 11 | ||||
-rw-r--r-- | drivers/usb/host/uhci-q.c | 2 |
4 files changed, 32 insertions, 54 deletions
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 0d5d2545bf07..0c024898cbea 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -97,14 +97,9 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci); | |||
97 | /* to make sure it doesn't hog all of the bandwidth */ | 97 | /* to make sure it doesn't hog all of the bandwidth */ |
98 | #define DEPTH_INTERVAL 5 | 98 | #define DEPTH_INTERVAL 5 |
99 | 99 | ||
100 | static inline void restart_timer(struct uhci_hcd *uhci) | ||
101 | { | ||
102 | mod_timer(&uhci->stall_timer, jiffies + msecs_to_jiffies(100)); | ||
103 | } | ||
104 | |||
105 | #include "uhci-hub.c" | ||
106 | #include "uhci-debug.c" | 100 | #include "uhci-debug.c" |
107 | #include "uhci-q.c" | 101 | #include "uhci-q.c" |
102 | #include "uhci-hub.c" | ||
108 | 103 | ||
109 | /* | 104 | /* |
110 | * Make sure the controller is completely inactive, unable to | 105 | * Make sure the controller is completely inactive, unable to |
@@ -160,7 +155,6 @@ static void hc_died(struct uhci_hcd *uhci) | |||
160 | { | 155 | { |
161 | reset_hc(uhci); | 156 | reset_hc(uhci); |
162 | uhci->hc_inaccessible = 1; | 157 | uhci->hc_inaccessible = 1; |
163 | del_timer(&uhci->stall_timer); | ||
164 | } | 158 | } |
165 | 159 | ||
166 | /* | 160 | /* |
@@ -287,8 +281,11 @@ __acquires(uhci->lock) | |||
287 | /* Enable resume-detect interrupts if they work. | 281 | /* Enable resume-detect interrupts if they work. |
288 | * Then enter Global Suspend mode, still configured. | 282 | * Then enter Global Suspend mode, still configured. |
289 | */ | 283 | */ |
290 | int_enable = (resume_detect_interrupts_are_broken(uhci) ? | 284 | uhci->working_RD = 1; |
291 | 0 : USBINTR_RESUME); | 285 | int_enable = USBINTR_RESUME; |
286 | if (resume_detect_interrupts_are_broken(uhci)) { | ||
287 | uhci->working_RD = int_enable = 0; | ||
288 | } | ||
292 | outw(int_enable, uhci->io_addr + USBINTR); | 289 | outw(int_enable, uhci->io_addr + USBINTR); |
293 | outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD); | 290 | outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD); |
294 | mb(); | 291 | mb(); |
@@ -315,7 +312,6 @@ __acquires(uhci->lock) | |||
315 | 312 | ||
316 | uhci->rh_state = new_state; | 313 | uhci->rh_state = new_state; |
317 | uhci->is_stopped = UHCI_IS_STOPPED; | 314 | uhci->is_stopped = UHCI_IS_STOPPED; |
318 | del_timer(&uhci->stall_timer); | ||
319 | uhci_to_hcd(uhci)->poll_rh = !int_enable; | 315 | uhci_to_hcd(uhci)->poll_rh = !int_enable; |
320 | 316 | ||
321 | uhci_scan_schedule(uhci, NULL); | 317 | uhci_scan_schedule(uhci, NULL); |
@@ -335,7 +331,6 @@ static void start_rh(struct uhci_hcd *uhci) | |||
335 | mb(); | 331 | mb(); |
336 | uhci->rh_state = UHCI_RH_RUNNING; | 332 | uhci->rh_state = UHCI_RH_RUNNING; |
337 | uhci_to_hcd(uhci)->poll_rh = 1; | 333 | uhci_to_hcd(uhci)->poll_rh = 1; |
338 | restart_timer(uhci); | ||
339 | } | 334 | } |
340 | 335 | ||
341 | static void wakeup_rh(struct uhci_hcd *uhci) | 336 | static void wakeup_rh(struct uhci_hcd *uhci) |
@@ -374,20 +369,6 @@ __acquires(uhci->lock) | |||
374 | mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); | 369 | mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); |
375 | } | 370 | } |
376 | 371 | ||
377 | static void stall_callback(unsigned long _uhci) | ||
378 | { | ||
379 | struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci; | ||
380 | unsigned long flags; | ||
381 | |||
382 | spin_lock_irqsave(&uhci->lock, flags); | ||
383 | uhci_scan_schedule(uhci, NULL); | ||
384 | check_fsbr(uhci); | ||
385 | |||
386 | if (!uhci->is_stopped) | ||
387 | restart_timer(uhci); | ||
388 | spin_unlock_irqrestore(&uhci->lock, flags); | ||
389 | } | ||
390 | |||
391 | static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | 372 | static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) |
392 | { | 373 | { |
393 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 374 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
@@ -418,8 +399,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | |||
418 | "host controller halted, " | 399 | "host controller halted, " |
419 | "very bad!\n"); | 400 | "very bad!\n"); |
420 | hc_died(uhci); | 401 | hc_died(uhci); |
421 | spin_unlock_irqrestore(&uhci->lock, flags); | 402 | |
422 | return IRQ_HANDLED; | 403 | /* Force a callback in case there are |
404 | * pending unlinks */ | ||
405 | mod_timer(&hcd->rh_timer, jiffies); | ||
423 | } | 406 | } |
424 | spin_unlock_irqrestore(&uhci->lock, flags); | 407 | spin_unlock_irqrestore(&uhci->lock, flags); |
425 | } | 408 | } |
@@ -427,10 +410,11 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | |||
427 | 410 | ||
428 | if (status & USBSTS_RD) | 411 | if (status & USBSTS_RD) |
429 | usb_hcd_poll_rh_status(hcd); | 412 | usb_hcd_poll_rh_status(hcd); |
430 | 413 | else { | |
431 | spin_lock_irqsave(&uhci->lock, flags); | 414 | spin_lock_irqsave(&uhci->lock, flags); |
432 | uhci_scan_schedule(uhci, regs); | 415 | uhci_scan_schedule(uhci, regs); |
433 | spin_unlock_irqrestore(&uhci->lock, flags); | 416 | spin_unlock_irqrestore(&uhci->lock, flags); |
417 | } | ||
434 | 418 | ||
435 | return IRQ_HANDLED; | 419 | return IRQ_HANDLED; |
436 | } | 420 | } |
@@ -595,10 +579,6 @@ static int uhci_start(struct usb_hcd *hcd) | |||
595 | 579 | ||
596 | init_waitqueue_head(&uhci->waitqh); | 580 | init_waitqueue_head(&uhci->waitqh); |
597 | 581 | ||
598 | init_timer(&uhci->stall_timer); | ||
599 | uhci->stall_timer.function = stall_callback; | ||
600 | uhci->stall_timer.data = (unsigned long) uhci; | ||
601 | |||
602 | uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), | 582 | uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), |
603 | &dma_handle, 0); | 583 | &dma_handle, 0); |
604 | if (!uhci->fl) { | 584 | if (!uhci->fl) { |
@@ -745,11 +725,11 @@ static void uhci_stop(struct usb_hcd *hcd) | |||
745 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 725 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
746 | 726 | ||
747 | spin_lock_irq(&uhci->lock); | 727 | spin_lock_irq(&uhci->lock); |
748 | reset_hc(uhci); | 728 | if (!uhci->hc_inaccessible) |
729 | reset_hc(uhci); | ||
749 | uhci_scan_schedule(uhci, NULL); | 730 | uhci_scan_schedule(uhci, NULL); |
750 | spin_unlock_irq(&uhci->lock); | 731 | spin_unlock_irq(&uhci->lock); |
751 | 732 | ||
752 | del_timer_sync(&uhci->stall_timer); | ||
753 | release_uhci(uhci); | 733 | release_uhci(uhci); |
754 | } | 734 | } |
755 | 735 | ||
@@ -811,13 +791,12 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) | |||
811 | */ | 791 | */ |
812 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); | 792 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); |
813 | uhci->hc_inaccessible = 1; | 793 | uhci->hc_inaccessible = 1; |
794 | hcd->poll_rh = 0; | ||
814 | 795 | ||
815 | /* FIXME: Enable non-PME# remote wakeup? */ | 796 | /* FIXME: Enable non-PME# remote wakeup? */ |
816 | 797 | ||
817 | done: | 798 | done: |
818 | spin_unlock_irq(&uhci->lock); | 799 | spin_unlock_irq(&uhci->lock); |
819 | if (rc == 0) | ||
820 | del_timer_sync(&hcd->rh_timer); | ||
821 | return rc; | 800 | return rc; |
822 | } | 801 | } |
823 | 802 | ||
@@ -850,8 +829,11 @@ static int uhci_resume(struct usb_hcd *hcd) | |||
850 | 829 | ||
851 | spin_unlock_irq(&uhci->lock); | 830 | spin_unlock_irq(&uhci->lock); |
852 | 831 | ||
853 | if (hcd->poll_rh) | 832 | if (!uhci->working_RD) { |
833 | /* Suspended root hub needs to be polled */ | ||
834 | hcd->poll_rh = 1; | ||
854 | usb_hcd_poll_rh_status(hcd); | 835 | usb_hcd_poll_rh_status(hcd); |
836 | } | ||
855 | return 0; | 837 | return 0; |
856 | } | 838 | } |
857 | #endif | 839 | #endif |
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index bf9c5f9b508b..282f40b75881 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h | |||
@@ -345,9 +345,6 @@ enum uhci_rh_state { | |||
345 | 345 | ||
346 | /* | 346 | /* |
347 | * This describes the full uhci information. | 347 | * This describes the full uhci information. |
348 | * | ||
349 | * Note how the "proper" USB information is just | ||
350 | * a subset of what the full implementation needs. | ||
351 | */ | 348 | */ |
352 | struct uhci_hcd { | 349 | struct uhci_hcd { |
353 | 350 | ||
@@ -360,8 +357,6 @@ struct uhci_hcd { | |||
360 | struct dma_pool *qh_pool; | 357 | struct dma_pool *qh_pool; |
361 | struct dma_pool *td_pool; | 358 | struct dma_pool *td_pool; |
362 | 359 | ||
363 | struct usb_bus *bus; | ||
364 | |||
365 | struct uhci_td *term_td; /* Terminating TD, see UHCI bug */ | 360 | struct uhci_td *term_td; /* Terminating TD, see UHCI bug */ |
366 | struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ | 361 | struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ |
367 | 362 | ||
@@ -380,6 +375,8 @@ struct uhci_hcd { | |||
380 | unsigned int scan_in_progress:1; /* Schedule scan is running */ | 375 | unsigned int scan_in_progress:1; /* Schedule scan is running */ |
381 | unsigned int need_rescan:1; /* Redo the schedule scan */ | 376 | unsigned int need_rescan:1; /* Redo the schedule scan */ |
382 | unsigned int hc_inaccessible:1; /* HC is suspended or dead */ | 377 | unsigned int hc_inaccessible:1; /* HC is suspended or dead */ |
378 | unsigned int working_RD:1; /* Suspended root hub doesn't | ||
379 | need to be polled */ | ||
383 | 380 | ||
384 | /* Support for port suspend/resume/reset */ | 381 | /* Support for port suspend/resume/reset */ |
385 | unsigned long port_c_suspend; /* Bit-arrays of ports */ | 382 | unsigned long port_c_suspend; /* Bit-arrays of ports */ |
@@ -405,9 +402,7 @@ struct uhci_hcd { | |||
405 | /* List of URB's awaiting completion callback */ | 402 | /* List of URB's awaiting completion callback */ |
406 | struct list_head complete_list; /* P: uhci->lock */ | 403 | struct list_head complete_list; /* P: uhci->lock */ |
407 | 404 | ||
408 | int rh_numports; | 405 | int rh_numports; /* Number of root-hub ports */ |
409 | |||
410 | struct timer_list stall_timer; | ||
411 | 406 | ||
412 | wait_queue_head_t waitqh; /* endpoint_disable waiters */ | 407 | wait_queue_head_t waitqh; /* endpoint_disable waiters */ |
413 | }; | 408 | }; |
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 4eace2b19ddb..a71e48a66805 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c | |||
@@ -145,15 +145,16 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
145 | { | 145 | { |
146 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 146 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
147 | unsigned long flags; | 147 | unsigned long flags; |
148 | int status; | 148 | int status = 0; |
149 | 149 | ||
150 | spin_lock_irqsave(&uhci->lock, flags); | 150 | spin_lock_irqsave(&uhci->lock, flags); |
151 | if (uhci->hc_inaccessible) { | ||
152 | status = 0; | ||
153 | goto done; | ||
154 | } | ||
155 | 151 | ||
152 | uhci_scan_schedule(uhci, NULL); | ||
153 | if (uhci->hc_inaccessible) | ||
154 | goto done; | ||
155 | check_fsbr(uhci); | ||
156 | uhci_check_ports(uhci); | 156 | uhci_check_ports(uhci); |
157 | |||
157 | status = get_hub_status_data(uhci, buf); | 158 | status = get_hub_status_data(uhci, buf); |
158 | 159 | ||
159 | switch (uhci->rh_state) { | 160 | switch (uhci->rh_state) { |
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index bbb36cd6ed61..ea0d168a8c67 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
@@ -33,7 +33,7 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci); | |||
33 | static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci) | 33 | static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci) |
34 | { | 34 | { |
35 | if (uhci->is_stopped) | 35 | if (uhci->is_stopped) |
36 | mod_timer(&uhci->stall_timer, jiffies); | 36 | mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); |
37 | uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); | 37 | uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); |
38 | } | 38 | } |
39 | 39 | ||