consistent.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  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/cacheflush.h>
  13. #include <asm/addrspace.h>
  14. #include <asm/io.h>
  15. void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle)
  16. {
  17. struct page *page, *end, *free;
  18. void *ret;
  19. int order;
  20. size = PAGE_ALIGN(size);
  21. order = get_order(size);
  22. page = alloc_pages(gfp, order);
  23. if (!page)
  24. return NULL;
  25. split_page(page, order);
  26. ret = page_address(page);
  27. memset(ret, 0, size);
  28. *handle = virt_to_phys(ret);
  29. /*
  30. * We must flush the cache before we pass it on to the device
  31. */
  32. dma_cache_wback_inv(ret, size);
  33. page = virt_to_page(ret);
  34. free = page + (size >> PAGE_SHIFT);
  35. end = page + (1 << order);
  36. while (++page < end) {
  37. /* Free any unused pages */
  38. if (page >= free) {
  39. __free_page(page);
  40. }
  41. }
  42. return P2SEGADDR(ret);
  43. }
  44. void consistent_free(void *vaddr, size_t size)
  45. {
  46. unsigned long addr = P1SEGADDR((unsigned long)vaddr);
  47. struct page *page=virt_to_page(addr);
  48. int num_pages=(size+PAGE_SIZE-1) >> PAGE_SHIFT;
  49. int i;
  50. for(i=0;i<num_pages;i++) {
  51. __free_page((page+i));
  52. }
  53. }
  54. void consistent_sync(void *vaddr, size_t size, int direction)
  55. {
  56. void * p1addr = (void*) P1SEGADDR((unsigned long)vaddr);
  57. switch (direction) {
  58. case DMA_FROM_DEVICE: /* invalidate only */
  59. dma_cache_inv(p1addr, size);
  60. break;
  61. case DMA_TO_DEVICE: /* writeback only */
  62. dma_cache_wback(p1addr, size);
  63. break;
  64. case DMA_BIDIRECTIONAL: /* writeback and invalidate */
  65. dma_cache_wback_inv(p1addr, size);
  66. break;
  67. default:
  68. BUG();
  69. }
  70. }
  71. EXPORT_SYMBOL(consistent_alloc);
  72. EXPORT_SYMBOL(consistent_free);
  73. EXPORT_SYMBOL(consistent_sync);