Skip to content

Commit

Permalink
Merge tag 'drm-misc-next-2022-10-20' of git://anongit.freedesktop.org…
Browse files Browse the repository at this point in the history
…/drm/drm-misc into drm-next

drm-misc-next for 6.2:

UAPI Changes:
  - Documentation for page-flip flags

Cross-subsystem Changes:
  - dma-buf: Add unlocked variant of vmapping and attachment-mapping
    functions

Core Changes:
  - atomic-helpers: CRTC primary plane test fixes
  - connector: TV API consistency improvements, cmdline parsing
    improvements
  - crtc-helpers: Introduce drm_crtc_helper_atomic_check() helper
  - edid: Fixes for HFVSDB parsing,
  - fourcc: Addition of the Vivante tiled modifier
  - makefile: Sort and reorganize the objects files
  - mode_config: Remove fb_base from drm_mode_config_funcs
  - sched: Add a module parameter to change the scheduling policy,
    refcounting fix for fences
  - tests: Sort the Kunit tests in the Makefile, improvements to the
    DP-MST tests
  - ttm: Remove unnecessary drm_mm_clean() call

Driver Changes:
  - New driver: ofdrm
  - Move all drivers to a common dma-buf locking convention
  - bridge:
    - adv7533: Remove dynamic lane switching
    - it6505: Runtime PM support
    - ps8640: Handle AUX defer messages
    - tc358775: Drop soft-reset over I2C
  - ast: Atomic Gamma LUT Support, Convert to SHMEM, various
    improvements
  - lcdif: Support for YUV planes
  - mgag200: Fix PLL Setup on some revisions
  - udl: Modesetting improvements, hot-unplug support
  - vc4: Fix support for PAL-M

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Maxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20221020072405.g3o4hxuk75gmeumw@houat
  • Loading branch information
Dave Airlie committed Oct 25, 2022
2 parents 247f34f + 7c99616 commit b837d3d
Show file tree
Hide file tree
Showing 110 changed files with 3,849 additions and 1,353 deletions.
6 changes: 6 additions & 0 deletions Documentation/driver-api/dma-buf.rst
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ DMA Buffer ioctls

.. kernel-doc:: include/uapi/linux/dma-buf.h

DMA-BUF locking convention
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. kernel-doc:: drivers/dma-buf/dma-buf.c
:doc: locking convention

Kernel Functions and Structures Reference
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -6692,6 +6692,7 @@ L: dri-devel@lists.freedesktop.org
S: Maintained
T: git git://anongit.freedesktop.org/drm/drm-misc
F: drivers/gpu/drm/drm_aperture.c
F: drivers/gpu/drm/tiny/ofdrm.c
F: drivers/gpu/drm/tiny/simpledrm.c
F: drivers/video/aperture.c
F: include/drm/drm_aperture.h
Expand Down
216 changes: 185 additions & 31 deletions drivers/dma-buf/dma-buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,6 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)

dmabuf->file = file;

mutex_init(&dmabuf->lock);
INIT_LIST_HEAD(&dmabuf->attachments);

mutex_lock(&db_list.lock);
Expand Down Expand Up @@ -795,6 +794,70 @@ static struct sg_table * __map_dma_buf(struct dma_buf_attachment *attach,
return sg_table;
}

/**
* DOC: locking convention
*
* In order to avoid deadlock situations between dma-buf exports and importers,
* all dma-buf API users must follow the common dma-buf locking convention.
*
* Convention for importers
*
* 1. Importers must hold the dma-buf reservation lock when calling these
* functions:
*
* - dma_buf_pin()
* - dma_buf_unpin()
* - dma_buf_map_attachment()
* - dma_buf_unmap_attachment()
* - dma_buf_vmap()
* - dma_buf_vunmap()
*
* 2. Importers must not hold the dma-buf reservation lock when calling these
* functions:
*
* - dma_buf_attach()
* - dma_buf_dynamic_attach()
* - dma_buf_detach()
* - dma_buf_export(
* - dma_buf_fd()
* - dma_buf_get()
* - dma_buf_put()
* - dma_buf_mmap()
* - dma_buf_begin_cpu_access()
* - dma_buf_end_cpu_access()
* - dma_buf_map_attachment_unlocked()
* - dma_buf_unmap_attachment_unlocked()
* - dma_buf_vmap_unlocked()
* - dma_buf_vunmap_unlocked()
*
* Convention for exporters
*
* 1. These &dma_buf_ops callbacks are invoked with unlocked dma-buf
* reservation and exporter can take the lock:
*
* - &dma_buf_ops.attach()
* - &dma_buf_ops.detach()
* - &dma_buf_ops.release()
* - &dma_buf_ops.begin_cpu_access()
* - &dma_buf_ops.end_cpu_access()
*
* 2. These &dma_buf_ops callbacks are invoked with locked dma-buf
* reservation and exporter can't take the lock:
*
* - &dma_buf_ops.pin()
* - &dma_buf_ops.unpin()
* - &dma_buf_ops.map_dma_buf()
* - &dma_buf_ops.unmap_dma_buf()
* - &dma_buf_ops.mmap()
* - &dma_buf_ops.vmap()
* - &dma_buf_ops.vunmap()
*
* 3. Exporters must hold the dma-buf reservation lock when calling these
* functions:
*
* - dma_buf_move_notify()
*/

/**
* dma_buf_dynamic_attach - Add the device to dma_buf's attachments list
* @dmabuf: [in] buffer to attach device to.
Expand Down Expand Up @@ -859,8 +922,8 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
dma_buf_is_dynamic(dmabuf)) {
struct sg_table *sgt;

dma_resv_lock(attach->dmabuf->resv, NULL);
if (dma_buf_is_dynamic(attach->dmabuf)) {
dma_resv_lock(attach->dmabuf->resv, NULL);
ret = dmabuf->ops->pin(attach);
if (ret)
goto err_unlock;
Expand All @@ -873,8 +936,7 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
ret = PTR_ERR(sgt);
goto err_unpin;
}
if (dma_buf_is_dynamic(attach->dmabuf))
dma_resv_unlock(attach->dmabuf->resv);
dma_resv_unlock(attach->dmabuf->resv);
attach->sgt = sgt;
attach->dir = DMA_BIDIRECTIONAL;
}
Expand All @@ -890,8 +952,7 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
dmabuf->ops->unpin(attach);

err_unlock:
if (dma_buf_is_dynamic(attach->dmabuf))
dma_resv_unlock(attach->dmabuf->resv);
dma_resv_unlock(attach->dmabuf->resv);

dma_buf_detach(dmabuf, attach);
return ERR_PTR(ret);
Expand Down Expand Up @@ -937,21 +998,19 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
if (WARN_ON(!dmabuf || !attach))
return;

dma_resv_lock(attach->dmabuf->resv, NULL);

if (attach->sgt) {
if (dma_buf_is_dynamic(attach->dmabuf))
dma_resv_lock(attach->dmabuf->resv, NULL);

__unmap_dma_buf(attach, attach->sgt, attach->dir);

if (dma_buf_is_dynamic(attach->dmabuf)) {
if (dma_buf_is_dynamic(attach->dmabuf))
dmabuf->ops->unpin(attach);
dma_resv_unlock(attach->dmabuf->resv);
}
}

dma_resv_lock(dmabuf->resv, NULL);
list_del(&attach->node);

dma_resv_unlock(dmabuf->resv);

if (dmabuf->ops->detach)
dmabuf->ops->detach(dmabuf, attach);

Expand Down Expand Up @@ -1042,8 +1101,7 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
if (WARN_ON(!attach || !attach->dmabuf))
return ERR_PTR(-EINVAL);

if (dma_buf_attachment_is_dynamic(attach))
dma_resv_assert_held(attach->dmabuf->resv);
dma_resv_assert_held(attach->dmabuf->resv);

if (attach->sgt) {
/*
Expand All @@ -1058,7 +1116,6 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
}

if (dma_buf_is_dynamic(attach->dmabuf)) {
dma_resv_assert_held(attach->dmabuf->resv);
if (!IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY)) {
r = attach->dmabuf->ops->pin(attach);
if (r)
Expand Down Expand Up @@ -1100,6 +1157,34 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
}
EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment, DMA_BUF);

/**
* dma_buf_map_attachment_unlocked - Returns the scatterlist table of the attachment;
* mapped into _device_ address space. Is a wrapper for map_dma_buf() of the
* dma_buf_ops.
* @attach: [in] attachment whose scatterlist is to be returned
* @direction: [in] direction of DMA transfer
*
* Unlocked variant of dma_buf_map_attachment().
*/
struct sg_table *
dma_buf_map_attachment_unlocked(struct dma_buf_attachment *attach,
enum dma_data_direction direction)
{
struct sg_table *sg_table;

might_sleep();

if (WARN_ON(!attach || !attach->dmabuf))
return ERR_PTR(-EINVAL);

dma_resv_lock(attach->dmabuf->resv, NULL);
sg_table = dma_buf_map_attachment(attach, direction);
dma_resv_unlock(attach->dmabuf->resv);

return sg_table;
}
EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment_unlocked, DMA_BUF);

/**
* dma_buf_unmap_attachment - unmaps and decreases usecount of the buffer;might
* deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf() of
Expand All @@ -1119,15 +1204,11 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
return;

if (dma_buf_attachment_is_dynamic(attach))
dma_resv_assert_held(attach->dmabuf->resv);
dma_resv_assert_held(attach->dmabuf->resv);

if (attach->sgt == sg_table)
return;

if (dma_buf_is_dynamic(attach->dmabuf))
dma_resv_assert_held(attach->dmabuf->resv);

__unmap_dma_buf(attach, sg_table, direction);

if (dma_buf_is_dynamic(attach->dmabuf) &&
Expand All @@ -1136,6 +1217,31 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
}
EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment, DMA_BUF);

/**
* dma_buf_unmap_attachment_unlocked - unmaps and decreases usecount of the buffer;might
* deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf() of
* dma_buf_ops.
* @attach: [in] attachment to unmap buffer from
* @sg_table: [in] scatterlist info of the buffer to unmap
* @direction: [in] direction of DMA transfer
*
* Unlocked variant of dma_buf_unmap_attachment().
*/
void dma_buf_unmap_attachment_unlocked(struct dma_buf_attachment *attach,
struct sg_table *sg_table,
enum dma_data_direction direction)
{
might_sleep();

if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
return;

dma_resv_lock(attach->dmabuf->resv, NULL);
dma_buf_unmap_attachment(attach, sg_table, direction);
dma_resv_unlock(attach->dmabuf->resv);
}
EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment_unlocked, DMA_BUF);

/**
* dma_buf_move_notify - notify attachments that DMA-buf is moving
*
Expand Down Expand Up @@ -1347,6 +1453,8 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_end_cpu_access, DMA_BUF);
int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
unsigned long pgoff)
{
int ret;

if (WARN_ON(!dmabuf || !vma))
return -EINVAL;

Expand All @@ -1367,7 +1475,11 @@ int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
vma_set_file(vma, dmabuf->file);
vma->vm_pgoff = pgoff;

return dmabuf->ops->mmap(dmabuf, vma);
dma_resv_lock(dmabuf->resv, NULL);
ret = dmabuf->ops->mmap(dmabuf, vma);
dma_resv_unlock(dmabuf->resv);

return ret;
}
EXPORT_SYMBOL_NS_GPL(dma_buf_mmap, DMA_BUF);

Expand All @@ -1390,41 +1502,67 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_mmap, DMA_BUF);
int dma_buf_vmap(struct dma_buf *dmabuf, struct iosys_map *map)
{
struct iosys_map ptr;
int ret = 0;
int ret;

iosys_map_clear(map);

if (WARN_ON(!dmabuf))
return -EINVAL;

dma_resv_assert_held(dmabuf->resv);

if (!dmabuf->ops->vmap)
return -EINVAL;

mutex_lock(&dmabuf->lock);
if (dmabuf->vmapping_counter) {
dmabuf->vmapping_counter++;
BUG_ON(iosys_map_is_null(&dmabuf->vmap_ptr));
*map = dmabuf->vmap_ptr;
goto out_unlock;
return 0;
}

BUG_ON(iosys_map_is_set(&dmabuf->vmap_ptr));

ret = dmabuf->ops->vmap(dmabuf, &ptr);
if (WARN_ON_ONCE(ret))
goto out_unlock;
return ret;

dmabuf->vmap_ptr = ptr;
dmabuf->vmapping_counter = 1;

*map = dmabuf->vmap_ptr;

out_unlock:
mutex_unlock(&dmabuf->lock);
return ret;
return 0;
}
EXPORT_SYMBOL_NS_GPL(dma_buf_vmap, DMA_BUF);

/**
* dma_buf_vmap_unlocked - Create virtual mapping for the buffer object into kernel
* address space. Same restrictions as for vmap and friends apply.
* @dmabuf: [in] buffer to vmap
* @map: [out] returns the vmap pointer
*
* Unlocked version of dma_buf_vmap()
*
* Returns 0 on success, or a negative errno code otherwise.
*/
int dma_buf_vmap_unlocked(struct dma_buf *dmabuf, struct iosys_map *map)
{
int ret;

iosys_map_clear(map);

if (WARN_ON(!dmabuf))
return -EINVAL;

dma_resv_lock(dmabuf->resv, NULL);
ret = dma_buf_vmap(dmabuf, map);
dma_resv_unlock(dmabuf->resv);

return ret;
}
EXPORT_SYMBOL_NS_GPL(dma_buf_vmap_unlocked, DMA_BUF);

/**
* dma_buf_vunmap - Unmap a vmap obtained by dma_buf_vmap.
* @dmabuf: [in] buffer to vunmap
Expand All @@ -1435,20 +1573,36 @@ void dma_buf_vunmap(struct dma_buf *dmabuf, struct iosys_map *map)
if (WARN_ON(!dmabuf))
return;

dma_resv_assert_held(dmabuf->resv);

BUG_ON(iosys_map_is_null(&dmabuf->vmap_ptr));
BUG_ON(dmabuf->vmapping_counter == 0);
BUG_ON(!iosys_map_is_equal(&dmabuf->vmap_ptr, map));

mutex_lock(&dmabuf->lock);
if (--dmabuf->vmapping_counter == 0) {
if (dmabuf->ops->vunmap)
dmabuf->ops->vunmap(dmabuf, map);
iosys_map_clear(&dmabuf->vmap_ptr);
}
mutex_unlock(&dmabuf->lock);
}
EXPORT_SYMBOL_NS_GPL(dma_buf_vunmap, DMA_BUF);

/**
* dma_buf_vunmap_unlocked - Unmap a vmap obtained by dma_buf_vmap.
* @dmabuf: [in] buffer to vunmap
* @map: [in] vmap pointer to vunmap
*/
void dma_buf_vunmap_unlocked(struct dma_buf *dmabuf, struct iosys_map *map)
{
if (WARN_ON(!dmabuf))
return;

dma_resv_lock(dmabuf->resv, NULL);
dma_buf_vunmap(dmabuf, map);
dma_resv_unlock(dmabuf->resv);
}
EXPORT_SYMBOL_NS_GPL(dma_buf_vunmap_unlocked, DMA_BUF);

#ifdef CONFIG_DEBUG_FS
static int dma_buf_debug_show(struct seq_file *s, void *unused)
{
Expand Down
Loading

0 comments on commit b837d3d

Please sign in to comment.