linux/drivers/media/v4l2-core/videobuf2-dma-sg.c
<<
>>
Prefs
   1/*
   2 * videobuf2-dma-sg.c - dma scatter/gather memory allocator for videobuf2
   3 *
   4 * Copyright (C) 2010 Samsung Electronics
   5 *
   6 * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation.
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/mm.h>
  15#include <linux/scatterlist.h>
  16#include <linux/sched.h>
  17#include <linux/slab.h>
  18#include <linux/vmalloc.h>
  19
  20#include <media/videobuf2-core.h>
  21#include <media/videobuf2-memops.h>
  22#include <media/videobuf2-dma-sg.h>
  23
  24static int debug;
  25module_param(debug, int, 0644);
  26
  27#define dprintk(level, fmt, arg...)                                     \
  28        do {                                                            \
  29                if (debug >= level)                                     \
  30                        printk(KERN_DEBUG "vb2-dma-sg: " fmt, ## arg);  \
  31        } while (0)
  32
  33struct vb2_dma_sg_conf {
  34        struct device           *dev;
  35};
  36
  37struct vb2_dma_sg_buf {
  38        struct device                   *dev;
  39        void                            *vaddr;
  40        struct page                     **pages;
  41        struct frame_vector             *vec;
  42        int                             offset;
  43        enum dma_data_direction         dma_dir;
  44        struct sg_table                 sg_table;
  45        /*
  46         * This will point to sg_table when used with the MMAP or USERPTR
  47         * memory model, and to the dma_buf sglist when used with the
  48         * DMABUF memory model.
  49         */
  50        struct sg_table                 *dma_sgt;
  51        size_t                          size;
  52        unsigned int                    num_pages;
  53        atomic_t                        refcount;
  54        struct vb2_vmarea_handler       handler;
  55
  56        struct dma_buf_attachment       *db_attach;
  57};
  58
  59static void vb2_dma_sg_put(void *buf_priv);
  60
  61static int vb2_dma_sg_alloc_compacted(struct vb2_dma_sg_buf *buf,
  62                gfp_t gfp_flags)
  63{
  64        unsigned int last_page = 0;
  65        int size = buf->size;
  66
  67        while (size > 0) {
  68                struct page *pages;
  69                int order;
  70                int i;
  71
  72                order = get_order(size);
  73                /* Dont over allocate*/
  74                if ((PAGE_SIZE << order) > size)
  75                        order--;
  76
  77                pages = NULL;
  78                while (!pages) {
  79                        pages = alloc_pages(GFP_KERNEL | __GFP_ZERO |
  80                                        __GFP_NOWARN | gfp_flags, order);
  81                        if (pages)
  82                                break;
  83
  84                        if (order == 0) {
  85                                while (last_page--)
  86                                        __free_page(buf->pages[last_page]);
  87                                return -ENOMEM;
  88                        }
  89                        order--;
  90                }
  91
  92                split_page(pages, order);
  93                for (i = 0; i < (1 << order); i++)
  94                        buf->pages[last_page++] = &pages[i];
  95
  96                size -= PAGE_SIZE << order;
  97        }
  98
  99        return 0;
 100}
 101
 102static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size,
 103                              enum dma_data_direction dma_dir, gfp_t gfp_flags)
 104{
 105        struct vb2_dma_sg_conf *conf = alloc_ctx;
 106        struct vb2_dma_sg_buf *buf;
 107        struct sg_table *sgt;
 108        int ret;
 109        int num_pages;
 110        DEFINE_DMA_ATTRS(attrs);
 111
 112        dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
 113
 114        if (WARN_ON(alloc_ctx == NULL))
 115                return NULL;
 116        buf = kzalloc(sizeof *buf, GFP_KERNEL);
 117        if (!buf)
 118                return NULL;
 119
 120        buf->vaddr = NULL;
 121        buf->dma_dir = dma_dir;
 122        buf->offset = 0;
 123        buf->size = size;
 124        /* size is already page aligned */
 125        buf->num_pages = size >> PAGE_SHIFT;
 126        buf->dma_sgt = &buf->sg_table;
 127
 128        buf->pages = kzalloc(buf->num_pages * sizeof(struct page *),
 129                             GFP_KERNEL);
 130        if (!buf->pages)
 131                goto fail_pages_array_alloc;
 132
 133        ret = vb2_dma_sg_alloc_compacted(buf, gfp_flags);
 134        if (ret)
 135                goto fail_pages_alloc;
 136
 137        ret = sg_alloc_table_from_pages(buf->dma_sgt, buf->pages,
 138                        buf->num_pages, 0, size, GFP_KERNEL);
 139        if (ret)
 140                goto fail_table_alloc;
 141
 142        /* Prevent the device from being released while the buffer is used */
 143        buf->dev = get_device(conf->dev);
 144
 145        sgt = &buf->sg_table;
 146        /*
 147         * No need to sync to the device, this will happen later when the
 148         * prepare() memop is called.
 149         */
 150        sgt->nents = dma_map_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
 151                                      buf->dma_dir, &attrs);
 152        if (!sgt->nents)
 153                goto fail_map;
 154
 155        buf->handler.refcount = &buf->refcount;
 156        buf->handler.put = vb2_dma_sg_put;
 157        buf->handler.arg = buf;
 158
 159        atomic_inc(&buf->refcount);
 160
 161        dprintk(1, "%s: Allocated buffer of %d pages\n",
 162                __func__, buf->num_pages);
 163        return buf;
 164
 165fail_map:
 166        put_device(buf->dev);
 167        sg_free_table(buf->dma_sgt);
 168fail_table_alloc:
 169        num_pages = buf->num_pages;
 170        while (num_pages--)
 171                __free_page(buf->pages[num_pages]);
 172fail_pages_alloc:
 173        kfree(buf->pages);
 174fail_pages_array_alloc:
 175        kfree(buf);
 176        return NULL;
 177}
 178
 179static void vb2_dma_sg_put(void *buf_priv)
 180{
 181        struct vb2_dma_sg_buf *buf = buf_priv;
 182        struct sg_table *sgt = &buf->sg_table;
 183        int i = buf->num_pages;
 184
 185        if (atomic_dec_and_test(&buf->refcount)) {
 186                DEFINE_DMA_ATTRS(attrs);
 187
 188                dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
 189                dprintk(1, "%s: Freeing buffer of %d pages\n", __func__,
 190                        buf->num_pages);
 191                dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
 192                                   buf->dma_dir, &attrs);
 193                if (buf->vaddr)
 194                        vm_unmap_ram(buf->vaddr, buf->num_pages);
 195                sg_free_table(buf->dma_sgt);
 196                while (--i >= 0)
 197                        __free_page(buf->pages[i]);
 198                kfree(buf->pages);
 199                put_device(buf->dev);
 200                kfree(buf);
 201        }
 202}
 203
 204static void vb2_dma_sg_prepare(void *buf_priv)
 205{
 206        struct vb2_dma_sg_buf *buf = buf_priv;
 207        struct sg_table *sgt = buf->dma_sgt;
 208
 209        /* DMABUF exporter will flush the cache for us */
 210        if (buf->db_attach)
 211                return;
 212
 213        dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
 214}
 215
 216static void vb2_dma_sg_finish(void *buf_priv)
 217{
 218        struct vb2_dma_sg_buf *buf = buf_priv;
 219        struct sg_table *sgt = buf->dma_sgt;
 220
 221        /* DMABUF exporter will flush the cache for us */
 222        if (buf->db_attach)
 223                return;
 224
 225        dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
 226}
 227
 228static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 229                                    unsigned long size,
 230                                    enum dma_data_direction dma_dir)
 231{
 232        struct vb2_dma_sg_conf *conf = alloc_ctx;
 233        struct vb2_dma_sg_buf *buf;
 234        struct sg_table *sgt;
 235        DEFINE_DMA_ATTRS(attrs);
 236        struct frame_vector *vec;
 237
 238        dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
 239        buf = kzalloc(sizeof *buf, GFP_KERNEL);
 240        if (!buf)
 241                return NULL;
 242
 243        buf->vaddr = NULL;
 244        buf->dev = conf->dev;
 245        buf->dma_dir = dma_dir;
 246        buf->offset = vaddr & ~PAGE_MASK;
 247        buf->size = size;
 248        buf->dma_sgt = &buf->sg_table;
 249        vec = vb2_create_framevec(vaddr, size, buf->dma_dir == DMA_FROM_DEVICE);
 250        if (IS_ERR(vec))
 251                goto userptr_fail_pfnvec;
 252        buf->vec = vec;
 253
 254        buf->pages = frame_vector_pages(vec);
 255        if (IS_ERR(buf->pages))
 256                goto userptr_fail_sgtable;
 257        buf->num_pages = frame_vector_count(vec);
 258
 259        if (sg_alloc_table_from_pages(buf->dma_sgt, buf->pages,
 260                        buf->num_pages, buf->offset, size, 0))
 261                goto userptr_fail_sgtable;
 262
 263        sgt = &buf->sg_table;
 264        /*
 265         * No need to sync to the device, this will happen later when the
 266         * prepare() memop is called.
 267         */
 268        sgt->nents = dma_map_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
 269                                      buf->dma_dir, &attrs);
 270        if (!sgt->nents)
 271                goto userptr_fail_map;
 272
 273        return buf;
 274
 275userptr_fail_map:
 276        sg_free_table(&buf->sg_table);
 277userptr_fail_sgtable:
 278        vb2_destroy_framevec(vec);
 279userptr_fail_pfnvec:
 280        kfree(buf);
 281        return NULL;
 282}
 283
 284/*
 285 * @put_userptr: inform the allocator that a USERPTR buffer will no longer
 286 *               be used
 287 */
 288static void vb2_dma_sg_put_userptr(void *buf_priv)
 289{
 290        struct vb2_dma_sg_buf *buf = buf_priv;
 291        struct sg_table *sgt = &buf->sg_table;
 292        int i = buf->num_pages;
 293        DEFINE_DMA_ATTRS(attrs);
 294
 295        dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
 296
 297        dprintk(1, "%s: Releasing userspace buffer of %d pages\n",
 298               __func__, buf->num_pages);
 299        dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir,
 300                           &attrs);
 301        if (buf->vaddr)
 302                vm_unmap_ram(buf->vaddr, buf->num_pages);
 303        sg_free_table(buf->dma_sgt);
 304        while (--i >= 0) {
 305                if (buf->dma_dir == DMA_FROM_DEVICE)
 306                        set_page_dirty_lock(buf->pages[i]);
 307        }
 308        vb2_destroy_framevec(buf->vec);
 309        kfree(buf);
 310}
 311
 312static void *vb2_dma_sg_vaddr(void *buf_priv)
 313{
 314        struct vb2_dma_sg_buf *buf = buf_priv;
 315
 316        BUG_ON(!buf);
 317
 318        if (!buf->vaddr) {
 319                if (buf->db_attach)
 320                        buf->vaddr = dma_buf_vmap(buf->db_attach->dmabuf);
 321                else
 322                        buf->vaddr = vm_map_ram(buf->pages,
 323                                        buf->num_pages, -1, PAGE_KERNEL);
 324        }
 325
 326        /* add offset in case userptr is not page-aligned */
 327        return buf->vaddr ? buf->vaddr + buf->offset : NULL;
 328}
 329
 330static unsigned int vb2_dma_sg_num_users(void *buf_priv)
 331{
 332        struct vb2_dma_sg_buf *buf = buf_priv;
 333
 334        return atomic_read(&buf->refcount);
 335}
 336
 337static int vb2_dma_sg_mmap(void *buf_priv, struct vm_area_struct *vma)
 338{
 339        struct vb2_dma_sg_buf *buf = buf_priv;
 340        unsigned long uaddr = vma->vm_start;
 341        unsigned long usize = vma->vm_end - vma->vm_start;
 342        int i = 0;
 343
 344        if (!buf) {
 345                printk(KERN_ERR "No memory to map\n");
 346                return -EINVAL;
 347        }
 348
 349        do {
 350                int ret;
 351
 352                ret = vm_insert_page(vma, uaddr, buf->pages[i++]);
 353                if (ret) {
 354                        printk(KERN_ERR "Remapping memory, error: %d\n", ret);
 355                        return ret;
 356                }
 357
 358                uaddr += PAGE_SIZE;
 359                usize -= PAGE_SIZE;
 360        } while (usize > 0);
 361
 362
 363        /*
 364         * Use common vm_area operations to track buffer refcount.
 365         */
 366        vma->vm_private_data    = &buf->handler;
 367        vma->vm_ops             = &vb2_common_vm_ops;
 368
 369        vma->vm_ops->open(vma);
 370
 371        return 0;
 372}
 373
 374/*********************************************/
 375/*         DMABUF ops for exporters          */
 376/*********************************************/
 377
 378struct vb2_dma_sg_attachment {
 379        struct sg_table sgt;
 380        enum dma_data_direction dma_dir;
 381};
 382
 383static int vb2_dma_sg_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
 384        struct dma_buf_attachment *dbuf_attach)
 385{
 386        struct vb2_dma_sg_attachment *attach;
 387        unsigned int i;
 388        struct scatterlist *rd, *wr;
 389        struct sg_table *sgt;
 390        struct vb2_dma_sg_buf *buf = dbuf->priv;
 391        int ret;
 392
 393        attach = kzalloc(sizeof(*attach), GFP_KERNEL);
 394        if (!attach)
 395                return -ENOMEM;
 396
 397        sgt = &attach->sgt;
 398        /* Copy the buf->base_sgt scatter list to the attachment, as we can't
 399         * map the same scatter list to multiple attachments at the same time.
 400         */
 401        ret = sg_alloc_table(sgt, buf->dma_sgt->orig_nents, GFP_KERNEL);
 402        if (ret) {
 403                kfree(attach);
 404                return -ENOMEM;
 405        }
 406
 407        rd = buf->dma_sgt->sgl;
 408        wr = sgt->sgl;
 409        for (i = 0; i < sgt->orig_nents; ++i) {
 410                sg_set_page(wr, sg_page(rd), rd->length, rd->offset);
 411                rd = sg_next(rd);
 412                wr = sg_next(wr);
 413        }
 414
 415        attach->dma_dir = DMA_NONE;
 416        dbuf_attach->priv = attach;
 417
 418        return 0;
 419}
 420
 421static void vb2_dma_sg_dmabuf_ops_detach(struct dma_buf *dbuf,
 422        struct dma_buf_attachment *db_attach)
 423{
 424        struct vb2_dma_sg_attachment *attach = db_attach->priv;
 425        struct sg_table *sgt;
 426
 427        if (!attach)
 428                return;
 429
 430        sgt = &attach->sgt;
 431
 432        /* release the scatterlist cache */
 433        if (attach->dma_dir != DMA_NONE)
 434                dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
 435                        attach->dma_dir);
 436        sg_free_table(sgt);
 437        kfree(attach);
 438        db_attach->priv = NULL;
 439}
 440
 441static struct sg_table *vb2_dma_sg_dmabuf_ops_map(
 442        struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir)
 443{
 444        struct vb2_dma_sg_attachment *attach = db_attach->priv;
 445        /* stealing dmabuf mutex to serialize map/unmap operations */
 446        struct mutex *lock = &db_attach->dmabuf->lock;
 447        struct sg_table *sgt;
 448
 449        mutex_lock(lock);
 450
 451        sgt = &attach->sgt;
 452        /* return previously mapped sg table */
 453        if (attach->dma_dir == dma_dir) {
 454                mutex_unlock(lock);
 455                return sgt;
 456        }
 457
 458        /* release any previous cache */
 459        if (attach->dma_dir != DMA_NONE) {
 460                dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
 461                        attach->dma_dir);
 462                attach->dma_dir = DMA_NONE;
 463        }
 464
 465        /* mapping to the client with new direction */
 466        sgt->nents = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
 467                                dma_dir);
 468        if (!sgt->nents) {
 469                pr_err("failed to map scatterlist\n");
 470                mutex_unlock(lock);
 471                return ERR_PTR(-EIO);
 472        }
 473
 474        attach->dma_dir = dma_dir;
 475
 476        mutex_unlock(lock);
 477
 478        return sgt;
 479}
 480
 481static void vb2_dma_sg_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach,
 482        struct sg_table *sgt, enum dma_data_direction dma_dir)
 483{
 484        /* nothing to be done here */
 485}
 486
 487static void vb2_dma_sg_dmabuf_ops_release(struct dma_buf *dbuf)
 488{
 489        /* drop reference obtained in vb2_dma_sg_get_dmabuf */
 490        vb2_dma_sg_put(dbuf->priv);
 491}
 492
 493static void *vb2_dma_sg_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum)
 494{
 495        struct vb2_dma_sg_buf *buf = dbuf->priv;
 496
 497        return buf->vaddr ? buf->vaddr + pgnum * PAGE_SIZE : NULL;
 498}
 499
 500static void *vb2_dma_sg_dmabuf_ops_vmap(struct dma_buf *dbuf)
 501{
 502        struct vb2_dma_sg_buf *buf = dbuf->priv;
 503
 504        return vb2_dma_sg_vaddr(buf);
 505}
 506
 507static int vb2_dma_sg_dmabuf_ops_mmap(struct dma_buf *dbuf,
 508        struct vm_area_struct *vma)
 509{
 510        return vb2_dma_sg_mmap(dbuf->priv, vma);
 511}
 512
 513static struct dma_buf_ops vb2_dma_sg_dmabuf_ops = {
 514        .attach = vb2_dma_sg_dmabuf_ops_attach,
 515        .detach = vb2_dma_sg_dmabuf_ops_detach,
 516        .map_dma_buf = vb2_dma_sg_dmabuf_ops_map,
 517        .unmap_dma_buf = vb2_dma_sg_dmabuf_ops_unmap,
 518        .kmap = vb2_dma_sg_dmabuf_ops_kmap,
 519        .kmap_atomic = vb2_dma_sg_dmabuf_ops_kmap,
 520        .vmap = vb2_dma_sg_dmabuf_ops_vmap,
 521        .mmap = vb2_dma_sg_dmabuf_ops_mmap,
 522        .release = vb2_dma_sg_dmabuf_ops_release,
 523};
 524
 525static struct dma_buf *vb2_dma_sg_get_dmabuf(void *buf_priv, unsigned long flags)
 526{
 527        struct vb2_dma_sg_buf *buf = buf_priv;
 528        struct dma_buf *dbuf;
 529        DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
 530
 531        exp_info.ops = &vb2_dma_sg_dmabuf_ops;
 532        exp_info.size = buf->size;
 533        exp_info.flags = flags;
 534        exp_info.priv = buf;
 535
 536        if (WARN_ON(!buf->dma_sgt))
 537                return NULL;
 538
 539        dbuf = dma_buf_export(&exp_info);
 540        if (IS_ERR(dbuf))
 541                return NULL;
 542
 543        /* dmabuf keeps reference to vb2 buffer */
 544        atomic_inc(&buf->refcount);
 545
 546        return dbuf;
 547}
 548
 549/*********************************************/
 550/*       callbacks for DMABUF buffers        */
 551/*********************************************/
 552
 553static int vb2_dma_sg_map_dmabuf(void *mem_priv)
 554{
 555        struct vb2_dma_sg_buf *buf = mem_priv;
 556        struct sg_table *sgt;
 557
 558        if (WARN_ON(!buf->db_attach)) {
 559                pr_err("trying to pin a non attached buffer\n");
 560                return -EINVAL;
 561        }
 562
 563        if (WARN_ON(buf->dma_sgt)) {
 564                pr_err("dmabuf buffer is already pinned\n");
 565                return 0;
 566        }
 567
 568        /* get the associated scatterlist for this buffer */
 569        sgt = dma_buf_map_attachment(buf->db_attach, buf->dma_dir);
 570        if (IS_ERR(sgt)) {
 571                pr_err("Error getting dmabuf scatterlist\n");
 572                return -EINVAL;
 573        }
 574
 575        buf->dma_sgt = sgt;
 576        buf->vaddr = NULL;
 577
 578        return 0;
 579}
 580
 581static void vb2_dma_sg_unmap_dmabuf(void *mem_priv)
 582{
 583        struct vb2_dma_sg_buf *buf = mem_priv;
 584        struct sg_table *sgt = buf->dma_sgt;
 585
 586        if (WARN_ON(!buf->db_attach)) {
 587                pr_err("trying to unpin a not attached buffer\n");
 588                return;
 589        }
 590
 591        if (WARN_ON(!sgt)) {
 592                pr_err("dmabuf buffer is already unpinned\n");
 593                return;
 594        }
 595
 596        if (buf->vaddr) {
 597                dma_buf_vunmap(buf->db_attach->dmabuf, buf->vaddr);
 598                buf->vaddr = NULL;
 599        }
 600        dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir);
 601
 602        buf->dma_sgt = NULL;
 603}
 604
 605static void vb2_dma_sg_detach_dmabuf(void *mem_priv)
 606{
 607        struct vb2_dma_sg_buf *buf = mem_priv;
 608
 609        /* if vb2 works correctly you should never detach mapped buffer */
 610        if (WARN_ON(buf->dma_sgt))
 611                vb2_dma_sg_unmap_dmabuf(buf);
 612
 613        /* detach this attachment */
 614        dma_buf_detach(buf->db_attach->dmabuf, buf->db_attach);
 615        kfree(buf);
 616}
 617
 618static void *vb2_dma_sg_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
 619        unsigned long size, enum dma_data_direction dma_dir)
 620{
 621        struct vb2_dma_sg_conf *conf = alloc_ctx;
 622        struct vb2_dma_sg_buf *buf;
 623        struct dma_buf_attachment *dba;
 624
 625        if (dbuf->size < size)
 626                return ERR_PTR(-EFAULT);
 627
 628        buf = kzalloc(sizeof(*buf), GFP_KERNEL);
 629        if (!buf)
 630                return ERR_PTR(-ENOMEM);
 631
 632        buf->dev = conf->dev;
 633        /* create attachment for the dmabuf with the user device */
 634        dba = dma_buf_attach(dbuf, buf->dev);
 635        if (IS_ERR(dba)) {
 636                pr_err("failed to attach dmabuf\n");
 637                kfree(buf);
 638                return dba;
 639        }
 640
 641        buf->dma_dir = dma_dir;
 642        buf->size = size;
 643        buf->db_attach = dba;
 644
 645        return buf;
 646}
 647
 648static void *vb2_dma_sg_cookie(void *buf_priv)
 649{
 650        struct vb2_dma_sg_buf *buf = buf_priv;
 651
 652        return buf->dma_sgt;
 653}
 654
 655const struct vb2_mem_ops vb2_dma_sg_memops = {
 656        .alloc          = vb2_dma_sg_alloc,
 657        .put            = vb2_dma_sg_put,
 658        .get_userptr    = vb2_dma_sg_get_userptr,
 659        .put_userptr    = vb2_dma_sg_put_userptr,
 660        .prepare        = vb2_dma_sg_prepare,
 661        .finish         = vb2_dma_sg_finish,
 662        .vaddr          = vb2_dma_sg_vaddr,
 663        .mmap           = vb2_dma_sg_mmap,
 664        .num_users      = vb2_dma_sg_num_users,
 665        .get_dmabuf     = vb2_dma_sg_get_dmabuf,
 666        .map_dmabuf     = vb2_dma_sg_map_dmabuf,
 667        .unmap_dmabuf   = vb2_dma_sg_unmap_dmabuf,
 668        .attach_dmabuf  = vb2_dma_sg_attach_dmabuf,
 669        .detach_dmabuf  = vb2_dma_sg_detach_dmabuf,
 670        .cookie         = vb2_dma_sg_cookie,
 671};
 672EXPORT_SYMBOL_GPL(vb2_dma_sg_memops);
 673
 674void *vb2_dma_sg_init_ctx(struct device *dev)
 675{
 676        struct vb2_dma_sg_conf *conf;
 677
 678        conf = kzalloc(sizeof(*conf), GFP_KERNEL);
 679        if (!conf)
 680                return ERR_PTR(-ENOMEM);
 681
 682        conf->dev = dev;
 683
 684        return conf;
 685}
 686EXPORT_SYMBOL_GPL(vb2_dma_sg_init_ctx);
 687
 688void vb2_dma_sg_cleanup_ctx(void *alloc_ctx)
 689{
 690        if (!IS_ERR_OR_NULL(alloc_ctx))
 691                kfree(alloc_ctx);
 692}
 693EXPORT_SYMBOL_GPL(vb2_dma_sg_cleanup_ctx);
 694
 695MODULE_DESCRIPTION("dma scatter/gather memory handling routines for videobuf2");
 696MODULE_AUTHOR("Andrzej Pietrasiewicz");
 697MODULE_LICENSE("GPL");
 698