@@ -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
892954err_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}
11011158EXPORT_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}
11371218EXPORT_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);
13471453int 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}
13721484EXPORT_SYMBOL_NS_GPL (dma_buf_mmap , DMA_BUF );
13731485
@@ -1390,41 +1502,67 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_mmap, DMA_BUF);
13901502int 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}
14261537EXPORT_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}
14501588EXPORT_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
14531607static int dma_buf_debug_show (struct seq_file * s , void * unused )
14541608{
0 commit comments