pcipool.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:10k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.   NOTE:
  3.   this code was lifted straight out of drivers/pci/pci.c;
  4.   when compiling for the Intel StrongARM SA-1110/SA-1111 the
  5.   usb-ohci.c driver needs these routines even when the architecture
  6.   has no pci bus...
  7. */
  8. #include <linux/config.h>
  9. #include <linux/module.h>
  10. #include <linux/types.h>
  11. #include <linux/kernel.h>
  12. #include <linux/pci.h>
  13. #include <linux/string.h>
  14. #include <linux/init.h>
  15. #include <linux/slab.h>
  16. #include <linux/spinlock.h>
  17. #include <linux/bitops.h>
  18. #include <asm/page.h>
  19. #include "pcipool.h"
  20. /*
  21.  * Pool allocator ... wraps the pci_alloc_consistent page allocator, so
  22.  * small blocks are easily used by drivers for bus mastering controllers.
  23.  * This should probably be sharing the guts of the slab allocator.
  24.  */
  25. struct pci_pool { /* the pool */
  26. struct list_head page_list;
  27. spinlock_t lock;
  28. size_t blocks_per_page;
  29. size_t size;
  30. int flags;
  31. struct pci_dev *dev;
  32. size_t allocation;
  33. char name [32];
  34. wait_queue_head_t waitq;
  35. };
  36. struct pci_page { /* cacheable header for 'allocation' bytes */
  37. struct list_head page_list;
  38. void *vaddr;
  39. dma_addr_t dma;
  40. unsigned long bitmap [0];
  41. };
  42. #define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000)
  43. #define POOL_POISON_BYTE 0xa7
  44. //#define CONFIG_PCIPOOL_DEBUG 1
  45. /**
  46.  * pci_pool_create - Creates a pool of pci consistent memory blocks, for dma.
  47.  * @name: name of pool, for diagnostics
  48.  * @pdev: pci device that will be doing the DMA
  49.  * @size: size of the blocks in this pool.
  50.  * @align: alignment requirement for blocks; must be a power of two
  51.  * @allocation: returned blocks won't cross this boundary (or zero)
  52.  * @flags: SLAB_* flags (not all are supported).
  53.  *
  54.  * Returns a pci allocation pool with the requested characteristics, or
  55.  * null if one can't be created.  Given one of these pools, pci_pool_alloc()
  56.  * may be used to allocate memory.  Such memory will all have "consistent"
  57.  * DMA mappings, accessible by the device and its driver without using
  58.  * cache flushing primitives.  The actual size of blocks allocated may be
  59.  * larger than requested because of alignment.
  60.  *
  61.  * If allocation is nonzero, objects returned from pci_pool_alloc() won't
  62.  * cross that size boundary.  This is useful for devices which have
  63.  * addressing restrictions on individual DMA transfers, such as not crossing
  64.  * boundaries of 4KBytes.
  65.  */
  66. struct pci_pool *
  67. pci_pool_create (const char *name, struct pci_dev *pdev,
  68. size_t size, size_t align, size_t allocation, int flags)
  69. {
  70. struct pci_pool *retval;
  71. if (align == 0)
  72. align = 1;
  73. if (size == 0)
  74. return 0;
  75. else if (size < align)
  76. size = align;
  77. else if ((size % align) != 0) {
  78. size += align + 1;
  79. size &= ~(align - 1);
  80. }
  81. if (allocation == 0) {
  82. if (PAGE_SIZE < size)
  83. allocation = size;
  84. else
  85. allocation = PAGE_SIZE;
  86. // FIXME: round up for less fragmentation
  87. } else if (allocation < size)
  88. return 0;
  89. if (!(retval = kmalloc (sizeof *retval, flags)))
  90. return retval;
  91. #ifdef CONFIG_PCIPOOL_DEBUG
  92. flags |= SLAB_POISON;
  93. #endif
  94. strncpy (retval->name, name, sizeof retval->name);
  95. retval->name [sizeof retval->name - 1] = 0;
  96. retval->dev = pdev;
  97. INIT_LIST_HEAD (&retval->page_list);
  98. spin_lock_init (&retval->lock);
  99. retval->size = size;
  100. retval->flags = flags;
  101. retval->allocation = allocation;
  102. retval->blocks_per_page = allocation / size;
  103. init_waitqueue_head (&retval->waitq);
  104. #ifdef CONFIG_PCIPOOL_DEBUG
  105. printk ("pcipool create %s/%s size %d, %d/page (%d alloc)n",
  106. pdev ? pdev->slot_name : "NULL", retval->name, size,
  107. retval->blocks_per_page, allocation);
  108. #endif
  109. return retval;
  110. }
  111. static struct pci_page *
  112. pool_alloc_page (struct pci_pool *pool, int mem_flags)
  113. {
  114. struct pci_page *page;
  115. int mapsize;
  116. mapsize = pool->blocks_per_page;
  117. mapsize = (mapsize + BITS_PER_LONG - 1) / BITS_PER_LONG;
  118. mapsize *= sizeof (long);
  119. page = (struct pci_page *) kmalloc (mapsize + sizeof *page, mem_flags);
  120. if (!page)
  121. return 0;
  122. page->vaddr = pci_alloc_consistent (pool->dev,
  123. pool->allocation, &page->dma);
  124. if (page->vaddr) {
  125. memset (page->bitmap, 0xff, mapsize); // bit set == free
  126. if (pool->flags & SLAB_POISON)
  127. memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
  128. list_add (&page->page_list, &pool->page_list);
  129. } else {
  130. kfree (page);
  131. page = 0;
  132. }
  133. return page;
  134. }
  135. static inline int
  136. is_page_busy (int blocks, unsigned long *bitmap)
  137. {
  138. while (blocks > 0) {
  139. if (*bitmap++ != ~0UL)
  140. return 1;
  141. blocks -= BITS_PER_LONG;
  142. }
  143. return 0;
  144. }
  145. static void
  146. pool_free_page (struct pci_pool *pool, struct pci_page *page)
  147. {
  148. dma_addr_t dma = page->dma;
  149. if (pool->flags & SLAB_POISON)
  150. memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
  151. pci_free_consistent (pool->dev, pool->allocation, page->vaddr, dma);
  152. list_del (&page->page_list);
  153. kfree (page);
  154. }
  155. /**
  156.  * pci_pool_destroy - destroys a pool of pci memory blocks.
  157.  * @pool: pci pool that will be destroyed
  158.  *
  159.  * Caller guarantees that no more memory from the pool is in use,
  160.  * and that nothing will try to use the pool after this call.
  161.  */
  162. void
  163. pci_pool_destroy (struct pci_pool *pool)
  164. {
  165. unsigned long flags;
  166. #ifdef CONFIG_PCIPOOL_DEBUG
  167. printk ("pcipool destroy %s/%sn",
  168. pool->dev ? pool->dev->slot_name : NULL,
  169. pool->name);
  170. #endif
  171. spin_lock_irqsave (&pool->lock, flags);
  172. while (!list_empty (&pool->page_list)) {
  173. struct pci_page *page;
  174. page = list_entry (pool->page_list.next,
  175. struct pci_page, page_list);
  176. if (is_page_busy (pool->blocks_per_page, page->bitmap)) {
  177. printk ("pci_pool_destroy %s/%s, %p busyn",
  178. pool->dev ? pool->dev->slot_name : NULL,
  179. pool->name, page->vaddr);
  180. /* leak the still-in-use consistent memory */
  181. list_del (&page->page_list);
  182. kfree (page);
  183. } else
  184. pool_free_page (pool, page);
  185. }
  186. spin_unlock_irqrestore (&pool->lock, flags);
  187. kfree (pool);
  188. }
  189. /**
  190.  * pci_pool_alloc - get a block of consistent memory
  191.  * @pool: pci pool that will produce the block
  192.  * @mem_flags: SLAB_KERNEL or SLAB_ATOMIC
  193.  * @handle: pointer to dma address of block
  194.  *
  195.  * This returns the kernel virtual address of a currently unused block,
  196.  * and reports its dma address through the handle.
  197.  * If such a memory block can't be allocated, null is returned.
  198.  */
  199. void *
  200. pci_pool_alloc (struct pci_pool *pool, int mem_flags, dma_addr_t *handle)
  201. {
  202. unsigned long flags;
  203. struct list_head *entry;
  204. struct pci_page *page;
  205. int map, block;
  206. size_t offset;
  207. void *retval;
  208. restart:
  209. spin_lock_irqsave (&pool->lock, flags);
  210. list_for_each (entry, &pool->page_list) {
  211. int i;
  212. page = list_entry (entry, struct pci_page, page_list);
  213. /* only cachable accesses here ... */
  214. for (map = 0, i = 0;
  215. i < pool->blocks_per_page;
  216. i += BITS_PER_LONG, map++) {
  217. if (page->bitmap [map] == 0)
  218. continue;
  219. block = ffz (~ page->bitmap [map]);
  220. if ((i + block) < pool->blocks_per_page) {
  221. clear_bit (block, &page->bitmap [map]);
  222. offset = (BITS_PER_LONG * map) + block;
  223. offset *= pool->size;
  224. goto ready;
  225. }
  226. }
  227. }
  228. if (!(page = pool_alloc_page (pool, mem_flags))) {
  229. if (mem_flags == SLAB_KERNEL) {
  230. DECLARE_WAITQUEUE (wait, current);
  231. current->state = TASK_INTERRUPTIBLE;
  232. add_wait_queue (&pool->waitq, &wait);
  233. spin_unlock_irqrestore (&pool->lock, flags);
  234. schedule_timeout (POOL_TIMEOUT_JIFFIES);
  235. current->state = TASK_RUNNING;
  236. remove_wait_queue (&pool->waitq, &wait);
  237. goto restart;
  238. }
  239. retval = 0;
  240. goto done;
  241. }
  242. clear_bit (0, &page->bitmap [0]);
  243. offset = 0;
  244. ready:
  245. retval = offset + page->vaddr;
  246. *handle = offset + page->dma;
  247. done:
  248. spin_unlock_irqrestore (&pool->lock, flags);
  249. return retval;
  250. }
  251. static struct pci_page *
  252. pool_find_page (struct pci_pool *pool, dma_addr_t dma)
  253. {
  254. unsigned long flags;
  255. struct list_head *entry;
  256. struct pci_page *page;
  257. spin_lock_irqsave (&pool->lock, flags);
  258. list_for_each (entry, &pool->page_list) {
  259. page = list_entry (entry, struct pci_page, page_list);
  260. if (dma < page->dma)
  261. continue;
  262. if (dma < (page->dma + pool->allocation))
  263. goto done;
  264. }
  265. page = 0;
  266. done:
  267. spin_unlock_irqrestore (&pool->lock, flags);
  268. return page;
  269. }
  270. /**
  271.  * pci_pool_free - put block back into pci pool
  272.  * @pool: the pci pool holding the block
  273.  * @vaddr: virtual address of block
  274.  * @dma: dma address of block
  275.  *
  276.  * Caller promises neither device nor driver will again touch this block
  277.  * unless it is first re-allocated.
  278.  */
  279. void
  280. pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t dma)
  281. {
  282. struct pci_page *page;
  283. unsigned long flags;
  284. int map, block;
  285. if ((page = pool_find_page (pool, dma)) == 0) {
  286. printk ("pci_pool_free %s/%s, %p/%x (bad dma)n",
  287. pool->dev ? pool->dev->slot_name : NULL,
  288. pool->name, vaddr, dma);
  289. return;
  290. }
  291. #ifdef CONFIG_PCIPOOL_DEBUG
  292. if (((dma - page->dma) + (void *)page->vaddr) != vaddr) {
  293. printk ("pci_pool_free %s/%s, %p (bad vaddr)/%xn",
  294. pool->dev ? pool->dev->slot_name : NULL,
  295. pool->name, vaddr, dma);
  296. return;
  297. }
  298. #endif
  299. block = dma - page->dma;
  300. block /= pool->size;
  301. map = block / BITS_PER_LONG;
  302. block %= BITS_PER_LONG;
  303. #ifdef CONFIG_PCIPOOL_DEBUG
  304. if (page->bitmap [map] & (1UL << block)) {
  305. printk ("pci_pool_free %s/%s, dma %x already freen",
  306. pool->dev ? pool->dev->slot_name : NULL,
  307. pool->name, dma);
  308. return;
  309. }
  310. #endif
  311. if (pool->flags & SLAB_POISON)
  312. memset (vaddr, POOL_POISON_BYTE, pool->size);
  313. spin_lock_irqsave (&pool->lock, flags);
  314. set_bit (block, &page->bitmap [map]);
  315. if (waitqueue_active (&pool->waitq))
  316. wake_up (&pool->waitq);
  317. /*
  318.  * Resist a temptation to do
  319.  *    if (!is_page_busy(bpp, page->bitmap)) pool_free_page(pool, page);
  320.  * it is not interrupt safe. Better have empty pages hang around.
  321.  */
  322. spin_unlock_irqrestore (&pool->lock, flags);
  323. }
  324. EXPORT_SYMBOL (pci_pool_create);
  325. EXPORT_SYMBOL (pci_pool_destroy);
  326. EXPORT_SYMBOL (pci_pool_alloc);
  327. EXPORT_SYMBOL (pci_pool_free);