consistent.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  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(gfp_t 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. split_page(page, order);
  24. ret = page_address(page);
  25. *handle = virt_to_phys(ret);
  26. /*
  27. * We must flush the cache before we pass it on to the device
  28. */
  29. dma_cache_wback_inv(ret, size);
  30. page = virt_to_page(ret);
  31. free = page + (size >> PAGE_SHIFT);
  32. end = page + (1 << order);
  33. while (++page < end) {
  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);