LCOV - code coverage report
Current view: top level - drivers/gpu/drm - drm_prime.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 339 0.0 %
Date: 2022-04-01 14:17:54 Functions: 0 24 0.0 %
Branches: 0 122 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright © 2012 Red Hat
       3                 :            :  *
       4                 :            :  * Permission is hereby granted, free of charge, to any person obtaining a
       5                 :            :  * copy of this software and associated documentation files (the "Software"),
       6                 :            :  * to deal in the Software without restriction, including without limitation
       7                 :            :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       8                 :            :  * and/or sell copies of the Software, and to permit persons to whom the
       9                 :            :  * Software is furnished to do so, subject to the following conditions:
      10                 :            :  *
      11                 :            :  * The above copyright notice and this permission notice (including the next
      12                 :            :  * paragraph) shall be included in all copies or substantial portions of the
      13                 :            :  * Software.
      14                 :            :  *
      15                 :            :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16                 :            :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17                 :            :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      18                 :            :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19                 :            :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      20                 :            :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
      21                 :            :  * IN THE SOFTWARE.
      22                 :            :  *
      23                 :            :  * Authors:
      24                 :            :  *      Dave Airlie <airlied@redhat.com>
      25                 :            :  *      Rob Clark <rob.clark@linaro.org>
      26                 :            :  *
      27                 :            :  */
      28                 :            : 
      29                 :            : #include <linux/export.h>
      30                 :            : #include <linux/dma-buf.h>
      31                 :            : #include <linux/rbtree.h>
      32                 :            : 
      33                 :            : #include <drm/drm.h>
      34                 :            : #include <drm/drm_drv.h>
      35                 :            : #include <drm/drm_file.h>
      36                 :            : #include <drm/drm_framebuffer.h>
      37                 :            : #include <drm/drm_gem.h>
      38                 :            : #include <drm/drm_prime.h>
      39                 :            : 
      40                 :            : #include "drm_internal.h"
      41                 :            : 
      42                 :            : /**
      43                 :            :  * DOC: overview and lifetime rules
      44                 :            :  *
      45                 :            :  * Similar to GEM global names, PRIME file descriptors are also used to share
      46                 :            :  * buffer objects across processes. They offer additional security: as file
      47                 :            :  * descriptors must be explicitly sent over UNIX domain sockets to be shared
      48                 :            :  * between applications, they can't be guessed like the globally unique GEM
      49                 :            :  * names.
      50                 :            :  *
      51                 :            :  * Drivers that support the PRIME API implement the
      52                 :            :  * &drm_driver.prime_handle_to_fd and &drm_driver.prime_fd_to_handle operations.
      53                 :            :  * GEM based drivers must use drm_gem_prime_handle_to_fd() and
      54                 :            :  * drm_gem_prime_fd_to_handle() to implement these. For GEM based drivers the
      55                 :            :  * actual driver interfaces is provided through the &drm_gem_object_funcs.export
      56                 :            :  * and &drm_driver.gem_prime_import hooks.
      57                 :            :  *
      58                 :            :  * &dma_buf_ops implementations for GEM drivers are all individually exported
      59                 :            :  * for drivers which need to overwrite or reimplement some of them.
      60                 :            :  *
      61                 :            :  * Reference Counting for GEM Drivers
      62                 :            :  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      63                 :            :  *
      64                 :            :  * On the export the &dma_buf holds a reference to the exported buffer object,
      65                 :            :  * usually a &drm_gem_object. It takes this reference in the PRIME_HANDLE_TO_FD
      66                 :            :  * IOCTL, when it first calls &drm_gem_object_funcs.export
      67                 :            :  * and stores the exporting GEM object in the &dma_buf.priv field. This
      68                 :            :  * reference needs to be released when the final reference to the &dma_buf
      69                 :            :  * itself is dropped and its &dma_buf_ops.release function is called.  For
      70                 :            :  * GEM-based drivers, the &dma_buf should be exported using
      71                 :            :  * drm_gem_dmabuf_export() and then released by drm_gem_dmabuf_release().
      72                 :            :  *
      73                 :            :  * Thus the chain of references always flows in one direction, avoiding loops:
      74                 :            :  * importing GEM object -> dma-buf -> exported GEM bo. A further complication
      75                 :            :  * are the lookup caches for import and export. These are required to guarantee
      76                 :            :  * that any given object will always have only one uniqe userspace handle. This
      77                 :            :  * is required to allow userspace to detect duplicated imports, since some GEM
      78                 :            :  * drivers do fail command submissions if a given buffer object is listed more
      79                 :            :  * than once. These import and export caches in &drm_prime_file_private only
      80                 :            :  * retain a weak reference, which is cleaned up when the corresponding object is
      81                 :            :  * released.
      82                 :            :  *
      83                 :            :  * Self-importing: If userspace is using PRIME as a replacement for flink then
      84                 :            :  * it will get a fd->handle request for a GEM object that it created.  Drivers
      85                 :            :  * should detect this situation and return back the underlying object from the
      86                 :            :  * dma-buf private. For GEM based drivers this is handled in
      87                 :            :  * drm_gem_prime_import() already.
      88                 :            :  */
      89                 :            : 
      90                 :            : struct drm_prime_member {
      91                 :            :         struct dma_buf *dma_buf;
      92                 :            :         uint32_t handle;
      93                 :            : 
      94                 :            :         struct rb_node dmabuf_rb;
      95                 :            :         struct rb_node handle_rb;
      96                 :            : };
      97                 :            : 
      98                 :          0 : static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv,
      99                 :            :                                     struct dma_buf *dma_buf, uint32_t handle)
     100                 :            : {
     101                 :          0 :         struct drm_prime_member *member;
     102                 :          0 :         struct rb_node **p, *rb;
     103                 :            : 
     104                 :          0 :         member = kmalloc(sizeof(*member), GFP_KERNEL);
     105         [ #  # ]:          0 :         if (!member)
     106                 :            :                 return -ENOMEM;
     107                 :            : 
     108                 :          0 :         get_dma_buf(dma_buf);
     109                 :          0 :         member->dma_buf = dma_buf;
     110                 :          0 :         member->handle = handle;
     111                 :            : 
     112                 :          0 :         rb = NULL;
     113                 :          0 :         p = &prime_fpriv->dmabufs.rb_node;
     114         [ #  # ]:          0 :         while (*p) {
     115                 :          0 :                 struct drm_prime_member *pos;
     116                 :            : 
     117                 :          0 :                 rb = *p;
     118                 :          0 :                 pos = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
     119         [ #  # ]:          0 :                 if (dma_buf > pos->dma_buf)
     120                 :          0 :                         p = &rb->rb_right;
     121                 :            :                 else
     122                 :          0 :                         p = &rb->rb_left;
     123                 :            :         }
     124                 :          0 :         rb_link_node(&member->dmabuf_rb, rb, p);
     125                 :          0 :         rb_insert_color(&member->dmabuf_rb, &prime_fpriv->dmabufs);
     126                 :            : 
     127                 :          0 :         rb = NULL;
     128                 :          0 :         p = &prime_fpriv->handles.rb_node;
     129         [ #  # ]:          0 :         while (*p) {
     130                 :          0 :                 struct drm_prime_member *pos;
     131                 :            : 
     132                 :          0 :                 rb = *p;
     133                 :          0 :                 pos = rb_entry(rb, struct drm_prime_member, handle_rb);
     134         [ #  # ]:          0 :                 if (handle > pos->handle)
     135                 :          0 :                         p = &rb->rb_right;
     136                 :            :                 else
     137                 :          0 :                         p = &rb->rb_left;
     138                 :            :         }
     139                 :          0 :         rb_link_node(&member->handle_rb, rb, p);
     140                 :          0 :         rb_insert_color(&member->handle_rb, &prime_fpriv->handles);
     141                 :            : 
     142                 :          0 :         return 0;
     143                 :            : }
     144                 :            : 
     145                 :          0 : static struct dma_buf *drm_prime_lookup_buf_by_handle(struct drm_prime_file_private *prime_fpriv,
     146                 :            :                                                       uint32_t handle)
     147                 :            : {
     148                 :          0 :         struct rb_node *rb;
     149                 :            : 
     150                 :          0 :         rb = prime_fpriv->handles.rb_node;
     151         [ #  # ]:          0 :         while (rb) {
     152                 :          0 :                 struct drm_prime_member *member;
     153                 :            : 
     154                 :          0 :                 member = rb_entry(rb, struct drm_prime_member, handle_rb);
     155         [ #  # ]:          0 :                 if (member->handle == handle)
     156                 :          0 :                         return member->dma_buf;
     157         [ #  # ]:          0 :                 else if (member->handle < handle)
     158                 :          0 :                         rb = rb->rb_right;
     159                 :            :                 else
     160                 :          0 :                         rb = rb->rb_left;
     161                 :            :         }
     162                 :            : 
     163                 :            :         return NULL;
     164                 :            : }
     165                 :            : 
     166                 :          0 : static int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpriv,
     167                 :            :                                        struct dma_buf *dma_buf,
     168                 :            :                                        uint32_t *handle)
     169                 :            : {
     170                 :          0 :         struct rb_node *rb;
     171                 :            : 
     172                 :          0 :         rb = prime_fpriv->dmabufs.rb_node;
     173         [ #  # ]:          0 :         while (rb) {
     174                 :          0 :                 struct drm_prime_member *member;
     175                 :            : 
     176                 :          0 :                 member = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
     177         [ #  # ]:          0 :                 if (member->dma_buf == dma_buf) {
     178                 :          0 :                         *handle = member->handle;
     179                 :          0 :                         return 0;
     180         [ #  # ]:          0 :                 } else if (member->dma_buf < dma_buf) {
     181                 :          0 :                         rb = rb->rb_right;
     182                 :            :                 } else {
     183                 :          0 :                         rb = rb->rb_left;
     184                 :            :                 }
     185                 :            :         }
     186                 :            : 
     187                 :            :         return -ENOENT;
     188                 :            : }
     189                 :            : 
     190                 :          0 : void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv,
     191                 :            :                                         struct dma_buf *dma_buf)
     192                 :            : {
     193                 :          0 :         struct rb_node *rb;
     194                 :            : 
     195                 :          0 :         rb = prime_fpriv->dmabufs.rb_node;
     196         [ #  # ]:          0 :         while (rb) {
     197                 :          0 :                 struct drm_prime_member *member;
     198                 :            : 
     199                 :          0 :                 member = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
     200         [ #  # ]:          0 :                 if (member->dma_buf == dma_buf) {
     201                 :          0 :                         rb_erase(&member->handle_rb, &prime_fpriv->handles);
     202                 :          0 :                         rb_erase(&member->dmabuf_rb, &prime_fpriv->dmabufs);
     203                 :            : 
     204                 :          0 :                         dma_buf_put(dma_buf);
     205                 :          0 :                         kfree(member);
     206                 :          0 :                         return;
     207         [ #  # ]:          0 :                 } else if (member->dma_buf < dma_buf) {
     208                 :          0 :                         rb = rb->rb_right;
     209                 :            :                 } else {
     210                 :          0 :                         rb = rb->rb_left;
     211                 :            :                 }
     212                 :            :         }
     213                 :            : }
     214                 :            : 
     215                 :          0 : void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
     216                 :            : {
     217                 :          0 :         mutex_init(&prime_fpriv->lock);
     218                 :          0 :         prime_fpriv->dmabufs = RB_ROOT;
     219                 :          0 :         prime_fpriv->handles = RB_ROOT;
     220                 :          0 : }
     221                 :            : 
     222                 :          0 : void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv)
     223                 :            : {
     224                 :            :         /* by now drm_gem_release should've made sure the list is empty */
     225         [ #  # ]:          0 :         WARN_ON(!RB_EMPTY_ROOT(&prime_fpriv->dmabufs));
     226                 :          0 : }
     227                 :            : 
     228                 :            : /**
     229                 :            :  * drm_gem_dmabuf_export - &dma_buf export implementation for GEM
     230                 :            :  * @dev: parent device for the exported dmabuf
     231                 :            :  * @exp_info: the export information used by dma_buf_export()
     232                 :            :  *
     233                 :            :  * This wraps dma_buf_export() for use by generic GEM drivers that are using
     234                 :            :  * drm_gem_dmabuf_release(). In addition to calling dma_buf_export(), we take
     235                 :            :  * a reference to the &drm_device and the exported &drm_gem_object (stored in
     236                 :            :  * &dma_buf_export_info.priv) which is released by drm_gem_dmabuf_release().
     237                 :            :  *
     238                 :            :  * Returns the new dmabuf.
     239                 :            :  */
     240                 :          0 : struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
     241                 :            :                                       struct dma_buf_export_info *exp_info)
     242                 :            : {
     243                 :          0 :         struct drm_gem_object *obj = exp_info->priv;
     244                 :          0 :         struct dma_buf *dma_buf;
     245                 :            : 
     246                 :          0 :         dma_buf = dma_buf_export(exp_info);
     247         [ #  # ]:          0 :         if (IS_ERR(dma_buf))
     248                 :            :                 return dma_buf;
     249                 :            : 
     250                 :          0 :         drm_dev_get(dev);
     251                 :          0 :         drm_gem_object_get(obj);
     252                 :          0 :         dma_buf->file->f_mapping = obj->dev->anon_inode->i_mapping;
     253                 :            : 
     254                 :          0 :         return dma_buf;
     255                 :            : }
     256                 :            : EXPORT_SYMBOL(drm_gem_dmabuf_export);
     257                 :            : 
     258                 :            : /**
     259                 :            :  * drm_gem_dmabuf_release - &dma_buf release implementation for GEM
     260                 :            :  * @dma_buf: buffer to be released
     261                 :            :  *
     262                 :            :  * Generic release function for dma_bufs exported as PRIME buffers. GEM drivers
     263                 :            :  * must use this in their &dma_buf_ops structure as the release callback.
     264                 :            :  * drm_gem_dmabuf_release() should be used in conjunction with
     265                 :            :  * drm_gem_dmabuf_export().
     266                 :            :  */
     267                 :          0 : void drm_gem_dmabuf_release(struct dma_buf *dma_buf)
     268                 :            : {
     269                 :          0 :         struct drm_gem_object *obj = dma_buf->priv;
     270                 :          0 :         struct drm_device *dev = obj->dev;
     271                 :            : 
     272                 :            :         /* drop the reference on the export fd holds */
     273                 :          0 :         drm_gem_object_put_unlocked(obj);
     274                 :            : 
     275                 :          0 :         drm_dev_put(dev);
     276                 :          0 : }
     277                 :            : EXPORT_SYMBOL(drm_gem_dmabuf_release);
     278                 :            : 
     279                 :            : /**
     280                 :            :  * drm_gem_prime_fd_to_handle - PRIME import function for GEM drivers
     281                 :            :  * @dev: dev to export the buffer from
     282                 :            :  * @file_priv: drm file-private structure
     283                 :            :  * @prime_fd: fd id of the dma-buf which should be imported
     284                 :            :  * @handle: pointer to storage for the handle of the imported buffer object
     285                 :            :  *
     286                 :            :  * This is the PRIME import function which must be used mandatorily by GEM
     287                 :            :  * drivers to ensure correct lifetime management of the underlying GEM object.
     288                 :            :  * The actual importing of GEM object from the dma-buf is done through the
     289                 :            :  * &drm_driver.gem_prime_import driver callback.
     290                 :            :  *
     291                 :            :  * Returns 0 on success or a negative error code on failure.
     292                 :            :  */
     293                 :          0 : int drm_gem_prime_fd_to_handle(struct drm_device *dev,
     294                 :            :                                struct drm_file *file_priv, int prime_fd,
     295                 :            :                                uint32_t *handle)
     296                 :            : {
     297                 :          0 :         struct dma_buf *dma_buf;
     298                 :          0 :         struct drm_gem_object *obj;
     299                 :          0 :         int ret;
     300                 :            : 
     301                 :          0 :         dma_buf = dma_buf_get(prime_fd);
     302         [ #  # ]:          0 :         if (IS_ERR(dma_buf))
     303                 :          0 :                 return PTR_ERR(dma_buf);
     304                 :            : 
     305                 :          0 :         mutex_lock(&file_priv->prime.lock);
     306                 :            : 
     307                 :          0 :         ret = drm_prime_lookup_buf_handle(&file_priv->prime,
     308                 :            :                         dma_buf, handle);
     309                 :          0 :         if (ret == 0)
     310                 :          0 :                 goto out_put;
     311                 :            : 
     312                 :            :         /* never seen this one, need to import */
     313                 :          0 :         mutex_lock(&dev->object_name_lock);
     314         [ #  # ]:          0 :         if (dev->driver->gem_prime_import)
     315                 :          0 :                 obj = dev->driver->gem_prime_import(dev, dma_buf);
     316                 :            :         else
     317                 :          0 :                 obj = drm_gem_prime_import(dev, dma_buf);
     318         [ #  # ]:          0 :         if (IS_ERR(obj)) {
     319                 :          0 :                 ret = PTR_ERR(obj);
     320                 :          0 :                 goto out_unlock;
     321                 :            :         }
     322                 :            : 
     323         [ #  # ]:          0 :         if (obj->dma_buf) {
     324         [ #  # ]:          0 :                 WARN_ON(obj->dma_buf != dma_buf);
     325                 :            :         } else {
     326                 :          0 :                 obj->dma_buf = dma_buf;
     327                 :          0 :                 get_dma_buf(dma_buf);
     328                 :            :         }
     329                 :            : 
     330                 :            :         /* _handle_create_tail unconditionally unlocks dev->object_name_lock. */
     331                 :          0 :         ret = drm_gem_handle_create_tail(file_priv, obj, handle);
     332                 :          0 :         drm_gem_object_put_unlocked(obj);
     333         [ #  # ]:          0 :         if (ret)
     334                 :          0 :                 goto out_put;
     335                 :            : 
     336                 :          0 :         ret = drm_prime_add_buf_handle(&file_priv->prime,
     337                 :            :                         dma_buf, *handle);
     338                 :          0 :         mutex_unlock(&file_priv->prime.lock);
     339         [ #  # ]:          0 :         if (ret)
     340                 :          0 :                 goto fail;
     341                 :            : 
     342                 :          0 :         dma_buf_put(dma_buf);
     343                 :            : 
     344                 :          0 :         return 0;
     345                 :            : 
     346                 :            : fail:
     347                 :            :         /* hmm, if driver attached, we are relying on the free-object path
     348                 :            :          * to detach.. which seems ok..
     349                 :            :          */
     350                 :          0 :         drm_gem_handle_delete(file_priv, *handle);
     351                 :          0 :         dma_buf_put(dma_buf);
     352                 :          0 :         return ret;
     353                 :            : 
     354                 :            : out_unlock:
     355                 :          0 :         mutex_unlock(&dev->object_name_lock);
     356                 :          0 : out_put:
     357                 :          0 :         mutex_unlock(&file_priv->prime.lock);
     358                 :          0 :         dma_buf_put(dma_buf);
     359                 :          0 :         return ret;
     360                 :            : }
     361                 :            : EXPORT_SYMBOL(drm_gem_prime_fd_to_handle);
     362                 :            : 
     363                 :          0 : int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
     364                 :            :                                  struct drm_file *file_priv)
     365                 :            : {
     366                 :          0 :         struct drm_prime_handle *args = data;
     367                 :            : 
     368         [ #  # ]:          0 :         if (!dev->driver->prime_fd_to_handle)
     369                 :            :                 return -ENOSYS;
     370                 :            : 
     371                 :          0 :         return dev->driver->prime_fd_to_handle(dev, file_priv,
     372                 :          0 :                         args->fd, &args->handle);
     373                 :            : }
     374                 :            : 
     375                 :            : static struct dma_buf *export_and_register_object(struct drm_device *dev,
     376                 :            :                                                   struct drm_gem_object *obj,
     377                 :            :                                                   uint32_t flags)
     378                 :            : {
     379                 :            :         struct dma_buf *dmabuf;
     380                 :            : 
     381                 :            :         /* prevent races with concurrent gem_close. */
     382                 :            :         if (obj->handle_count == 0) {
     383                 :            :                 dmabuf = ERR_PTR(-ENOENT);
     384                 :            :                 return dmabuf;
     385                 :            :         }
     386                 :            : 
     387                 :            :         if (obj->funcs && obj->funcs->export)
     388                 :            :                 dmabuf = obj->funcs->export(obj, flags);
     389                 :            :         else if (dev->driver->gem_prime_export)
     390                 :            :                 dmabuf = dev->driver->gem_prime_export(obj, flags);
     391                 :            :         else
     392                 :            :                 dmabuf = drm_gem_prime_export(obj, flags);
     393                 :            :         if (IS_ERR(dmabuf)) {
     394                 :            :                 /* normally the created dma-buf takes ownership of the ref,
     395                 :            :                  * but if that fails then drop the ref
     396                 :            :                  */
     397                 :            :                 return dmabuf;
     398                 :            :         }
     399                 :            : 
     400                 :            :         /*
     401                 :            :          * Note that callers do not need to clean up the export cache
     402                 :            :          * since the check for obj->handle_count guarantees that someone
     403                 :            :          * will clean it up.
     404                 :            :          */
     405                 :            :         obj->dma_buf = dmabuf;
     406                 :            :         get_dma_buf(obj->dma_buf);
     407                 :            : 
     408                 :            :         return dmabuf;
     409                 :            : }
     410                 :            : 
     411                 :            : /**
     412                 :            :  * drm_gem_prime_handle_to_fd - PRIME export function for GEM drivers
     413                 :            :  * @dev: dev to export the buffer from
     414                 :            :  * @file_priv: drm file-private structure
     415                 :            :  * @handle: buffer handle to export
     416                 :            :  * @flags: flags like DRM_CLOEXEC
     417                 :            :  * @prime_fd: pointer to storage for the fd id of the create dma-buf
     418                 :            :  *
     419                 :            :  * This is the PRIME export function which must be used mandatorily by GEM
     420                 :            :  * drivers to ensure correct lifetime management of the underlying GEM object.
     421                 :            :  * The actual exporting from GEM object to a dma-buf is done through the
     422                 :            :  * &drm_driver.gem_prime_export driver callback.
     423                 :            :  */
     424                 :          0 : int drm_gem_prime_handle_to_fd(struct drm_device *dev,
     425                 :            :                                struct drm_file *file_priv, uint32_t handle,
     426                 :            :                                uint32_t flags,
     427                 :            :                                int *prime_fd)
     428                 :            : {
     429                 :          0 :         struct drm_gem_object *obj;
     430                 :          0 :         int ret = 0;
     431                 :          0 :         struct dma_buf *dmabuf;
     432                 :            : 
     433                 :          0 :         mutex_lock(&file_priv->prime.lock);
     434                 :          0 :         obj = drm_gem_object_lookup(file_priv, handle);
     435         [ #  # ]:          0 :         if (!obj)  {
     436                 :          0 :                 ret = -ENOENT;
     437                 :          0 :                 goto out_unlock;
     438                 :            :         }
     439                 :            : 
     440                 :          0 :         dmabuf = drm_prime_lookup_buf_by_handle(&file_priv->prime, handle);
     441         [ #  # ]:          0 :         if (dmabuf) {
     442                 :          0 :                 get_dma_buf(dmabuf);
     443                 :          0 :                 goto out_have_handle;
     444                 :            :         }
     445                 :            : 
     446                 :          0 :         mutex_lock(&dev->object_name_lock);
     447                 :            :         /* re-export the original imported object */
     448         [ #  # ]:          0 :         if (obj->import_attach) {
     449                 :          0 :                 dmabuf = obj->import_attach->dmabuf;
     450                 :          0 :                 get_dma_buf(dmabuf);
     451                 :          0 :                 goto out_have_obj;
     452                 :            :         }
     453                 :            : 
     454         [ #  # ]:          0 :         if (obj->dma_buf) {
     455                 :          0 :                 get_dma_buf(obj->dma_buf);
     456                 :          0 :                 dmabuf = obj->dma_buf;
     457                 :          0 :                 goto out_have_obj;
     458                 :            :         }
     459                 :            : 
     460                 :          0 :         dmabuf = export_and_register_object(dev, obj, flags);
     461         [ #  # ]:          0 :         if (IS_ERR(dmabuf)) {
     462                 :            :                 /* normally the created dma-buf takes ownership of the ref,
     463                 :            :                  * but if that fails then drop the ref
     464                 :            :                  */
     465                 :          0 :                 ret = PTR_ERR(dmabuf);
     466                 :          0 :                 mutex_unlock(&dev->object_name_lock);
     467                 :          0 :                 goto out;
     468                 :            :         }
     469                 :            : 
     470                 :          0 : out_have_obj:
     471                 :            :         /*
     472                 :            :          * If we've exported this buffer then cheat and add it to the import list
     473                 :            :          * so we get the correct handle back. We must do this under the
     474                 :            :          * protection of dev->object_name_lock to ensure that a racing gem close
     475                 :            :          * ioctl doesn't miss to remove this buffer handle from the cache.
     476                 :            :          */
     477                 :          0 :         ret = drm_prime_add_buf_handle(&file_priv->prime,
     478                 :            :                                        dmabuf, handle);
     479                 :          0 :         mutex_unlock(&dev->object_name_lock);
     480         [ #  # ]:          0 :         if (ret)
     481                 :          0 :                 goto fail_put_dmabuf;
     482                 :            : 
     483                 :          0 : out_have_handle:
     484                 :          0 :         ret = dma_buf_fd(dmabuf, flags);
     485                 :            :         /*
     486                 :            :          * We must _not_ remove the buffer from the handle cache since the newly
     487                 :            :          * created dma buf is already linked in the global obj->dma_buf pointer,
     488                 :            :          * and that is invariant as long as a userspace gem handle exists.
     489                 :            :          * Closing the handle will clean out the cache anyway, so we don't leak.
     490                 :            :          */
     491         [ #  # ]:          0 :         if (ret < 0) {
     492                 :          0 :                 goto fail_put_dmabuf;
     493                 :            :         } else {
     494                 :          0 :                 *prime_fd = ret;
     495                 :          0 :                 ret = 0;
     496                 :            :         }
     497                 :            : 
     498                 :          0 :         goto out;
     499                 :            : 
     500                 :          0 : fail_put_dmabuf:
     501                 :          0 :         dma_buf_put(dmabuf);
     502                 :          0 : out:
     503                 :          0 :         drm_gem_object_put_unlocked(obj);
     504                 :          0 : out_unlock:
     505                 :          0 :         mutex_unlock(&file_priv->prime.lock);
     506                 :            : 
     507                 :          0 :         return ret;
     508                 :            : }
     509                 :            : EXPORT_SYMBOL(drm_gem_prime_handle_to_fd);
     510                 :            : 
     511                 :          0 : int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
     512                 :            :                                  struct drm_file *file_priv)
     513                 :            : {
     514                 :          0 :         struct drm_prime_handle *args = data;
     515                 :            : 
     516         [ #  # ]:          0 :         if (!dev->driver->prime_handle_to_fd)
     517                 :            :                 return -ENOSYS;
     518                 :            : 
     519                 :            :         /* check flags are valid */
     520         [ #  # ]:          0 :         if (args->flags & ~(DRM_CLOEXEC | DRM_RDWR))
     521                 :            :                 return -EINVAL;
     522                 :            : 
     523                 :          0 :         return dev->driver->prime_handle_to_fd(dev, file_priv,
     524                 :          0 :                         args->handle, args->flags, &args->fd);
     525                 :            : }
     526                 :            : 
     527                 :            : /**
     528                 :            :  * DOC: PRIME Helpers
     529                 :            :  *
     530                 :            :  * Drivers can implement &drm_gem_object_funcs.export and
     531                 :            :  * &drm_driver.gem_prime_import in terms of simpler APIs by using the helper
     532                 :            :  * functions drm_gem_prime_export() and drm_gem_prime_import(). These functions
     533                 :            :  * implement dma-buf support in terms of some lower-level helpers, which are
     534                 :            :  * again exported for drivers to use individually:
     535                 :            :  *
     536                 :            :  * Exporting buffers
     537                 :            :  * ~~~~~~~~~~~~~~~~~
     538                 :            :  *
     539                 :            :  * Optional pinning of buffers is handled at dma-buf attach and detach time in
     540                 :            :  * drm_gem_map_attach() and drm_gem_map_detach(). Backing storage itself is
     541                 :            :  * handled by drm_gem_map_dma_buf() and drm_gem_unmap_dma_buf(), which relies on
     542                 :            :  * &drm_gem_object_funcs.get_sg_table.
     543                 :            :  *
     544                 :            :  * For kernel-internal access there's drm_gem_dmabuf_vmap() and
     545                 :            :  * drm_gem_dmabuf_vunmap(). Userspace mmap support is provided by
     546                 :            :  * drm_gem_dmabuf_mmap().
     547                 :            :  *
     548                 :            :  * Note that these export helpers can only be used if the underlying backing
     549                 :            :  * storage is fully coherent and either permanently pinned, or it is safe to pin
     550                 :            :  * it indefinitely.
     551                 :            :  *
     552                 :            :  * FIXME: The underlying helper functions are named rather inconsistently.
     553                 :            :  *
     554                 :            :  * Exporting buffers
     555                 :            :  * ~~~~~~~~~~~~~~~~~
     556                 :            :  *
     557                 :            :  * Importing dma-bufs using drm_gem_prime_import() relies on
     558                 :            :  * &drm_driver.gem_prime_import_sg_table.
     559                 :            :  *
     560                 :            :  * Note that similarly to the export helpers this permanently pins the
     561                 :            :  * underlying backing storage. Which is ok for scanout, but is not the best
     562                 :            :  * option for sharing lots of buffers for rendering.
     563                 :            :  */
     564                 :            : 
     565                 :            : /**
     566                 :            :  * drm_gem_map_attach - dma_buf attach implementation for GEM
     567                 :            :  * @dma_buf: buffer to attach device to
     568                 :            :  * @attach: buffer attachment data
     569                 :            :  *
     570                 :            :  * Calls &drm_gem_object_funcs.pin for device specific handling. This can be
     571                 :            :  * used as the &dma_buf_ops.attach callback. Must be used together with
     572                 :            :  * drm_gem_map_detach().
     573                 :            :  *
     574                 :            :  * Returns 0 on success, negative error code on failure.
     575                 :            :  */
     576                 :          0 : int drm_gem_map_attach(struct dma_buf *dma_buf,
     577                 :            :                        struct dma_buf_attachment *attach)
     578                 :            : {
     579                 :          0 :         struct drm_gem_object *obj = dma_buf->priv;
     580                 :            : 
     581                 :          0 :         return drm_gem_pin(obj);
     582                 :            : }
     583                 :            : EXPORT_SYMBOL(drm_gem_map_attach);
     584                 :            : 
     585                 :            : /**
     586                 :            :  * drm_gem_map_detach - dma_buf detach implementation for GEM
     587                 :            :  * @dma_buf: buffer to detach from
     588                 :            :  * @attach: attachment to be detached
     589                 :            :  *
     590                 :            :  * Calls &drm_gem_object_funcs.pin for device specific handling.  Cleans up
     591                 :            :  * &dma_buf_attachment from drm_gem_map_attach(). This can be used as the
     592                 :            :  * &dma_buf_ops.detach callback.
     593                 :            :  */
     594                 :          0 : void drm_gem_map_detach(struct dma_buf *dma_buf,
     595                 :            :                         struct dma_buf_attachment *attach)
     596                 :            : {
     597                 :          0 :         struct drm_gem_object *obj = dma_buf->priv;
     598                 :            : 
     599                 :          0 :         drm_gem_unpin(obj);
     600                 :          0 : }
     601                 :            : EXPORT_SYMBOL(drm_gem_map_detach);
     602                 :            : 
     603                 :            : /**
     604                 :            :  * drm_gem_map_dma_buf - map_dma_buf implementation for GEM
     605                 :            :  * @attach: attachment whose scatterlist is to be returned
     606                 :            :  * @dir: direction of DMA transfer
     607                 :            :  *
     608                 :            :  * Calls &drm_gem_object_funcs.get_sg_table and then maps the scatterlist. This
     609                 :            :  * can be used as the &dma_buf_ops.map_dma_buf callback. Should be used together
     610                 :            :  * with drm_gem_unmap_dma_buf().
     611                 :            :  *
     612                 :            :  * Returns:sg_table containing the scatterlist to be returned; returns ERR_PTR
     613                 :            :  * on error. May return -EINTR if it is interrupted by a signal.
     614                 :            :  */
     615                 :          0 : struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
     616                 :            :                                      enum dma_data_direction dir)
     617                 :            : {
     618                 :          0 :         struct drm_gem_object *obj = attach->dmabuf->priv;
     619                 :          0 :         struct sg_table *sgt;
     620                 :            : 
     621   [ #  #  #  # ]:          0 :         if (WARN_ON(dir == DMA_NONE))
     622                 :            :                 return ERR_PTR(-EINVAL);
     623                 :            : 
     624         [ #  # ]:          0 :         if (obj->funcs)
     625                 :          0 :                 sgt = obj->funcs->get_sg_table(obj);
     626                 :            :         else
     627                 :          0 :                 sgt = obj->dev->driver->gem_prime_get_sg_table(obj);
     628                 :            : 
     629         [ #  # ]:          0 :         if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
     630                 :            :                               DMA_ATTR_SKIP_CPU_SYNC)) {
     631                 :          0 :                 sg_free_table(sgt);
     632                 :          0 :                 kfree(sgt);
     633                 :          0 :                 sgt = ERR_PTR(-ENOMEM);
     634                 :            :         }
     635                 :            : 
     636                 :            :         return sgt;
     637                 :            : }
     638                 :            : EXPORT_SYMBOL(drm_gem_map_dma_buf);
     639                 :            : 
     640                 :            : /**
     641                 :            :  * drm_gem_unmap_dma_buf - unmap_dma_buf implementation for GEM
     642                 :            :  * @attach: attachment to unmap buffer from
     643                 :            :  * @sgt: scatterlist info of the buffer to unmap
     644                 :            :  * @dir: direction of DMA transfer
     645                 :            :  *
     646                 :            :  * This can be used as the &dma_buf_ops.unmap_dma_buf callback.
     647                 :            :  */
     648                 :          0 : void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
     649                 :            :                            struct sg_table *sgt,
     650                 :            :                            enum dma_data_direction dir)
     651                 :            : {
     652         [ #  # ]:          0 :         if (!sgt)
     653                 :            :                 return;
     654                 :            : 
     655                 :          0 :         dma_unmap_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
     656                 :            :                            DMA_ATTR_SKIP_CPU_SYNC);
     657                 :          0 :         sg_free_table(sgt);
     658                 :          0 :         kfree(sgt);
     659                 :            : }
     660                 :            : EXPORT_SYMBOL(drm_gem_unmap_dma_buf);
     661                 :            : 
     662                 :            : /**
     663                 :            :  * drm_gem_dmabuf_vmap - dma_buf vmap implementation for GEM
     664                 :            :  * @dma_buf: buffer to be mapped
     665                 :            :  *
     666                 :            :  * Sets up a kernel virtual mapping. This can be used as the &dma_buf_ops.vmap
     667                 :            :  * callback. Calls into &drm_gem_object_funcs.vmap for device specific handling.
     668                 :            :  *
     669                 :            :  * Returns the kernel virtual address or NULL on failure.
     670                 :            :  */
     671                 :          0 : void *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf)
     672                 :            : {
     673                 :          0 :         struct drm_gem_object *obj = dma_buf->priv;
     674                 :          0 :         void *vaddr;
     675                 :            : 
     676                 :          0 :         vaddr = drm_gem_vmap(obj);
     677         [ #  # ]:          0 :         if (IS_ERR(vaddr))
     678                 :          0 :                 vaddr = NULL;
     679                 :            : 
     680                 :          0 :         return vaddr;
     681                 :            : }
     682                 :            : EXPORT_SYMBOL(drm_gem_dmabuf_vmap);
     683                 :            : 
     684                 :            : /**
     685                 :            :  * drm_gem_dmabuf_vunmap - dma_buf vunmap implementation for GEM
     686                 :            :  * @dma_buf: buffer to be unmapped
     687                 :            :  * @vaddr: the virtual address of the buffer
     688                 :            :  *
     689                 :            :  * Releases a kernel virtual mapping. This can be used as the
     690                 :            :  * &dma_buf_ops.vunmap callback. Calls into &drm_gem_object_funcs.vunmap for device specific handling.
     691                 :            :  */
     692                 :          0 : void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
     693                 :            : {
     694                 :          0 :         struct drm_gem_object *obj = dma_buf->priv;
     695                 :            : 
     696                 :          0 :         drm_gem_vunmap(obj, vaddr);
     697                 :          0 : }
     698                 :            : EXPORT_SYMBOL(drm_gem_dmabuf_vunmap);
     699                 :            : 
     700                 :            : /**
     701                 :            :  * drm_gem_prime_mmap - PRIME mmap function for GEM drivers
     702                 :            :  * @obj: GEM object
     703                 :            :  * @vma: Virtual address range
     704                 :            :  *
     705                 :            :  * This function sets up a userspace mapping for PRIME exported buffers using
     706                 :            :  * the same codepath that is used for regular GEM buffer mapping on the DRM fd.
     707                 :            :  * The fake GEM offset is added to vma->vm_pgoff and &drm_driver->fops->mmap is
     708                 :            :  * called to set up the mapping.
     709                 :            :  *
     710                 :            :  * Drivers can use this as their &drm_driver.gem_prime_mmap callback.
     711                 :            :  */
     712                 :          0 : int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
     713                 :            : {
     714                 :          0 :         struct drm_file *priv;
     715                 :          0 :         struct file *fil;
     716                 :          0 :         int ret;
     717                 :            : 
     718                 :            :         /* Add the fake offset */
     719         [ #  # ]:          0 :         vma->vm_pgoff += drm_vma_node_start(&obj->vma_node);
     720                 :            : 
     721   [ #  #  #  # ]:          0 :         if (obj->funcs && obj->funcs->mmap) {
     722                 :          0 :                 ret = obj->funcs->mmap(obj, vma);
     723         [ #  # ]:          0 :                 if (ret)
     724                 :            :                         return ret;
     725                 :          0 :                 vma->vm_private_data = obj;
     726                 :          0 :                 drm_gem_object_get(obj);
     727                 :          0 :                 return 0;
     728                 :            :         }
     729                 :            : 
     730                 :          0 :         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
     731                 :          0 :         fil = kzalloc(sizeof(*fil), GFP_KERNEL);
     732         [ #  # ]:          0 :         if (!priv || !fil) {
     733                 :          0 :                 ret = -ENOMEM;
     734                 :          0 :                 goto out;
     735                 :            :         }
     736                 :            : 
     737                 :            :         /* Used by drm_gem_mmap() to lookup the GEM object */
     738                 :          0 :         priv->minor = obj->dev->primary;
     739                 :          0 :         fil->private_data = priv;
     740                 :            : 
     741                 :          0 :         ret = drm_vma_node_allow(&obj->vma_node, priv);
     742         [ #  # ]:          0 :         if (ret)
     743                 :          0 :                 goto out;
     744                 :            : 
     745                 :          0 :         ret = obj->dev->driver->fops->mmap(fil, vma);
     746                 :            : 
     747                 :          0 :         drm_vma_node_revoke(&obj->vma_node, priv);
     748                 :          0 : out:
     749                 :          0 :         kfree(priv);
     750                 :          0 :         kfree(fil);
     751                 :            : 
     752                 :          0 :         return ret;
     753                 :            : }
     754                 :            : EXPORT_SYMBOL(drm_gem_prime_mmap);
     755                 :            : 
     756                 :            : /**
     757                 :            :  * drm_gem_dmabuf_mmap - dma_buf mmap implementation for GEM
     758                 :            :  * @dma_buf: buffer to be mapped
     759                 :            :  * @vma: virtual address range
     760                 :            :  *
     761                 :            :  * Provides memory mapping for the buffer. This can be used as the
     762                 :            :  * &dma_buf_ops.mmap callback. It just forwards to &drm_driver.gem_prime_mmap,
     763                 :            :  * which should be set to drm_gem_prime_mmap().
     764                 :            :  *
     765                 :            :  * FIXME: There's really no point to this wrapper, drivers which need anything
     766                 :            :  * else but drm_gem_prime_mmap can roll their own &dma_buf_ops.mmap callback.
     767                 :            :  *
     768                 :            :  * Returns 0 on success or a negative error code on failure.
     769                 :            :  */
     770                 :          0 : int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma)
     771                 :            : {
     772                 :          0 :         struct drm_gem_object *obj = dma_buf->priv;
     773                 :          0 :         struct drm_device *dev = obj->dev;
     774                 :            : 
     775         [ #  # ]:          0 :         if (!dev->driver->gem_prime_mmap)
     776                 :            :                 return -ENOSYS;
     777                 :            : 
     778                 :          0 :         return dev->driver->gem_prime_mmap(obj, vma);
     779                 :            : }
     780                 :            : EXPORT_SYMBOL(drm_gem_dmabuf_mmap);
     781                 :            : 
     782                 :            : static const struct dma_buf_ops drm_gem_prime_dmabuf_ops =  {
     783                 :            :         .cache_sgt_mapping = true,
     784                 :            :         .attach = drm_gem_map_attach,
     785                 :            :         .detach = drm_gem_map_detach,
     786                 :            :         .map_dma_buf = drm_gem_map_dma_buf,
     787                 :            :         .unmap_dma_buf = drm_gem_unmap_dma_buf,
     788                 :            :         .release = drm_gem_dmabuf_release,
     789                 :            :         .mmap = drm_gem_dmabuf_mmap,
     790                 :            :         .vmap = drm_gem_dmabuf_vmap,
     791                 :            :         .vunmap = drm_gem_dmabuf_vunmap,
     792                 :            : };
     793                 :            : 
     794                 :            : /**
     795                 :            :  * drm_prime_pages_to_sg - converts a page array into an sg list
     796                 :            :  * @pages: pointer to the array of page pointers to convert
     797                 :            :  * @nr_pages: length of the page vector
     798                 :            :  *
     799                 :            :  * This helper creates an sg table object from a set of pages
     800                 :            :  * the driver is responsible for mapping the pages into the
     801                 :            :  * importers address space for use with dma_buf itself.
     802                 :            :  *
     803                 :            :  * This is useful for implementing &drm_gem_object_funcs.get_sg_table.
     804                 :            :  */
     805                 :          0 : struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages)
     806                 :            : {
     807                 :          0 :         struct sg_table *sg = NULL;
     808                 :          0 :         int ret;
     809                 :            : 
     810                 :          0 :         sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
     811         [ #  # ]:          0 :         if (!sg) {
     812                 :          0 :                 ret = -ENOMEM;
     813                 :          0 :                 goto out;
     814                 :            :         }
     815                 :            : 
     816                 :          0 :         ret = sg_alloc_table_from_pages(sg, pages, nr_pages, 0,
     817                 :          0 :                                 nr_pages << PAGE_SHIFT, GFP_KERNEL);
     818         [ #  # ]:          0 :         if (ret)
     819                 :          0 :                 goto out;
     820                 :            : 
     821                 :            :         return sg;
     822                 :          0 : out:
     823                 :          0 :         kfree(sg);
     824                 :          0 :         return ERR_PTR(ret);
     825                 :            : }
     826                 :            : EXPORT_SYMBOL(drm_prime_pages_to_sg);
     827                 :            : 
     828                 :            : /**
     829                 :            :  * drm_gem_prime_export - helper library implementation of the export callback
     830                 :            :  * @obj: GEM object to export
     831                 :            :  * @flags: flags like DRM_CLOEXEC and DRM_RDWR
     832                 :            :  *
     833                 :            :  * This is the implementation of the &drm_gem_object_funcs.export functions for GEM drivers
     834                 :            :  * using the PRIME helpers. It is used as the default in
     835                 :            :  * drm_gem_prime_handle_to_fd().
     836                 :            :  */
     837                 :          0 : struct dma_buf *drm_gem_prime_export(struct drm_gem_object *obj,
     838                 :            :                                      int flags)
     839                 :            : {
     840                 :          0 :         struct drm_device *dev = obj->dev;
     841                 :          0 :         struct dma_buf_export_info exp_info = {
     842                 :            :                 .exp_name = KBUILD_MODNAME, /* white lie for debug */
     843                 :          0 :                 .owner = dev->driver->fops->owner,
     844                 :            :                 .ops = &drm_gem_prime_dmabuf_ops,
     845                 :          0 :                 .size = obj->size,
     846                 :            :                 .flags = flags,
     847                 :            :                 .priv = obj,
     848                 :          0 :                 .resv = obj->resv,
     849                 :            :         };
     850                 :            : 
     851                 :          0 :         return drm_gem_dmabuf_export(dev, &exp_info);
     852                 :            : }
     853                 :            : EXPORT_SYMBOL(drm_gem_prime_export);
     854                 :            : 
     855                 :            : /**
     856                 :            :  * drm_gem_prime_import_dev - core implementation of the import callback
     857                 :            :  * @dev: drm_device to import into
     858                 :            :  * @dma_buf: dma-buf object to import
     859                 :            :  * @attach_dev: struct device to dma_buf attach
     860                 :            :  *
     861                 :            :  * This is the core of drm_gem_prime_import(). It's designed to be called by
     862                 :            :  * drivers who want to use a different device structure than &drm_device.dev for
     863                 :            :  * attaching via dma_buf. This function calls
     864                 :            :  * &drm_driver.gem_prime_import_sg_table internally.
     865                 :            :  *
     866                 :            :  * Drivers must arrange to call drm_prime_gem_destroy() from their
     867                 :            :  * &drm_gem_object_funcs.free hook when using this function.
     868                 :            :  */
     869                 :          0 : struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
     870                 :            :                                             struct dma_buf *dma_buf,
     871                 :            :                                             struct device *attach_dev)
     872                 :            : {
     873                 :          0 :         struct dma_buf_attachment *attach;
     874                 :          0 :         struct sg_table *sgt;
     875                 :          0 :         struct drm_gem_object *obj;
     876                 :          0 :         int ret;
     877                 :            : 
     878         [ #  # ]:          0 :         if (dma_buf->ops == &drm_gem_prime_dmabuf_ops) {
     879                 :          0 :                 obj = dma_buf->priv;
     880         [ #  # ]:          0 :                 if (obj->dev == dev) {
     881                 :            :                         /*
     882                 :            :                          * Importing dmabuf exported from out own gem increases
     883                 :            :                          * refcount on gem itself instead of f_count of dmabuf.
     884                 :            :                          */
     885                 :          0 :                         drm_gem_object_get(obj);
     886                 :          0 :                         return obj;
     887                 :            :                 }
     888                 :            :         }
     889                 :            : 
     890         [ #  # ]:          0 :         if (!dev->driver->gem_prime_import_sg_table)
     891                 :            :                 return ERR_PTR(-EINVAL);
     892                 :            : 
     893                 :          0 :         attach = dma_buf_attach(dma_buf, attach_dev);
     894         [ #  # ]:          0 :         if (IS_ERR(attach))
     895                 :            :                 return ERR_CAST(attach);
     896                 :            : 
     897                 :          0 :         get_dma_buf(dma_buf);
     898                 :            : 
     899                 :          0 :         sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
     900         [ #  # ]:          0 :         if (IS_ERR(sgt)) {
     901                 :          0 :                 ret = PTR_ERR(sgt);
     902                 :          0 :                 goto fail_detach;
     903                 :            :         }
     904                 :            : 
     905                 :          0 :         obj = dev->driver->gem_prime_import_sg_table(dev, attach, sgt);
     906         [ #  # ]:          0 :         if (IS_ERR(obj)) {
     907                 :          0 :                 ret = PTR_ERR(obj);
     908                 :          0 :                 goto fail_unmap;
     909                 :            :         }
     910                 :            : 
     911                 :          0 :         obj->import_attach = attach;
     912                 :          0 :         obj->resv = dma_buf->resv;
     913                 :            : 
     914                 :          0 :         return obj;
     915                 :            : 
     916                 :            : fail_unmap:
     917                 :          0 :         dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
     918                 :          0 : fail_detach:
     919                 :          0 :         dma_buf_detach(dma_buf, attach);
     920                 :          0 :         dma_buf_put(dma_buf);
     921                 :            : 
     922                 :          0 :         return ERR_PTR(ret);
     923                 :            : }
     924                 :            : EXPORT_SYMBOL(drm_gem_prime_import_dev);
     925                 :            : 
     926                 :            : /**
     927                 :            :  * drm_gem_prime_import - helper library implementation of the import callback
     928                 :            :  * @dev: drm_device to import into
     929                 :            :  * @dma_buf: dma-buf object to import
     930                 :            :  *
     931                 :            :  * This is the implementation of the gem_prime_import functions for GEM drivers
     932                 :            :  * using the PRIME helpers. Drivers can use this as their
     933                 :            :  * &drm_driver.gem_prime_import implementation. It is used as the default
     934                 :            :  * implementation in drm_gem_prime_fd_to_handle().
     935                 :            :  *
     936                 :            :  * Drivers must arrange to call drm_prime_gem_destroy() from their
     937                 :            :  * &drm_gem_object_funcs.free hook when using this function.
     938                 :            :  */
     939                 :          0 : struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
     940                 :            :                                             struct dma_buf *dma_buf)
     941                 :            : {
     942                 :          0 :         return drm_gem_prime_import_dev(dev, dma_buf, dev->dev);
     943                 :            : }
     944                 :            : EXPORT_SYMBOL(drm_gem_prime_import);
     945                 :            : 
     946                 :            : /**
     947                 :            :  * drm_prime_sg_to_page_addr_arrays - convert an sg table into a page array
     948                 :            :  * @sgt: scatter-gather table to convert
     949                 :            :  * @pages: optional array of page pointers to store the page array in
     950                 :            :  * @addrs: optional array to store the dma bus address of each page
     951                 :            :  * @max_entries: size of both the passed-in arrays
     952                 :            :  *
     953                 :            :  * Exports an sg table into an array of pages and addresses. This is currently
     954                 :            :  * required by the TTM driver in order to do correct fault handling.
     955                 :            :  *
     956                 :            :  * Drivers can use this in their &drm_driver.gem_prime_import_sg_table
     957                 :            :  * implementation.
     958                 :            :  */
     959                 :          0 : int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
     960                 :            :                                      dma_addr_t *addrs, int max_entries)
     961                 :            : {
     962                 :          0 :         unsigned count;
     963                 :          0 :         struct scatterlist *sg;
     964                 :          0 :         struct page *page;
     965                 :          0 :         u32 len, index;
     966                 :          0 :         dma_addr_t addr;
     967                 :            : 
     968                 :          0 :         index = 0;
     969         [ #  # ]:          0 :         for_each_sg(sgt->sgl, sg, sgt->nents, count) {
     970                 :          0 :                 len = sg_dma_len(sg);
     971                 :          0 :                 page = sg_page(sg);
     972                 :          0 :                 addr = sg_dma_address(sg);
     973                 :            : 
     974         [ #  # ]:          0 :                 while (len > 0) {
     975   [ #  #  #  # ]:          0 :                         if (WARN_ON(index >= max_entries))
     976                 :            :                                 return -1;
     977         [ #  # ]:          0 :                         if (pages)
     978                 :          0 :                                 pages[index] = page;
     979         [ #  # ]:          0 :                         if (addrs)
     980                 :          0 :                                 addrs[index] = addr;
     981                 :            : 
     982                 :          0 :                         page++;
     983                 :          0 :                         addr += PAGE_SIZE;
     984                 :          0 :                         len -= PAGE_SIZE;
     985                 :          0 :                         index++;
     986                 :            :                 }
     987                 :            :         }
     988                 :            :         return 0;
     989                 :            : }
     990                 :            : EXPORT_SYMBOL(drm_prime_sg_to_page_addr_arrays);
     991                 :            : 
     992                 :            : /**
     993                 :            :  * drm_prime_gem_destroy - helper to clean up a PRIME-imported GEM object
     994                 :            :  * @obj: GEM object which was created from a dma-buf
     995                 :            :  * @sg: the sg-table which was pinned at import time
     996                 :            :  *
     997                 :            :  * This is the cleanup functions which GEM drivers need to call when they use
     998                 :            :  * drm_gem_prime_import() or drm_gem_prime_import_dev() to import dma-bufs.
     999                 :            :  */
    1000                 :          0 : void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg)
    1001                 :            : {
    1002                 :          0 :         struct dma_buf_attachment *attach;
    1003                 :          0 :         struct dma_buf *dma_buf;
    1004                 :          0 :         attach = obj->import_attach;
    1005         [ #  # ]:          0 :         if (sg)
    1006                 :          0 :                 dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL);
    1007                 :          0 :         dma_buf = attach->dmabuf;
    1008                 :          0 :         dma_buf_detach(attach->dmabuf, attach);
    1009                 :            :         /* remove the reference */
    1010                 :          0 :         dma_buf_put(dma_buf);
    1011                 :          0 : }
    1012                 :            : EXPORT_SYMBOL(drm_prime_gem_destroy);

Generated by: LCOV version 1.14