~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/m68k/kernel/dma.c

Version: ~ [ linux-5.4-rc7 ] ~ [ linux-5.3.11 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.84 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.154 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.201 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.201 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.77 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * This file is subject to the terms and conditions of the GNU General Public
  3  * License.  See the file COPYING in the main directory of this archive
  4  * for more details.
  5  */
  6 
  7 #undef DEBUG
  8 
  9 #include <linux/dma-mapping.h>
 10 #include <linux/device.h>
 11 #include <linux/kernel.h>
 12 #include <linux/scatterlist.h>
 13 #include <linux/slab.h>
 14 #include <linux/vmalloc.h>
 15 #include <linux/export.h>
 16 
 17 #include <asm/pgalloc.h>
 18 
 19 #if defined(CONFIG_MMU) && !defined(CONFIG_COLDFIRE)
 20 
 21 void *dma_alloc_coherent(struct device *dev, size_t size,
 22                          dma_addr_t *handle, gfp_t flag)
 23 {
 24         struct page *page, **map;
 25         pgprot_t pgprot;
 26         void *addr;
 27         int i, order;
 28 
 29         pr_debug("dma_alloc_coherent: %d,%x\n", size, flag);
 30 
 31         size = PAGE_ALIGN(size);
 32         order = get_order(size);
 33 
 34         page = alloc_pages(flag, order);
 35         if (!page)
 36                 return NULL;
 37 
 38         *handle = page_to_phys(page);
 39         map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA);
 40         if (!map) {
 41                 __free_pages(page, order);
 42                 return NULL;
 43         }
 44         split_page(page, order);
 45 
 46         order = 1 << order;
 47         size >>= PAGE_SHIFT;
 48         map[0] = page;
 49         for (i = 1; i < size; i++)
 50                 map[i] = page + i;
 51         for (; i < order; i++)
 52                 __free_page(page + i);
 53         pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
 54         if (CPU_IS_040_OR_060)
 55                 pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S;
 56         else
 57                 pgprot_val(pgprot) |= _PAGE_NOCACHE030;
 58         addr = vmap(map, size, VM_MAP, pgprot);
 59         kfree(map);
 60 
 61         return addr;
 62 }
 63 
 64 void dma_free_coherent(struct device *dev, size_t size,
 65                        void *addr, dma_addr_t handle)
 66 {
 67         pr_debug("dma_free_coherent: %p, %x\n", addr, handle);
 68         vfree(addr);
 69 }
 70 
 71 #else
 72 
 73 #include <asm/cacheflush.h>
 74 
 75 void *dma_alloc_coherent(struct device *dev, size_t size,
 76                            dma_addr_t *dma_handle, gfp_t gfp)
 77 {
 78         void *ret;
 79         /* ignore region specifiers */
 80         gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
 81 
 82         if (dev == NULL || (*dev->dma_mask < 0xffffffff))
 83                 gfp |= GFP_DMA;
 84         ret = (void *)__get_free_pages(gfp, get_order(size));
 85 
 86         if (ret != NULL) {
 87                 memset(ret, 0, size);
 88                 *dma_handle = virt_to_phys(ret);
 89         }
 90         return ret;
 91 }
 92 
 93 void dma_free_coherent(struct device *dev, size_t size,
 94                          void *vaddr, dma_addr_t dma_handle)
 95 {
 96         free_pages((unsigned long)vaddr, get_order(size));
 97 }
 98 
 99 #endif /* CONFIG_MMU && !CONFIG_COLDFIRE */
100 
101 EXPORT_SYMBOL(dma_alloc_coherent);
102 EXPORT_SYMBOL(dma_free_coherent);
103 
104 void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
105                                 size_t size, enum dma_data_direction dir)
106 {
107         switch (dir) {
108         case DMA_BIDIRECTIONAL:
109         case DMA_TO_DEVICE:
110                 cache_push(handle, size);
111                 break;
112         case DMA_FROM_DEVICE:
113                 cache_clear(handle, size);
114                 break;
115         default:
116                 if (printk_ratelimit())
117                         printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
118                 break;
119         }
120 }
121 EXPORT_SYMBOL(dma_sync_single_for_device);
122 
123 void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
124                             enum dma_data_direction dir)
125 {
126         int i;
127 
128         for (i = 0; i < nents; sg++, i++)
129                 dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
130 }
131 EXPORT_SYMBOL(dma_sync_sg_for_device);
132 
133 dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
134                           enum dma_data_direction dir)
135 {
136         dma_addr_t handle = virt_to_bus(addr);
137 
138         dma_sync_single_for_device(dev, handle, size, dir);
139         return handle;
140 }
141 EXPORT_SYMBOL(dma_map_single);
142 
143 dma_addr_t dma_map_page(struct device *dev, struct page *page,
144                         unsigned long offset, size_t size,
145                         enum dma_data_direction dir)
146 {
147         dma_addr_t handle = page_to_phys(page) + offset;
148 
149         dma_sync_single_for_device(dev, handle, size, dir);
150         return handle;
151 }
152 EXPORT_SYMBOL(dma_map_page);
153 
154 int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
155                enum dma_data_direction dir)
156 {
157         int i;
158 
159         for (i = 0; i < nents; sg++, i++) {
160                 sg->dma_address = sg_phys(sg);
161                 dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
162         }
163         return nents;
164 }
165 EXPORT_SYMBOL(dma_map_sg);
166 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp