ChangeSet 1.970, 2003/01/27 23:10:42+11:00, [EMAIL PROTECTED]
[PATCH] USB ohci-hcd, don't force SLAB_ATOMIC allocations
This is a minor cleanup to let per-request memory allocations block,
when the caller allows (it provided the bitmask). The driver used
to work that way until something like 2.4.3; an update (a few months
back) to how the "dma_addr_t" hashes to a "struct ohci_td *" lets us
simplify things again. Another benfit: it blocks irqs for less time
on the submit path. (The ehci driver already acts this way.)
diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
--- a/drivers/usb/host/ohci-hcd.c Tue Feb 4 15:17:52 2003
+++ b/drivers/usb/host/ohci-hcd.c Tue Feb 4 15:17:52 2003
@@ -203,27 +203,27 @@
return -ENOMEM;
memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (struct td *));
- spin_lock_irqsave (&ohci->lock, flags);
-
- /* don't submit to a dead HC */
- if (ohci->disabled || ohci->sleeping) {
- retval = -ENODEV;
- goto fail;
- }
-
/* fill the private part of the URB */
urb_priv->length = size;
urb_priv->ed = ed;
- /* allocate the TDs (updating hash chains) */
+ /* allocate the TDs (deferring hash chain updates) */
for (i = 0; i < size; i++) {
- urb_priv->td [i] = td_alloc (ohci, SLAB_ATOMIC);
+ urb_priv->td [i] = td_alloc (ohci, mem_flags);
if (!urb_priv->td [i]) {
urb_priv->length = i;
- retval = -ENOMEM;
- goto fail;
+ urb_free_priv (ohci, urb_priv);
+ return -ENOMEM;
}
}
+
+ spin_lock_irqsave (&ohci->lock, flags);
+
+ /* don't submit to a dead HC */
+ if (ohci->disabled || ohci->sleeping) {
+ retval = -ENODEV;
+ goto fail;
+ }
/* schedule the ed if needed */
if (ed->state == ED_IDLE) {
diff -Nru a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
--- a/drivers/usb/host/ohci-mem.c Tue Feb 4 15:17:52 2003
+++ b/drivers/usb/host/ohci-mem.c Tue Feb 4 15:17:52 2003
@@ -97,17 +97,11 @@
td = pci_pool_alloc (hc->td_cache, mem_flags, &dma);
if (td) {
- int hash;
-
/* in case hc fetches it, make it look dead */
memset (td, 0, sizeof *td);
td->hwNextTD = cpu_to_le32 (dma);
td->td_dma = dma;
-
- /* hash it for later reverse mapping */
- hash = TD_HASH_FUNC (dma);
- td->td_hash = hc->td_hash [hash];
- hc->td_hash [hash] = td;
+ /* hashed in td_fill */
}
return td;
}
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- a/drivers/usb/host/ohci-q.c Tue Feb 4 15:17:52 2003
+++ b/drivers/usb/host/ohci-q.c Tue Feb 4 15:17:52 2003
@@ -463,13 +463,14 @@
/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
static void
-td_fill (unsigned int info,
+td_fill (struct ohci_hcd *ohci, u32 info,
dma_addr_t data, int len,
struct urb *urb, int index)
{
struct td *td, *td_pt;
struct urb_priv *urb_priv = urb->hcpriv;
int is_iso = info & TD_ISO;
+ int hash;
// ASSERT (index < urb_priv->length);
@@ -516,11 +517,16 @@
td->hwBE = 0;
td->hwNextTD = cpu_to_le32 (td_pt->td_dma);
- /* HC might read the TD right after we link it ... */
- wmb ();
-
/* append to queue */
list_add_tail (&td->td_list, &td->ed->td_list);
+
+ /* hash it for later reverse mapping */
+ hash = TD_HASH_FUNC (td->td_dma);
+ td->td_hash = ohci->td_hash [hash];
+ ohci->td_hash [hash] = td;
+
+ /* HC might read the TD (or cachelines) right away ... */
+ wmb ();
td->ed->hwTailP = td->hwNextTD;
}
@@ -578,7 +584,7 @@
: TD_T_TOGGLE | TD_CC | TD_DP_IN;
/* TDs _could_ transfer up to 8K each */
while (data_len > 4096) {
- td_fill (info, data, 4096, urb, cnt);
+ td_fill (ohci, info, data, 4096, urb, cnt);
data += 4096;
data_len -= 4096;
cnt++;
@@ -586,11 +592,11 @@
/* maybe avoid ED halt on final TD short read */
if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
info |= TD_R;
- td_fill (info, data, data_len, urb, cnt);
+ td_fill (ohci, info, data, data_len, urb, cnt);
cnt++;
if ((urb->transfer_flags & URB_ZERO_PACKET)
&& cnt < urb_priv->length) {
- td_fill (info, 0, 0, urb, cnt);
+ td_fill (ohci, info, 0, 0, urb, cnt);
cnt++;
}
/* maybe kickstart bulk list */
@@ -605,17 +611,17 @@
*/
case PIPE_CONTROL:
info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
- td_fill (info, urb->setup_dma, 8, urb, cnt++);
+ td_fill (ohci, info, urb->setup_dma, 8, urb, cnt++);
if (data_len > 0) {
info = TD_CC | TD_R | TD_T_DATA1;
info |= is_out ? TD_DP_OUT : TD_DP_IN;
/* NOTE: mishandles transfers >8K, some >4K */
- td_fill (info, data, data_len, urb, cnt++);
+ td_fill (ohci, info, data, data_len, urb, cnt++);
}
info = is_out
? TD_CC | TD_DP_IN | TD_T_DATA1
: TD_CC | TD_DP_OUT | TD_T_DATA1;
- td_fill (info, data, 0, urb, cnt++);
+ td_fill (ohci, info, data, 0, urb, cnt++);
/* maybe kickstart control list */
wmb ();
writel (OHCI_CLF, &ohci->regs->cmdstatus);
@@ -634,7 +640,7 @@
// a 2^16 iso range, vs other HCs max of 2^10)
frame += cnt * urb->interval;
frame &= 0xffff;
- td_fill (TD_CC | TD_ISO | frame,
+ td_fill (ohci, TD_CC | TD_ISO | frame,
data + urb->iso_frame_desc [cnt].offset,
urb->iso_frame_desc [cnt].length, urb, cnt);
}
-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel