aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/uhci-q.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/uhci-q.c')
-rw-r--r--drivers/usb/host/uhci-q.c62
1 files changed, 35 insertions, 27 deletions
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 4e0fbe2c1a9a..7e46887d9e12 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -89,10 +89,10 @@ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td,
89 td->frame = framenum; 89 td->frame = framenum;
90 90
91 /* Is there a TD already mapped there? */ 91 /* Is there a TD already mapped there? */
92 if (uhci->fl->frame_cpu[framenum]) { 92 if (uhci->frame_cpu[framenum]) {
93 struct uhci_td *ftd, *ltd; 93 struct uhci_td *ftd, *ltd;
94 94
95 ftd = uhci->fl->frame_cpu[framenum]; 95 ftd = uhci->frame_cpu[framenum];
96 ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list); 96 ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
97 97
98 list_add_tail(&td->fl_list, &ftd->fl_list); 98 list_add_tail(&td->fl_list, &ftd->fl_list);
@@ -101,29 +101,32 @@ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td,
101 wmb(); 101 wmb();
102 ltd->link = cpu_to_le32(td->dma_handle); 102 ltd->link = cpu_to_le32(td->dma_handle);
103 } else { 103 } else {
104 td->link = uhci->fl->frame[framenum]; 104 td->link = uhci->frame[framenum];
105 wmb(); 105 wmb();
106 uhci->fl->frame[framenum] = cpu_to_le32(td->dma_handle); 106 uhci->frame[framenum] = cpu_to_le32(td->dma_handle);
107 uhci->fl->frame_cpu[framenum] = td; 107 uhci->frame_cpu[framenum] = td;
108 } 108 }
109} 109}
110 110
111static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td) 111static inline void uhci_remove_td_frame_list(struct uhci_hcd *uhci,
112 struct uhci_td *td)
112{ 113{
113 /* If it's not inserted, don't remove it */ 114 /* If it's not inserted, don't remove it */
114 if (td->frame == -1 && list_empty(&td->fl_list)) 115 if (td->frame == -1) {
116 WARN_ON(!list_empty(&td->fl_list));
115 return; 117 return;
118 }
116 119
117 if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) { 120 if (uhci->frame_cpu[td->frame] == td) {
118 if (list_empty(&td->fl_list)) { 121 if (list_empty(&td->fl_list)) {
119 uhci->fl->frame[td->frame] = td->link; 122 uhci->frame[td->frame] = td->link;
120 uhci->fl->frame_cpu[td->frame] = NULL; 123 uhci->frame_cpu[td->frame] = NULL;
121 } else { 124 } else {
122 struct uhci_td *ntd; 125 struct uhci_td *ntd;
123 126
124 ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list); 127 ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
125 uhci->fl->frame[td->frame] = cpu_to_le32(ntd->dma_handle); 128 uhci->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
126 uhci->fl->frame_cpu[td->frame] = ntd; 129 uhci->frame_cpu[td->frame] = ntd;
127 } 130 }
128 } else { 131 } else {
129 struct uhci_td *ptd; 132 struct uhci_td *ptd;
@@ -132,13 +135,20 @@ static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
132 ptd->link = td->link; 135 ptd->link = td->link;
133 } 136 }
134 137
135 wmb();
136 td->link = UHCI_PTR_TERM;
137
138 list_del_init(&td->fl_list); 138 list_del_init(&td->fl_list);
139 td->frame = -1; 139 td->frame = -1;
140} 140}
141 141
142static void unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb)
143{
144 struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
145 struct uhci_td *td;
146
147 list_for_each_entry(td, &urbp->td_list, list)
148 uhci_remove_td_frame_list(uhci, td);
149 wmb();
150}
151
142/* 152/*
143 * Inserts a td list into qh. 153 * Inserts a td list into qh.
144 */ 154 */
@@ -443,7 +453,6 @@ static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *u
443 453
444 memset((void *)urbp, 0, sizeof(*urbp)); 454 memset((void *)urbp, 0, sizeof(*urbp));
445 455
446 urbp->inserttime = jiffies;
447 urbp->fsbrtime = jiffies; 456 urbp->fsbrtime = jiffies;
448 urbp->urb = urb; 457 urbp->urb = urb;
449 458
@@ -462,8 +471,6 @@ static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td)
462{ 471{
463 struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; 472 struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
464 473
465 td->urb = urb;
466
467 list_add_tail(&td->list, &urbp->td_list); 474 list_add_tail(&td->list, &urbp->td_list);
468} 475}
469 476
@@ -473,8 +480,6 @@ static void uhci_remove_td_from_urb(struct uhci_td *td)
473 return; 480 return;
474 481
475 list_del_init(&td->list); 482 list_del_init(&td->list);
476
477 td->urb = NULL;
478} 483}
479 484
480static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb) 485static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
@@ -503,7 +508,6 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
503 508
504 list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { 509 list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
505 uhci_remove_td_from_urb(td); 510 uhci_remove_td_from_urb(td);
506 uhci_remove_td(uhci, td);
507 list_add(&td->remove_list, &uhci->td_remove_list); 511 list_add(&td->remove_list, &uhci->td_remove_list);
508 } 512 }
509 513
@@ -1073,6 +1077,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
1073 struct uhci_td *td; 1077 struct uhci_td *td;
1074 int i, ret, frame; 1078 int i, ret, frame;
1075 int status, destination; 1079 int status, destination;
1080 struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
1076 1081
1077 status = TD_CTRL_ACTIVE | TD_CTRL_IOS; 1082 status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
1078 destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); 1083 destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
@@ -1081,11 +1086,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
1081 if (ret) 1086 if (ret)
1082 return ret; 1087 return ret;
1083 1088
1084 frame = urb->start_frame; 1089 for (i = 0; i < urb->number_of_packets; i++) {
1085 for (i = 0; i < urb->number_of_packets; i++, frame += urb->interval) {
1086 if (!urb->iso_frame_desc[i].length)
1087 continue;
1088
1089 td = uhci_alloc_td(uhci); 1090 td = uhci_alloc_td(uhci);
1090 if (!td) 1091 if (!td)
1091 return -ENOMEM; 1092 return -ENOMEM;
@@ -1096,8 +1097,12 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
1096 1097
1097 if (i + 1 >= urb->number_of_packets) 1098 if (i + 1 >= urb->number_of_packets)
1098 td->status |= cpu_to_le32(TD_CTRL_IOC); 1099 td->status |= cpu_to_le32(TD_CTRL_IOC);
1100 }
1099 1101
1102 frame = urb->start_frame;
1103 list_for_each_entry(td, &urbp->td_list, list) {
1100 uhci_insert_td_frame_list(uhci, td, frame); 1104 uhci_insert_td_frame_list(uhci, td, frame);
1105 frame += urb->interval;
1101 } 1106 }
1102 1107
1103 return -EINPROGRESS; 1108 return -EINPROGRESS;
@@ -1110,7 +1115,7 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
1110 int status; 1115 int status;
1111 int i, ret = 0; 1116 int i, ret = 0;
1112 1117
1113 urb->actual_length = 0; 1118 urb->actual_length = urb->error_count = 0;
1114 1119
1115 i = 0; 1120 i = 0;
1116 list_for_each_entry(td, &urbp->td_list, list) { 1121 list_for_each_entry(td, &urbp->td_list, list) {
@@ -1134,6 +1139,7 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
1134 1139
1135 i++; 1140 i++;
1136 } 1141 }
1142 unlink_isochronous_tds(uhci, urb);
1137 1143
1138 return ret; 1144 return ret;
1139} 1145}
@@ -1366,6 +1372,8 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
1366 goto done; 1372 goto done;
1367 list_del_init(&urbp->urb_list); 1373 list_del_init(&urbp->urb_list);
1368 1374
1375 if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
1376 unlink_isochronous_tds(uhci, urb);
1369 uhci_unlink_generic(uhci, urb); 1377 uhci_unlink_generic(uhci, urb);
1370 1378
1371 uhci_get_current_frame_number(uhci); 1379 uhci_get_current_frame_number(uhci);