linux/drivers/base/dma-mapping.c
<<
>>
Prefs
   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/dma-mapping.h>
  11
  12/*
  13 * Managed DMA API
  14 */
  15struct dma_devres {
  16        size_t          size;
  17        void            *vaddr;
  18        dma_addr_t      dma_handle;
  19};
  20
  21static void dmam_coherent_release(struct device *dev, void *res)
  22{
  23        struct dma_devres *this = res;
  24
  25        dma_free_coherent(dev, this->size, this->vaddr, this->dma_handle);
  26}
  27
  28static void dmam_noncoherent_release(struct device *dev, void *res)
  29{
  30        struct dma_devres *this = res;
  31
  32        dma_free_noncoherent(dev, this->size, this->vaddr, this->dma_handle);
  33}
  34
  35static int dmam_match(struct device *dev, void *res, void *match_data)
  36{
  37        struct dma_devres *this = res, *match = match_data;
  38
  39        if (this->vaddr == match->vaddr) {
  40                WARN_ON(this->size != match->size ||
  41                        this->dma_handle != match->dma_handle);
  42                return 1;
  43        }
  44        return 0;
  45}
  46
  47/**
  48 * dmam_alloc_coherent - Managed dma_alloc_coherent()
  49 * @dev: Device to allocate coherent memory for
  50 * @size: Size of allocation
  51 * @dma_handle: Out argument for allocated DMA handle
  52 * @gfp: Allocation flags
  53 *
  54 * Managed dma_alloc_coherent().  Memory allocated using this function
  55 * will be automatically released on driver detach.
  56 *
  57 * RETURNS:
  58 * Pointer to allocated memory on success, NULL on failure.
  59 */
  60void * dmam_alloc_coherent(struct device *dev, size_t size,
  61                           dma_addr_t *dma_handle, gfp_t gfp)
  62{
  63        struct dma_devres *dr;
  64        void *vaddr;
  65
  66        dr = devres_alloc(dmam_coherent_release, sizeof(*dr), gfp);
  67        if (!dr)
  68                return NULL;
  69
  70        vaddr = dma_alloc_coherent(dev, size, dma_handle, gfp);
  71        if (!vaddr) {
  72                devres_free(dr);
  73                return NULL;
  74        }
  75
  76        dr->vaddr = vaddr;
  77        dr->dma_handle = *dma_handle;
  78        dr->size = size;
  79
  80        devres_add(dev, dr);
  81
  82        return vaddr;
  83}
  84EXPORT_SYMBOL(dmam_alloc_coherent);
  85
  86/**
  87 * dmam_free_coherent - Managed dma_free_coherent()
  88 * @dev: Device to free coherent memory for
  89 * @size: Size of allocation
  90 * @vaddr: Virtual address of the memory to free
  91 * @dma_handle: DMA handle of the memory to free
  92 *
  93 * Managed dma_free_coherent().
  94 */
  95void dmam_free_coherent(struct device *dev, size_t size, void *vaddr,
  96                        dma_addr_t dma_handle)
  97{
  98        struct dma_devres match_data = { size, vaddr, dma_handle };
  99
 100        dma_free_coherent(dev, size, vaddr, dma_handle);
 101        WARN_ON(devres_destroy(dev, dmam_coherent_release, dmam_match,
 102                               &match_data));
 103}
 104EXPORT_SYMBOL(dmam_free_coherent);
 105
 106/**
 107 * dmam_alloc_non_coherent - Managed dma_alloc_non_coherent()
 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 *
 113 * Managed dma_alloc_non_coherent().  Memory allocated using this
 114 * function will be automatically released on driver detach.
 115 *
 116 * RETURNS:
 117 * Pointer to allocated memory on success, NULL on failure.
 118 */
 119void *dmam_alloc_noncoherent(struct device *dev, size_t size,
 120                             dma_addr_t *dma_handle, gfp_t gfp)
 121{
 122        struct dma_devres *dr;
 123        void *vaddr;
 124
 125        dr = devres_alloc(dmam_noncoherent_release, sizeof(*dr), gfp);
 126        if (!dr)
 127                return NULL;
 128
 129        vaddr = dma_alloc_noncoherent(dev, size, dma_handle, gfp);
 130        if (!vaddr) {
 131                devres_free(dr);
 132                return NULL;
 133        }
 134
 135        dr->vaddr = vaddr;
 136        dr->dma_handle = *dma_handle;
 137        dr->size = size;
 138
 139        devres_add(dev, dr);
 140
 141        return vaddr;
 142}
 143EXPORT_SYMBOL(dmam_alloc_noncoherent);
 144
 145/**
 146 * dmam_free_coherent - Managed dma_free_noncoherent()
 147 * @dev: Device to free noncoherent memory for
 148 * @size: Size of allocation
 149 * @vaddr: Virtual address of the memory to free
 150 * @dma_handle: DMA handle of the memory to free
 151 *
 152 * Managed dma_free_noncoherent().
 153 */
 154void dmam_free_noncoherent(struct device *dev, size_t size, void *vaddr,
 155                           dma_addr_t dma_handle)
 156{
 157        struct dma_devres match_data = { size, vaddr, dma_handle };
 158
 159        dma_free_noncoherent(dev, size, vaddr, dma_handle);
 160        WARN_ON(!devres_destroy(dev, dmam_noncoherent_release, dmam_match,
 161                                &match_data));
 162}
 163EXPORT_SYMBOL(dmam_free_noncoherent);
 164
 165#ifdef ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
 166
 167static void dmam_coherent_decl_release(struct device *dev, void *res)
 168{
 169        dma_release_declared_memory(dev);
 170}
 171
 172/**
 173 * dmam_declare_coherent_memory - Managed dma_declare_coherent_memory()
 174 * @dev: Device to declare coherent memory for
 175 * @bus_addr: Bus address of coherent memory to be declared
 176 * @device_addr: Device address of coherent memory to be declared
 177 * @size: Size of coherent memory to be declared
 178 * @flags: Flags
 179 *
 180 * Managed dma_declare_coherent_memory().
 181 *
 182 * RETURNS:
 183 * 0 on success, -errno on failure.
 184 */
 185int dmam_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
 186                                 dma_addr_t device_addr, size_t size, int flags)
 187{
 188        void *res;
 189        int rc;
 190
 191        res = devres_alloc(dmam_coherent_decl_release, 0, GFP_KERNEL);
 192        if (!res)
 193                return -ENOMEM;
 194
 195        rc = dma_declare_coherent_memory(dev, bus_addr, device_addr, size,
 196                                         flags);
 197        if (rc == 0)
 198                devres_add(dev, res);
 199        else
 200                devres_free(res);
 201
 202        return rc;
 203}
 204EXPORT_SYMBOL(dmam_declare_coherent_memory);
 205
 206/**
 207 * dmam_release_declared_memory - Managed dma_release_declared_memory().
 208 * @dev: Device to release declared coherent memory for
 209 *
 210 * Managed dmam_release_declared_memory().
 211 */
 212void dmam_release_declared_memory(struct device *dev)
 213{
 214        WARN_ON(devres_destroy(dev, dmam_coherent_decl_release, NULL, NULL));
 215}
 216EXPORT_SYMBOL(dmam_release_declared_memory);
 217
 218#endif
 219