186,7 → 186,34 |
return page; |
} |
|
static struct pci_page * |
pool_alloc_page_usb (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_usb (pool->dev, pool->allocation, &page->dma); |
if (page->vaddr) { |
memset (page->bitmap, 0xff, mapsize); // bit set == free |
#ifdef CONFIG_DEBUG_SLAB |
memset (page->vaddr, POOL_POISON_FREED, pool->allocation); |
#endif |
list_add (&page->page_list, &pool->page_list); |
page->in_use = 0; |
} else { |
kfree (page); |
page = 0; |
} |
return page; |
} |
|
static inline int |
is_page_busy (int blocks, unsigned long *bitmap) |
{ |
211,7 → 238,6 |
kfree (page); |
} |
|
|
/** |
* pci_pool_destroy - destroys a pool of pci memory blocks. |
* @pool: pci pool that will be destroyed |
247,7 → 273,6 |
kfree (pool); |
} |
|
|
/** |
* pci_pool_alloc - get a block of consistent memory |
* @pool: pci pool that will produce the block |
319,7 → 344,77 |
return retval; |
} |
|
/** |
* pci_pool_alloc_usb - get a block of consistent memory |
* @pool: pci pool that will produce the block |
* @mem_flags: SLAB_KERNEL or SLAB_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. |
* If such a memory block can't be allocated, null is returned. |
*/ |
void * |
pci_pool_alloc_usb (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 = ffz (~ page->bitmap [map]); |
if ((i + block) < pool->blocks_per_page) { |
clear_bit (block, &page->bitmap [map]); |
offset = (BITS_PER_LONG * map) + block; |
offset *= pool->size; |
goto ready; |
} |
} |
} |
if (!(page = pool_alloc_page_usb (pool, SLAB_ATOMIC))) { |
if (mem_flags == SLAB_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); |
|
remove_wait_queue (&pool->waitq, &wait); |
goto restart; |
} |
retval = 0; |
goto done; |
} |
|
clear_bit (0, &page->bitmap [0]); |
offset = 0; |
ready: |
page->in_use++; |
retval = offset + page->vaddr; |
*handle = offset + page->dma; |
#ifdef CONFIG_DEBUG_SLAB |
memset (retval, POOL_POISON_ALLOCATED, pool->size); |
#endif |
done: |
spin_unlock_irqrestore (&pool->lock, flags); |
return retval; |
} |
|
static struct pci_page * |
pool_find_page (struct pci_pool *pool, dma_addr_t dma) |
{ |
341,7 → 436,6 |
return page; |
} |
|
|
/** |
* pci_pool_free - put block back into pci pool |
* @pool: the pci pool holding the block |
399,7 → 493,6 |
spin_unlock_irqrestore (&pool->lock, flags); |
} |
|
|
EXPORT_SYMBOL (pci_pool_create); |
EXPORT_SYMBOL (pci_pool_destroy); |
EXPORT_SYMBOL (pci_pool_alloc); |