Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at cfd63736726a7fabb3dd89ea91cff143ac4dc8a7 374 lines 8.8 kB view raw
1/* 2 * drivers/base/dma-mapping.c - arch-independent dma-mapping routines 3 * 4 * Copyright (c) 2006 SUSE Linux Products GmbH 5 * Copyright (c) 2006 Tejun Heo <teheo@suse.de> 6 * 7 * This file is released under the GPLv2. 8 */ 9 10#include <linux/acpi.h> 11#include <linux/dma-mapping.h> 12#include <linux/export.h> 13#include <linux/gfp.h> 14#include <linux/of_device.h> 15#include <linux/slab.h> 16#include <linux/vmalloc.h> 17 18/* 19 * Managed DMA API 20 */ 21struct dma_devres { 22 size_t size; 23 void *vaddr; 24 dma_addr_t dma_handle; 25 unsigned long attrs; 26}; 27 28static void dmam_release(struct device *dev, void *res) 29{ 30 struct dma_devres *this = res; 31 32 dma_free_attrs(dev, this->size, this->vaddr, this->dma_handle, 33 this->attrs); 34} 35 36static int dmam_match(struct device *dev, void *res, void *match_data) 37{ 38 struct dma_devres *this = res, *match = match_data; 39 40 if (this->vaddr == match->vaddr) { 41 WARN_ON(this->size != match->size || 42 this->dma_handle != match->dma_handle); 43 return 1; 44 } 45 return 0; 46} 47 48/** 49 * dmam_alloc_coherent - Managed dma_alloc_coherent() 50 * @dev: Device to allocate coherent memory for 51 * @size: Size of allocation 52 * @dma_handle: Out argument for allocated DMA handle 53 * @gfp: Allocation flags 54 * 55 * Managed dma_alloc_coherent(). Memory allocated using this function 56 * will be automatically released on driver detach. 57 * 58 * RETURNS: 59 * Pointer to allocated memory on success, NULL on failure. 60 */ 61void *dmam_alloc_coherent(struct device *dev, size_t size, 62 dma_addr_t *dma_handle, gfp_t gfp) 63{ 64 struct dma_devres *dr; 65 void *vaddr; 66 67 dr = devres_alloc(dmam_release, sizeof(*dr), gfp); 68 if (!dr) 69 return NULL; 70 71 vaddr = dma_alloc_coherent(dev, size, dma_handle, gfp); 72 if (!vaddr) { 73 devres_free(dr); 74 return NULL; 75 } 76 77 dr->vaddr = vaddr; 78 dr->dma_handle = *dma_handle; 79 dr->size = size; 80 81 devres_add(dev, dr); 82 83 return vaddr; 84} 85EXPORT_SYMBOL(dmam_alloc_coherent); 86 87/** 88 * dmam_free_coherent - Managed dma_free_coherent() 89 * @dev: Device to free coherent memory for 90 * @size: Size of allocation 91 * @vaddr: Virtual address of the memory to free 92 * @dma_handle: DMA handle of the memory to free 93 * 94 * Managed dma_free_coherent(). 95 */ 96void dmam_free_coherent(struct device *dev, size_t size, void *vaddr, 97 dma_addr_t dma_handle) 98{ 99 struct dma_devres match_data = { size, vaddr, dma_handle }; 100 101 dma_free_coherent(dev, size, vaddr, dma_handle); 102 WARN_ON(devres_destroy(dev, dmam_release, dmam_match, &match_data)); 103} 104EXPORT_SYMBOL(dmam_free_coherent); 105 106/** 107 * dmam_alloc_attrs - Managed dma_alloc_attrs() 108 * @dev: Device to allocate non_coherent memory for 109 * @size: Size of allocation 110 * @dma_handle: Out argument for allocated DMA handle 111 * @gfp: Allocation flags 112 * @attrs: Flags in the DMA_ATTR_* namespace. 113 * 114 * Managed dma_alloc_attrs(). Memory allocated using this function will be 115 * automatically released on driver detach. 116 * 117 * RETURNS: 118 * Pointer to allocated memory on success, NULL on failure. 119 */ 120void *dmam_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle, 121 gfp_t gfp, unsigned long attrs) 122{ 123 struct dma_devres *dr; 124 void *vaddr; 125 126 dr = devres_alloc(dmam_release, sizeof(*dr), gfp); 127 if (!dr) 128 return NULL; 129 130 vaddr = dma_alloc_attrs(dev, size, dma_handle, gfp, attrs); 131 if (!vaddr) { 132 devres_free(dr); 133 return NULL; 134 } 135 136 dr->vaddr = vaddr; 137 dr->dma_handle = *dma_handle; 138 dr->size = size; 139 dr->attrs = attrs; 140 141 devres_add(dev, dr); 142 143 return vaddr; 144} 145EXPORT_SYMBOL(dmam_alloc_attrs); 146 147#ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT 148 149static void dmam_coherent_decl_release(struct device *dev, void *res) 150{ 151 dma_release_declared_memory(dev); 152} 153 154/** 155 * dmam_declare_coherent_memory - Managed dma_declare_coherent_memory() 156 * @dev: Device to declare coherent memory for 157 * @phys_addr: Physical address of coherent memory to be declared 158 * @device_addr: Device address of coherent memory to be declared 159 * @size: Size of coherent memory to be declared 160 * @flags: Flags 161 * 162 * Managed dma_declare_coherent_memory(). 163 * 164 * RETURNS: 165 * 0 on success, -errno on failure. 166 */ 167int dmam_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, 168 dma_addr_t device_addr, size_t size, int flags) 169{ 170 void *res; 171 int rc; 172 173 res = devres_alloc(dmam_coherent_decl_release, 0, GFP_KERNEL); 174 if (!res) 175 return -ENOMEM; 176 177 rc = dma_declare_coherent_memory(dev, phys_addr, device_addr, size, 178 flags); 179 if (rc) { 180 devres_add(dev, res); 181 rc = 0; 182 } else { 183 devres_free(res); 184 rc = -ENOMEM; 185 } 186 187 return rc; 188} 189EXPORT_SYMBOL(dmam_declare_coherent_memory); 190 191/** 192 * dmam_release_declared_memory - Managed dma_release_declared_memory(). 193 * @dev: Device to release declared coherent memory for 194 * 195 * Managed dmam_release_declared_memory(). 196 */ 197void dmam_release_declared_memory(struct device *dev) 198{ 199 WARN_ON(devres_destroy(dev, dmam_coherent_decl_release, NULL, NULL)); 200} 201EXPORT_SYMBOL(dmam_release_declared_memory); 202 203#endif 204 205/* 206 * Create scatter-list for the already allocated DMA buffer. 207 */ 208int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt, 209 void *cpu_addr, dma_addr_t handle, size_t size) 210{ 211 struct page *page = virt_to_page(cpu_addr); 212 int ret; 213 214 ret = sg_alloc_table(sgt, 1, GFP_KERNEL); 215 if (unlikely(ret)) 216 return ret; 217 218 sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0); 219 return 0; 220} 221EXPORT_SYMBOL(dma_common_get_sgtable); 222 223/* 224 * Create userspace mapping for the DMA-coherent memory. 225 */ 226int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, 227 void *cpu_addr, dma_addr_t dma_addr, size_t size) 228{ 229 int ret = -ENXIO; 230#ifndef CONFIG_ARCH_NO_COHERENT_DMA_MMAP 231 unsigned long user_count = vma_pages(vma); 232 unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; 233 unsigned long pfn = page_to_pfn(virt_to_page(cpu_addr)); 234 unsigned long off = vma->vm_pgoff; 235 236 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 237 238 if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret)) 239 return ret; 240 241 if (off < count && user_count <= (count - off)) { 242 ret = remap_pfn_range(vma, vma->vm_start, 243 pfn + off, 244 user_count << PAGE_SHIFT, 245 vma->vm_page_prot); 246 } 247#endif /* !CONFIG_ARCH_NO_COHERENT_DMA_MMAP */ 248 249 return ret; 250} 251EXPORT_SYMBOL(dma_common_mmap); 252 253#ifdef CONFIG_MMU 254static struct vm_struct *__dma_common_pages_remap(struct page **pages, 255 size_t size, unsigned long vm_flags, pgprot_t prot, 256 const void *caller) 257{ 258 struct vm_struct *area; 259 260 area = get_vm_area_caller(size, vm_flags, caller); 261 if (!area) 262 return NULL; 263 264 if (map_vm_area(area, prot, pages)) { 265 vunmap(area->addr); 266 return NULL; 267 } 268 269 return area; 270} 271 272/* 273 * remaps an array of PAGE_SIZE pages into another vm_area 274 * Cannot be used in non-sleeping contexts 275 */ 276void *dma_common_pages_remap(struct page **pages, size_t size, 277 unsigned long vm_flags, pgprot_t prot, 278 const void *caller) 279{ 280 struct vm_struct *area; 281 282 area = __dma_common_pages_remap(pages, size, vm_flags, prot, caller); 283 if (!area) 284 return NULL; 285 286 area->pages = pages; 287 288 return area->addr; 289} 290 291/* 292 * remaps an allocated contiguous region into another vm_area. 293 * Cannot be used in non-sleeping contexts 294 */ 295 296void *dma_common_contiguous_remap(struct page *page, size_t size, 297 unsigned long vm_flags, 298 pgprot_t prot, const void *caller) 299{ 300 int i; 301 struct page **pages; 302 struct vm_struct *area; 303 304 pages = kmalloc(sizeof(struct page *) << get_order(size), GFP_KERNEL); 305 if (!pages) 306 return NULL; 307 308 for (i = 0; i < (size >> PAGE_SHIFT); i++) 309 pages[i] = nth_page(page, i); 310 311 area = __dma_common_pages_remap(pages, size, vm_flags, prot, caller); 312 313 kfree(pages); 314 315 if (!area) 316 return NULL; 317 return area->addr; 318} 319 320/* 321 * unmaps a range previously mapped by dma_common_*_remap 322 */ 323void dma_common_free_remap(void *cpu_addr, size_t size, unsigned long vm_flags) 324{ 325 struct vm_struct *area = find_vm_area(cpu_addr); 326 327 if (!area || (area->flags & vm_flags) != vm_flags) { 328 WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr); 329 return; 330 } 331 332 unmap_kernel_range((unsigned long)cpu_addr, PAGE_ALIGN(size)); 333 vunmap(cpu_addr); 334} 335#endif 336 337/* 338 * Common configuration to enable DMA API use for a device 339 */ 340#include <linux/pci.h> 341 342int dma_configure(struct device *dev) 343{ 344 struct device *bridge = NULL, *dma_dev = dev; 345 enum dev_dma_attr attr; 346 int ret = 0; 347 348 if (dev_is_pci(dev)) { 349 bridge = pci_get_host_bridge_device(to_pci_dev(dev)); 350 dma_dev = bridge; 351 if (IS_ENABLED(CONFIG_OF) && dma_dev->parent && 352 dma_dev->parent->of_node) 353 dma_dev = dma_dev->parent; 354 } 355 356 if (dma_dev->of_node) { 357 ret = of_dma_configure(dev, dma_dev->of_node); 358 } else if (has_acpi_companion(dma_dev)) { 359 attr = acpi_get_dma_attr(to_acpi_device_node(dma_dev->fwnode)); 360 if (attr != DEV_DMA_NOT_SUPPORTED) 361 ret = acpi_dma_configure(dev, attr); 362 } 363 364 if (bridge) 365 pci_put_host_bridge_device(bridge); 366 367 return ret; 368} 369 370void dma_deconfigure(struct device *dev) 371{ 372 of_dma_deconfigure(dev); 373 acpi_dma_deconfigure(dev); 374}