Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] USB UHCI: remove the FSBR kernel timer

This patch (as558) removes from the UHCI driver a kernel timer used for
checking Full Speed Bandwidth Reclamation (FSBR). The checking can be
done during normal root-hub polling; it doesn't need a separate timer.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Alan Stern and committed by
Greg Kroah-Hartman
1f09df8b f1a15606

+32 -54
+22 -40
drivers/usb/host/uhci-hcd.c
··· 97 97 /* to make sure it doesn't hog all of the bandwidth */ 98 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 100 #include "uhci-debug.c" 107 101 #include "uhci-q.c" 102 + #include "uhci-hub.c" 108 103 109 104 /* 110 105 * Make sure the controller is completely inactive, unable to ··· 155 160 { 156 161 reset_hc(uhci); 157 162 uhci->hc_inaccessible = 1; 158 - del_timer(&uhci->stall_timer); 159 163 } 160 164 161 165 /* ··· 281 287 /* Enable resume-detect interrupts if they work. 282 288 * Then enter Global Suspend mode, still configured. 283 289 */ 284 - int_enable = (resume_detect_interrupts_are_broken(uhci) ? 285 - 0 : USBINTR_RESUME); 290 + uhci->working_RD = 1; 291 + int_enable = USBINTR_RESUME; 292 + if (resume_detect_interrupts_are_broken(uhci)) { 293 + uhci->working_RD = int_enable = 0; 294 + } 286 295 outw(int_enable, uhci->io_addr + USBINTR); 287 296 outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD); 288 297 mb(); ··· 312 315 313 316 uhci->rh_state = new_state; 314 317 uhci->is_stopped = UHCI_IS_STOPPED; 315 - del_timer(&uhci->stall_timer); 316 318 uhci_to_hcd(uhci)->poll_rh = !int_enable; 317 319 318 320 uhci_scan_schedule(uhci, NULL); ··· 331 335 mb(); 332 336 uhci->rh_state = UHCI_RH_RUNNING; 333 337 uhci_to_hcd(uhci)->poll_rh = 1; 334 - restart_timer(uhci); 335 338 } 336 339 337 340 static void wakeup_rh(struct uhci_hcd *uhci) ··· 369 374 mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); 370 375 } 371 376 372 - static void stall_callback(unsigned long _uhci) 373 - { 374 - struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci; 375 - unsigned long flags; 376 - 377 - spin_lock_irqsave(&uhci->lock, flags); 378 - uhci_scan_schedule(uhci, NULL); 379 - check_fsbr(uhci); 380 - 381 - if (!uhci->is_stopped) 382 - restart_timer(uhci); 383 - spin_unlock_irqrestore(&uhci->lock, flags); 384 - } 385 - 386 377 static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) 387 378 { 388 379 struct uhci_hcd *uhci = hcd_to_uhci(hcd); ··· 399 418 "host controller halted, " 400 419 "very bad!\n"); 401 420 hc_died(uhci); 402 - spin_unlock_irqrestore(&uhci->lock, flags); 403 - return IRQ_HANDLED; 421 + 422 + /* Force a callback in case there are 423 + * pending unlinks */ 424 + mod_timer(&hcd->rh_timer, jiffies); 404 425 } 405 426 spin_unlock_irqrestore(&uhci->lock, flags); 406 427 } ··· 410 427 411 428 if (status & USBSTS_RD) 412 429 usb_hcd_poll_rh_status(hcd); 413 - 414 - spin_lock_irqsave(&uhci->lock, flags); 415 - uhci_scan_schedule(uhci, regs); 416 - spin_unlock_irqrestore(&uhci->lock, flags); 430 + else { 431 + spin_lock_irqsave(&uhci->lock, flags); 432 + uhci_scan_schedule(uhci, regs); 433 + spin_unlock_irqrestore(&uhci->lock, flags); 434 + } 417 435 418 436 return IRQ_HANDLED; 419 437 } ··· 579 595 580 596 init_waitqueue_head(&uhci->waitqh); 581 597 582 - init_timer(&uhci->stall_timer); 583 - uhci->stall_timer.function = stall_callback; 584 - uhci->stall_timer.data = (unsigned long) uhci; 585 - 586 598 uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), 587 599 &dma_handle, 0); 588 600 if (!uhci->fl) { ··· 725 745 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 726 746 727 747 spin_lock_irq(&uhci->lock); 728 - reset_hc(uhci); 748 + if (!uhci->hc_inaccessible) 749 + reset_hc(uhci); 729 750 uhci_scan_schedule(uhci, NULL); 730 751 spin_unlock_irq(&uhci->lock); 731 752 732 - del_timer_sync(&uhci->stall_timer); 733 753 release_uhci(uhci); 734 754 } 735 755 ··· 791 811 */ 792 812 pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); 793 813 uhci->hc_inaccessible = 1; 814 + hcd->poll_rh = 0; 794 815 795 816 /* FIXME: Enable non-PME# remote wakeup? */ 796 817 797 818 done: 798 819 spin_unlock_irq(&uhci->lock); 799 - if (rc == 0) 800 - del_timer_sync(&hcd->rh_timer); 801 820 return rc; 802 821 } 803 822 ··· 829 850 830 851 spin_unlock_irq(&uhci->lock); 831 852 832 - if (hcd->poll_rh) 853 + if (!uhci->working_RD) { 854 + /* Suspended root hub needs to be polled */ 855 + hcd->poll_rh = 1; 833 856 usb_hcd_poll_rh_status(hcd); 857 + } 834 858 return 0; 835 859 } 836 860 #endif
+3 -8
drivers/usb/host/uhci-hcd.h
··· 345 345 346 346 /* 347 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 349 struct uhci_hcd { 353 350 ··· 356 359 357 360 struct dma_pool *qh_pool; 358 361 struct dma_pool *td_pool; 359 - 360 - struct usb_bus *bus; 361 362 362 363 struct uhci_td *term_td; /* Terminating TD, see UHCI bug */ 363 364 struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ ··· 375 380 unsigned int scan_in_progress:1; /* Schedule scan is running */ 376 381 unsigned int need_rescan:1; /* Redo the schedule scan */ 377 382 unsigned int hc_inaccessible:1; /* HC is suspended or dead */ 383 + unsigned int working_RD:1; /* Suspended root hub doesn't 384 + need to be polled */ 378 385 379 386 /* Support for port suspend/resume/reset */ 380 387 unsigned long port_c_suspend; /* Bit-arrays of ports */ ··· 402 405 /* List of URB's awaiting completion callback */ 403 406 struct list_head complete_list; /* P: uhci->lock */ 404 407 405 - int rh_numports; 406 - 407 - struct timer_list stall_timer; 408 + int rh_numports; /* Number of root-hub ports */ 408 409 409 410 wait_queue_head_t waitqh; /* endpoint_disable waiters */ 410 411 };
+6 -5
drivers/usb/host/uhci-hub.c
··· 145 145 { 146 146 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 147 147 unsigned long flags; 148 - int status; 148 + int status = 0; 149 149 150 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 156 uhci_check_ports(uhci); 157 + 157 158 status = get_hub_status_data(uhci, buf); 158 159 159 160 switch (uhci->rh_state) {
+1 -1
drivers/usb/host/uhci-q.c
··· 33 33 static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci) 34 34 { 35 35 if (uhci->is_stopped) 36 - mod_timer(&uhci->stall_timer, jiffies); 36 + mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); 37 37 uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); 38 38 } 39 39