diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2005-12-17 17:58:46 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-03-20 17:49:57 -0500 |
commit | dccf4a48d47120a42382ba526f1a0848c13ba2a4 (patch) | |
tree | 788a0a9f491d1a42df1dee1781156ccfc363b6ef /drivers/usb/host/uhci-hcd.c | |
parent | 499003e815344304c7b0c93aad923ddf644d24e0 (diff) |
[PATCH] UHCI: use one QH per endpoint, not per URB
This patch (as623) changes the uhci-hcd driver to make it use one QH per
device endpoint, instead of a QH per URB as it does now. Numerous areas
of the code are affected by this. For example, the distinction between
"queued" URBs and non-"queued" URBs no longer exists; all URBs belong to
a queue and some just happen to be at the queue's head.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/uhci-hcd.c')
-rw-r--r-- | drivers/usb/host/uhci-hcd.c | 65 |
1 files changed, 41 insertions, 24 deletions
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index dfe121d35887..1ff4b8806372 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -54,7 +54,7 @@ | |||
54 | /* | 54 | /* |
55 | * Version Information | 55 | * Version Information |
56 | */ | 56 | */ |
57 | #define DRIVER_VERSION "v2.3" | 57 | #define DRIVER_VERSION "v3.0" |
58 | #define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \ | 58 | #define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \ |
59 | Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \ | 59 | Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \ |
60 | Alan Stern" | 60 | Alan Stern" |
@@ -489,15 +489,11 @@ static int uhci_start(struct usb_hcd *hcd) | |||
489 | uhci->fsbrtimeout = 0; | 489 | uhci->fsbrtimeout = 0; |
490 | 490 | ||
491 | spin_lock_init(&uhci->lock); | 491 | spin_lock_init(&uhci->lock); |
492 | INIT_LIST_HEAD(&uhci->qh_remove_list); | ||
493 | 492 | ||
494 | INIT_LIST_HEAD(&uhci->td_remove_list); | 493 | INIT_LIST_HEAD(&uhci->td_remove_list); |
495 | |||
496 | INIT_LIST_HEAD(&uhci->urb_remove_list); | ||
497 | |||
498 | INIT_LIST_HEAD(&uhci->urb_list); | 494 | INIT_LIST_HEAD(&uhci->urb_list); |
499 | |||
500 | INIT_LIST_HEAD(&uhci->complete_list); | 495 | INIT_LIST_HEAD(&uhci->complete_list); |
496 | INIT_LIST_HEAD(&uhci->idle_qh_list); | ||
501 | 497 | ||
502 | init_waitqueue_head(&uhci->waitqh); | 498 | init_waitqueue_head(&uhci->waitqh); |
503 | 499 | ||
@@ -540,7 +536,7 @@ static int uhci_start(struct usb_hcd *hcd) | |||
540 | } | 536 | } |
541 | 537 | ||
542 | for (i = 0; i < UHCI_NUM_SKELQH; i++) { | 538 | for (i = 0; i < UHCI_NUM_SKELQH; i++) { |
543 | uhci->skelqh[i] = uhci_alloc_qh(uhci); | 539 | uhci->skelqh[i] = uhci_alloc_qh(uhci, NULL, NULL); |
544 | if (!uhci->skelqh[i]) { | 540 | if (!uhci->skelqh[i]) { |
545 | dev_err(uhci_dev(uhci), "unable to allocate QH\n"); | 541 | dev_err(uhci_dev(uhci), "unable to allocate QH\n"); |
546 | goto err_alloc_skelqh; | 542 | goto err_alloc_skelqh; |
@@ -557,13 +553,17 @@ static int uhci_start(struct usb_hcd *hcd) | |||
557 | uhci->skel_int16_qh->link = | 553 | uhci->skel_int16_qh->link = |
558 | uhci->skel_int8_qh->link = | 554 | uhci->skel_int8_qh->link = |
559 | uhci->skel_int4_qh->link = | 555 | uhci->skel_int4_qh->link = |
560 | uhci->skel_int2_qh->link = | 556 | uhci->skel_int2_qh->link = UHCI_PTR_QH | |
561 | cpu_to_le32(uhci->skel_int1_qh->dma_handle) | UHCI_PTR_QH; | 557 | cpu_to_le32(uhci->skel_int1_qh->dma_handle); |
562 | uhci->skel_int1_qh->link = cpu_to_le32(uhci->skel_ls_control_qh->dma_handle) | UHCI_PTR_QH; | 558 | |
563 | 559 | uhci->skel_int1_qh->link = UHCI_PTR_QH | | |
564 | uhci->skel_ls_control_qh->link = cpu_to_le32(uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH; | 560 | cpu_to_le32(uhci->skel_ls_control_qh->dma_handle); |
565 | uhci->skel_fs_control_qh->link = cpu_to_le32(uhci->skel_bulk_qh->dma_handle) | UHCI_PTR_QH; | 561 | uhci->skel_ls_control_qh->link = UHCI_PTR_QH | |
566 | uhci->skel_bulk_qh->link = cpu_to_le32(uhci->skel_term_qh->dma_handle) | UHCI_PTR_QH; | 562 | cpu_to_le32(uhci->skel_fs_control_qh->dma_handle); |
563 | uhci->skel_fs_control_qh->link = UHCI_PTR_QH | | ||
564 | cpu_to_le32(uhci->skel_bulk_qh->dma_handle); | ||
565 | uhci->skel_bulk_qh->link = UHCI_PTR_QH | | ||
566 | cpu_to_le32(uhci->skel_term_qh->dma_handle); | ||
567 | 567 | ||
568 | /* This dummy TD is to work around a bug in Intel PIIX controllers */ | 568 | /* This dummy TD is to work around a bug in Intel PIIX controllers */ |
569 | uhci_fill_td(uhci->term_td, 0, uhci_explen(0) | | 569 | uhci_fill_td(uhci->term_td, 0, uhci_explen(0) | |
@@ -589,15 +589,15 @@ static int uhci_start(struct usb_hcd *hcd) | |||
589 | 589 | ||
590 | /* | 590 | /* |
591 | * ffs (Find First bit Set) does exactly what we need: | 591 | * ffs (Find First bit Set) does exactly what we need: |
592 | * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[6], | 592 | * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[8], |
593 | * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[5], etc. | 593 | * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc. |
594 | * ffs > 6 => not on any high-period queue, so use | 594 | * ffs >= 7 => not on any high-period queue, so use |
595 | * skel_int1_qh = skelqh[7]. | 595 | * skel_int1_qh = skelqh[9]. |
596 | * Add UHCI_NUMFRAMES to insure at least one bit is set. | 596 | * Add UHCI_NUMFRAMES to insure at least one bit is set. |
597 | */ | 597 | */ |
598 | irq = 6 - (int) __ffs(i + UHCI_NUMFRAMES); | 598 | irq = 8 - (int) __ffs(i + UHCI_NUMFRAMES); |
599 | if (irq < 0) | 599 | if (irq <= 1) |
600 | irq = 7; | 600 | irq = 9; |
601 | 601 | ||
602 | /* Only place we don't use the frame list routines */ | 602 | /* Only place we don't use the frame list routines */ |
603 | uhci->frame[i] = UHCI_PTR_QH | | 603 | uhci->frame[i] = UHCI_PTR_QH | |
@@ -767,13 +767,30 @@ static int uhci_resume(struct usb_hcd *hcd) | |||
767 | } | 767 | } |
768 | #endif | 768 | #endif |
769 | 769 | ||
770 | /* Wait until all the URBs for a particular device/endpoint are gone */ | 770 | /* Wait until a particular device/endpoint's QH is idle, and free it */ |
771 | static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd, | 771 | static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd, |
772 | struct usb_host_endpoint *ep) | 772 | struct usb_host_endpoint *hep) |
773 | { | 773 | { |
774 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 774 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
775 | struct uhci_qh *qh; | ||
776 | |||
777 | spin_lock_irq(&uhci->lock); | ||
778 | qh = (struct uhci_qh *) hep->hcpriv; | ||
779 | if (qh == NULL) | ||
780 | goto done; | ||
775 | 781 | ||
776 | wait_event_interruptible(uhci->waitqh, list_empty(&ep->urb_list)); | 782 | while (qh->state != QH_STATE_IDLE) { |
783 | ++uhci->num_waiting; | ||
784 | spin_unlock_irq(&uhci->lock); | ||
785 | wait_event_interruptible(uhci->waitqh, | ||
786 | qh->state == QH_STATE_IDLE); | ||
787 | spin_lock_irq(&uhci->lock); | ||
788 | --uhci->num_waiting; | ||
789 | } | ||
790 | |||
791 | uhci_free_qh(uhci, qh); | ||
792 | done: | ||
793 | spin_unlock_irq(&uhci->lock); | ||
777 | } | 794 | } |
778 | 795 | ||
779 | static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) | 796 | static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) |