We make the invalid assumption in arm_smmu_detach_dev() that the ATC is clear after calling pci_disable_ats(). For one thing, only enabling the PCIe ATS capability constitutes an implicit invalidation event, so the comment was wrong. More importantly, the ATS capability isn't necessarily disabled by pci_disable_ats() in a PF, if the associated VFs have ATS enabled. Explicitly invalidate all ATC entries in arm_smmu_detach_dev(). The endpoint cannot form new ATC entries because STE.EATS is clear.
Unified · Split
| @@ -1892,9 +1892,13 @@ static int arm_smmu_enable_ats(struct arm_smmu_master *master) · 1891 unmodified lines | ||
| 1892 | 1892 | |
| 1893 | 1893 | static void arm_smmu_disable_ats(struct arm_smmu_master *master) |
| 1894 | 1894 | { |
| 1895 | + struct arm_smmu_cmdq_ent cmd; | |
| 1896 | + | |
| 1895 | 1897 | if (!master->ats_enabled || !dev_is_pci(master->dev)) |
| 1896 | 1898 | return; |
| 1897 | 1899 | |
| 1900 | + arm_smmu_atc_inv_to_cmd(0, 0, 0, &cmd); | |
| 1901 | + arm_smmu_atc_inv_master(master, &cmd); | |
| 1898 | 1902 | pci_disable_ats(to_pci_dev(master->dev)); |
| 1899 | 1903 | master->ats_enabled = false; |
| 1900 | 1904 | } |
| @@ -1914,7 +1918,6 @@ static void arm_smmu_detach_dev(struct arm_smmu_master *master) · 13 unmodified lines | ||
| 1914 | 1918 | master->domain = NULL; |
| 1915 | 1919 | arm_smmu_install_ste_for_dev(master); |
| 1916 | 1920 | |
| 1917 | − /* Disabling ATS invalidates all ATC entries */ | |
| 1918 | 1921 | arm_smmu_disable_ats(master); |
| 1919 | 1922 | } |
| 1920 | 1923 | |