# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.447.16.5 -> 1.447.16.6 # drivers/usb/host/ohci-hcd.c 1.13 -> 1.14 # drivers/usb/host/ohci-q.c 1.9 -> 1.10 # drivers/usb/host/ohci.h 1.6 -> 1.7 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/06/10 david-b@pacbell.net 1.447.16.6 # [PATCH] ohci-hcd, speedups+misc # # - Delays or eliminates some IRQs It'll mostly affect control # or iso transfers, which typically have multiple TDs per URB, # by making only the last TD generate an IRQ. # # - Shortens some of the submit path that needs to run with # IRQs disabled ... no need to use the dma_to_td hashtable. # (Of course that path is still pretty long...) # # - Gets rid of case where the ED state was confused ... now # there's only one such state, not two. # -------------------------------------------- # diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c --- a/drivers/usb/host/ohci-hcd.c Tue Jun 11 14:58:55 2002 +++ b/drivers/usb/host/ohci-hcd.c Tue Jun 11 14:58:55 2002 @@ -100,7 +100,7 @@ * - lots more testing!! */ -#define DRIVER_VERSION "2002-Jun-01" +#define DRIVER_VERSION "2002-Jun-10" #define DRIVER_AUTHOR "Roman Weissgaerber , David Brownell" #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" @@ -307,7 +307,6 @@ spin_lock_irqsave (&ohci->lock, flags); for (i = 0; i < 32; i++) { struct ed *ed = dev->ep [i]; - struct td *tdTailP; if (!ed) continue; @@ -319,10 +318,7 @@ case ED_NEW: break; case ED_UNLINK: - tdTailP = dma_to_td (ohci, - le32_to_cpup (&ed->hwTailP) & 0xfffffff0); - td_free (ohci, tdTailP); /* free dummy td */ - hash_free_ed (ohci, ed); + td_free (ohci, ed->dummy); break; case ED_OPER: diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c --- a/drivers/usb/host/ohci-q.c Tue Jun 11 14:58:55 2002 +++ b/drivers/usb/host/ohci-q.c Tue Jun 11 14:58:55 2002 @@ -440,14 +440,16 @@ spin_unlock_irqrestore (&ohci->lock, flags); return NULL; } + ed->dummy = td; ed->hwTailP = cpu_to_le32 (td->td_dma); - ed->hwHeadP = ed->hwTailP; + ed->hwHeadP = ed->hwTailP; /* ED_C, ED_H zeroed */ ed->state = ED_UNLINK; ed->type = usb_pipetype (pipe); } -// FIXME: don't do this if it's linked to the HC, -// we might clobber data toggle or other state ... +// FIXME: don't do this if it's linked to the HC, or without knowing it's +// safe to clobber state/mode info tied to (previous) config/altsetting. +// (but dev0/ep0, used by set_address, must get clobbered) ed->hwINFO = cpu_to_le32 (usb_pipedevice (pipe) | usb_pipeendpoint (pipe) << 7 @@ -523,27 +525,31 @@ dma_addr_t data, int len, struct urb *urb, int index) { - volatile struct td *td, *td_pt; + struct td *td, *td_pt; urb_priv_t *urb_priv = urb->hcpriv; + int is_iso = info & TD_ISO; if (index >= urb_priv->length) { err ("internal OHCI error: TD index > length"); return; } -#if 0 - /* no interrupt needed except for URB's last TD */ + /* aim for only one interrupt per urb. mostly applies to control + * and iso; other urbs rarely need more than one TD per urb. + * + * NOTE: could delay interrupts even for the last TD, and get fewer + * interrupts ... increasing per-urb latency by sharing interrupts. + */ if (index != (urb_priv->length - 1)) - info |= TD_DI; -#endif + info |= is_iso ? TD_DI_SET (7) : TD_DI_SET (1); /* use this td as the next dummy */ td_pt = urb_priv->td [index]; td_pt->hwNextTD = 0; /* fill the old dummy TD */ - td = urb_priv->td [index] = dma_to_td (ohci, - le32_to_cpup (&urb_priv->ed->hwTailP)); + td = urb_priv->td [index] = urb_priv->ed->dummy; + urb_priv->ed->dummy = td_pt; td->ed = urb_priv->ed; td->next_dl_td = NULL; @@ -554,7 +560,7 @@ data = 0; td->hwINFO = cpu_to_le32 (info); - if ((td->ed->type) == PIPE_ISOCHRONOUS) { + if (is_iso) { td->hwCBP = cpu_to_le32 (data & 0xFFFFF000); td->ed->intriso.last_iso = info & 0xffff; } else { @@ -901,6 +907,7 @@ * [a2] some (earlier) URBs still linked, re-enable * (b) finishing ED unlink * [b1] no URBs queued, ED is truly idle now + * ... we could set state ED_NEW and free dummy * [b2] URBs now queued, link ED back into schedule * right now we only have (a) */ @@ -910,9 +917,6 @@ if (tdHeadP == tdTailP) { if (ed->state == ED_OPER) start_ed_unlink (ohci, ed); - td_free (ohci, tdTailP); - ed->hwINFO = ED_SKIP; - ed->state = ED_NEW; } else ed->hwINFO &= ~ED_SKIP; diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h --- a/drivers/usb/host/ohci.h Tue Jun 11 14:58:55 2002 +++ b/drivers/usb/host/ohci.h Tue Jun 11 14:58:55 2002 @@ -29,6 +29,7 @@ /* rest are purely for the driver's use */ dma_addr_t dma; /* addr of ED */ struct ed *ed_prev; /* for non-interrupt EDs */ + struct td *dummy; u8 type; /* PIPE_{BULK,...} */ u8 interval; /* interrupt, isochronous */ @@ -63,24 +64,33 @@ struct td { /* first fields are hardware-specified, le32 */ __u32 hwINFO; /* transfer info bitmask */ + + /* hwINFO bits for both general and iso tds: */ #define TD_CC 0xf0000000 /* condition code */ #define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) //#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) +#define TD_DI 0x00E00000 /* frames before interrupt */ +#define TD_DI_SET(X) (((X) & 0x07)<< 21) + /* these two bits are available for definition/use by HCDs in both + * general and iso tds ... others are available for only one type + */ +//#define TD____ 0x00020000 +#define TD_ISO 0x00010000 /* copy of ED_ISO */ + + /* hwINFO bits for general tds: */ #define TD_EC 0x0C000000 /* error count */ #define TD_T 0x03000000 /* data toggle state */ #define TD_T_DATA0 0x02000000 /* DATA0 */ #define TD_T_DATA1 0x03000000 /* DATA1 */ #define TD_T_TOGGLE 0x00000000 /* uses ED_C */ -#define TD_DI 0x00E00000 /* frames before interrupt */ -//#define TD_DI_SET(X) (((X) & 0x07)<< 21) #define TD_DP 0x00180000 /* direction/pid */ #define TD_DP_SETUP 0x00000000 /* SETUP pid */ #define TD_DP_IN 0x00100000 /* IN pid */ #define TD_DP_OUT 0x00080000 /* OUT pid */ /* 0x00180000 rsvd */ #define TD_R 0x00040000 /* round: short packets OK? */ - /* bits 0x1ffff are defined by HCD */ -#define TD_ISO 0x00010000 /* copy of ED_ISO */ + + /* (no hwINFO #defines yet for iso tds) */ __u32 hwCBP; /* Current Buffer Pointer (or 0) */ __u32 hwNextTD; /* Next TD Pointer */