consistent.c 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /*
  2. * arch/sh/mm/consistent.c
  3. *
  4. * Copyright (C) 2004 Paul Mundt
  5. *
  6. * This file is subject to the terms and conditions of the GNU General Public
  7. * License. See the file "COPYING" in the main directory of this archive
  8. * for more details.
  9. */
  10. #include <linux/mm.h>
  11. #include <linux/dma-mapping.h>
  12. #include <asm/io.h>
  13. void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle)
  14. {
  15. struct page *page, *end, *free;
  16. void *ret;
  17. int order;
  18. size = PAGE_ALIGN(size);
  19. order = get_order(size);
  20. page = alloc_pages(gfp, order);
  21. if (!page)
  22. return NULL;
  23. ret = page_address(page);
  24. *handle = virt_to_phys(ret);
  25. /*
  26. * We must flush the cache before we pass it on to the device
  27. */
  28. dma_cache_wback_inv(ret, size);
  29. page = virt_to_page(ret);
  30. free = page + (size >> PAGE_SHIFT);
  31. end = page + (1 << order);
  32. while (++page < end) {
  33. set_page_count(page, 1);
  34. /* Free any unused pages */
  35. if (page >= free) {
  36. __free_page(page);
  37. }
  38. }
  39. return P2SEGADDR(ret);
  40. }
  41. void consistent_free(void *vaddr, size_t size)
  42. {
  43. unsigned long addr = P1SEGADDR((unsigned long)vaddr);
  44. struct page *page=virt_to_page(addr);
  45. int num_pages=(size+PAGE_SIZE-1) >> PAGE_SHIFT;
  46. int i;
  47. for(i=0;i<num_pages;i++) {
  48. __free_page((page+i));
  49. }
  50. }
  51. void consistent_sync(void *vaddr, size_t size, int direction)
  52. {
  53. void * p1addr = (void*) P1SEGADDR((unsigned long)vaddr);
  54. switch (direction) {
  55. case DMA_FROM_DEVICE: /* invalidate only */
  56. dma_cache_inv(p1addr, size);
  57. break;
  58. case DMA_TO_DEVICE: /* writeback only */
  59. dma_cache_wback(p1addr, size);
  60. break;
  61. case DMA_BIDIRECTIONAL: /* writeback and invalidate */
  62. dma_cache_wback_inv(p1addr, size);
  63. break;
  64. default:
  65. BUG();
  66. }
  67. }
  68. EXPORT_SYMBOL(consistent_alloc);
  69. EXPORT_SYMBOL(consistent_free);
  70. EXPORT_SYMBOL(consistent_sync);