--- drivers/usb/usb-uhci-orig.h	Mon May 15 12:05:15 2000
+++ drivers/usb/usb-uhci.h	Thu Mar 22 21:39:06 2001
@@ -212,7 +212,10 @@
 	struct list_head urb_unlinked;	// list of all unlinked  urbs
 	long timeout_check;
 	int timeout_urbs;
+#ifdef	CONFIG_PCI
 	struct pci_dev *uhci_pci;
+	struct pci_pool *desc_pool;
+#endif
 } uhci_t, *puhci_t;
 
 
--- drivers/usb/usb-uhci-orig.c	Wed Mar 14 12:40:36 2001
+++ drivers/usb/usb-uhci.c	Fri Mar 23 10:12:27 2001
@@ -7,7 +7,7 @@
  *               Roman Weissgaerber, weissg@vienna.at (virt root hub) (studio porter)
  * (c) 2000      Yggdrasil Computing, Inc. (port of new PCI interface support
  *               from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
- * (C) 2000      David Brownell, david-b@pacbell.net (usb-ohci.c)
+ * (C) 2000-2001 David Brownell, david-b@pacbell.net (pci from usb-ohci.c, pci_pool)
  *          
  * HW-initalization based on material of
  *
@@ -44,7 +44,7 @@
 //#define ISO_SANITY_CHECK
 
 /* This enables debug printks */
-#define DEBUG
+#undef DEBUG
 
 /* This enables all symbols to be exported, to ease debugging oopses */
 //#define DEBUG_SYMBOLS
@@ -58,10 +58,6 @@
 #include "usb-uhci.h"
 #include "usb-uhci-debug.h"
 
-#undef DEBUG
-#undef dbg
-#define dbg(format, arg...) do {} while (0)
-#define DEBUG_SYMBOLS
 #ifdef DEBUG_SYMBOLS
 	#define _static
 	#ifndef EXPORT_SYMTAB
@@ -75,7 +71,6 @@
 #define async_dbg dbg //err
 
 #ifdef DEBUG_SLAB
-	static kmem_cache_t *uhci_desc_kmem;
 	static kmem_cache_t *urb_priv_kmem;
 #endif
 
@@ -226,10 +221,11 @@
 
 }
 /*-------------------------------------------------------------------*/
-_static int alloc_td (uhci_desc_t ** new, int flags)
+_static int alloc_td (uhci_t *s, uhci_desc_t ** new, int flags)
 {
-#ifdef DEBUG_SLAB
-	*new= kmem_cache_alloc(uhci_desc_kmem, SLAB_FLAG);
+#ifdef CONFIG_PCI
+	dma_addr_t	dma;
+	*new= pci_pool_alloc (s->desc_pool, SLAB_FLAG, &dma);
 #else
 	*new = (uhci_desc_t *) kmalloc (sizeof (uhci_desc_t), KMALLOC_FLAG);
 #endif
@@ -340,10 +336,10 @@
 }
 
 /*-------------------------------------------------------------------*/
-_static int delete_desc (uhci_desc_t *element)
+_static int delete_desc (uhci_t *s, uhci_desc_t *element)
 {
-#ifdef DEBUG_SLAB
-	kmem_cache_free(uhci_desc_kmem, element);
+#ifdef CONFIG_PCI
+	pci_pool_free(s->desc_pool, element, virt_to_bus (element));
 #else
 	kfree (element);
 #endif
@@ -351,10 +347,11 @@
 }
 /*-------------------------------------------------------------------*/
 // Allocates qh element
-_static int alloc_qh (uhci_desc_t ** new)
+_static int alloc_qh (uhci_t *s, uhci_desc_t ** new)
 {
-#ifdef DEBUG_SLAB
-	*new= kmem_cache_alloc(uhci_desc_kmem, SLAB_FLAG);
+#ifdef CONFIG_PCI
+	dma_addr_t	dma;
+	*new= pci_pool_alloc (s->desc_pool, SLAB_FLAG, &dma);
 #else
 	*new = (uhci_desc_t *) kmalloc (sizeof (uhci_desc_t), KMALLOC_FLAG);
 #endif	
@@ -439,15 +436,15 @@
 		td = list_entry (p, uhci_desc_t, vertical);
 		dbg("unlink td @ %p",td);
 		unlink_td (s, td, 0); // no physical unlink
-		delete_desc (td);
+		delete_desc (s, td);
 	}
 
-	delete_desc (qh);
+	delete_desc (s, qh);
 	
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static void clean_td_chain (uhci_desc_t *td)
+_static void clean_td_chain (uhci_t *s, uhci_desc_t *td)
 {
 	struct list_head *p;
 	uhci_desc_t *td1;
@@ -457,10 +454,10 @@
 	
 	while ((p = td->horizontal.next) != &td->horizontal) {
 		td1 = list_entry (p, uhci_desc_t, horizontal);
-		delete_desc (td1);
+		delete_desc (s, td1);
 	}
 	
-	delete_desc (td);
+	delete_desc (s, td);
 }
 
 /*-------------------------------------------------------------------*/
@@ -485,18 +482,18 @@
 	if (s->td32ms) {
 	
 		unlink_td(s,s->td32ms,1);
-		delete_desc(s->td32ms);
+		delete_desc(s, s->td32ms);
 	}
 
 	for (n = 0; n < 8; n++) {
 		td = s->int_chain[n];
-		clean_td_chain (td);
+		clean_td_chain (s, td);
 	}
 
 	if (s->iso_td) {
 		for (n = 0; n < 1024; n++) {
 			td = s->iso_td[n];
-			clean_td_chain (td);
+			clean_td_chain (s, td);
 		}
 		kfree (s->iso_td);
 	}
@@ -519,13 +516,13 @@
 	}
 	else {
 		if (s->ls_control_chain)
-			delete_desc (s->ls_control_chain);
+			delete_desc (s, s->ls_control_chain);
 		if (s->control_chain)
-			 delete_desc(s->control_chain);
+			 delete_desc(s, s->control_chain);
 		if (s->bulk_chain)
-			delete_desc (s->bulk_chain);
+			delete_desc (s, s->bulk_chain);
 		if (s->chain_end)
-			delete_desc (s->chain_end);
+			delete_desc (s, s->chain_end);
 	}
 	dbg("cleanup_skel finished");	
 }
@@ -560,7 +557,7 @@
 	dbg("allocating iso descs");
 	for (n = 0; n < 1024; n++) {
 	 	// allocate skeleton iso/irq-tds
-		ret = alloc_td (&td, 0);
+		ret = alloc_td (s, &td, 0);
 		if (ret)
 			goto init_skel_cleanup;
 		s->iso_td[n] = td;
@@ -568,14 +565,14 @@
 	}
 
 	dbg("allocating qh: chain_end");
-	ret = alloc_qh (&qh);
+	ret = alloc_qh (s, &qh);
 	
 	if (ret)
 		goto init_skel_cleanup;
 				
 	s->chain_end = qh;
 
-	ret = alloc_td (&td, 0);
+	ret = alloc_td (s, &td, 0);
 
 	if (ret)
 		goto init_skel_cleanup;
@@ -586,7 +583,7 @@
 	s->td1ms=td;
 
 	dbg("allocating qh: bulk_chain");
-	ret = alloc_qh (&qh);
+	ret = alloc_qh (s, &qh);
 	if (ret)
 		goto init_skel_cleanup;
 	
@@ -594,7 +591,7 @@
 	s->bulk_chain = qh;
 
 	dbg("allocating qh: control_chain");
-	ret = alloc_qh (&qh);
+	ret = alloc_qh (s, &qh);
 	if (ret)
 		goto init_skel_cleanup;
 	
@@ -607,7 +604,7 @@
 #endif
 
 	dbg("allocating qh: ls_control_chain");
-	ret = alloc_qh (&qh);
+	ret = alloc_qh (s, &qh);
 	if (ret)
 		goto init_skel_cleanup;
 	
@@ -622,7 +619,7 @@
 	for (n = 0; n < 8; n++) {
 		uhci_desc_t *td;
 
-		alloc_td (&td, 0);
+		alloc_td (s, &td, 0);
 		if (!td)
 			goto init_skel_cleanup;
 		s->int_chain[n] = td;
@@ -639,7 +636,7 @@
 	for (n = 0; n < 1024; n++) {
 		// link all iso-tds to the interrupt chains
 		int m, o;
-		dbg("framelist[%i]=%x",n,s->framelist[n]);
+		// dbg("framelist[%i]=%x",n,s->framelist[n]);
 		if ((n&127)==127) 
 			((uhci_desc_t*) s->iso_td[n])->hw.td.link = virt_to_bus(s->int_chain[0]);
 		else 
@@ -648,7 +645,7 @@
 					((uhci_desc_t*) s->iso_td[n])->hw.td.link = virt_to_bus (s->int_chain[o]);
 	}
 
-	ret = alloc_td (&td, 0);
+	ret = alloc_td (s, &td, 0);
 
 	if (ret)
 		goto init_skel_cleanup;
@@ -689,12 +686,12 @@
 	}
 
 	dbg("uhci_submit_control start");
-	alloc_qh (&qh);		// alloc qh for this request
+	alloc_qh (s, &qh);		// alloc qh for this request
 
 	if (!qh)
 		return -ENOMEM;
 
-	alloc_td (&td, UHCI_PTR_DEPTH * depth_first);		// get td for setup stage
+	alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first);		// get td for setup stage
 
 	if (!td) {
 		delete_qh (s, qh);
@@ -732,7 +729,7 @@
 	while (len > 0) {
 		int pktsze = len;
 
-		alloc_td (&td, UHCI_PTR_DEPTH * depth_first);
+		alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first);
 		if (!td) {
 			delete_qh (s, qh);
 			return -ENOMEM;
@@ -764,7 +761,7 @@
 
 	destination |= 1 << TD_TOKEN_TOGGLE;	/* End in Data1 */
 
-	alloc_td (&td, UHCI_PTR_DEPTH);
+	alloc_td (s, &td, UHCI_PTR_DEPTH);
 	
 	if (!td) {
 		delete_qh (s, qh);
@@ -829,15 +826,15 @@
 	upriv = (urb_priv_t*)urb->hcpriv;
 
 	if (!bulk_urb) {
-		alloc_qh (&qh);		// get qh for this request
+		alloc_qh (s, &qh);		// get qh for this request
 		
 		if (!qh)
 			return -ENOMEM;
 
 		if (urb->transfer_flags & USB_QUEUE_BULK) {
-			alloc_qh(&nqh); // placeholder for clean unlink
+			alloc_qh(s, &nqh); // placeholder for clean unlink
 			if (!nqh) {
-				delete_desc (qh);
+				delete_desc (s, qh);
 				return -ENOMEM;
 			}
 			upriv->next_qh = nqh;
@@ -853,12 +850,12 @@
 	}
 
 	if (urb->transfer_flags & USB_QUEUE_BULK) {
-		alloc_qh (&bqh); // "bottom" QH,
+		alloc_qh (s, &bqh); // "bottom" QH,
 		
 		if (!bqh) {
 			if (!bulk_urb) { 
-				delete_desc(qh);
-				delete_desc(nqh);
+				delete_desc(s, qh);
+				delete_desc(s, nqh);
 			}
 			return -ENOMEM;
 		}
@@ -882,7 +879,7 @@
 	do {					// TBD: Really allow zero-length packets?
 		int pktsze = len;
 
-		alloc_td (&td, UHCI_PTR_DEPTH * depth_first);
+		alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first);
 
 		if (!td) {
 			delete_qh (s, qh);
@@ -962,9 +959,9 @@
 	uhci_desc_t *td;
 
 	while ((p = urb_priv->desc_list.next) != &urb_priv->desc_list) {
-				td = list_entry (p, uhci_desc_t, desc_list);
-				list_del (p);
-				delete_desc (td);
+		td = list_entry (p, uhci_desc_t, desc_list);
+		list_del (p);
+		delete_desc (s, td);
 	}
 }
 /*-------------------------------------------------------------------*/
@@ -1449,7 +1446,7 @@
 	if (urb->transfer_buffer_length > usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)))
 		return -EINVAL;
 
-	ret = alloc_td (&td, UHCI_PTR_DEPTH);
+	ret = alloc_td (s, &td, UHCI_PTR_DEPTH);
 
 	if (ret)
 		return -ENOMEM;
@@ -1521,14 +1518,14 @@
 		}
 		else
 #endif
-		ret = alloc_td (&td, UHCI_PTR_DEPTH);
+		ret = alloc_td (s, &td, UHCI_PTR_DEPTH);
 
 		if (ret) {
 			int i;	// Cleanup allocated TDs
 
 			for (i = 0; i < n; n++)
 				if (tdm[i])
-					 delete_desc(tdm[i]);
+					 delete_desc(s, tdm[i]);
 			kfree (tdm);
 			goto err;
 		}
@@ -2511,7 +2508,7 @@
 
 		list_del (p);
 		p = p->next;
-		delete_desc (desc);
+		delete_desc (s, desc);
 	}
 	
 	dbg("process_iso: exit %i (%d), actual_len %i", i, ret,urb->actual_length);
@@ -2566,6 +2563,7 @@
 #else
 		kfree (urb->hcpriv);
 #endif
+		urb->hcpriv = 0;
 
 		if ((usb_pipetype (urb->pipe) != PIPE_INTERRUPT)) {  // process_interrupt does completion on its own		
 			urb_t *next_urb = urb->next;
@@ -2625,19 +2623,22 @@
 
 			// Completion
 			if (urb->complete) {
+				int was_unlinked = (urb->status == -ENOENT);
 				urb->dev = NULL;
 				spin_unlock(&s->urb_list_lock);
 				urb->complete ((struct urb *) urb);
 				// Re-submit the URB if ring-linked
-				if (is_ring && (urb->status != -ENOENT) && !contains_killed) {
+				if (is_ring && !was_unlinked && !contains_killed) {
 					urb->dev=usb_dev;
 					uhci_submit_urb (urb);
-				}
+				} else
+					urb = 0;
 				spin_lock(&s->urb_list_lock);
 			}
 			
 			usb_dec_dev_use (usb_dev);
-			spin_unlock(&urb->lock);		
+			if (urb)
+				spin_unlock(&urb->lock);		
 		}
 	}
 
@@ -2791,6 +2792,11 @@
 	free_irq (s->irq, s);
 	usb_free_bus (s->bus);
 	cleanup_skel (s);
+
+#ifdef CONFIG_PCI
+	pci_pool_destroy(s->desc_pool);
+#endif
+
 	kfree (s);
 }
 
@@ -2840,6 +2846,7 @@
 #endif
 	printk(KERN_INFO __FILE__ ": USB UHCI at I/O 0x%x, IRQ %s\n",
 		io_addr, bufp);
+	printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name);
 
 	s = kmalloc (sizeof (uhci_t), GFP_KERNEL);
 	if (!s)
@@ -2860,8 +2867,33 @@
 	s->timeout_check = 0;
 	s->uhci_pci=dev;
 
+#ifdef CONFIG_PCI
+
+	s->desc_pool = pci_pool_create("uhci_desc", dev,
+		sizeof(uhci_desc_t),
+		16 /* byte alignment */,
+		0 /* no page-crossing issues */,
+		SLAB_KERNEL);
+	
+	if(!s->desc_pool) {
+		err("pci_pool_create for uhci_desc failed (out of memory)");
+		goto pci1;
+	}
+
+#endif	
+	info(VERSTR);
+
+#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
+	info("High bandwidth mode enabled");	
+#endif
+
 	bus = usb_alloc_bus (&uhci_device_operations);
 	if (!bus) {
+exit3:
+#ifdef CONFIG_PCI
+		pci_pool_destroy(s->desc_pool);
+pci1:
+#endif
 		kfree (s);
 		return -1;
 	}
@@ -2896,9 +2928,9 @@
 	s->rh.numports = s->maxports;
 	s->loop_usage=0;
 	if (init_skel (s)) {
+exit4:
 		usb_free_bus (bus);
-		kfree(s);
-		return -1;
+		goto exit3;
 	}
 
 	request_region (s->io_addr, io_size, MODNAME);
@@ -2913,8 +2945,7 @@
 		reset_hc (s);
 		release_region (s->io_addr, s->io_size);
 		cleanup_skel(s);
-		kfree(s);
-		return -1;
+		goto exit4;
 	}
 
 	/* Enable PIRQ */
@@ -2924,7 +2955,7 @@
 
 	if(uhci_start_usb (s) < 0) {
 		uhci_pci_remove(dev);
-		return -1;
+		return -ENODEV;
 	}
 
 	//chain new uhci device into global list
@@ -3001,53 +3032,27 @@
 {
 	int retval;
 
-#ifdef DEBUG_SLAB
-
-	uhci_desc_kmem = kmem_cache_create("uhci_desc", sizeof(uhci_desc_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
-	
-	if(!uhci_desc_kmem) {
-		err("kmem_cache_create for uhci_desc failed (out of memory)");
-		return -ENOMEM;
-	}
-
-	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)");
-		kmem_cache_destroy(uhci_desc_kmem);
+#ifdef	DEBUG_SLAB
+	urb_priv_kmem = kmem_cache_create ("uhci_urb_priv",
+		sizeof (urb_priv_t), 0,
+		SLAB_HWCACHE_ALIGN, NULL, NULL);
+	if (!urb_priv_kmem)
 		return -ENOMEM;
-	}
-#endif	
-	info(VERSTR);
-
-#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
-	info("High bandwidth mode enabled");	
 #endif
-
 	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");
-		if (kmem_cache_destroy(uhci_desc_kmem))
-			err("uhci_desc_kmem remained");
-	}
+#ifdef	DEBUG_SLAB
+	if (retval)
+		kmem_cache_destroy (urb_priv_kmem);
 #endif
-	
 	return retval;
 }
 
 static void __exit uhci_hcd_cleanup (void) 
 {      
 	pci_unregister_driver (&uhci_pci_driver);
-	
-#ifdef DEBUG_SLAB
-	if(kmem_cache_destroy(uhci_desc_kmem))
-		err("uhci_desc_kmem remained");
-
-	if(kmem_cache_destroy(urb_priv_kmem))
-		err("urb_priv_kmem remained");
+#ifdef	DEBUG_SLAB
+	if (urb_priv_kmem && kmem_cache_destroy (urb_priv_kmem))
+		err ("urb_priv cache not empty");
 #endif
 }
 
--- drivers/usb/usb-uhci-debug-orig.h	Sat Jul  8 19:38:16 2000
+++ drivers/usb/usb-uhci-debug.h	Thu Mar 22 21:39:06 2001
@@ -23,7 +23,7 @@
 }
 #endif
 
-static void uhci_show_td (puhci_desc_t td)
+static void __attribute__((__unused__)) uhci_show_td (puhci_desc_t td)
 {
 	char *spid;
 	
