LCOV - code coverage report
Current view: top level - drivers/gpu/drm/i915/gem - i915_gem_dmabuf.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 136 0.0 %
Date: 2022-03-28 16:04:14 Functions: 0 11 0.0 %
Branches: 0 44 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * SPDX-License-Identifier: MIT
       3                 :            :  *
       4                 :            :  * Copyright 2012 Red Hat Inc
       5                 :            :  */
       6                 :            : 
       7                 :            : #include <linux/dma-buf.h>
       8                 :            : #include <linux/highmem.h>
       9                 :            : #include <linux/dma-resv.h>
      10                 :            : 
      11                 :            : #include "i915_drv.h"
      12                 :            : #include "i915_gem_object.h"
      13                 :            : #include "i915_scatterlist.h"
      14                 :            : 
      15                 :          0 : static struct drm_i915_gem_object *dma_buf_to_obj(struct dma_buf *buf)
      16                 :            : {
      17                 :          0 :         return to_intel_bo(buf->priv);
      18                 :            : }
      19                 :            : 
      20                 :          0 : static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachment,
      21                 :            :                                              enum dma_data_direction dir)
      22                 :            : {
      23                 :          0 :         struct drm_i915_gem_object *obj = dma_buf_to_obj(attachment->dmabuf);
      24                 :          0 :         struct sg_table *st;
      25                 :          0 :         struct scatterlist *src, *dst;
      26                 :          0 :         int ret, i;
      27                 :            : 
      28                 :          0 :         ret = i915_gem_object_pin_pages(obj);
      29         [ #  # ]:          0 :         if (ret)
      30                 :          0 :                 goto err;
      31                 :            : 
      32                 :            :         /* Copy sg so that we make an independent mapping */
      33                 :          0 :         st = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
      34         [ #  # ]:          0 :         if (st == NULL) {
      35                 :          0 :                 ret = -ENOMEM;
      36                 :          0 :                 goto err_unpin_pages;
      37                 :            :         }
      38                 :            : 
      39                 :          0 :         ret = sg_alloc_table(st, obj->mm.pages->nents, GFP_KERNEL);
      40         [ #  # ]:          0 :         if (ret)
      41                 :          0 :                 goto err_free;
      42                 :            : 
      43                 :          0 :         src = obj->mm.pages->sgl;
      44                 :          0 :         dst = st->sgl;
      45         [ #  # ]:          0 :         for (i = 0; i < obj->mm.pages->nents; i++) {
      46                 :          0 :                 sg_set_page(dst, sg_page(src), src->length, 0);
      47                 :          0 :                 dst = sg_next(dst);
      48                 :          0 :                 src = sg_next(src);
      49                 :            :         }
      50                 :            : 
      51         [ #  # ]:          0 :         if (!dma_map_sg(attachment->dev, st->sgl, st->nents, dir)) {
      52                 :          0 :                 ret = -ENOMEM;
      53                 :          0 :                 goto err_free_sg;
      54                 :            :         }
      55                 :            : 
      56                 :            :         return st;
      57                 :            : 
      58                 :            : err_free_sg:
      59                 :          0 :         sg_free_table(st);
      60                 :          0 : err_free:
      61                 :          0 :         kfree(st);
      62                 :          0 : err_unpin_pages:
      63                 :          0 :         i915_gem_object_unpin_pages(obj);
      64                 :          0 : err:
      65                 :          0 :         return ERR_PTR(ret);
      66                 :            : }
      67                 :            : 
      68                 :          0 : static void i915_gem_unmap_dma_buf(struct dma_buf_attachment *attachment,
      69                 :            :                                    struct sg_table *sg,
      70                 :            :                                    enum dma_data_direction dir)
      71                 :            : {
      72                 :          0 :         struct drm_i915_gem_object *obj = dma_buf_to_obj(attachment->dmabuf);
      73                 :            : 
      74                 :          0 :         dma_unmap_sg(attachment->dev, sg->sgl, sg->nents, dir);
      75                 :          0 :         sg_free_table(sg);
      76                 :          0 :         kfree(sg);
      77                 :            : 
      78                 :          0 :         i915_gem_object_unpin_pages(obj);
      79                 :          0 : }
      80                 :            : 
      81                 :          0 : static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf)
      82                 :            : {
      83                 :          0 :         struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
      84                 :            : 
      85                 :          0 :         return i915_gem_object_pin_map(obj, I915_MAP_WB);
      86                 :            : }
      87                 :            : 
      88                 :          0 : static void i915_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
      89                 :            : {
      90                 :          0 :         struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
      91                 :            : 
      92                 :          0 :         i915_gem_object_flush_map(obj);
      93                 :          0 :         i915_gem_object_unpin_map(obj);
      94                 :          0 : }
      95                 :            : 
      96                 :          0 : static int i915_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma)
      97                 :            : {
      98         [ #  # ]:          0 :         struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
      99                 :          0 :         int ret;
     100                 :            : 
     101         [ #  # ]:          0 :         if (obj->base.size < vma->vm_end - vma->vm_start)
     102                 :            :                 return -EINVAL;
     103                 :            : 
     104         [ #  # ]:          0 :         if (!obj->base.filp)
     105                 :            :                 return -ENODEV;
     106                 :            : 
     107                 :          0 :         ret = call_mmap(obj->base.filp, vma);
     108         [ #  # ]:          0 :         if (ret)
     109                 :            :                 return ret;
     110                 :            : 
     111                 :          0 :         fput(vma->vm_file);
     112                 :          0 :         vma->vm_file = get_file(obj->base.filp);
     113                 :            : 
     114                 :          0 :         return 0;
     115                 :            : }
     116                 :            : 
     117                 :          0 : static int i915_gem_begin_cpu_access(struct dma_buf *dma_buf, enum dma_data_direction direction)
     118                 :            : {
     119                 :          0 :         struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
     120                 :          0 :         bool write = (direction == DMA_BIDIRECTIONAL || direction == DMA_TO_DEVICE);
     121                 :          0 :         int err;
     122                 :            : 
     123                 :          0 :         err = i915_gem_object_pin_pages(obj);
     124         [ #  # ]:          0 :         if (err)
     125                 :            :                 return err;
     126                 :            : 
     127                 :          0 :         err = i915_gem_object_lock_interruptible(obj);
     128         [ #  # ]:          0 :         if (err)
     129                 :          0 :                 goto out;
     130                 :            : 
     131                 :          0 :         err = i915_gem_object_set_to_cpu_domain(obj, write);
     132                 :          0 :         i915_gem_object_unlock(obj);
     133                 :            : 
     134                 :          0 : out:
     135                 :          0 :         i915_gem_object_unpin_pages(obj);
     136                 :          0 :         return err;
     137                 :            : }
     138                 :            : 
     139                 :          0 : static int i915_gem_end_cpu_access(struct dma_buf *dma_buf, enum dma_data_direction direction)
     140                 :            : {
     141                 :          0 :         struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
     142                 :          0 :         int err;
     143                 :            : 
     144                 :          0 :         err = i915_gem_object_pin_pages(obj);
     145         [ #  # ]:          0 :         if (err)
     146                 :            :                 return err;
     147                 :            : 
     148                 :          0 :         err = i915_gem_object_lock_interruptible(obj);
     149         [ #  # ]:          0 :         if (err)
     150                 :          0 :                 goto out;
     151                 :            : 
     152                 :          0 :         err = i915_gem_object_set_to_gtt_domain(obj, false);
     153                 :          0 :         i915_gem_object_unlock(obj);
     154                 :            : 
     155                 :          0 : out:
     156                 :          0 :         i915_gem_object_unpin_pages(obj);
     157                 :          0 :         return err;
     158                 :            : }
     159                 :            : 
     160                 :            : static const struct dma_buf_ops i915_dmabuf_ops =  {
     161                 :            :         .map_dma_buf = i915_gem_map_dma_buf,
     162                 :            :         .unmap_dma_buf = i915_gem_unmap_dma_buf,
     163                 :            :         .release = drm_gem_dmabuf_release,
     164                 :            :         .mmap = i915_gem_dmabuf_mmap,
     165                 :            :         .vmap = i915_gem_dmabuf_vmap,
     166                 :            :         .vunmap = i915_gem_dmabuf_vunmap,
     167                 :            :         .begin_cpu_access = i915_gem_begin_cpu_access,
     168                 :            :         .end_cpu_access = i915_gem_end_cpu_access,
     169                 :            : };
     170                 :            : 
     171                 :          0 : struct dma_buf *i915_gem_prime_export(struct drm_gem_object *gem_obj, int flags)
     172                 :            : {
     173         [ #  # ]:          0 :         struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
     174                 :          0 :         DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
     175                 :            : 
     176                 :          0 :         exp_info.ops = &i915_dmabuf_ops;
     177                 :          0 :         exp_info.size = gem_obj->size;
     178                 :          0 :         exp_info.flags = flags;
     179                 :          0 :         exp_info.priv = gem_obj;
     180                 :          0 :         exp_info.resv = obj->base.resv;
     181                 :            : 
     182         [ #  # ]:          0 :         if (obj->ops->dmabuf_export) {
     183                 :          0 :                 int ret = obj->ops->dmabuf_export(obj);
     184         [ #  # ]:          0 :                 if (ret)
     185                 :          0 :                         return ERR_PTR(ret);
     186                 :            :         }
     187                 :            : 
     188                 :          0 :         return drm_gem_dmabuf_export(gem_obj->dev, &exp_info);
     189                 :            : }
     190                 :            : 
     191                 :          0 : static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
     192                 :            : {
     193                 :          0 :         struct sg_table *pages;
     194                 :          0 :         unsigned int sg_page_sizes;
     195                 :            : 
     196                 :          0 :         pages = dma_buf_map_attachment(obj->base.import_attach,
     197                 :            :                                        DMA_BIDIRECTIONAL);
     198         [ #  # ]:          0 :         if (IS_ERR(pages))
     199                 :          0 :                 return PTR_ERR(pages);
     200                 :            : 
     201                 :          0 :         sg_page_sizes = i915_sg_page_sizes(pages->sgl);
     202                 :            : 
     203                 :          0 :         __i915_gem_object_set_pages(obj, pages, sg_page_sizes);
     204                 :            : 
     205                 :          0 :         return 0;
     206                 :            : }
     207                 :            : 
     208                 :          0 : static void i915_gem_object_put_pages_dmabuf(struct drm_i915_gem_object *obj,
     209                 :            :                                              struct sg_table *pages)
     210                 :            : {
     211                 :          0 :         dma_buf_unmap_attachment(obj->base.import_attach, pages,
     212                 :            :                                  DMA_BIDIRECTIONAL);
     213                 :          0 : }
     214                 :            : 
     215                 :            : static const struct drm_i915_gem_object_ops i915_gem_object_dmabuf_ops = {
     216                 :            :         .get_pages = i915_gem_object_get_pages_dmabuf,
     217                 :            :         .put_pages = i915_gem_object_put_pages_dmabuf,
     218                 :            : };
     219                 :            : 
     220                 :          0 : struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
     221                 :            :                                              struct dma_buf *dma_buf)
     222                 :            : {
     223                 :          0 :         static struct lock_class_key lock_class;
     224                 :          0 :         struct dma_buf_attachment *attach;
     225                 :          0 :         struct drm_i915_gem_object *obj;
     226                 :          0 :         int ret;
     227                 :            : 
     228                 :            :         /* is this one of own objects? */
     229         [ #  # ]:          0 :         if (dma_buf->ops == &i915_dmabuf_ops) {
     230         [ #  # ]:          0 :                 obj = dma_buf_to_obj(dma_buf);
     231                 :            :                 /* is it from our device? */
     232         [ #  # ]:          0 :                 if (obj->base.dev == dev) {
     233                 :            :                         /*
     234                 :            :                          * Importing dmabuf exported from out own gem increases
     235                 :            :                          * refcount on gem itself instead of f_count of dmabuf.
     236                 :            :                          */
     237                 :          0 :                         return &i915_gem_object_get(obj)->base;
     238                 :            :                 }
     239                 :            :         }
     240                 :            : 
     241                 :            :         /* need to attach */
     242                 :          0 :         attach = dma_buf_attach(dma_buf, dev->dev);
     243         [ #  # ]:          0 :         if (IS_ERR(attach))
     244                 :            :                 return ERR_CAST(attach);
     245                 :            : 
     246                 :          0 :         get_dma_buf(dma_buf);
     247                 :            : 
     248                 :          0 :         obj = i915_gem_object_alloc();
     249         [ #  # ]:          0 :         if (obj == NULL) {
     250                 :          0 :                 ret = -ENOMEM;
     251                 :          0 :                 goto fail_detach;
     252                 :            :         }
     253                 :            : 
     254                 :          0 :         drm_gem_private_object_init(dev, &obj->base, dma_buf->size);
     255                 :          0 :         i915_gem_object_init(obj, &i915_gem_object_dmabuf_ops, &lock_class);
     256                 :          0 :         obj->base.import_attach = attach;
     257                 :          0 :         obj->base.resv = dma_buf->resv;
     258                 :            : 
     259                 :            :         /* We use GTT as shorthand for a coherent domain, one that is
     260                 :            :          * neither in the GPU cache nor in the CPU cache, where all
     261                 :            :          * writes are immediately visible in memory. (That's not strictly
     262                 :            :          * true, but it's close! There are internal buffers such as the
     263                 :            :          * write-combined buffer or a delay through the chipset for GTT
     264                 :            :          * writes that do require us to treat GTT as a separate cache domain.)
     265                 :            :          */
     266                 :          0 :         obj->read_domains = I915_GEM_DOMAIN_GTT;
     267                 :          0 :         obj->write_domain = 0;
     268                 :            : 
     269                 :          0 :         return &obj->base;
     270                 :            : 
     271                 :            : fail_detach:
     272                 :          0 :         dma_buf_detach(dma_buf, attach);
     273                 :          0 :         dma_buf_put(dma_buf);
     274                 :            : 
     275                 :          0 :         return ERR_PTR(ret);
     276                 :            : }
     277                 :            : 
     278                 :            : #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
     279                 :            : #include "selftests/mock_dmabuf.c"
     280                 :            : #include "selftests/i915_gem_dmabuf.c"
     281                 :            : #endif

Generated by: LCOV version 1.14