Commit e6a8c9b3 authored by Joerg Roedel's avatar Joerg Roedel

iommu/vt-d: Use BUS_NOTIFY_REMOVED_DEVICE in hotplug path

In the PCI hotplug path of the Intel IOMMU driver, replace
the usage of the BUS_NOTIFY_DEL_DEVICE notifier, which is
executed before the driver is unbound from the device, with
BUS_NOTIFY_REMOVED_DEVICE, which runs after that.

This fixes a kernel BUG being triggered in the VT-d code
when the device driver tries to unmap DMA buffers and the
VT-d driver already destroyed all mappings.
Reported-by: default avatarStefani Seibold <stefani@seibold.net>
Cc: stable@vger.kernel.org # v4.3+
Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent b6809ee5
...@@ -329,7 +329,8 @@ static int dmar_pci_bus_notifier(struct notifier_block *nb, ...@@ -329,7 +329,8 @@ static int dmar_pci_bus_notifier(struct notifier_block *nb,
/* Only care about add/remove events for physical functions */ /* Only care about add/remove events for physical functions */
if (pdev->is_virtfn) if (pdev->is_virtfn)
return NOTIFY_DONE; return NOTIFY_DONE;
if (action != BUS_NOTIFY_ADD_DEVICE && action != BUS_NOTIFY_DEL_DEVICE) if (action != BUS_NOTIFY_ADD_DEVICE &&
action != BUS_NOTIFY_REMOVED_DEVICE)
return NOTIFY_DONE; return NOTIFY_DONE;
info = dmar_alloc_pci_notify_info(pdev, action); info = dmar_alloc_pci_notify_info(pdev, action);
...@@ -339,7 +340,7 @@ static int dmar_pci_bus_notifier(struct notifier_block *nb, ...@@ -339,7 +340,7 @@ static int dmar_pci_bus_notifier(struct notifier_block *nb,
down_write(&dmar_global_lock); down_write(&dmar_global_lock);
if (action == BUS_NOTIFY_ADD_DEVICE) if (action == BUS_NOTIFY_ADD_DEVICE)
dmar_pci_bus_add_dev(info); dmar_pci_bus_add_dev(info);
else if (action == BUS_NOTIFY_DEL_DEVICE) else if (action == BUS_NOTIFY_REMOVED_DEVICE)
dmar_pci_bus_del_dev(info); dmar_pci_bus_del_dev(info);
up_write(&dmar_global_lock); up_write(&dmar_global_lock);
......
...@@ -4367,7 +4367,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info) ...@@ -4367,7 +4367,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
rmrru->devices_cnt); rmrru->devices_cnt);
if(ret < 0) if(ret < 0)
return ret; return ret;
} else if (info->event == BUS_NOTIFY_DEL_DEVICE) { } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
dmar_remove_dev_scope(info, rmrr->segment, dmar_remove_dev_scope(info, rmrr->segment,
rmrru->devices, rmrru->devices_cnt); rmrru->devices, rmrru->devices_cnt);
} }
...@@ -4387,7 +4387,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info) ...@@ -4387,7 +4387,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
break; break;
else if(ret < 0) else if(ret < 0)
return ret; return ret;
} else if (info->event == BUS_NOTIFY_DEL_DEVICE) { } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
if (dmar_remove_dev_scope(info, atsr->segment, if (dmar_remove_dev_scope(info, atsr->segment,
atsru->devices, atsru->devices_cnt)) atsru->devices, atsru->devices_cnt))
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment