diff options
Diffstat (limited to 'drivers/usb/host/uhci-q.c')
-rw-r--r-- | drivers/usb/host/uhci-q.c | 58 |
1 files changed, 36 insertions, 22 deletions
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 2a7c19501f24..5f18084a116d 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
@@ -32,6 +32,8 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci); | |||
32 | */ | 32 | */ |
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) | ||
36 | mod_timer(&uhci->stall_timer, jiffies); | ||
35 | uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); | 37 | uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); |
36 | } | 38 | } |
37 | 39 | ||
@@ -46,7 +48,7 @@ static inline void uhci_moveto_complete(struct uhci_hcd *uhci, | |||
46 | list_move_tail(&urbp->urb_list, &uhci->complete_list); | 48 | list_move_tail(&urbp->urb_list, &uhci->complete_list); |
47 | } | 49 | } |
48 | 50 | ||
49 | static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *dev) | 51 | static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci) |
50 | { | 52 | { |
51 | dma_addr_t dma_handle; | 53 | dma_addr_t dma_handle; |
52 | struct uhci_td *td; | 54 | struct uhci_td *td; |
@@ -61,14 +63,11 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *d | |||
61 | td->buffer = 0; | 63 | td->buffer = 0; |
62 | 64 | ||
63 | td->frame = -1; | 65 | td->frame = -1; |
64 | td->dev = dev; | ||
65 | 66 | ||
66 | INIT_LIST_HEAD(&td->list); | 67 | INIT_LIST_HEAD(&td->list); |
67 | INIT_LIST_HEAD(&td->remove_list); | 68 | INIT_LIST_HEAD(&td->remove_list); |
68 | INIT_LIST_HEAD(&td->fl_list); | 69 | INIT_LIST_HEAD(&td->fl_list); |
69 | 70 | ||
70 | usb_get_dev(dev); | ||
71 | |||
72 | return td; | 71 | return td; |
73 | } | 72 | } |
74 | 73 | ||
@@ -168,13 +167,10 @@ static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td) | |||
168 | if (!list_empty(&td->fl_list)) | 167 | if (!list_empty(&td->fl_list)) |
169 | dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td); | 168 | dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td); |
170 | 169 | ||
171 | if (td->dev) | ||
172 | usb_put_dev(td->dev); | ||
173 | |||
174 | dma_pool_free(uhci->td_pool, td, td->dma_handle); | 170 | dma_pool_free(uhci->td_pool, td, td->dma_handle); |
175 | } | 171 | } |
176 | 172 | ||
177 | static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *dev) | 173 | static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci) |
178 | { | 174 | { |
179 | dma_addr_t dma_handle; | 175 | dma_addr_t dma_handle; |
180 | struct uhci_qh *qh; | 176 | struct uhci_qh *qh; |
@@ -188,14 +184,11 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *d | |||
188 | qh->element = UHCI_PTR_TERM; | 184 | qh->element = UHCI_PTR_TERM; |
189 | qh->link = UHCI_PTR_TERM; | 185 | qh->link = UHCI_PTR_TERM; |
190 | 186 | ||
191 | qh->dev = dev; | ||
192 | qh->urbp = NULL; | 187 | qh->urbp = NULL; |
193 | 188 | ||
194 | INIT_LIST_HEAD(&qh->list); | 189 | INIT_LIST_HEAD(&qh->list); |
195 | INIT_LIST_HEAD(&qh->remove_list); | 190 | INIT_LIST_HEAD(&qh->remove_list); |
196 | 191 | ||
197 | usb_get_dev(dev); | ||
198 | |||
199 | return qh; | 192 | return qh; |
200 | } | 193 | } |
201 | 194 | ||
@@ -206,9 +199,6 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
206 | if (!list_empty(&qh->remove_list)) | 199 | if (!list_empty(&qh->remove_list)) |
207 | dev_warn(uhci_dev(uhci), "qh %p still in remove_list!\n", qh); | 200 | dev_warn(uhci_dev(uhci), "qh %p still in remove_list!\n", qh); |
208 | 201 | ||
209 | if (qh->dev) | ||
210 | usb_put_dev(qh->dev); | ||
211 | |||
212 | dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); | 202 | dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); |
213 | } | 203 | } |
214 | 204 | ||
@@ -597,7 +587,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur | |||
597 | /* | 587 | /* |
598 | * Build the TD for the control request setup packet | 588 | * Build the TD for the control request setup packet |
599 | */ | 589 | */ |
600 | td = uhci_alloc_td(uhci, urb->dev); | 590 | td = uhci_alloc_td(uhci); |
601 | if (!td) | 591 | if (!td) |
602 | return -ENOMEM; | 592 | return -ENOMEM; |
603 | 593 | ||
@@ -626,7 +616,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur | |||
626 | if (pktsze > maxsze) | 616 | if (pktsze > maxsze) |
627 | pktsze = maxsze; | 617 | pktsze = maxsze; |
628 | 618 | ||
629 | td = uhci_alloc_td(uhci, urb->dev); | 619 | td = uhci_alloc_td(uhci); |
630 | if (!td) | 620 | if (!td) |
631 | return -ENOMEM; | 621 | return -ENOMEM; |
632 | 622 | ||
@@ -644,7 +634,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur | |||
644 | /* | 634 | /* |
645 | * Build the final TD for control status | 635 | * Build the final TD for control status |
646 | */ | 636 | */ |
647 | td = uhci_alloc_td(uhci, urb->dev); | 637 | td = uhci_alloc_td(uhci); |
648 | if (!td) | 638 | if (!td) |
649 | return -ENOMEM; | 639 | return -ENOMEM; |
650 | 640 | ||
@@ -666,7 +656,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur | |||
666 | uhci_fill_td(td, status | TD_CTRL_IOC, | 656 | uhci_fill_td(td, status | TD_CTRL_IOC, |
667 | destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0); | 657 | destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0); |
668 | 658 | ||
669 | qh = uhci_alloc_qh(uhci, urb->dev); | 659 | qh = uhci_alloc_qh(uhci); |
670 | if (!qh) | 660 | if (!qh) |
671 | return -ENOMEM; | 661 | return -ENOMEM; |
672 | 662 | ||
@@ -865,7 +855,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb | |||
865 | status &= ~TD_CTRL_SPD; | 855 | status &= ~TD_CTRL_SPD; |
866 | } | 856 | } |
867 | 857 | ||
868 | td = uhci_alloc_td(uhci, urb->dev); | 858 | td = uhci_alloc_td(uhci); |
869 | if (!td) | 859 | if (!td) |
870 | return -ENOMEM; | 860 | return -ENOMEM; |
871 | 861 | ||
@@ -891,7 +881,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb | |||
891 | */ | 881 | */ |
892 | if (usb_pipeout(urb->pipe) && (urb->transfer_flags & URB_ZERO_PACKET) && | 882 | if (usb_pipeout(urb->pipe) && (urb->transfer_flags & URB_ZERO_PACKET) && |
893 | !len && urb->transfer_buffer_length) { | 883 | !len && urb->transfer_buffer_length) { |
894 | td = uhci_alloc_td(uhci, urb->dev); | 884 | td = uhci_alloc_td(uhci); |
895 | if (!td) | 885 | if (!td) |
896 | return -ENOMEM; | 886 | return -ENOMEM; |
897 | 887 | ||
@@ -913,7 +903,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb | |||
913 | * flag setting. */ | 903 | * flag setting. */ |
914 | td->status |= cpu_to_le32(TD_CTRL_IOC); | 904 | td->status |= cpu_to_le32(TD_CTRL_IOC); |
915 | 905 | ||
916 | qh = uhci_alloc_qh(uhci, urb->dev); | 906 | qh = uhci_alloc_qh(uhci); |
917 | if (!qh) | 907 | if (!qh) |
918 | return -ENOMEM; | 908 | return -ENOMEM; |
919 | 909 | ||
@@ -1096,7 +1086,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb) | |||
1096 | if (!urb->iso_frame_desc[i].length) | 1086 | if (!urb->iso_frame_desc[i].length) |
1097 | continue; | 1087 | continue; |
1098 | 1088 | ||
1099 | td = uhci_alloc_td(uhci, urb->dev); | 1089 | td = uhci_alloc_td(uhci); |
1100 | if (!td) | 1090 | if (!td) |
1101 | return -ENOMEM; | 1091 | return -ENOMEM; |
1102 | 1092 | ||
@@ -1497,6 +1487,7 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) | |||
1497 | rescan: | 1487 | rescan: |
1498 | uhci->need_rescan = 0; | 1488 | uhci->need_rescan = 0; |
1499 | 1489 | ||
1490 | uhci_clear_next_interrupt(uhci); | ||
1500 | uhci_get_current_frame_number(uhci); | 1491 | uhci_get_current_frame_number(uhci); |
1501 | 1492 | ||
1502 | if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age) | 1493 | if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age) |
@@ -1537,3 +1528,26 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) | |||
1537 | /* Wake up anyone waiting for an URB to complete */ | 1528 | /* Wake up anyone waiting for an URB to complete */ |
1538 | wake_up_all(&uhci->waitqh); | 1529 | wake_up_all(&uhci->waitqh); |
1539 | } | 1530 | } |
1531 | |||
1532 | static void check_fsbr(struct uhci_hcd *uhci) | ||
1533 | { | ||
1534 | struct urb_priv *up; | ||
1535 | |||
1536 | list_for_each_entry(up, &uhci->urb_list, urb_list) { | ||
1537 | struct urb *u = up->urb; | ||
1538 | |||
1539 | spin_lock(&u->lock); | ||
1540 | |||
1541 | /* Check if the FSBR timed out */ | ||
1542 | if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT)) | ||
1543 | uhci_fsbr_timeout(uhci, u); | ||
1544 | |||
1545 | spin_unlock(&u->lock); | ||
1546 | } | ||
1547 | |||
1548 | /* Really disable FSBR */ | ||
1549 | if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) { | ||
1550 | uhci->fsbrtimeout = 0; | ||
1551 | uhci->skel_term_qh->link = UHCI_PTR_TERM; | ||
1552 | } | ||
1553 | } | ||