@@ -721,13 +721,13 @@ static int __init disable_ddw_setup(char *str)
721
721
722
722
early_param ("disable_ddw" , disable_ddw_setup );
723
723
724
- static void remove_ddw (struct device_node * np )
724
+ static void remove_ddw (struct device_node * np , bool remove_prop )
725
725
{
726
726
struct dynamic_dma_window_prop * dwp ;
727
727
struct property * win64 ;
728
728
const u32 * ddw_avail ;
729
729
u64 liobn ;
730
- int len , ret ;
730
+ int len , ret = 0 ;
731
731
732
732
ddw_avail = of_get_property (np , "ibm,ddw-applicable" , & len );
733
733
win64 = of_find_property (np , DIRECT64_PROPNAME , NULL );
@@ -761,7 +761,8 @@ static void remove_ddw(struct device_node *np)
761
761
np -> full_name , ret , ddw_avail [2 ], liobn );
762
762
763
763
delprop :
764
- ret = of_remove_property (np , win64 );
764
+ if (remove_prop )
765
+ ret = of_remove_property (np , win64 );
765
766
if (ret )
766
767
pr_warning ("%s: failed to remove direct window property: %d\n" ,
767
768
np -> full_name , ret );
@@ -805,7 +806,7 @@ static int find_existing_ddw_windows(void)
805
806
window = kzalloc (sizeof (* window ), GFP_KERNEL );
806
807
if (!window || len < sizeof (struct dynamic_dma_window_prop )) {
807
808
kfree (window );
808
- remove_ddw (pdn );
809
+ remove_ddw (pdn , true );
809
810
continue ;
810
811
}
811
812
@@ -1045,7 +1046,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
1045
1046
kfree (window );
1046
1047
1047
1048
out_clear_window :
1048
- remove_ddw (pdn );
1049
+ remove_ddw (pdn , true );
1049
1050
1050
1051
out_free_prop :
1051
1052
kfree (win64 -> name );
@@ -1255,7 +1256,14 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti
1255
1256
1256
1257
switch (action ) {
1257
1258
case OF_RECONFIG_DETACH_NODE :
1258
- remove_ddw (np );
1259
+ /*
1260
+ * Removing the property will invoke the reconfig
1261
+ * notifier again, which causes dead-lock on the
1262
+ * read-write semaphore of the notifier chain. So
1263
+ * we have to remove the property when releasing
1264
+ * the device node.
1265
+ */
1266
+ remove_ddw (np , false);
1259
1267
if (pci && pci -> iommu_table )
1260
1268
iommu_free_table (pci -> iommu_table , np -> full_name );
1261
1269
0 commit comments