consistent.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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. *handle = virt_to_phys(ret);
  28. /*
  29. * We must flush the cache before we pass it on to the device
  30. */
  31. dma_cache_wback_inv(ret, size);
  32. page = virt_to_page(ret);
  33. free = page + (size >> PAGE_SHIFT);
  34. end = page + (1 << order);
  35. while (++page < end) {
  36. /* Free any unused pages */
  37. if (page >= free) {
  38. __free_page(page);
  39. }
  40. }
  41. return P2SEGADDR(ret);
  42. }
  43. void consistent_free(void *vaddr, size_t size)
  44. {
  45. unsigned long addr = P1SEGADDR((unsigned long)vaddr);
  46. struct page *page=virt_to_page(addr);
  47. int num_pages=(size+PAGE_SIZE-1) >> PAGE_SHIFT;
  48. int i;
  49. for(i=0;i<num_pages;i++) {
  50. __free_page((page+i));
  51. }
  52. }
  53. void consistent_sync(void *vaddr, size_t size, int direction)
  54. {
  55. void * p1addr = (void*) P1SEGADDR((unsigned long)vaddr);
  56. switch (direction) {
  57. case DMA_FROM_DEVICE: /* invalidate only */
  58. dma_cache_inv(p1addr, size);
  59. break;
  60. case DMA_TO_DEVICE: /* writeback only */
  61. dma_cache_wback(p1addr, size);
  62. break;
  63. case DMA_BIDIRECTIONAL: /* writeback and invalidate */
  64. dma_cache_wback_inv(p1addr, size);
  65. break;
  66. default:
  67. BUG();
  68. }
  69. }
  70. EXPORT_SYMBOL(consistent_alloc);
  71. EXPORT_SYMBOL(consistent_free);
  72. EXPORT_SYMBOL(consistent_sync);