Commit b286bd16 authored by David Brownell's avatar David Brownell Committed by Linus Torvalds

[PATCH] PATCH -- pci_pool and CONFIG_DEBUG_SLAB

I got burnt one too many time by mismatches between
the pci_pool and "real" slabs... something changed in
mm/slab.c and broke a driver, so I'm going for the real
fix this time.  Having poisoning that _works_ is a huge
help in the innards of the USB host controller drivers.

This patch gets rid of some #ifdefs and makes the pci_pool
code poison memory if CONFIG_DEBUG_SLAB is set.
The functionality has always been there, but this makes
it simpler to get at.
parent ccd6307f
...@@ -1710,7 +1710,6 @@ struct pci_pool { /* the pool */ ...@@ -1710,7 +1710,6 @@ struct pci_pool { /* the pool */
spinlock_t lock; spinlock_t lock;
size_t blocks_per_page; size_t blocks_per_page;
size_t size; size_t size;
int flags;
struct pci_dev *dev; struct pci_dev *dev;
size_t allocation; size_t allocation;
char name [32]; char name [32];
...@@ -1727,8 +1726,6 @@ struct pci_page { /* cacheable header for 'allocation' bytes */ ...@@ -1727,8 +1726,6 @@ struct pci_page { /* cacheable header for 'allocation' bytes */
#define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000) #define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000)
#define POOL_POISON_BYTE 0xa7 #define POOL_POISON_BYTE 0xa7
// #define CONFIG_PCIPOOL_DEBUG
/** /**
* pci_pool_create - Creates a pool of pci consistent memory blocks, for dma. * pci_pool_create - Creates a pool of pci consistent memory blocks, for dma.
...@@ -1737,7 +1734,7 @@ struct pci_page { /* cacheable header for 'allocation' bytes */ ...@@ -1737,7 +1734,7 @@ struct pci_page { /* cacheable header for 'allocation' bytes */
* @size: size of the blocks in this pool. * @size: size of the blocks in this pool.
* @align: alignment requirement for blocks; must be a power of two * @align: alignment requirement for blocks; must be a power of two
* @allocation: returned blocks won't cross this boundary (or zero) * @allocation: returned blocks won't cross this boundary (or zero)
* @flags: SLAB_* flags (not all are supported). * @mem_flags: SLAB_* flags.
* *
* Returns a pci allocation pool with the requested characteristics, or * 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() * null if one can't be created. Given one of these pools, pci_pool_alloc()
...@@ -1753,7 +1750,7 @@ struct pci_page { /* cacheable header for 'allocation' bytes */ ...@@ -1753,7 +1750,7 @@ struct pci_page { /* cacheable header for 'allocation' bytes */
*/ */
struct pci_pool * struct pci_pool *
pci_pool_create (const char *name, struct pci_dev *pdev, pci_pool_create (const char *name, struct pci_dev *pdev,
size_t size, size_t align, size_t allocation, int flags) size_t size, size_t align, size_t allocation, int mem_flags)
{ {
struct pci_pool *retval; struct pci_pool *retval;
...@@ -1777,13 +1774,9 @@ pci_pool_create (const char *name, struct pci_dev *pdev, ...@@ -1777,13 +1774,9 @@ pci_pool_create (const char *name, struct pci_dev *pdev,
} else if (allocation < size) } else if (allocation < size)
return 0; return 0;
if (!(retval = kmalloc (sizeof *retval, flags))) if (!(retval = kmalloc (sizeof *retval, mem_flags)))
return retval; return retval;
#ifdef CONFIG_PCIPOOL_DEBUG
flags |= SLAB_POISON;
#endif
strncpy (retval->name, name, sizeof retval->name); strncpy (retval->name, name, sizeof retval->name);
retval->name [sizeof retval->name - 1] = 0; retval->name [sizeof retval->name - 1] = 0;
...@@ -1791,17 +1784,10 @@ pci_pool_create (const char *name, struct pci_dev *pdev, ...@@ -1791,17 +1784,10 @@ pci_pool_create (const char *name, struct pci_dev *pdev,
INIT_LIST_HEAD (&retval->page_list); INIT_LIST_HEAD (&retval->page_list);
spin_lock_init (&retval->lock); spin_lock_init (&retval->lock);
retval->size = size; retval->size = size;
retval->flags = flags;
retval->allocation = allocation; retval->allocation = allocation;
retval->blocks_per_page = allocation / size; retval->blocks_per_page = allocation / size;
init_waitqueue_head (&retval->waitq); init_waitqueue_head (&retval->waitq);
#ifdef CONFIG_PCIPOOL_DEBUG
printk (KERN_DEBUG "pcipool create %s/%s size %d, %d/page (%d alloc)\n",
pdev ? pdev->slot_name : NULL, retval->name, size,
retval->blocks_per_page, allocation);
#endif
return retval; return retval;
} }
...@@ -1824,8 +1810,9 @@ pool_alloc_page (struct pci_pool *pool, int mem_flags) ...@@ -1824,8 +1810,9 @@ pool_alloc_page (struct pci_pool *pool, int mem_flags)
&page->dma); &page->dma);
if (page->vaddr) { if (page->vaddr) {
memset (page->bitmap, 0xff, mapsize); // bit set == free memset (page->bitmap, 0xff, mapsize); // bit set == free
if (pool->flags & SLAB_POISON) #ifdef CONFIG_DEBUG_SLAB
memset (page->vaddr, POOL_POISON_BYTE, pool->allocation); memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
#endif
list_add (&page->page_list, &pool->page_list); list_add (&page->page_list, &pool->page_list);
} else { } else {
kfree (page); kfree (page);
...@@ -1851,8 +1838,9 @@ pool_free_page (struct pci_pool *pool, struct pci_page *page) ...@@ -1851,8 +1838,9 @@ pool_free_page (struct pci_pool *pool, struct pci_page *page)
{ {
dma_addr_t dma = page->dma; dma_addr_t dma = page->dma;
if (pool->flags & SLAB_POISON) #ifdef CONFIG_DEBUG_SLAB
memset (page->vaddr, POOL_POISON_BYTE, pool->allocation); memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
#endif
pci_free_consistent (pool->dev, pool->allocation, page->vaddr, dma); pci_free_consistent (pool->dev, pool->allocation, page->vaddr, dma);
list_del (&page->page_list); list_del (&page->page_list);
kfree (page); kfree (page);
...@@ -1871,12 +1859,6 @@ pci_pool_destroy (struct pci_pool *pool) ...@@ -1871,12 +1859,6 @@ pci_pool_destroy (struct pci_pool *pool)
{ {
unsigned long flags; unsigned long flags;
#ifdef CONFIG_PCIPOOL_DEBUG
printk (KERN_DEBUG "pcipool destroy %s/%s\n",
pool->dev ? pool->dev->slot_name : NULL,
pool->name);
#endif
spin_lock_irqsave (&pool->lock, flags); spin_lock_irqsave (&pool->lock, flags);
while (!list_empty (&pool->page_list)) { while (!list_empty (&pool->page_list)) {
struct pci_page *page; struct pci_page *page;
...@@ -2010,30 +1992,27 @@ pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t dma) ...@@ -2010,30 +1992,27 @@ pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t dma)
pool->name, vaddr, (unsigned long) dma); pool->name, vaddr, (unsigned long) dma);
return; return;
} }
#ifdef CONFIG_PCIPOOL_DEBUG
if (((dma - page->dma) + (void *)page->vaddr) != vaddr) {
printk (KERN_ERR "pci_pool_free %s/%s, %p (bad vaddr)/%lx\n",
pool->dev ? pool->dev->slot_name : NULL,
pool->name, vaddr, (unsigned long) dma);
return;
}
#endif
block = dma - page->dma; block = dma - page->dma;
block /= pool->size; block /= pool->size;
map = block / BITS_PER_LONG; map = block / BITS_PER_LONG;
block %= BITS_PER_LONG; block %= BITS_PER_LONG;
#ifdef CONFIG_PCIPOOL_DEBUG #ifdef CONFIG_DEBUG_SLAB
if (((dma - page->dma) + (void *)page->vaddr) != vaddr) {
printk (KERN_ERR "pci_pool_free %s/%s, %p (bad vaddr)/%lx\n",
pool->dev ? pool->dev->slot_name : NULL,
pool->name, vaddr, (unsigned long) dma);
return;
}
if (page->bitmap [map] & (1UL << block)) { if (page->bitmap [map] & (1UL << block)) {
printk (KERN_ERR "pci_pool_free %s/%s, dma %x already free\n", printk (KERN_ERR "pci_pool_free %s/%s, dma %x already free\n",
pool->dev ? pool->dev->slot_name : NULL, pool->dev ? pool->dev->slot_name : NULL,
pool->name, dma); pool->name, dma);
return; return;
} }
memset (vaddr, POOL_POISON_BYTE, pool->size);
#endif #endif
if (pool->flags & SLAB_POISON)
memset (vaddr, POOL_POISON_BYTE, pool->size);
spin_lock_irqsave (&pool->lock, flags); spin_lock_irqsave (&pool->lock, flags);
set_bit (block, &page->bitmap [map]); set_bit (block, &page->bitmap [map]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment