aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/uhci-hcd.h
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2007-02-19 15:52:45 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2007-02-23 18:03:45 -0500
commit17230acdc71137622ca7dfd789b3944c75d39404 (patch)
tree67eb75c5e8d254b2d5490ea9982efe73952f90d5 /drivers/usb/host/uhci-hcd.h
parent28b9325e6ae45ffb5e99fedcafe00f25fcaacf06 (diff)
UHCI: Eliminate asynchronous skeleton Queue Headers
This patch (as856) attempts to improve the performance of uhci-hcd by removing the asynchronous skeleton Queue Headers. They don't contain any useful information but the controller has to read through them at least once every millisecond, incurring a non-zero DMA overhead. Now all the asynchronous queues are combined, along with the period-1 interrupt queue, into a single list with a single skeleton QH. The start of the low-speed control, full-speed control, and bulk sublists is determined by linear search. Since there should rarely be more than a couple of QHs in the list, the searches should incur a much smaller total load than keeping the skeleton QHs. 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.h')
-rw-r--r--drivers/usb/host/uhci-hcd.h74
1 files changed, 36 insertions, 38 deletions
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index a8c256b44d8e..1b3d23406ac4 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -135,7 +135,6 @@ struct uhci_qh {
135 struct usb_host_endpoint *hep; /* Endpoint information */ 135 struct usb_host_endpoint *hep; /* Endpoint information */
136 struct usb_device *udev; 136 struct usb_device *udev;
137 struct list_head queue; /* Queue of urbps for this QH */ 137 struct list_head queue; /* Queue of urbps for this QH */
138 struct uhci_qh *skel; /* Skeleton for this QH */
139 struct uhci_td *dummy_td; /* Dummy TD to end the queue */ 138 struct uhci_td *dummy_td; /* Dummy TD to end the queue */
140 struct uhci_td *post_td; /* Last TD completed */ 139 struct uhci_td *post_td; /* Last TD completed */
141 140
@@ -151,6 +150,7 @@ struct uhci_qh {
151 150
152 int state; /* QH_STATE_xxx; see above */ 151 int state; /* QH_STATE_xxx; see above */
153 int type; /* Queue type (control, bulk, etc) */ 152 int type; /* Queue type (control, bulk, etc) */
153 int skel; /* Skeleton queue number */
154 154
155 unsigned int initial_toggle:1; /* Endpoint's current toggle value */ 155 unsigned int initial_toggle:1; /* Endpoint's current toggle value */
156 unsigned int needs_fixup:1; /* Must fix the TD toggle values */ 156 unsigned int needs_fixup:1; /* Must fix the TD toggle values */
@@ -276,12 +276,13 @@ static inline u32 td_status(struct uhci_td *td) {
276/* 276/*
277 * The UHCI driver uses QHs with Interrupt, Control and Bulk URBs for 277 * The UHCI driver uses QHs with Interrupt, Control and Bulk URBs for
278 * automatic queuing. To make it easy to insert entries into the schedule, 278 * automatic queuing. To make it easy to insert entries into the schedule,
279 * we have a skeleton of QHs for each predefined Interrupt latency, 279 * we have a skeleton of QHs for each predefined Interrupt latency.
280 * low-speed control, full-speed control, bulk, and terminating QH 280 * Asynchronous QHs (low-speed control, full-speed control, and bulk)
281 * (see explanation for the terminating QH below). 281 * go onto the period-1 interrupt list, since they all get accessed on
282 * every frame.
282 * 283 *
283 * When we want to add a new QH, we add it to the end of the list for the 284 * When we want to add a new QH, we add it to the list starting from the
284 * skeleton QH. For instance, the schedule list can look like this: 285 * appropriate skeleton QH. For instance, the schedule can look like this:
285 * 286 *
286 * skel int128 QH 287 * skel int128 QH
287 * dev 1 interrupt QH 288 * dev 1 interrupt QH
@@ -289,50 +290,47 @@ static inline u32 td_status(struct uhci_td *td) {
289 * skel int64 QH 290 * skel int64 QH
290 * skel int32 QH 291 * skel int32 QH
291 * ... 292 * ...
292 * skel int1 QH 293 * skel int1 + async QH
293 * skel low-speed control QH 294 * dev 5 low-speed control QH
294 * dev 5 control QH
295 * skel full-speed control QH
296 * skel bulk QH
297 * dev 1 bulk QH 295 * dev 1 bulk QH
298 * dev 2 bulk QH 296 * dev 2 bulk QH
299 * skel terminating QH
300 * 297 *
301 * The terminating QH is used for 2 reasons: 298 * There is a special terminating QH used to keep full-speed bandwidth
302 * - To place a terminating TD which is used to workaround a PIIX bug 299 * reclamation active when no full-speed control or bulk QHs are linked
303 * (see Intel errata for explanation), and 300 * into the schedule. It has an inactive TD (to work around a PIIX bug,
304 * - To loop back to the full-speed control queue for full-speed bandwidth 301 * see the Intel errata) and it points back to itself.
305 * reclamation.
306 * 302 *
307 * There's a special skeleton QH for Isochronous QHs. It never appears 303 * There's a special skeleton QH for Isochronous QHs which never appears
308 * on the schedule, and Isochronous TDs go on the schedule before the 304 * on the schedule. Isochronous TDs go on the schedule before the
309 * the skeleton QHs. The hardware accesses them directly rather than 305 * the skeleton QHs. The hardware accesses them directly rather than
310 * through their QH, which is used only for bookkeeping purposes. 306 * through their QH, which is used only for bookkeeping purposes.
311 * While the UHCI spec doesn't forbid the use of QHs for Isochronous, 307 * While the UHCI spec doesn't forbid the use of QHs for Isochronous,
312 * it doesn't use them either. And the spec says that queues never 308 * it doesn't use them either. And the spec says that queues never
313 * advance on an error completion status, which makes them totally 309 * advance on an error completion status, which makes them totally
314 * unsuitable for Isochronous transfers. 310 * unsuitable for Isochronous transfers.
311 *
312 * There's also a special skeleton QH used for QHs which are in the process
313 * of unlinking and so may still be in use by the hardware. It too never
314 * appears on the schedule.
315 */ 315 */
316 316
317#define UHCI_NUM_SKELQH 14 317#define UHCI_NUM_SKELQH 11
318#define skel_unlink_qh skelqh[0] 318#define SKEL_UNLINK 0
319#define skel_iso_qh skelqh[1] 319#define skel_unlink_qh skelqh[SKEL_UNLINK]
320#define skel_int128_qh skelqh[2] 320#define SKEL_ISO 1
321#define skel_int64_qh skelqh[3] 321#define skel_iso_qh skelqh[SKEL_ISO]
322#define skel_int32_qh skelqh[4] 322 /* int128, int64, ..., int1 = 2, 3, ..., 9 */
323#define skel_int16_qh skelqh[5] 323#define SKEL_INDEX(exponent) (9 - exponent)
324#define skel_int8_qh skelqh[6] 324#define SKEL_ASYNC 9
325#define skel_int4_qh skelqh[7] 325#define skel_async_qh skelqh[SKEL_ASYNC]
326#define skel_int2_qh skelqh[8] 326#define SKEL_TERM 10
327#define skel_int1_qh skelqh[9] 327#define skel_term_qh skelqh[SKEL_TERM]
328#define skel_ls_control_qh skelqh[10] 328
329#define skel_fs_control_qh skelqh[11] 329/* The following entries refer to sublists of skel_async_qh */
330#define skel_bulk_qh skelqh[12] 330#define SKEL_LS_CONTROL 20
331#define skel_term_qh skelqh[13] 331#define SKEL_FS_CONTROL 21
332 332#define SKEL_FSBR SKEL_FS_CONTROL
333/* Find the skelqh entry corresponding to an interval exponent */ 333#define SKEL_BULK 22
334#define UHCI_SKEL_INDEX(exponent) (9 - exponent)
335
336 334
337/* 335/*
338 * The UHCI controller and root hub 336 * The UHCI controller and root hub