* PATCHES: usb with CONFIG_SLAB_DEBUG (using new pci_pool API)
@ 2001-03-23 19:57 David Brownell
0 siblings, 0 replies; only message in thread
From: David Brownell @ 2001-03-23 19:57 UTC (permalink / raw)
To: linux-usb-devel, lkml
[-- Attachment #1: Type: text/plain, Size: 1267 bytes --]
Hi,
Here are updated patches getting usb-ohci and usb-uhci to
behave on an ac20 kernel with slab debugging enabled.
It uses the pci_pool API, discussed earlier.
- pcipool-0323.patch ... adds pci_pool apis to <linux/pci.h>;
bugfixes vs what I sent to linux-usb-devel yesterday
- ohci-0323.patch ... basically what I sent yesterday
- uhci-0323.patch ... bugfixes vs what I sent yesterday;
adds a fix for an unrelated oops (referencing an urb
after the completion function freed it)
I don't know about any problems with these, but that doesn't
mean they're not lurking. Converting usb-ohci to use the rest
of the pci dma mapping APIs is being done separately, and
I think Johannes has an update pending to "uhci.c". The EHCI
host controller driver (latest) is also using "pci_pool".
Does anyone want particularly want to see further discussion
about the pci_pool API? This version dropped the explicit
address mapping primitive that was contentious last time,
and nothing else appeared to be troublesome. (Shouldn't be!)
This version does add another pci_pool_create() parameter,
as needed to handle a 4KB-crossing restriction for ehci. That
verges on too many arguments, any more and I'd want them
wrapped into a (readonly) structure.
- Dave
[-- Attachment #2: pcipool-0323.patch --]
[-- Type: application/octet-stream, Size: 10816 bytes --]
--- include/linux/pci-orig.h Wed Mar 14 12:40:44 2001
+++ include/linux/pci.h Thu Mar 22 14:06:46 2001
@@ -553,6 +553,14 @@
struct pci_driver *pci_dev_driver(const struct pci_dev *);
const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev);
+/* kmem_cache style wrapper around pci_alloc_consistent() */
+struct pci_pool *pci_pool_create (const char *name, struct pci_dev *dev,
+ size_t size, size_t align, size_t allocation, int flags);
+void pci_pool_destroy (struct pci_pool *pool);
+
+void *pci_pool_alloc (struct pci_pool *pool, int flags, dma_addr_t *handle);
+void pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t addr);
+
#endif /* CONFIG_PCI */
/* Include architecture-dependent settings and functions */
--- drivers/pci/pci-orig.c Wed Mar 14 12:40:27 2001
+++ drivers/pci/pci.c Fri Mar 23 10:12:46 2001
@@ -1339,6 +1339,344 @@
}
#endif
+/*
+ * Pool allocator ... useful for many drivers. This wraps the core
+ * pci_alloc_consistent allocator, so small blocks can easily be used
+ * by drivers for bus mastering controllers. This should probably be
+ * sharing the guts of the slab allocator.
+ */
+
+struct pci_pool { /* the pool */
+ struct list_head page_list;
+ spinlock_t lock;
+ size_t blocks_per_page;
+ size_t size;
+ int flags;
+ struct pci_dev *dev;
+ size_t allocation;
+ char name [32];
+ wait_queue_head_t waitq;
+};
+
+struct pci_page { /* cacheable header for 'allocation' bytes */
+ struct list_head page_list;
+ void *vaddr;
+ dma_addr_t dma;
+ unsigned long bitmap [0];
+};
+
+#define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000)
+#define POOL_POISON_BYTE 0x97
+
+// #define CONFIG_PCIPOOL_DEBUG
+
+
+/**
+ * pci_pool_create - Creates a pool of pci consistent memory blocks, for dma.
+ * @name: name of pool, for diagnostics
+ * @pdev: pci device that will be doing the DMA
+ * @size: size of the blocks in this pool.
+ * @align: alignment requirement for blocks; must be a power of two
+ * @allocation: returned blocks won't cross this boundary (or zero)
+ * @flags: SLAB_* (or GFP_*) flags (not all are supported).
+ *
+ * Returns a pci allocation pool with the requested characteristics, or
+ * null if one can't be created. Given one of these pools, pci_pool_alloc()
+ * may be used to allocate memory. Such memory will all have "consistent"
+ * DMA mappings, accessible by the device and its driver without using
+ * cache flushing primitives. The actual size of blocks allocated may be
+ * larger than requested because of alignment.
+ *
+ * If allocation is nonzero, objects returned from pci_pool_alloc() won't
+ * cross that size boundary. This may be useful for devices which have
+ * addressing restrictions on individual DMA transfers, such as not crossing
+ * boundaries of 4KBytes.
+ */
+struct pci_pool *
+pci_pool_create (const char *name, struct pci_dev *pdev,
+ size_t size, size_t align, size_t allocation, int flags)
+{
+ struct pci_pool *retval;
+
+ if (size == 0)
+ return 0;
+ else if (size < align)
+ size = align;
+ else if ((size % align) != 0) {
+ size += align + 1;
+ size &= ~(align - 1);
+ }
+
+ if (allocation == 0) {
+ if (PAGE_SIZE < size)
+ allocation = size;
+ else
+ allocation = PAGE_SIZE;
+ // FIXME: round up for less fragmentation
+ } else if (allocation < size)
+ return 0;
+
+ if (!(retval = kmalloc (sizeof *retval, flags)))
+ return retval;
+
+#ifdef CONFIG_PCIPOOL_DEBUG
+ flags |= SLAB_POISON;
+#endif
+
+ strncpy (retval->name, name, sizeof retval->name);
+ retval->name [sizeof retval->name - 1] = 0;
+
+ retval->dev = pdev;
+ INIT_LIST_HEAD (&retval->page_list);
+ spin_lock_init (&retval->lock);
+ retval->size = size;
+ retval->flags = flags;
+ retval->allocation = allocation;
+ retval->blocks_per_page = allocation / size;
+ init_waitqueue_head (&retval->waitq);
+
+#ifdef CONFIG_PCIPOOL_DEBUG
+ printk (KERN_DEBUG "pcipool create %s/%s size %d, %d/page (%d alloc)\n",
+ pdev->slot_name, retval->name, size,
+ retval->blocks_per_page, allocation);
+#endif
+
+ return retval;
+}
+
+
+static struct pci_page *
+pool_alloc_page (struct pci_pool *pool, int mem_flags)
+{
+ struct pci_page *page;
+ int mapsize;
+
+ mapsize = pool->blocks_per_page;
+ mapsize = (mapsize + BITS_PER_LONG - 1) / BITS_PER_LONG;
+ mapsize *= sizeof (long);
+
+ page = (struct pci_page *) kmalloc (mapsize + sizeof *page, mem_flags);
+ if (!page)
+ return 0;
+ page->vaddr = pci_alloc_consistent (pool->dev,
+ pool->allocation, &page->dma);
+ if (page->vaddr) {
+ memset (page->bitmap, ~0, mapsize); // bit set == free
+ if (pool->flags & SLAB_POISON)
+ memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
+ list_add (&page->page_list, &pool->page_list);
+ }
+ return page;
+}
+
+
+static inline int
+is_page_busy (int blocks, unsigned long *bitmap)
+{
+ while (blocks > 0) {
+ if (*bitmap++ != ~0)
+ return 1;
+ blocks -= BITS_PER_LONG;
+ }
+ return 0;
+}
+
+static void
+pool_free_page (struct pci_pool *pool, struct pci_page *page)
+{
+ dma_addr_t dma = page->dma;
+
+#ifdef CONFIG_PCIPOOL_DEBUG
+ if (is_page_busy (pool->blocks_per_page, page->bitmap)) {
+ printk (KERN_ERR "pcipool %s/%s, free_page %p busy; leaked\n",
+ pool->dev->slot_name, pool->name, page->vaddr);
+ goto done;
+ }
+#endif
+
+ if (pool->flags & SLAB_POISON)
+ memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
+ pci_free_consistent (pool->dev, pool->allocation, page->vaddr, dma);
+done:
+ list_del (&page->page_list);
+ kfree (page);
+}
+
+
+/**
+ * pci_pool_destroy - destroys a pool of pci memory blocks.
+ * @pool: pci pool that will be destroyed
+ *
+ * Caller guarantees that no more memory from the pool is in use,
+ * and that nothing will try to use the pool after this call.
+ */
+void
+pci_pool_destroy (struct pci_pool *pool)
+{
+ unsigned long flags;
+
+#ifdef CONFIG_PCIPOOL_DEBUG
+ printk (KERN_DEBUG "pcipool destroy %s/%s\n",
+ pool->dev->slot_name, pool->name);
+#endif
+
+ spin_lock_irqsave (&pool->lock, flags);
+ while (!list_empty (&pool->page_list)) {
+ struct pci_page *page;
+ page = list_entry (pool->page_list.next,
+ struct pci_page, page_list);
+ pool_free_page (pool, page);
+ }
+ spin_unlock_irqrestore (&pool->lock, flags);
+ kfree (pool);
+}
+
+
+/**
+ * pci_pool_alloc - get a block of consistent memory
+ * @pool: pci pool that will produce the block
+ * @mem_flags: GFP_KERNEL or GFP_ATOMIC
+ * @handle: pointer to dma address of block
+ *
+ * This returns the kernel virtual address of a currently unused block,
+ * and reports its dma address through the handle.
+ */
+void *
+pci_pool_alloc (struct pci_pool *pool, int mem_flags, dma_addr_t *handle)
+{
+ unsigned long flags;
+ struct list_head *entry;
+ struct pci_page *page;
+ int map, block;
+ size_t offset;
+ void *retval;
+
+restart:
+ spin_lock_irqsave (&pool->lock, flags);
+ list_for_each (entry, &pool->page_list) {
+ int i;
+ page = list_entry (entry, struct pci_page, page_list);
+ /* only cachable accesses here ... */
+ for (map = 0, i = 0;
+ i < pool->blocks_per_page;
+ i += BITS_PER_LONG, map++) {
+ if (page->bitmap [map] == 0)
+ continue;
+ block = ffs (page->bitmap [map]);
+ if ((i + block) <= pool->blocks_per_page) {
+ block--;
+ clear_bit (block, &page->bitmap [map]);
+ offset = (BITS_PER_LONG * map) + block;
+ offset *= pool->size;
+ goto ready;
+ }
+ }
+ }
+ if (!(page = pool_alloc_page (pool, mem_flags))) {
+ if (mem_flags == GFP_KERNEL) {
+ DECLARE_WAITQUEUE (wait, current);
+
+ current->state = TASK_INTERRUPTIBLE;
+ add_wait_queue (&pool->waitq, &wait);
+ spin_unlock_irqrestore (&pool->lock, flags);
+
+ schedule_timeout (POOL_TIMEOUT_JIFFIES);
+
+ current->state = TASK_RUNNING;
+ remove_wait_queue (&pool->waitq, &wait);
+ goto restart;
+ }
+ retval = 0;
+ goto done;
+ }
+
+ clear_bit (0, &page->bitmap [0]);
+ offset = 0;
+ready:
+ retval = offset + page->vaddr;
+ *handle = offset + page->dma;
+done:
+ spin_unlock_irqrestore (&pool->lock, flags);
+ return retval;
+}
+
+
+static struct pci_page *
+pool_find_page (struct pci_pool *pool, dma_addr_t dma)
+{
+ unsigned long flags;
+ struct list_head *entry;
+ struct pci_page *page;
+
+ spin_lock_irqsave (&pool->lock, flags);
+ list_for_each (entry, &pool->page_list) {
+ page = list_entry (entry, struct pci_page, page_list);
+ if (dma < page->dma)
+ continue;
+ if (dma < (page->dma + pool->allocation))
+ goto done;
+ }
+ page = 0;
+done:
+ spin_unlock_irqrestore (&pool->lock, flags);
+ return page;
+}
+
+
+/**
+ * pci_pool_free - put block back into pci pool
+ * @pool: the pci pool holding the block
+ * @vaddr: virtual address of block
+ * @dma: dma address of block
+ *
+ * Caller promises neither device nor driver will again touch this block
+ * unless it is first re-allocated.
+ */
+void
+pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t dma)
+{
+ struct pci_page *page;
+ unsigned long flags;
+ int map, block;
+
+ if ((page = pool_find_page (pool, dma)) == 0) {
+ printk (KERN_ERR "pci_pool_free %s/%s, %p/%x (bad dma)\n",
+ pool->dev->slot_name, pool->name, vaddr, dma);
+ return;
+ }
+#ifdef CONFIG_PCIPOOL_DEBUG
+ if (((dma - page->dma) + (void *)page->vaddr) != vaddr) {
+ printk (KERN_ERR "pci_pool_free %s/%s, %p (bad vaddr)/%x\n",
+ pool->dev->slot_name, pool->name, vaddr, dma);
+ return;
+ }
+#endif
+
+ block = dma - page->dma;
+ block /= pool->size;
+ map = block / BITS_PER_LONG;
+ block %= BITS_PER_LONG;
+
+#ifdef CONFIG_PCIPOOL_DEBUG
+ if (page->bitmap [map] & (1 << block)) {
+ printk (KERN_ERR "pci_pool_free %s/%s, dma %x already free\n",
+ pool->dev->slot_name, pool->name, dma);
+ return;
+ }
+#endif
+ if (pool->flags & SLAB_POISON)
+ memset (vaddr, POOL_POISON_BYTE, pool->size);
+
+ spin_lock_irqsave (&pool->lock, flags);
+ set_bit (block, &page->bitmap [map]);
+ if (waitqueue_active (&pool->waitq))
+ wake_up (&pool->waitq);
+ else if (!is_page_busy (pool->blocks_per_page, page->bitmap))
+ pool_free_page (pool, page);
+ spin_unlock_irqrestore (&pool->lock, flags);
+}
+
+
void __init pci_init(void)
{
struct pci_dev *dev;
@@ -1420,4 +1758,11 @@
EXPORT_SYMBOL(isa_dma_bridge_buggy);
EXPORT_SYMBOL(pci_pci_problems);
+
+/* Pool allocator (layer over pci_alloc_consistent) */
+
+EXPORT_SYMBOL (pci_pool_create);
+EXPORT_SYMBOL (pci_pool_destroy);
+EXPORT_SYMBOL (pci_pool_alloc);
+EXPORT_SYMBOL (pci_pool_free);
[-- Attachment #3: ohci-0323.patch --]
[-- Type: application/octet-stream, Size: 14879 bytes --]
--- drivers/usb/usb-ohci-orig.h Wed Mar 14 12:40:36 2001
+++ drivers/usb/usb-ohci.h Fri Mar 23 10:13:17 2001
@@ -39,7 +39,7 @@
#define ED_URB_DEL 0x08
/* usb_ohci_ed */
-typedef struct ed {
+struct ed {
__u32 hwINFO;
__u32 hwTailP;
__u32 hwHeadP;
@@ -53,9 +53,12 @@
__u8 state;
__u8 type;
__u16 last_iso;
- struct ed * ed_rm_list;
-
-} ed_t;
+ struct ed * ed_rm_list;
+
+ dma_addr_t dma;
+ __u32 unused[3];
+} __attribute((aligned(16)));
+typedef struct ed ed_t;
/* TD info field */
@@ -96,19 +99,23 @@
#define MAXPSW 1
-typedef struct td {
+struct td {
__u32 hwINFO;
__u32 hwCBP; /* Current Buffer Pointer */
__u32 hwNextTD; /* Next TD Pointer */
__u32 hwBE; /* Memory Buffer End Pointer */
- __u16 hwPSW[MAXPSW];
+ __u16 hwPSW[MAXPSW];
__u8 unused;
__u8 index;
struct ed * ed;
struct td * next_dl_td;
urb_t * urb;
-} td_t;
+
+ dma_addr_t td_dma;
+ __u32 unused2[3];
+} __attribute((aligned(16)));
+typedef struct td td_t;
#define OHCI_ED_SKIP (1 << 14)
@@ -121,7 +128,7 @@
#define NUM_INTS 32 /* part of the OHCI standard */
struct ohci_hcca {
- __u32 int_table[NUM_INTS]; /* Interrupt ED table */
+ __u32 int_table[NUM_INTS]; /* Interrupt ED table */
__u16 frame_no; /* current frame number */
__u16 pad1; /* set to 0 on each frame_no change */
__u32 done_head; /* info returned for an interrupt */
@@ -356,7 +363,7 @@
struct ohci_regs * regs; /* OHCI controller's memory */
struct list_head ohci_hcd_list; /* list of all ohci_hcd */
- struct ohci * next; // chain of uhci device contexts
+ struct ohci * next; // chain of ohci device contexts
// struct list_head urb_list; // list of all pending urbs
// spinlock_t urb_list_lock; // lock to keep consistency
@@ -371,17 +378,18 @@
struct usb_device * dev[128];
struct virt_root_hub rh;
- /* PCI device handle and settings */
+ /* PCI device handle, settings, ... */
struct pci_dev *ohci_dev;
u8 pci_latency;
+ struct pci_pool *td_cache;
+ struct pci_pool *dev_cache;
} ohci_t;
-
-#define NUM_TDS 0 /* num of preallocated transfer descriptors */
#define NUM_EDS 32 /* num of preallocated endpoint descriptors */
struct ohci_device {
ed_t ed[NUM_EDS];
+ dma_addr_t dma;
int ed_cnt;
wait_queue_head_t * wait;
};
@@ -393,7 +401,7 @@
/* endpoint */
static int ep_link(ohci_t * ohci, ed_t * ed);
static int ep_unlink(ohci_t * ohci, ed_t * ed);
-static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned int pipe, int interval, int load);
+static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned int pipe, int interval, int load, int mem_flags);
static void ep_rm_ed(struct usb_device * usb_dev, ed_t * ed);
/* td */
static void td_fill(unsigned int info, void * data, int len, urb_t * urb, int index);
@@ -406,97 +414,91 @@
/*-------------------------------------------------------------------------*/
#define ALLOC_FLAGS (in_interrupt () ? GFP_ATOMIC : GFP_KERNEL)
-
-#ifdef OHCI_MEM_SLAB
-#define __alloc(t,c) kmem_cache_alloc(c,ALLOC_FLAGS)
-#define __free(c,x) kmem_cache_free(c,x)
-static kmem_cache_t *td_cache, *ed_cache;
-/*
- * WARNING: do NOT use this with "forced slab debug"; it won't respect
- * our hardware alignment requirement.
- */
-#ifndef OHCI_MEM_FLAGS
-#define OHCI_MEM_FLAGS 0
+#ifdef DEBUG
+# define OHCI_MEM_FLAGS SLAB_POISON
+#else
+# define OHCI_MEM_FLAGS 0
+#endif
+
+#ifndef CONFIG_PCI
+# error "usb-ohci currently requires PCI-based controllers"
+ /* to support non-PCI OHCIs, you need custom bus/mem/... glue */
#endif
-static int ohci_mem_init (void)
+static int ohci_mem_init (struct ohci *ohci)
{
- /* redzoning (or forced debug!) breaks alignment */
- int flags = (OHCI_MEM_FLAGS) & ~SLAB_RED_ZONE;
-
- /* TDs accessed by controllers and host */
- td_cache = kmem_cache_create ("ohci_td", sizeof (struct td), 0,
- flags | SLAB_HWCACHE_ALIGN, NULL, NULL);
- if (!td_cache) {
- dbg ("no TD cache?");
+ ohci->td_cache = pci_pool_create ("ohci_td", ohci->ohci_dev,
+ sizeof (struct td),
+ 16 /* byte alignment */,
+ 0 /* no page-crossing issues */,
+ GFP_KERNEL | OHCI_MEM_FLAGS);
+ if (!ohci->td_cache)
return -ENOMEM;
- }
-
- /* EDs are accessed by controllers and host; dev part is host-only */
- ed_cache = kmem_cache_create ("ohci_ed", sizeof (struct ohci_device), 0,
- flags | SLAB_HWCACHE_ALIGN, NULL, NULL);
- if (!ed_cache) {
- dbg ("no ED cache?");
- kmem_cache_destroy (td_cache);
- td_cache = 0;
+ ohci->dev_cache = pci_pool_create ("ohci_dev", ohci->ohci_dev,
+ sizeof (struct ohci_device),
+ 16 /* byte alignment */,
+ 0 /* no page-crossing issues */,
+ GFP_KERNEL | OHCI_MEM_FLAGS);
+ if (!ohci->dev_cache)
return -ENOMEM;
- }
- dbg ("slab flags 0x%x", flags);
return 0;
}
-static void ohci_mem_cleanup (void)
+static void ohci_mem_cleanup (struct ohci *ohci)
{
- if (ed_cache && kmem_cache_destroy (ed_cache))
- err ("ed_cache remained");
- ed_cache = 0;
-
- if (td_cache && kmem_cache_destroy (td_cache))
- err ("td_cache remained");
- td_cache = 0;
+ if (ohci->td_cache) {
+ pci_pool_destroy (ohci->td_cache);
+ ohci->td_cache = 0;
+ }
+ if (ohci->dev_cache) {
+ pci_pool_destroy (ohci->dev_cache);
+ ohci->dev_cache = 0;
+ }
}
-#else
-#define __alloc(t,c) kmalloc(sizeof(t),ALLOC_FLAGS)
-#define __free(dev,x) kfree(x)
-#define td_cache 0
-#define ed_cache 0
-
-static inline int ohci_mem_init (void) { return 0; }
-static inline void ohci_mem_cleanup (void) { return; }
-
-/* FIXME: pci_consistent version */
-
-#endif
-
-
/* TDs ... */
static inline struct td *
-td_alloc (struct ohci *hc)
+td_alloc (struct ohci *hc, int mem_flags)
{
- struct td *td = (struct td *) __alloc (struct td, td_cache);
+ dma_addr_t dma;
+ struct td *td;
+
+ td = pci_pool_alloc (hc->td_cache, mem_flags, &dma);
+ if (td)
+ td->td_dma = dma;
return td;
}
static inline void
td_free (struct ohci *hc, struct td *td)
{
- __free (td_cache, td);
+ pci_pool_free (hc->td_cache, td, td->td_dma);
}
/* DEV + EDs ... only the EDs need to be consistent */
static inline struct ohci_device *
-dev_alloc (struct ohci *hc)
+dev_alloc (struct ohci *hc, int mem_flags)
{
- struct ohci_device *dev = (struct ohci_device *)
- __alloc (struct ohci_device, ed_cache);
+ dma_addr_t dma;
+ struct ohci_device *dev;
+ int i, offset;
+
+ dev = pci_pool_alloc (hc->dev_cache, mem_flags, &dma);
+ if (dev) {
+ memset (dev, 0, sizeof (*dev));
+ dev->dma = dma;
+ offset = ((char *)&dev->ed) - ((char *)dev);
+ for (i = 0; i < NUM_EDS; i++, offset += sizeof dev->ed [0])
+ dev->ed [i].dma = dma + offset;
+ }
return dev;
}
static inline void
-dev_free (struct ohci_device *dev)
+dev_free (struct ohci *hc, struct ohci_device *dev)
{
- __free (ed_cache, dev);
+ pci_pool_free (hc->dev_cache, dev, dev->dma);
}
+
--- drivers/usb/usb-ohci-orig.c Wed Mar 14 12:40:36 2001
+++ drivers/usb/usb-ohci.c Wed Mar 21 17:33:06 2001
@@ -12,11 +12,12 @@
*
* History:
*
+ * 2001/03/21 td and dev/ed allocation uses new pci_pool API (db)
* 2001/03/07 hcca allocation uses pci_alloc_consistent (Steve Longerbeam)
* 2000/09/26 fixed races in removing the private portion of the urb
* 2000/09/07 disable bulk and control lists when unlinking the last
* endpoint descriptor in order to avoid unrecoverable errors on
- * the Lucent chips.
+ * the Lucent chips. (rwc@sgi)
* 2000/08/29 use bandwidth claiming hooks (thanks Randy!), fix some
* urb unlink probs, indentation fixes
* 2000/08/11 various oops fixes mostly affecting iso and cleanup from
@@ -65,8 +66,6 @@
#define OHCI_USE_NPS // force NoPowerSwitching mode
// #define OHCI_VERBOSE_DEBUG /* not always helpful */
-// #define OHCI_MEM_SLAB
-// #define OHCI_MEM_FLAGS SLAB_POISON /* no redzones; see mm/slab.c */
#include "usb-ohci.h"
@@ -132,7 +131,7 @@
}
}
- urb_free_priv ((struct ohci *)urb->dev->bus, urb_priv);
+ urb_free_priv ((struct ohci *)urb->dev->bus->hcpriv, urb_priv);
usb_dec_dev_use (urb->dev);
urb->dev = NULL;
}
@@ -460,6 +459,7 @@
int i, size = 0;
unsigned long flags;
int bustime = 0;
+ int mem_flags = ALLOC_FLAGS;
if (!urb->dev || !urb->dev->bus)
return -ENODEV;
@@ -489,7 +489,7 @@
}
/* every endpoint has a ed, locate and fill it */
- if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1))) {
+ if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1, mem_flags))) {
usb_dec_dev_use (urb->dev);
return -ENOMEM;
}
@@ -534,8 +534,9 @@
/* allocate the TDs */
for (i = 0; i < size; i++) {
- urb_priv->td[i] = td_alloc (ohci);
+ urb_priv->td[i] = td_alloc (ohci, mem_flags);
if (!urb_priv->td[i]) {
+ urb_priv->length = i;
urb_free_priv (ohci, urb_priv);
usb_dec_dev_use (urb->dev);
return -ENOMEM;
@@ -687,18 +688,11 @@
{
struct ohci_device * dev;
- /* FIXME: ED allocation with pci_consistent memory
- * must know the controller ... either pass it in here,
- * or decouple ED allocation from dev allocation.
- */
- dev = dev_alloc (NULL);
+ dev = dev_alloc ((struct ohci *) usb_dev->bus->hcpriv, ALLOC_FLAGS);
if (!dev)
return -ENOMEM;
-
- memset (dev, 0, sizeof (*dev));
usb_dev->hcpriv = dev;
-
return 0;
}
@@ -783,7 +777,7 @@
}
/* free device, and associated EDs */
- dev_free (dev);
+ dev_free (ohci, dev);
return 0;
}
@@ -877,9 +871,9 @@
case PIPE_CONTROL:
ed->hwNextED = 0;
if (ohci->ed_controltail == NULL) {
- writel (virt_to_bus (ed), &ohci->regs->ed_controlhead);
+ writel (ed->dma, &ohci->regs->ed_controlhead);
} else {
- ohci->ed_controltail->hwNextED = cpu_to_le32 (virt_to_bus (ed));
+ ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma);
}
ed->ed_prev = ohci->ed_controltail;
if (!ohci->ed_controltail && !ohci->ed_rm_list[0] &&
@@ -893,9 +887,9 @@
case PIPE_BULK:
ed->hwNextED = 0;
if (ohci->ed_bulktail == NULL) {
- writel (virt_to_bus (ed), &ohci->regs->ed_bulkhead);
+ writel (ed->dma, &ohci->regs->ed_bulkhead);
} else {
- ohci->ed_bulktail->hwNextED = cpu_to_le32 (virt_to_bus (ed));
+ ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma);
}
ed->ed_prev = ohci->ed_bulktail;
if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] &&
@@ -920,7 +914,7 @@
ed_p = &(((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->hwNextED))
inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval);
ed->hwNextED = *ed_p;
- *ed_p = cpu_to_le32 (virt_to_bus (ed));
+ *ed_p = cpu_to_le32 (ed->dma);
}
#ifdef DEBUG
ep_print_int_eds (ohci, "LINK_INT");
@@ -931,7 +925,7 @@
ed->hwNextED = 0;
ed->int_interval = 1;
if (ohci->ed_isotail != NULL) {
- ohci->ed_isotail->hwNextED = cpu_to_le32 (virt_to_bus (ed));
+ ohci->ed_isotail->hwNextED = cpu_to_le32 (ed->dma);
ed->ed_prev = ohci->ed_isotail;
} else {
for ( i = 0; i < 32; i += inter) {
@@ -940,7 +934,7 @@
*ed_p != 0;
ed_p = &(((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->hwNextED))
inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval);
- *ed_p = cpu_to_le32 (virt_to_bus (ed));
+ *ed_p = cpu_to_le32 (ed->dma);
}
ed->ed_prev = NULL;
}
@@ -1066,7 +1060,13 @@
* in all other cases the state is left unchanged
* the ed info fields are setted anyway even though most of them should not change */
-static ed_t * ep_add_ed (struct usb_device * usb_dev, unsigned int pipe, int interval, int load)
+static ed_t * ep_add_ed (
+ struct usb_device * usb_dev,
+ unsigned int pipe,
+ int interval,
+ int load,
+ int mem_flags
+)
{
ohci_t * ohci = usb_dev->bus->hcpriv;
td_t * td;
@@ -1089,13 +1089,13 @@
if (ed->state == ED_NEW) {
ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */
/* dummy td; end of td list for ed */
- td = td_alloc (ohci);
+ td = td_alloc (ohci, mem_flags);
if (!td) {
/* out of memory */
spin_unlock_irqrestore (&usb_ed_lock, flags);
return NULL;
}
- ed->hwTailP = cpu_to_le32 (virt_to_bus (td));
+ ed->hwTailP = cpu_to_le32 (td->td_dma);
ed->hwHeadP = ed->hwTailP;
ed->state = ED_UNLINK;
ed->type = usb_pipetype (pipe);
@@ -1164,7 +1164,7 @@
* TD handling functions
*-------------------------------------------------------------------------*/
-/* prepare a TD */
+/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
static void td_fill (unsigned int info, void * data, int len, urb_t * urb, int index)
{
@@ -1176,7 +1176,10 @@
return;
}
+ /* 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] = (td_t *)
bus_to_virt (le32_to_cpup (&urb_priv->ed->hwTailP) & 0xfffffff0);
@@ -1198,9 +1201,11 @@
td->hwBE = cpu_to_le32 ((!data || !len )
? 0
: virt_to_bus (data + len - 1));
- td->hwNextTD = cpu_to_le32 (virt_to_bus (td_pt));
+ td->hwNextTD = cpu_to_le32 (td_pt->td_dma);
+
td->hwPSW [0] = cpu_to_le16 ((virt_to_bus (data) & 0x0FFF) | 0xE000);
- td_pt->hwNextTD = 0;
+
+ /* append to queue */
td->ed->hwTailP = td->hwNextTD;
}
@@ -1765,9 +1770,6 @@
wIndex = le16_to_cpu (cmd->index);
wLength = le16_to_cpu (cmd->length);
- dbg ("rh_submit_urb, req = %d(%x) len=%d", bmRType_bReq,
- bmRType_bReq, wLength);
-
switch (bmRType_bReq) {
/* Request Destination:
without flags: Device,
@@ -2199,6 +2201,8 @@
list_del (&ohci->ohci_hcd_list);
INIT_LIST_HEAD (&ohci->ohci_hcd_list);
+
+ ohci_mem_cleanup (ohci);
/* unmap the IO address space */
iounmap (ohci->regs);
@@ -2221,6 +2225,7 @@
ohci_t * ohci;
u8 latency, limit;
char buf[8], *bufp = buf;
+ int ret;
#ifndef __sparc__
sprintf(buf, "%d", irq);
@@ -2235,6 +2240,10 @@
if (!ohci) {
return -ENOMEM;
}
+ if ((ret = ohci_mem_init (ohci)) < 0) {
+ hc_release_ohci (ohci);
+ return ret;
+ }
/* bad pci latencies can contribute to overruns */
pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
@@ -2566,11 +2575,7 @@
{
int ret;
- if ((ret = ohci_mem_init ()) < 0)
- return ret;
-
if ((ret = pci_module_init (&ohci_pci_driver)) < 0) {
- ohci_mem_cleanup ();
return ret;
}
@@ -2588,7 +2593,6 @@
pmu_unregister_sleep_notifier (&ohci_sleep_notifier);
#endif
pci_unregister_driver (&ohci_pci_driver);
- ohci_mem_cleanup ();
}
module_init (ohci_hcd_init);
[-- Attachment #4: uhci-0323.patch --]
[-- Type: application/octet-stream, Size: 14112 bytes --]
--- 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;
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2001-03-23 20:03 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-03-23 19:57 PATCHES: usb with CONFIG_SLAB_DEBUG (using new pci_pool API) David Brownell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®