--- include/linux/usb-dist.h	Thu Mar 14 12:45:55 2002
+++ include/linux/usb.h	Thu Mar 14 13:40:51 2002
@@ -432,6 +432,7 @@
 #define URB_NO_INTERRUPT	0x0080	/* HINT: no non-error interrupt needed */
 					/* ... less overhead for QUEUE_BULK */
 #define USB_TIMEOUT_KILLED	0x1000	// only set by HCD!
+#define URB_HCD_OWNED		0x2000	// only set by HCD!
 
 typedef struct
 {
@@ -447,8 +448,8 @@
 typedef struct urb
 {
 	spinlock_t lock;		// lock for the URB
-	void *hcpriv;			// private data for host controller
-	struct list_head urb_list;	// list pointer to all active urbs 
+	struct list_head urb_list;	// list pointer, for URB owner
+	char data [64];			// scratch, also for URB owner
 	struct urb *next;		// pointer to next URB	
 	struct usb_device *dev;		// pointer to associated USB device
 	unsigned int pipe;		// pipe information
--- drivers/usb-dist/usb.c	Wed Mar  6 09:36:16 2002
+++ drivers/usb/usb.c	Thu Mar 14 12:48:57 2002
@@ -1019,18 +1019,22 @@
 /*-------------------------------------------------------------------*/
 int usb_submit_urb(urb_t *urb)
 {
-	if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
+	if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op) {
+		if (urb->transfer_flags & URB_HCD_OWNED)
+			return -EINVAL;
 		return urb->dev->bus->op->submit_urb(urb);
-	else
+	} else
 		return -ENODEV;
 }
 
 /*-------------------------------------------------------------------*/
 int usb_unlink_urb(urb_t *urb)
 {
-	if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
+	if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op) {
+		if (!(urb->transfer_flags & URB_HCD_OWNED))
+			return -EINVAL;
 		return urb->dev->bus->op->unlink_urb(urb);
-	else
+	} else
 		return -ENODEV;
 }
 /*-------------------------------------------------------------------*
--- drivers/usb-dist/usb-ohci.c	Wed Mar  6 09:36:16 2002
+++ drivers/usb/usb-ohci.c	Thu Mar 14 12:48:57 2002
@@ -170,16 +170,13 @@
 				td_free (hc, td);
 		}
 	}
-
-	kfree (urb_priv);
 }
  
 static void urb_rm_priv_locked (urb_t * urb) 
 {
-	urb_priv_t * urb_priv = urb->hcpriv;
+	urb_priv_t * urb_priv = (urb_priv_t *) urb->data;
 	
-	if (urb_priv) {
-		urb->hcpriv = NULL;
+	if (urb->transfer_flags & URB_HCD_OWNED) {
 
 #ifdef	DO_TIMEOUTS
 		if (urb->timeout) {
@@ -204,6 +201,7 @@
 
 		urb_free_priv ((struct ohci *)urb->dev->bus->hcpriv, urb_priv);
 		usb_dec_dev_use (urb->dev);
+		urb->transfer_flags &= ~URB_HCD_OWNED;
 		urb->dev = NULL;
 	}
 }
@@ -456,7 +454,7 @@
  
 static int sohci_return_urb (struct ohci *hc, urb_t * urb)
 {
-	urb_priv_t * urb_priv = urb->hcpriv;
+	urb_priv_t * urb_priv = (urb_priv_t *) urb->data;
 	urb_t * urbt;
 	unsigned long flags;
 	int i;
@@ -548,9 +546,6 @@
 	if (!urb->dev || !urb->dev->bus)
 		return -ENODEV;
 	
-	if (urb->hcpriv)			/* urb already in use */
-		return -EINVAL;
-
 //	if(usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) 
 //		return -EPIPE;
 	
@@ -613,12 +608,11 @@
 	}
 
 	/* allocate the private part of the URB */
-	urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (td_t *), 
-							in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
-	if (!urb_priv) {
+	if ((sizeof (urb_priv_t) + size * sizeof (td_t *)) > sizeof urb->data) {
 		usb_dec_dev_use (urb->dev);	
 		return -ENOMEM;
 	}
+	urb_priv = (urb_priv_t *) urb->data;
 	memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (td_t *));
 	
 	/* fill the private part of the URB */
@@ -673,7 +667,7 @@
 	}
 
 	urb->actual_length = 0;
-	urb->hcpriv = urb_priv;
+	urb->transfer_flags |= URB_HCD_OWNED;
 	urb->status = USB_ST_URB_PENDING;
 
 	/* link the ed into a chain if is not already */
@@ -738,7 +732,8 @@
 	if (usb_pipedevice (urb->pipe) == ohci->rh.devnum)
 		return rh_unlink_urb (urb);
 
-	if (urb->hcpriv && (urb->status == USB_ST_URB_PENDING)) { 
+	if ((urb->transfer_flags & URB_HCD_OWNED)
+			&& (urb->status == USB_ST_URB_PENDING)) { 
 		if (!ohci->disabled) {
 			urb_priv_t  * urb_priv;
 
@@ -756,9 +751,10 @@
 			 * upcoming SF interrupt delete list processing
 			 */
 			spin_lock_irqsave (&usb_ed_lock, flags);
-			urb_priv = urb->hcpriv;
+			urb_priv = (urb_priv_t *) urb->data;
 
-			if (!urb_priv || (urb_priv->state == URB_DEL)) {
+			if (!(urb->transfer_flags & URB_HCD_OWNED)
+					|| (urb_priv->state == URB_DEL)) {
 				spin_unlock_irqrestore (&usb_ed_lock, flags);
 				return 0;
 			}
@@ -1299,7 +1295,7 @@
 	urb_t * urb, int index)
 {
 	volatile td_t  * td, * td_pt;
-	urb_priv_t * urb_priv = urb->hcpriv;
+	urb_priv_t * urb_priv = (urb_priv_t *) urb->data;
 	
 	if (index >= urb_priv->length) {
 		err("internal OHCI error: TD index > length");
@@ -1346,7 +1342,7 @@
 
 static void td_submit_urb (urb_t * urb)
 { 
-	urb_priv_t * urb_priv = urb->hcpriv;
+	urb_priv_t * urb_priv = (urb_priv_t *) urb->data;
 	ohci_t * ohci = (ohci_t *) urb->dev->bus->hcpriv;
 	dma_addr_t data;
 	int data_len = urb->transfer_buffer_length;
@@ -1454,7 +1450,7 @@
 	__u32 tdINFO, tdBE, tdCBP;
  	__u16 tdPSW;
  	urb_t * urb = td->urb;
- 	urb_priv_t * urb_priv = urb->hcpriv;
+ 	urb_priv_t * urb_priv = (urb_priv_t *) urb->data;
 	int dlen = 0;
 	int cc = 0;
 	
@@ -1496,7 +1492,7 @@
 
 static void dl_del_urb (urb_t * urb)
 {
-	wait_queue_head_t * wait_head = ((urb_priv_t *)(urb->hcpriv))->wait;
+	wait_queue_head_t * wait_head = ((urb_priv_t *)(urb->data))->wait;
 
 	urb_rm_priv_locked (urb);
 
@@ -1535,7 +1531,7 @@
 		td_list = dma_to_td (ohci, td_list_hc);
 
 		if (TD_CC_GET (le32_to_cpup (&td_list->hwINFO))) {
-			urb_priv = (urb_priv_t *) td_list->urb->hcpriv;
+			urb_priv = (urb_priv_t *) td_list->urb->data;
 			dbg(" USB-error/status: %x : %p", 
 					TD_CC_GET (le32_to_cpup (&td_list->hwINFO)), td_list);
 			if (td_list->ed->hwHeadP & cpu_to_le32 (0x1)) {
@@ -1584,7 +1580,7 @@
 
 		for (td = tdHeadP; td != tdTailP; td = td_next) { 
 			urb_t * urb = td->urb;
-			urb_priv_t * urb_priv = td->urb->hcpriv;
+			urb_priv_t * urb_priv = (urb_priv_t *) td->urb->data;
 			
 			td_next = dma_to_td (ohci, le32_to_cpup (&td->hwNextTD) & 0xfffffff0);
 			if ((urb_priv->state == URB_DEL) || (ed->state & ED_DEL)) {
@@ -1681,7 +1677,7 @@
    		td_list_next = td_list->next_dl_td;
    		
   		urb = td_list->urb;
-  		urb_priv = urb->hcpriv;
+  		urb_priv = (urb_priv_t *) urb->data;
   		tdINFO = le32_to_cpup (&td_list->hwINFO);
   		
    		ed = td_list->ed;
@@ -2097,7 +2093,6 @@
 	urb_print (urb, "RET(rh)", usb_pipeout (urb->pipe));
 #endif
 
-	urb->hcpriv = NULL;
 	usb_dec_dev_use (usb_dev);
 	urb->dev = NULL;
 	if (urb->complete)
@@ -2116,7 +2111,7 @@
 		del_timer (&ohci->rh.rh_int_timer);
 		ohci->rh.urb = NULL;
 
-		urb->hcpriv = NULL;
+		urb->transfer_flags &= ~URB_HCD_OWNED;
 		usb_dec_dev_use(urb->dev);
 		urb->dev = NULL;
 		if (urb->transfer_flags & USB_ASYNC_UNLINK) {
@@ -2874,6 +2869,12 @@
 
 static int __init ohci_hcd_init (void) 
 {
+	/* compiler _should_ optimize out this test, or rest of the driver */
+	if (sizeof (urb_priv_t) > sizeof ((struct urb *)0)->data) {
+		err ("urb_priv too big for urb->data");
+		return -ENOMEM;
+	}
+
 	return pci_module_init (&ohci_pci_driver);
 }
 
--- drivers/usb-dist/usb-uhci.c	Wed Mar  6 09:36:16 2002
+++ drivers/usb/usb-uhci.c	Thu Mar 14 13:20:58 2002
@@ -82,11 +82,6 @@
 #define queue_dbg dbg //err
 #define async_dbg dbg //err
 
-#ifdef DEBUG_SLAB
-	static kmem_cache_t *urb_priv_kmem;
-#endif
-
-#define SLAB_FLAG     (in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL)
 #define KMALLOC_FLAG  (in_interrupt ()? GFP_ATOMIC : GFP_KERNEL)
 
 /* CONFIG_USB_UHCI_HIGH_BANDWITH turns on Full Speed Bandwidth
@@ -179,7 +174,7 @@
 	s->chain_end->hw.qh.head&=cpu_to_le32(~UHCI_PTR_TERM);
 	mb();
 	s->loop_usage++;
-	((urb_priv_t*)urb->hcpriv)->use_loop=1;
+	((urb_priv_t*)urb->data)->use_loop=1;
 	spin_unlock_irqrestore (&s->qh_lock, flags);
 }
 /*-------------------------------------------------------------------*/
@@ -191,14 +186,14 @@
 		return;
 
 	spin_lock_irqsave (&s->qh_lock, flags);
-	if (((urb_priv_t*)urb->hcpriv)->use_loop) {
+	if (((urb_priv_t*)urb->data)->use_loop) {
 		s->loop_usage--;
 
 		if (!s->loop_usage) {
 			s->chain_end->hw.qh.head|=cpu_to_le32(UHCI_PTR_TERM);
 			mb();
 		}
-		((urb_priv_t*)urb->hcpriv)->use_loop=0;
+		((urb_priv_t*)urb->data)->use_loop=0;
 	}
 	spin_unlock_irqrestore (&s->qh_lock, flags);
 }
@@ -217,7 +212,7 @@
 	}
 #endif
 	urb->status = -EINPROGRESS;
-	((urb_priv_t*)urb->hcpriv)->started=jiffies;
+	((urb_priv_t*)urb->data)->started=jiffies;
 	list_add (p, &s->urb_list);
 	if (urb->timeout)
 		s->timeout_urbs++;
@@ -702,7 +697,7 @@
 {
 	uhci_desc_t *qh, *td;
 	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
-	urb_priv_t *urb_priv = urb->hcpriv;
+	urb_priv_t *urb_priv = (urb_priv_t *) urb->data;
 	unsigned long destination, status;
 	int maxsze = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe));
 	unsigned long len;
@@ -818,7 +813,7 @@
 _static int uhci_submit_bulk_urb (urb_t *urb, urb_t *bulk_urb)
 {
 	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
-	urb_priv_t *urb_priv = urb->hcpriv, *upriv, *bpriv=NULL;
+	urb_priv_t *urb_priv = (urb_priv_t *) urb->data, *upriv, *bpriv=NULL;
 	uhci_desc_t *qh, *td, *nqh=NULL, *bqh=NULL, *first_td=NULL;
 	unsigned long destination, status;
 	char *data;
@@ -833,7 +828,7 @@
 	queue_dbg("uhci_submit_bulk_urb: urb %p, old %p, pipe %08x, len %i",
 		  urb,bulk_urb,urb->pipe,urb->transfer_buffer_length);
 
-	upriv = (urb_priv_t*)urb->hcpriv;
+	upriv = (urb_priv_t*)urb->data;
 
 	if (!bulk_urb) {
 		if (alloc_qh (s, &qh))		// get qh for this request
@@ -850,7 +845,7 @@
 		}
 	}
 	else { 
-		bpriv = (urb_priv_t*)bulk_urb->hcpriv;
+		bpriv = (urb_priv_t*)bulk_urb->data;
 		qh = bpriv->bottom_qh;  // re-use bottom qh and next qh
 		nqh = bpriv->next_qh;
 		upriv->next_qh=nqh;	
@@ -981,7 +976,7 @@
 {
 	uhci_desc_t *bqh, *nqh, *prevqh, *prevtd;
 	int now;
-	urb_priv_t *priv=(urb_priv_t*)urb->hcpriv;
+	urb_priv_t *priv=(urb_priv_t*)urb->data;
 
 	now=UHCI_GET_CURRENT_FRAME(s);
 
@@ -993,7 +988,7 @@
 	
 		if (priv->prev_queued_urb && mode != CLEAN_TRANSFER_DELETION_MARK) {  // qh not top of the queue
 				unsigned long flags; 
-				urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv;
+				urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->data;
 
 				spin_lock_irqsave (&s->qh_lock, flags);
 				prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list);
@@ -1045,8 +1040,8 @@
 				list_add (&bqh->horizontal, &prevqh->horizontal); // insert next bqh in horizontal chain
 			}
 			else {		// intermediate QH
-				urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv;
-				urb_priv_t* npriv=(urb_priv_t*)nurb->hcpriv;
+				urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->data;
+				urb_priv_t* npriv=(urb_priv_t*)nurb->data;
 				uhci_desc_t * bnqh;
 				
 				bnqh = list_entry (npriv->desc_list.next, uhci_desc_t, desc_list);
@@ -1057,7 +1052,7 @@
 			}
 
 			mb();
-			((urb_priv_t*)nurb->hcpriv)->prev_queued_urb=priv->prev_queued_urb;
+			((urb_priv_t*)nurb->data)->prev_queued_urb=priv->prev_queued_urb;
 			spin_unlock_irqrestore (&s->qh_lock, flags);
 		}		
 	}
@@ -1128,9 +1123,9 @@
 	async_dbg("unlink_urb_async called %p",urb);
 
 	if ((urb->status == -EINPROGRESS) ||
-	    ((usb_pipetype (urb->pipe) ==  PIPE_INTERRUPT) && ((urb_priv_t*)urb->hcpriv)->flags))
+	    ((usb_pipetype (urb->pipe) ==  PIPE_INTERRUPT) && ((urb_priv_t*)urb->data)->flags))
 	{
-		((urb_priv_t*)urb->hcpriv)->started = ~0;  // mark
+		((urb_priv_t*)urb->data)->started = ~0;  // mark
 		dequeue_urb (s, urb);
 
 		if (mode==UNLINK_ASYNC_STORE_URB)
@@ -1141,7 +1136,7 @@
 		uhci_release_bandwidth(urb);
 
 		urb->status = -ECONNABORTED;	// mark urb as "waiting to be killed"	
-		urb_priv = (urb_priv_t*)urb->hcpriv;
+		urb_priv = (urb_priv_t*)urb->data;
 
 		switch (usb_pipetype (urb->pipe)) {
 		case PIPE_INTERRUPT:
@@ -1157,7 +1152,7 @@
 			uhci_clean_transfer (s, urb, qh, CLEAN_TRANSFER_NO_DELETION);
 			break;
 		}
-		((urb_priv_t*)urb->hcpriv)->started = UHCI_GET_CURRENT_FRAME(s);
+		((urb_priv_t*)urb->data)->started = UHCI_GET_CURRENT_FRAME(s);
 		return -EINPROGRESS;  // completion will follow
 	}		
 
@@ -1179,7 +1174,7 @@
 		// move descriptors out the the running chains, dequeue urb
 		uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_DONT_STORE);
 
-		urb_priv = urb->hcpriv;
+		urb_priv = (urb_priv_t *) urb->data;
 		urb->status = -ENOENT;	// prevent from double deletion after unlock		
 		spin_unlock_irqrestore (&s->urb_list_lock, flags);
 		
@@ -1200,13 +1195,8 @@
 		}
 		urb->status = -ENOENT;	// mark urb as killed		
 					
-		uhci_urb_dma_unmap(s, urb, urb->hcpriv);
-
-#ifdef DEBUG_SLAB
-		kmem_cache_free (urb_priv_kmem, urb->hcpriv);
-#else
-		kfree (urb->hcpriv);
-#endif
+		uhci_urb_dma_unmap(s, urb, (urb_priv_t *) urb->data);
+		urb->transfer_flags &= ~URB_HCD_OWNED;
 		usb_dev = urb->dev;
 		if (urb->complete) {
 			dbg("unlink_urb: calling completion");
@@ -1241,7 +1231,7 @@
 
 		urb = list_entry (q, urb_t, urb_list);
 
-		urb_priv = (urb_priv_t*)urb->hcpriv;
+		urb_priv = (urb_priv_t*)urb->data;
 		q = urb->urb_list.next;
 		
 		if (!urb_priv) // avoid crash when URB is corrupted
@@ -1273,19 +1263,11 @@
 		  		urb->status = -ECONNRESET; // mark as asynchronously killed
 
 			dev = urb->dev;	// completion may destroy all...
-			urb_priv = urb->hcpriv;
+			urb_priv = (urb_priv_t *) urb->data;
 			list_del (&urb->urb_list);
 			
 			uhci_urb_dma_sync(s, urb, urb_priv);
-			if (urb->complete) {
-				spin_unlock(&s->urb_list_lock);
-				urb->dev = NULL;
-				urb->complete ((struct urb *) urb);
-				spin_lock(&s->urb_list_lock);
-			}
-
-			if (!(urb->transfer_flags & USB_TIMEOUT_KILLED))
-				urb->status = -ENOENT;  // now the urb is really dead
+			uhci_urb_dma_unmap(s, urb, urb_priv);
 
 			switch (type) {
 			case PIPE_ISOCHRONOUS:
@@ -1294,15 +1276,18 @@
 				break;
 			}
 	
-			uhci_urb_dma_unmap(s, urb, urb_priv);
-
 			usb_dec_dev_use (dev);
-#ifdef DEBUG_SLAB
-			kmem_cache_free (urb_priv_kmem, urb_priv);
-#else
-			kfree (urb_priv);
-#endif
+			urb->dev = NULL;
+			urb->transfer_flags &= ~URB_HCD_OWNED;
+			if (urb->complete) {
+				spin_unlock(&s->urb_list_lock);
+				urb->complete ((struct urb *) urb);
+				spin_lock(&s->urb_list_lock);
+			}
 
+			// FIXME but the driver owns URB now!
+			if (!(urb->transfer_flags & USB_TIMEOUT_KILLED))
+				urb->status = -ENOENT;  // now the urb is really dead
 		}
 	}
 }
@@ -1321,15 +1306,17 @@
 	if (usb_pipedevice (urb->pipe) == s->rh.devnum)
 		return rh_unlink_urb (urb);
 
-	if (!urb->hcpriv)
-		return -EINVAL;
-
 	if (urb->transfer_flags & USB_ASYNC_UNLINK) {
 		int ret;
-       		spin_lock_irqsave (&s->urb_list_lock, flags);
+		spin_lock_irqsave (&s->urb_list_lock, flags);
        		
-		uhci_release_bandwidth(urb);
-		ret = uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB);
+		if (!(urb->transfer_flags & URB_HCD_OWNED))
+			ret = -EINVAL;
+		else {
+			uhci_release_bandwidth(urb);
+			ret = uhci_unlink_urb_async(s, urb,
+				UNLINK_ASYNC_STORE_URB);
+		}
 
 		spin_unlock_irqrestore (&s->urb_list_lock, flags);	
 		return ret;
@@ -1436,7 +1423,7 @@
 _static int uhci_submit_int_urb (urb_t *urb)
 {
 	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
-	urb_priv_t *urb_priv = urb->hcpriv;
+	urb_priv_t *urb_priv = (urb_priv_t *) urb->data;
 	int nint, n;
 	uhci_desc_t *td;
 	int status, destination;
@@ -1496,7 +1483,7 @@
 _static int uhci_submit_iso_urb (urb_t *urb)
 {
 	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
-	urb_priv_t *urb_priv = urb->hcpriv;
+	urb_priv_t *urb_priv = (urb_priv_t *) urb->data;
 #ifdef ISO_SANITY_CHECK
 	int pipe=urb->pipe;
 	int maxsze = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe));
@@ -1664,19 +1651,10 @@
 		}
 	}
 
-#ifdef DEBUG_SLAB
-	urb_priv = kmem_cache_alloc(urb_priv_kmem, SLAB_FLAG);
-#else
-	urb_priv = kmalloc (sizeof (urb_priv_t), KMALLOC_FLAG);
-#endif
-	if (!urb_priv) {
-		usb_dec_dev_use (urb->dev);
-		spin_unlock_irqrestore (&s->urb_list_lock, flags);
-		return -ENOMEM;
-	}
-
+	urb_priv = (urb_priv_t *) urb->data;
 	memset(urb_priv, 0, sizeof(urb_priv_t));
-	urb->hcpriv = urb_priv;
+	urb->transfer_flags |= URB_HCD_OWNED;
+
 	INIT_LIST_HEAD (&urb_priv->desc_list);
 
 	dbg("submit_urb: scheduling %p", urb);
@@ -1696,10 +1674,10 @@
 	if (type == PIPE_BULK) {
 	
 		if (queued_urb) {
-			while (((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb)  // find last queued bulk
-				queued_urb=((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb;
+			while (((urb_priv_t*)queued_urb->data)->next_queued_urb)  // find last queued bulk
+				queued_urb=((urb_priv_t*)queued_urb->data)->next_queued_urb;
 			
-			((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb=urb;
+			((urb_priv_t*)queued_urb->data)->next_queued_urb=urb;
 		}
 		atomic_inc (&s->avoid_bulk);
 		ret = uhci_submit_bulk_urb (urb, queued_urb);
@@ -1755,11 +1733,7 @@
 	if (ret != 0) {
 		uhci_urb_dma_unmap(s, urb, urb_priv);
 		usb_dec_dev_use (urb->dev);
-#ifdef DEBUG_SLAB
-		kmem_cache_free(urb_priv_kmem, urb_priv);
-#else
-		kfree (urb_priv);
-#endif
+		urb->transfer_flags &= ~URB_HCD_OWNED;
 		return ret;
 	}
 
@@ -1783,7 +1757,7 @@
 		urb = list_entry (p2, urb_t, urb_list);
 		type = usb_pipetype (urb->pipe);
 
-		hcpriv = (urb_priv_t*)urb->hcpriv;
+		hcpriv = (urb_priv_t*)urb->data;
 		
 		if ( urb->timeout && time_after(jiffies, hcpriv->started + urb->timeout)) {
 			urb->transfer_flags |= USB_TIMEOUT_KILLED | USB_ASYNC_UNLINK;
@@ -1986,6 +1960,7 @@
 		uhci->rh.urb = urb;
 		uhci->rh.send = 1;
 		uhci->rh.interval = urb->interval;
+		urb->transfer_flags |= URB_HCD_OWNED;
 		rh_init_int_timer (urb);
 
 		return 0;
@@ -2283,7 +2258,7 @@
 		       !usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)));
 
 	while(urb) {
-		urb_priv_t *priv=urb->hcpriv;		
+		urb_priv_t *priv=(urb_priv_t *) urb->data;		
 		uhci_desc_t *qh = list_entry (priv->desc_list.next, uhci_desc_t, desc_list);
 		struct list_head *p = qh->vertical.next;
 		uhci_desc_t *td;
@@ -2310,7 +2285,7 @@
 _static int process_transfer (uhci_t *s, urb_t *urb, int mode)
 {
 	int ret = 0;
-	urb_priv_t *urb_priv = urb->hcpriv;
+	urb_priv_t *urb_priv = (urb_priv_t *) urb->data;
 	struct list_head *qhl = urb_priv->desc_list.next;
 	uhci_desc_t *qh = list_entry (qhl, uhci_desc_t, desc_list);
 	struct list_head *p = qh->vertical.next;
@@ -2394,11 +2369,11 @@
 
 	if (usb_pipetype (urb->pipe) == PIPE_BULK ) {  /* toggle correction for short bulk transfers (nonqueued/queued) */
 
-		urb_priv_t *priv=(urb_priv_t*)urb->hcpriv;
+		urb_priv_t *priv=(urb_priv_t*)urb->data;
 		urb_t *next_queued_urb=priv->next_queued_urb;
 
 		if (next_queued_urb) {
-			urb_priv_t *next_priv=(urb_priv_t*)next_queued_urb->hcpriv;
+			urb_priv_t *next_priv=(urb_priv_t*)next_queued_urb->data;
 			uhci_desc_t *qh = list_entry (next_priv->desc_list.next, uhci_desc_t, desc_list);
 			uhci_desc_t *first_td=list_entry (qh->vertical.next, uhci_desc_t, vertical);
 
@@ -2429,7 +2404,7 @@
 _static int process_interrupt (uhci_t *s, urb_t *urb)
 {
 	int i, ret = -EINPROGRESS;
-	urb_priv_t *urb_priv = urb->hcpriv;
+	urb_priv_t *urb_priv = (urb_priv_t *) urb->data;
 	struct list_head *p = urb_priv->desc_list.next;
 	uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list);
 
@@ -2473,19 +2448,24 @@
 			urb->actual_length = actual_length;
 
 	recycle:
-		uhci_urb_dma_sync(s, urb, urb->hcpriv);
+		uhci_urb_dma_sync(s, urb, (urb_priv_t *) urb->data);
 		if (urb->complete) {
 			//dbg("process_interrupt: calling completion, status %i",status);
 			urb->status = status;
-			((urb_priv_t*)urb->hcpriv)->flags=1; // if unlink_urb is called during completion
+			((urb_priv_t*)urb->data)->flags=1; // if unlink_urb is called during completion
 
 			spin_unlock(&s->urb_list_lock);
+
+			if (urb->status == -ECONNABORTED
+					|| urb->status == ECONNRESET
+					|| urb->status == -ENOENT)
+				urb->transfer_flags &= ~URB_HCD_OWNED;
 			
 			urb->complete ((struct urb *) urb);
 			
 			spin_lock(&s->urb_list_lock);
 
-			((urb_priv_t*)urb->hcpriv)->flags=0;		       			
+			((urb_priv_t*)urb->data)->flags=0;		       			
 		}
 		
 		if ((urb->status != -ECONNABORTED) && (urb->status != ECONNRESET) &&
@@ -2498,7 +2478,7 @@
 				
 				desc->hw.td.info &= cpu_to_le32(~(1 << TD_TOKEN_TOGGLE));
 				if (status==0) {
-					((urb_priv_t*)urb->hcpriv)->started=jiffies;
+					((urb_priv_t*)urb->data)->started=jiffies;
 					desc->hw.td.info |= cpu_to_le32((usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
 									    usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE));
 					usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
@@ -2529,7 +2509,7 @@
 {
 	int i;
 	int ret = 0;
-	urb_priv_t *urb_priv = urb->hcpriv;
+	urb_priv_t *urb_priv = (urb_priv_t *) urb->data;
 	struct list_head *p = urb_priv->desc_list.next, *p_tmp;
 	uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list);
 
@@ -2634,16 +2614,11 @@
 		dbg("dequeued urb: %p", urb);
 		dequeue_urb (s, urb);
 
-		urb_priv = urb->hcpriv;
+		urb_priv = (urb_priv_t *) urb->data;
+		urb->transfer_flags &= ~URB_HCD_OWNED;
 
 		uhci_urb_dma_unmap(s, urb, urb_priv);
 
-#ifdef DEBUG_SLAB
-		kmem_cache_free(urb_priv_kmem, urb_priv);
-#else
-		kfree (urb_priv);
-#endif
-
 		if ((usb_pipetype (urb->pipe) != PIPE_INTERRUPT)) {  // process_interrupt does completion on its own		
 			urb_t *next_urb = urb->next;
 			int is_ring = 0;
@@ -3092,14 +3067,12 @@
 {
 	int retval;
 
-#ifdef DEBUG_SLAB
-	urb_priv_kmem = kmem_cache_create("urb_priv", sizeof(urb_priv_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
-	
-	if(!urb_priv_kmem) {
-		err("kmem_cache_create for urb_priv_t failed (out of memory)");
+	/* compiler _should_ optimize out this test, or rest of the driver */
+	if (sizeof (urb_priv_t) > sizeof ((struct urb *)0)->data) {
+		err ("urb_priv too big for urb->data");
 		return -ENOMEM;
 	}
-#endif	
+
 	info(VERSTR);
 
 #ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
@@ -3108,13 +3081,6 @@
 
 	retval = pci_module_init (&uhci_pci_driver);
 
-#ifdef DEBUG_SLAB
-	if (retval < 0 ) {
-		if (kmem_cache_destroy(urb_priv_kmem))
-			err("urb_priv_kmem remained");
-	}
-#endif
-	
 	info(DRIVER_VERSION ":" DRIVER_DESC);
 
 	return retval;
@@ -3123,11 +3089,6 @@
 static void __exit uhci_hcd_cleanup (void) 
 {      
 	pci_unregister_driver (&uhci_pci_driver);
-	
-#ifdef DEBUG_SLAB
-	if(kmem_cache_destroy(urb_priv_kmem))
-		err("urb_priv_kmem remained");
-#endif
 }
 
 module_init (uhci_hcd_init);
--- drivers/usb-dist/uhci.c	Thu Mar 14 12:45:49 2002
+++ drivers/usb/uhci.c	Thu Mar 14 14:10:40 2002
@@ -85,8 +85,6 @@
 
 #include "uhci-debug.h"
 
-static kmem_cache_t *uhci_up_cachep;	/* urb_priv */
-
 static int rh_submit_urb(struct urb *urb);
 static int rh_unlink_urb(struct urb *urb);
 static int uhci_get_current_frame_number(struct usb_device *dev);
@@ -137,7 +135,7 @@
 static inline void uhci_add_complete(struct urb *urb)
 {
 	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&uhci->complete_list_lock, flags);
@@ -278,7 +276,7 @@
 static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, int breadth)
 {
 	struct list_head *tmp, *head;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->data;
 	struct uhci_td *td, *ptd;
 
 	if (list_empty(&urbp->td_list))
@@ -364,7 +362,7 @@
  */
 static void _uhci_insert_qh(struct uhci *uhci, struct uhci_qh *skelqh, struct urb *urb)
 {
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->data;
 	struct list_head *head, *tmp;
 	struct uhci_qh *lqh;
 
@@ -413,7 +411,7 @@
 
 static void uhci_remove_qh(struct uhci *uhci, struct urb *urb)
 {
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->data;
 	unsigned long flags;
 	struct uhci_qh *qh = urbp->qh, *pqh;
 
@@ -464,7 +462,7 @@
 
 static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle)
 {
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->data;
 	struct list_head *head, *tmp;
 
 	head = &urbp->td_list;
@@ -495,8 +493,8 @@
 	struct uhci_td *lltd;
 	unsigned long flags;
 
-	eurbp = eurb->hcpriv;
-	urbp = urb->hcpriv;
+	eurbp = (struct urb_priv *) eurb->data;
+	urbp = (struct urb_priv *) urb->data;
 
 	spin_lock_irqsave(&uhci->frame_list_lock, flags);
 
@@ -548,7 +546,7 @@
 	unsigned int toggle;
 	unsigned long flags;
 
-	urbp = urb->hcpriv;
+	urbp = (struct urb_priv *) urb->data;
 
 	spin_lock_irqsave(&uhci->frame_list_lock, flags);
 
@@ -617,13 +615,7 @@
 
 static struct urb_priv *uhci_alloc_urb_priv(struct uhci *uhci, struct urb *urb)
 {
-	struct urb_priv *urbp;
-
-	urbp = kmem_cache_alloc(uhci_up_cachep, in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL);
-	if (!urbp) {
-		err("uhci_alloc_urb_priv: couldn't allocate memory for urb_priv\n");
-		return NULL;
-	}
+	struct urb_priv *urbp = (struct urb_priv *) urb->data;
 
 	memset((void *)urbp, 0, sizeof(*urbp));
 
@@ -636,8 +628,6 @@
 	INIT_LIST_HEAD(&urbp->queue_list);
 	INIT_LIST_HEAD(&urbp->complete_list);
 
-	urb->hcpriv = urbp;
-
 	if (urb->dev != uhci->rh.dev) {
 		if (urb->transfer_buffer_length) {
 			urbp->transfer_buffer_dma_handle = pci_map_single(uhci->dev,
@@ -657,6 +647,7 @@
 		}
 	}
 
+	urb->transfer_flags |= URB_HCD_OWNED;
 	return urbp;
 }
 
@@ -665,7 +656,7 @@
  */
 static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td)
 {
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->data;
 
 	td->urb = urb;
 
@@ -694,9 +685,9 @@
 	struct urb_priv *urbp;
 	struct uhci *uhci;
 
-	urbp = (struct urb_priv *)urb->hcpriv;
-	if (!urbp)
+	if (!(urb->transfer_flags & URB_HCD_OWNED))
 		return;
+	urbp = (struct urb_priv *)urb->data;
 
 	if (!urbp->dev || !urbp->dev->bus || !urbp->dev->bus->hcpriv) {
 		warn("uhci_destroy_urb_priv: urb %p belongs to disconnected device or bus?", urb);
@@ -735,15 +726,13 @@
 			PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
 		urbp->transfer_buffer_dma_handle = 0;
 	}
-
-	urb->hcpriv = NULL;
-	kmem_cache_free(uhci_up_cachep, urbp);
+	urb->transfer_flags &= ~URB_HCD_OWNED;
 }
 
 static void uhci_inc_fsbr(struct uhci *uhci, struct urb *urb)
 {
 	unsigned long flags;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->data;
 
 	spin_lock_irqsave(&uhci->frame_list_lock, flags);
 
@@ -759,7 +748,7 @@
 static void uhci_dec_fsbr(struct uhci *uhci, struct urb *urb)
 {
 	unsigned long flags;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->data;
 
 	spin_lock_irqsave(&uhci->frame_list_lock, flags);
 
@@ -809,7 +798,7 @@
  */
 static int uhci_submit_control(struct urb *urb)
 {
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->data;
 	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
 	struct uhci_td *td;
 	struct uhci_qh *qh;
@@ -918,7 +907,7 @@
 static int uhci_result_control(struct urb *urb)
 {
 	struct list_head *tmp, *head;
-	struct urb_priv *urbp = urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *) urb->data;
 	struct uhci_td *td;
 	unsigned int status;
 	int ret = 0;
@@ -1035,7 +1024,7 @@
 static int usb_control_retrigger_status(struct urb *urb)
 {
 	struct list_head *tmp, *head;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->data;
 	struct uhci *uhci = urb->dev->bus->hcpriv;
 
 	urbp->short_control_packet = 1;
@@ -1084,7 +1073,7 @@
 	struct uhci_td *td;
 	unsigned long destination, status;
 	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->data;
 
 	if (urb->transfer_buffer_length > usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)))
 		return -EINVAL;
@@ -1114,7 +1103,7 @@
 static int uhci_result_interrupt(struct urb *urb)
 {
 	struct list_head *tmp, *head;
-	struct urb_priv *urbp = urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *) urb->data;
 	struct uhci_td *td;
 	unsigned int status;
 	int ret = 0;
@@ -1186,7 +1175,7 @@
 static void uhci_reset_interrupt(struct urb *urb)
 {
 	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->data;
 	struct uhci_td *td;
 	unsigned long flags;
 
@@ -1220,7 +1209,7 @@
 	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
 	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
 	int len = urb->transfer_buffer_length;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->data;
 	dma_addr_t data = urbp->transfer_buffer_dma_handle;
 
 	if (len < 0)
@@ -1378,7 +1367,7 @@
 	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
 	int i, ret, framenum;
 	int status, destination;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->data;
 
 	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
 	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
@@ -1412,7 +1401,7 @@
 static int uhci_result_isochronous(struct urb *urb)
 {
 	struct list_head *tmp, *head;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->data;
 	int status;
 	int i, ret = 0;
 
@@ -1608,7 +1597,7 @@
 
 	spin_lock_irqsave(&urb->lock, flags);
 
-	urbp = (struct urb_priv *)urb->hcpriv;
+	urbp = (struct urb_priv *)urb->data;
 
 	if (urb->status != -EINPROGRESS) {
 		info("uhci_transfer_result: called for URB %p not in flight?", urb);
@@ -1680,7 +1669,7 @@
 static void uhci_unlink_generic(struct uhci *uhci, struct urb *urb)
 {
 	struct list_head *head, *tmp;
-	struct urb_priv *urbp = urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *) urb->data;
 	int prevactive = 1;
 
 	/* We can get called when urbp allocation fails, so check */
@@ -1733,7 +1722,7 @@
 {
 	struct uhci *uhci;
 	unsigned long flags;
-	struct urb_priv *urbp = urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *) urb->data;
 
 	if (!urb)
 		return -EINVAL;
@@ -1820,7 +1809,7 @@
 
 static int uhci_fsbr_timeout(struct uhci *uhci, struct urb *urb)
 {
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->data;
 	struct list_head *head, *tmp;
 
 	uhci_dec_fsbr(uhci, urb);
@@ -1945,7 +1934,7 @@
 static int rh_send_irq(struct urb *urb)
 {
 	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->data;
 	unsigned int io_addr = uhci->io_addr;
 	unsigned long flags;
 	int i, len = 1;
@@ -1992,7 +1981,7 @@
 	tmp = head->next;
 	while (tmp != head) {
 		struct urb *u = list_entry(tmp, struct urb, urb_list);
-		struct urb_priv *urbp = (struct urb_priv *)u->hcpriv;
+		struct urb_priv *urbp = (struct urb_priv *)u->data;
 
 		tmp = tmp->next;
 
@@ -2289,7 +2278,7 @@
 
 	spin_lock_irqsave(&urb->lock, flags);
 
-	urbp = (struct urb_priv *)urb->hcpriv;
+	urbp = (struct urb_priv *)urb->data;
 	if (!urbp || !urb->dev) {
 		spin_unlock_irqrestore(&urb->lock, flags);
 		return;
@@ -2402,7 +2391,7 @@
 	tmp = head->next;
 	while (tmp != head) {
 		struct urb *urb = list_entry(tmp, struct urb, urb_list);
-		struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+		struct urb_priv *urbp = (struct urb_priv *)urb->data;
 
 		tmp = tmp->next;
 
@@ -3078,6 +3067,12 @@
 {
 	int retval = -ENOMEM;
 
+	/* compiler _should_ optimize out this test, or rest of the driver */
+	if (sizeof (struct urb_priv) > sizeof ((struct urb *)0)->data) {
+		err ("urb_priv too big for urb->data");
+		goto errbuf_failed;
+	}
+
 	info(DRIVER_DESC " " DRIVER_VERSION);
 
 	if (debug) {
@@ -3092,11 +3087,6 @@
 		goto proc_failed;
 #endif
 
-	uhci_up_cachep = kmem_cache_create("uhci_urb_priv",
-		sizeof(struct urb_priv), 0, 0, NULL, NULL);
-	if (!uhci_up_cachep)
-		goto up_failed;
-
 	retval = pci_module_init(&uhci_pci_driver);
 	if (retval)
 		goto init_failed;
@@ -3104,10 +3094,6 @@
 	return 0;
 
 init_failed:
-	if (kmem_cache_destroy(uhci_up_cachep))
-		printk(KERN_INFO "uhci: not all urb_priv's were freed\n");
-
-up_failed:
 
 #ifdef CONFIG_PROC_FS
 	remove_proc_entry("uhci", 0);
@@ -3126,9 +3112,6 @@
 {
 	pci_unregister_driver(&uhci_pci_driver);
 	
-	if (kmem_cache_destroy(uhci_up_cachep))
-		printk(KERN_INFO "uhci: not all urb_priv's were freed\n");
-
 #ifdef CONFIG_PROC_FS
 	remove_proc_entry("uhci", 0);
 #endif
--- drivers/usb-dist/hcd.c	Thu Mar 14 12:45:49 2002
+++ drivers/usb/hcd.c	Thu Mar 14 12:49:14 2002
@@ -408,7 +408,6 @@
 		return -EINVAL;
 	}
 
-	urb->hcpriv = hcd;	/* nonzero to indicate it's queued */
 	init_timer (&hcd->rh_timer);
 	hcd->rh_timer.function = rh_report_status;
 	hcd->rh_timer.data = (unsigned long) urb;
@@ -462,7 +461,6 @@
 			spin_unlock_irqrestore (&urb->lock, flags);
 	} else {
 		/* this urb's been unlinked */
-		urb->hcpriv = 0;
 		spin_unlock_irqrestore (&urb->lock, flags);
 
 		usb_hcd_giveback_urb (hcd, urb);
@@ -925,7 +923,7 @@
 	int			pipe;
 	int			mem_flags;
 
-	if (!urb || urb->hcpriv || !urb->complete)
+	if (!urb || !urb->complete)
 		return -EINVAL;
 
 	urb->status = -EINPROGRESS;
@@ -1008,6 +1006,7 @@
 	if (HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_QUIESCING) {
 		usb_inc_dev_use (urb->dev);
 		list_add (&urb->urb_list, &dev->urb_list);
+		urb->transfer_flags |= URB_HCD_OWNED;
 		status = 0;
 	} else {
 		INIT_LIST_HEAD (&urb->urb_list);
@@ -1092,7 +1091,7 @@
 	 * which changes it while returning the urb.
 	 */
 	spin_lock_irqsave (&urb->lock, flags);
-	if (!urb->hcpriv
+	if (!(urb->transfer_flags & URB_HCD_OWNED)
 			|| urb->status != -EINPROGRESS
 			|| urb->transfer_flags & USB_TIMEOUT_KILLED) {
 		retval = -EINVAL;
@@ -1237,7 +1236,7 @@
  *
  * This hands the URB from HCD to its USB device driver, using its
  * completion function.  The HCD has freed all per-urb resources
- * (and is done using urb->hcpriv).  It also released all HCD locks;
+ * (and is done using urb->data).  It also released all HCD locks;
  * the device driver won't cause deadlocks if it resubmits this URB,
  * and won't confuse things by modifying and resubmitting this one.
  * Bandwidth and other resources will be deallocated.
@@ -1302,6 +1301,7 @@
 
 	/* pass ownership to the completion handler */
 	usb_dec_dev_use (dev);
+	urb->transfer_flags &= ~URB_HCD_OWNED;
 	urb->complete (urb);
 }
 EXPORT_SYMBOL (usb_hcd_giveback_urb);
--- drivers/usb-dist/hcd/ehci.h	Thu Mar 14 12:45:49 2002
+++ drivers/usb/hcd/ehci.h	Thu Mar 14 16:02:55 2002
@@ -255,6 +255,11 @@
 	void			*ptr;
 };
 
+/* urb->data holds a pointer to a QH, ITD, or SITD */
+#define urb_get_shadow(urb)	((union ehci_shadow *)(urb)->data)
+#define urb_get_qh(urb)		(urb_get_shadow(urb)->qh)
+#define urb_set_qh(urb,ptr)	(urb_get_qh(urb)=(ptr))
+
 /*-------------------------------------------------------------------------*/
 
 /*
--- drivers/usb-dist/hcd/ehci-hcd.c	Thu Mar 14 12:45:49 2002
+++ drivers/usb/hcd/ehci-hcd.c	Thu Mar 14 12:48:57 2002
@@ -490,7 +490,7 @@
  * urb + dev is in hcd_dev.urb_list
  * we're queueing TDs onto software and hardware lists
  *
- * hcd-specific init for hcpriv hasn't been done yet
+ * hcd-specific init for urb->data hasn't been done yet
  *
  * NOTE:  EHCI queues control and bulk requests transparently, like OHCI.
  */
@@ -542,7 +542,7 @@
 static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
-	struct ehci_qh		*qh = (struct ehci_qh *) urb->hcpriv;
+	struct ehci_qh		*qh = urb_get_qh (urb);
 	unsigned long		flags;
 
 	dbg ("%s urb_dequeue %p qh state %d",
--- drivers/usb-dist/hcd/ehci-q.c	Thu Mar 14 12:45:49 2002
+++ drivers/usb/hcd/ehci-q.c	Thu Mar 14 14:38:12 2002
@@ -186,6 +186,8 @@
 	dma_addr_t		addr,
 	struct urb		*urb
 ) {
+	struct ehci_qh		*qh = urb_get_qh (urb);
+
 	if (urb->transfer_buffer_length)
 		pci_unmap_single (ehci->hcd.pdev,
 			addr,
@@ -193,9 +195,9 @@
 			usb_pipein (urb->pipe)
 			    ? PCI_DMA_FROMDEVICE
 			    : PCI_DMA_TODEVICE);
-	if (likely (urb->hcpriv != 0)) {
-		qh_unput (ehci, (struct ehci_qh *) urb->hcpriv);
-		urb->hcpriv = 0;
+	if (likely (qh != 0)) {
+		qh_unput (ehci, qh);
+		urb_set_qh (urb, 0);	/* paranoia */
 	}
 
 	if (likely (urb->status == -EINPROGRESS)) {
@@ -246,7 +248,7 @@
 		u32		token = 0;
 
 		/* qh is non-null iff these qtds were queued to the HC */
-		qh = (struct ehci_qh *) urb->hcpriv;
+		qh = urb_get_qh (urb);
 
 		/* clean up any state from previous QTD ...*/
 		if (last) {
@@ -817,7 +819,7 @@
 	 * the HC and TT handle it when the TT has a buffer ready.
 	 */
 	if (likely (qh != 0)) {
-		urb->hcpriv = qh_put (qh);
+		urb_set_qh (urb, qh_put (qh));
 		if (likely (qh->qh_state == QH_STATE_IDLE))
 			qh_link_async (ehci, qh_put (qh));
 	}
--- drivers/usb-dist/hcd/ehci-sched.c	Thu Mar 14 12:45:49 2002
+++ drivers/usb/hcd/ehci-sched.c	Thu Mar 14 12:48:57 2002
@@ -338,7 +338,7 @@
 		qh->hw_info2 |= cpu_to_le32 (mult << 30);
 		qh->usecs = usecs;
 
-		urb->hcpriv = qh_put (qh);
+		urb_set_qh (urb, qh_put (qh));
 		status = -ENOSPC;
 
 		/* pick a set of schedule slots, link the QH into them */
