diff options
Diffstat (limited to 'arch/x86/kernel/amd_iommu.c')
-rw-r--r-- | arch/x86/kernel/amd_iommu.c | 35 |
1 files changed, 11 insertions, 24 deletions
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index b75fcd9b6a0f..32fb09102a13 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c | |||
@@ -1309,8 +1309,6 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain) | |||
1309 | { | 1309 | { |
1310 | u64 pte_root = virt_to_phys(domain->pt_root); | 1310 | u64 pte_root = virt_to_phys(domain->pt_root); |
1311 | 1311 | ||
1312 | BUG_ON(amd_iommu_pd_table[devid] != NULL); | ||
1313 | |||
1314 | pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK) | 1312 | pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK) |
1315 | << DEV_ENTRY_MODE_SHIFT; | 1313 | << DEV_ENTRY_MODE_SHIFT; |
1316 | pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV; | 1314 | pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV; |
@@ -1318,20 +1316,10 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain) | |||
1318 | amd_iommu_dev_table[devid].data[2] = domain->id; | 1316 | amd_iommu_dev_table[devid].data[2] = domain->id; |
1319 | amd_iommu_dev_table[devid].data[1] = upper_32_bits(pte_root); | 1317 | amd_iommu_dev_table[devid].data[1] = upper_32_bits(pte_root); |
1320 | amd_iommu_dev_table[devid].data[0] = lower_32_bits(pte_root); | 1318 | amd_iommu_dev_table[devid].data[0] = lower_32_bits(pte_root); |
1321 | |||
1322 | amd_iommu_pd_table[devid] = domain; | ||
1323 | |||
1324 | } | 1319 | } |
1325 | 1320 | ||
1326 | static void clear_dte_entry(u16 devid) | 1321 | static void clear_dte_entry(u16 devid) |
1327 | { | 1322 | { |
1328 | struct protection_domain *domain = amd_iommu_pd_table[devid]; | ||
1329 | |||
1330 | BUG_ON(domain == NULL); | ||
1331 | |||
1332 | /* remove domain from the lookup table */ | ||
1333 | amd_iommu_pd_table[devid] = NULL; | ||
1334 | |||
1335 | /* remove entry from the device table seen by the hardware */ | 1323 | /* remove entry from the device table seen by the hardware */ |
1336 | amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV; | 1324 | amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV; |
1337 | amd_iommu_dev_table[devid].data[1] = 0; | 1325 | amd_iommu_dev_table[devid].data[1] = 0; |
@@ -1641,15 +1629,11 @@ static struct protection_domain *get_domain(struct device *dev) | |||
1641 | 1629 | ||
1642 | static void update_device_table(struct protection_domain *domain) | 1630 | static void update_device_table(struct protection_domain *domain) |
1643 | { | 1631 | { |
1644 | unsigned long flags; | 1632 | struct iommu_dev_data *dev_data; |
1645 | int i; | ||
1646 | 1633 | ||
1647 | for (i = 0; i <= amd_iommu_last_bdf; ++i) { | 1634 | list_for_each_entry(dev_data, &domain->dev_list, list) { |
1648 | if (amd_iommu_pd_table[i] != domain) | 1635 | u16 devid = get_device_id(dev_data->dev); |
1649 | continue; | 1636 | set_dte_entry(devid, domain); |
1650 | write_lock_irqsave(&amd_iommu_devtable_lock, flags); | ||
1651 | set_dte_entry(i, domain); | ||
1652 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); | ||
1653 | } | 1637 | } |
1654 | } | 1638 | } |
1655 | 1639 | ||
@@ -2259,14 +2243,17 @@ free_domains: | |||
2259 | 2243 | ||
2260 | static void cleanup_domain(struct protection_domain *domain) | 2244 | static void cleanup_domain(struct protection_domain *domain) |
2261 | { | 2245 | { |
2246 | struct iommu_dev_data *dev_data, *next; | ||
2262 | unsigned long flags; | 2247 | unsigned long flags; |
2263 | u16 devid; | ||
2264 | 2248 | ||
2265 | write_lock_irqsave(&amd_iommu_devtable_lock, flags); | 2249 | write_lock_irqsave(&amd_iommu_devtable_lock, flags); |
2266 | 2250 | ||
2267 | for (devid = 0; devid <= amd_iommu_last_bdf; ++devid) | 2251 | list_for_each_entry_safe(dev_data, next, &domain->dev_list, list) { |
2268 | if (amd_iommu_pd_table[devid] == domain) | 2252 | struct device *dev = dev_data->dev; |
2269 | clear_dte_entry(devid); | 2253 | |
2254 | do_detach(dev); | ||
2255 | atomic_set(&dev_data->bind, 0); | ||
2256 | } | ||
2270 | 2257 | ||
2271 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); | 2258 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); |
2272 | } | 2259 | } |