Skip to content

Commit b837d3d

Browse files
committed
Merge tag 'drm-misc-next-2022-10-20' of git://anongit.freedesktop.org/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 <[email protected]> From: Maxime Ripard <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/20221020072405.g3o4hxuk75gmeumw@houat
2 parents 247f34f + 7c99616 commit b837d3d

File tree

110 files changed

+3849
-1353
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+3849
-1353
lines changed

Documentation/driver-api/dma-buf.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ DMA Buffer ioctls
119119

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

122+
DMA-BUF locking convention
123+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
124+
125+
.. kernel-doc:: drivers/dma-buf/dma-buf.c
126+
:doc: locking convention
127+
122128
Kernel Functions and Structures Reference
123129
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
124130

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6692,6 +6692,7 @@ L: [email protected]
66926692
S: Maintained
66936693
T: git git://anongit.freedesktop.org/drm/drm-misc
66946694
F: drivers/gpu/drm/drm_aperture.c
6695+
F: drivers/gpu/drm/tiny/ofdrm.c
66956696
F: drivers/gpu/drm/tiny/simpledrm.c
66966697
F: drivers/video/aperture.c
66976698
F: include/drm/drm_aperture.h

drivers/dma-buf/dma-buf.c

Lines changed: 185 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,6 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
657657

658658
dmabuf->file = file;
659659

660-
mutex_init(&dmabuf->lock);
661660
INIT_LIST_HEAD(&dmabuf->attachments);
662661

663662
mutex_lock(&db_list.lock);
@@ -795,6 +794,70 @@ static struct sg_table * __map_dma_buf(struct dma_buf_attachment *attach,
795794
return sg_table;
796795
}
797796

797+
/**
798+
* DOC: locking convention
799+
*
800+
* In order to avoid deadlock situations between dma-buf exports and importers,
801+
* all dma-buf API users must follow the common dma-buf locking convention.
802+
*
803+
* Convention for importers
804+
*
805+
* 1. Importers must hold the dma-buf reservation lock when calling these
806+
* functions:
807+
*
808+
* - dma_buf_pin()
809+
* - dma_buf_unpin()
810+
* - dma_buf_map_attachment()
811+
* - dma_buf_unmap_attachment()
812+
* - dma_buf_vmap()
813+
* - dma_buf_vunmap()
814+
*
815+
* 2. Importers must not hold the dma-buf reservation lock when calling these
816+
* functions:
817+
*
818+
* - dma_buf_attach()
819+
* - dma_buf_dynamic_attach()
820+
* - dma_buf_detach()
821+
* - dma_buf_export(
822+
* - dma_buf_fd()
823+
* - dma_buf_get()
824+
* - dma_buf_put()
825+
* - dma_buf_mmap()
826+
* - dma_buf_begin_cpu_access()
827+
* - dma_buf_end_cpu_access()
828+
* - dma_buf_map_attachment_unlocked()
829+
* - dma_buf_unmap_attachment_unlocked()
830+
* - dma_buf_vmap_unlocked()
831+
* - dma_buf_vunmap_unlocked()
832+
*
833+
* Convention for exporters
834+
*
835+
* 1. These &dma_buf_ops callbacks are invoked with unlocked dma-buf
836+
* reservation and exporter can take the lock:
837+
*
838+
* - &dma_buf_ops.attach()
839+
* - &dma_buf_ops.detach()
840+
* - &dma_buf_ops.release()
841+
* - &dma_buf_ops.begin_cpu_access()
842+
* - &dma_buf_ops.end_cpu_access()
843+
*
844+
* 2. These &dma_buf_ops callbacks are invoked with locked dma-buf
845+
* reservation and exporter can't take the lock:
846+
*
847+
* - &dma_buf_ops.pin()
848+
* - &dma_buf_ops.unpin()
849+
* - &dma_buf_ops.map_dma_buf()
850+
* - &dma_buf_ops.unmap_dma_buf()
851+
* - &dma_buf_ops.mmap()
852+
* - &dma_buf_ops.vmap()
853+
* - &dma_buf_ops.vunmap()
854+
*
855+
* 3. Exporters must hold the dma-buf reservation lock when calling these
856+
* functions:
857+
*
858+
* - dma_buf_move_notify()
859+
*/
860+
798861
/**
799862
* dma_buf_dynamic_attach - Add the device to dma_buf's attachments list
800863
* @dmabuf: [in] buffer to attach device to.
@@ -859,8 +922,8 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
859922
dma_buf_is_dynamic(dmabuf)) {
860923
struct sg_table *sgt;
861924

925+
dma_resv_lock(attach->dmabuf->resv, NULL);
862926
if (dma_buf_is_dynamic(attach->dmabuf)) {
863-
dma_resv_lock(attach->dmabuf->resv, NULL);
864927
ret = dmabuf->ops->pin(attach);
865928
if (ret)
866929
goto err_unlock;
@@ -873,8 +936,7 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
873936
ret = PTR_ERR(sgt);
874937
goto err_unpin;
875938
}
876-
if (dma_buf_is_dynamic(attach->dmabuf))
877-
dma_resv_unlock(attach->dmabuf->resv);
939+
dma_resv_unlock(attach->dmabuf->resv);
878940
attach->sgt = sgt;
879941
attach->dir = DMA_BIDIRECTIONAL;
880942
}
@@ -890,8 +952,7 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
890952
dmabuf->ops->unpin(attach);
891953

892954
err_unlock:
893-
if (dma_buf_is_dynamic(attach->dmabuf))
894-
dma_resv_unlock(attach->dmabuf->resv);
955+
dma_resv_unlock(attach->dmabuf->resv);
895956

896957
dma_buf_detach(dmabuf, attach);
897958
return ERR_PTR(ret);
@@ -937,21 +998,19 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
937998
if (WARN_ON(!dmabuf || !attach))
938999
return;
9391000

1001+
dma_resv_lock(attach->dmabuf->resv, NULL);
1002+
9401003
if (attach->sgt) {
941-
if (dma_buf_is_dynamic(attach->dmabuf))
942-
dma_resv_lock(attach->dmabuf->resv, NULL);
9431004

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

946-
if (dma_buf_is_dynamic(attach->dmabuf)) {
1007+
if (dma_buf_is_dynamic(attach->dmabuf))
9471008
dmabuf->ops->unpin(attach);
948-
dma_resv_unlock(attach->dmabuf->resv);
949-
}
9501009
}
951-
952-
dma_resv_lock(dmabuf->resv, NULL);
9531010
list_del(&attach->node);
1011+
9541012
dma_resv_unlock(dmabuf->resv);
1013+
9551014
if (dmabuf->ops->detach)
9561015
dmabuf->ops->detach(dmabuf, attach);
9571016

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

1045-
if (dma_buf_attachment_is_dynamic(attach))
1046-
dma_resv_assert_held(attach->dmabuf->resv);
1104+
dma_resv_assert_held(attach->dmabuf->resv);
10471105

10481106
if (attach->sgt) {
10491107
/*
@@ -1058,7 +1116,6 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
10581116
}
10591117

10601118
if (dma_buf_is_dynamic(attach->dmabuf)) {
1061-
dma_resv_assert_held(attach->dmabuf->resv);
10621119
if (!IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY)) {
10631120
r = attach->dmabuf->ops->pin(attach);
10641121
if (r)
@@ -1100,6 +1157,34 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
11001157
}
11011158
EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment, DMA_BUF);
11021159

1160+
/**
1161+
* dma_buf_map_attachment_unlocked - Returns the scatterlist table of the attachment;
1162+
* mapped into _device_ address space. Is a wrapper for map_dma_buf() of the
1163+
* dma_buf_ops.
1164+
* @attach: [in] attachment whose scatterlist is to be returned
1165+
* @direction: [in] direction of DMA transfer
1166+
*
1167+
* Unlocked variant of dma_buf_map_attachment().
1168+
*/
1169+
struct sg_table *
1170+
dma_buf_map_attachment_unlocked(struct dma_buf_attachment *attach,
1171+
enum dma_data_direction direction)
1172+
{
1173+
struct sg_table *sg_table;
1174+
1175+
might_sleep();
1176+
1177+
if (WARN_ON(!attach || !attach->dmabuf))
1178+
return ERR_PTR(-EINVAL);
1179+
1180+
dma_resv_lock(attach->dmabuf->resv, NULL);
1181+
sg_table = dma_buf_map_attachment(attach, direction);
1182+
dma_resv_unlock(attach->dmabuf->resv);
1183+
1184+
return sg_table;
1185+
}
1186+
EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment_unlocked, DMA_BUF);
1187+
11031188
/**
11041189
* dma_buf_unmap_attachment - unmaps and decreases usecount of the buffer;might
11051190
* deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf() of
@@ -1119,15 +1204,11 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
11191204
if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
11201205
return;
11211206

1122-
if (dma_buf_attachment_is_dynamic(attach))
1123-
dma_resv_assert_held(attach->dmabuf->resv);
1207+
dma_resv_assert_held(attach->dmabuf->resv);
11241208

11251209
if (attach->sgt == sg_table)
11261210
return;
11271211

1128-
if (dma_buf_is_dynamic(attach->dmabuf))
1129-
dma_resv_assert_held(attach->dmabuf->resv);
1130-
11311212
__unmap_dma_buf(attach, sg_table, direction);
11321213

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

1220+
/**
1221+
* dma_buf_unmap_attachment_unlocked - unmaps and decreases usecount of the buffer;might
1222+
* deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf() of
1223+
* dma_buf_ops.
1224+
* @attach: [in] attachment to unmap buffer from
1225+
* @sg_table: [in] scatterlist info of the buffer to unmap
1226+
* @direction: [in] direction of DMA transfer
1227+
*
1228+
* Unlocked variant of dma_buf_unmap_attachment().
1229+
*/
1230+
void dma_buf_unmap_attachment_unlocked(struct dma_buf_attachment *attach,
1231+
struct sg_table *sg_table,
1232+
enum dma_data_direction direction)
1233+
{
1234+
might_sleep();
1235+
1236+
if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
1237+
return;
1238+
1239+
dma_resv_lock(attach->dmabuf->resv, NULL);
1240+
dma_buf_unmap_attachment(attach, sg_table, direction);
1241+
dma_resv_unlock(attach->dmabuf->resv);
1242+
}
1243+
EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment_unlocked, DMA_BUF);
1244+
11391245
/**
11401246
* dma_buf_move_notify - notify attachments that DMA-buf is moving
11411247
*
@@ -1347,6 +1453,8 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_end_cpu_access, DMA_BUF);
13471453
int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
13481454
unsigned long pgoff)
13491455
{
1456+
int ret;
1457+
13501458
if (WARN_ON(!dmabuf || !vma))
13511459
return -EINVAL;
13521460

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

1370-
return dmabuf->ops->mmap(dmabuf, vma);
1478+
dma_resv_lock(dmabuf->resv, NULL);
1479+
ret = dmabuf->ops->mmap(dmabuf, vma);
1480+
dma_resv_unlock(dmabuf->resv);
1481+
1482+
return ret;
13711483
}
13721484
EXPORT_SYMBOL_NS_GPL(dma_buf_mmap, DMA_BUF);
13731485

@@ -1390,41 +1502,67 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_mmap, DMA_BUF);
13901502
int dma_buf_vmap(struct dma_buf *dmabuf, struct iosys_map *map)
13911503
{
13921504
struct iosys_map ptr;
1393-
int ret = 0;
1505+
int ret;
13941506

13951507
iosys_map_clear(map);
13961508

13971509
if (WARN_ON(!dmabuf))
13981510
return -EINVAL;
13991511

1512+
dma_resv_assert_held(dmabuf->resv);
1513+
14001514
if (!dmabuf->ops->vmap)
14011515
return -EINVAL;
14021516

1403-
mutex_lock(&dmabuf->lock);
14041517
if (dmabuf->vmapping_counter) {
14051518
dmabuf->vmapping_counter++;
14061519
BUG_ON(iosys_map_is_null(&dmabuf->vmap_ptr));
14071520
*map = dmabuf->vmap_ptr;
1408-
goto out_unlock;
1521+
return 0;
14091522
}
14101523

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

14131526
ret = dmabuf->ops->vmap(dmabuf, &ptr);
14141527
if (WARN_ON_ONCE(ret))
1415-
goto out_unlock;
1528+
return ret;
14161529

14171530
dmabuf->vmap_ptr = ptr;
14181531
dmabuf->vmapping_counter = 1;
14191532

14201533
*map = dmabuf->vmap_ptr;
14211534

1422-
out_unlock:
1423-
mutex_unlock(&dmabuf->lock);
1424-
return ret;
1535+
return 0;
14251536
}
14261537
EXPORT_SYMBOL_NS_GPL(dma_buf_vmap, DMA_BUF);
14271538

1539+
/**
1540+
* dma_buf_vmap_unlocked - Create virtual mapping for the buffer object into kernel
1541+
* address space. Same restrictions as for vmap and friends apply.
1542+
* @dmabuf: [in] buffer to vmap
1543+
* @map: [out] returns the vmap pointer
1544+
*
1545+
* Unlocked version of dma_buf_vmap()
1546+
*
1547+
* Returns 0 on success, or a negative errno code otherwise.
1548+
*/
1549+
int dma_buf_vmap_unlocked(struct dma_buf *dmabuf, struct iosys_map *map)
1550+
{
1551+
int ret;
1552+
1553+
iosys_map_clear(map);
1554+
1555+
if (WARN_ON(!dmabuf))
1556+
return -EINVAL;
1557+
1558+
dma_resv_lock(dmabuf->resv, NULL);
1559+
ret = dma_buf_vmap(dmabuf, map);
1560+
dma_resv_unlock(dmabuf->resv);
1561+
1562+
return ret;
1563+
}
1564+
EXPORT_SYMBOL_NS_GPL(dma_buf_vmap_unlocked, DMA_BUF);
1565+
14281566
/**
14291567
* dma_buf_vunmap - Unmap a vmap obtained by dma_buf_vmap.
14301568
* @dmabuf: [in] buffer to vunmap
@@ -1435,20 +1573,36 @@ void dma_buf_vunmap(struct dma_buf *dmabuf, struct iosys_map *map)
14351573
if (WARN_ON(!dmabuf))
14361574
return;
14371575

1576+
dma_resv_assert_held(dmabuf->resv);
1577+
14381578
BUG_ON(iosys_map_is_null(&dmabuf->vmap_ptr));
14391579
BUG_ON(dmabuf->vmapping_counter == 0);
14401580
BUG_ON(!iosys_map_is_equal(&dmabuf->vmap_ptr, map));
14411581

1442-
mutex_lock(&dmabuf->lock);
14431582
if (--dmabuf->vmapping_counter == 0) {
14441583
if (dmabuf->ops->vunmap)
14451584
dmabuf->ops->vunmap(dmabuf, map);
14461585
iosys_map_clear(&dmabuf->vmap_ptr);
14471586
}
1448-
mutex_unlock(&dmabuf->lock);
14491587
}
14501588
EXPORT_SYMBOL_NS_GPL(dma_buf_vunmap, DMA_BUF);
14511589

1590+
/**
1591+
* dma_buf_vunmap_unlocked - Unmap a vmap obtained by dma_buf_vmap.
1592+
* @dmabuf: [in] buffer to vunmap
1593+
* @map: [in] vmap pointer to vunmap
1594+
*/
1595+
void dma_buf_vunmap_unlocked(struct dma_buf *dmabuf, struct iosys_map *map)
1596+
{
1597+
if (WARN_ON(!dmabuf))
1598+
return;
1599+
1600+
dma_resv_lock(dmabuf->resv, NULL);
1601+
dma_buf_vunmap(dmabuf, map);
1602+
dma_resv_unlock(dmabuf->resv);
1603+
}
1604+
EXPORT_SYMBOL_NS_GPL(dma_buf_vunmap_unlocked, DMA_BUF);
1605+
14521606
#ifdef CONFIG_DEBUG_FS
14531607
static int dma_buf_debug_show(struct seq_file *s, void *unused)
14541608
{

0 commit comments

Comments
 (0)