@@ -2628,6 +2628,53 @@ static void arm_smmu_disable_ats(struct arm_smmu_master *master)
2628
2628
atomic_dec (& smmu_domain -> nr_ats_masters );
2629
2629
}
2630
2630
2631
+ static int arm_smmu_enable_pasid (struct arm_smmu_master * master )
2632
+ {
2633
+ int ret ;
2634
+ int features ;
2635
+ int num_pasids ;
2636
+ struct pci_dev * pdev ;
2637
+
2638
+ if (!dev_is_pci (master -> dev ))
2639
+ return - ENODEV ;
2640
+
2641
+ pdev = to_pci_dev (master -> dev );
2642
+
2643
+ features = pci_pasid_features (pdev );
2644
+ if (features < 0 )
2645
+ return features ;
2646
+
2647
+ num_pasids = pci_max_pasids (pdev );
2648
+ if (num_pasids <= 0 )
2649
+ return num_pasids ;
2650
+
2651
+ ret = pci_enable_pasid (pdev , features );
2652
+ if (ret ) {
2653
+ dev_err (& pdev -> dev , "Failed to enable PASID\n" );
2654
+ return ret ;
2655
+ }
2656
+
2657
+ master -> ssid_bits = min_t (u8 , ilog2 (num_pasids ),
2658
+ master -> smmu -> ssid_bits );
2659
+ return 0 ;
2660
+ }
2661
+
2662
+ static void arm_smmu_disable_pasid (struct arm_smmu_master * master )
2663
+ {
2664
+ struct pci_dev * pdev ;
2665
+
2666
+ if (!dev_is_pci (master -> dev ))
2667
+ return ;
2668
+
2669
+ pdev = to_pci_dev (master -> dev );
2670
+
2671
+ if (!pdev -> pasid_enabled )
2672
+ return ;
2673
+
2674
+ master -> ssid_bits = 0 ;
2675
+ pci_disable_pasid (pdev );
2676
+ }
2677
+
2631
2678
static void arm_smmu_detach_dev (struct arm_smmu_master * master )
2632
2679
{
2633
2680
unsigned long flags ;
@@ -2831,13 +2878,23 @@ static int arm_smmu_add_device(struct device *dev)
2831
2878
2832
2879
master -> ssid_bits = min (smmu -> ssid_bits , fwspec -> num_pasid_bits );
2833
2880
2881
+ /*
2882
+ * Note that PASID must be enabled before, and disabled after ATS:
2883
+ * PCI Express Base 4.0r1.0 - 10.5.1.3 ATS Control Register
2884
+ *
2885
+ * Behavior is undefined if this bit is Set and the value of the PASID
2886
+ * Enable, Execute Requested Enable, or Privileged Mode Requested bits
2887
+ * are changed.
2888
+ */
2889
+ arm_smmu_enable_pasid (master );
2890
+
2834
2891
if (!(smmu -> features & ARM_SMMU_FEAT_2_LVL_CDTAB ))
2835
2892
master -> ssid_bits = min_t (u8 , master -> ssid_bits ,
2836
2893
CTXDESC_LINEAR_CDMAX );
2837
2894
2838
2895
ret = iommu_device_link (& smmu -> iommu , dev );
2839
2896
if (ret )
2840
- goto err_free_master ;
2897
+ goto err_disable_pasid ;
2841
2898
2842
2899
group = iommu_group_get_for_dev (dev );
2843
2900
if (IS_ERR (group )) {
@@ -2850,6 +2907,8 @@ static int arm_smmu_add_device(struct device *dev)
2850
2907
2851
2908
err_unlink :
2852
2909
iommu_device_unlink (& smmu -> iommu , dev );
2910
+ err_disable_pasid :
2911
+ arm_smmu_disable_pasid (master );
2853
2912
err_free_master :
2854
2913
kfree (master );
2855
2914
fwspec -> iommu_priv = NULL ;
@@ -2870,6 +2929,7 @@ static void arm_smmu_remove_device(struct device *dev)
2870
2929
arm_smmu_detach_dev (master );
2871
2930
iommu_group_remove_device (dev );
2872
2931
iommu_device_unlink (& smmu -> iommu , dev );
2932
+ arm_smmu_disable_pasid (master );
2873
2933
kfree (master );
2874
2934
iommu_fwspec_free (dev );
2875
2935
}
0 commit comments