--- 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;