diff options
author | Fenghua Yu <fenghua.yu@intel.com> | 2009-11-11 07:23:06 -0800 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2009-11-12 02:28:45 +0000 |
commit | 99dcadede42f8898d4c963ef69192ef4b9b76ba8 (patch) | |
tree | 36db26e700bfa17f56a30ef05b4092372149e147 /drivers/pci | |
parent | e8bb910d1bbc65e7081e73aab4b3a3dd8630332c (diff) | |
download | kernel_goldelico_gta04-99dcadede42f8898d4c963ef69192ef4b9b76ba8.zip kernel_goldelico_gta04-99dcadede42f8898d4c963ef69192ef4b9b76ba8.tar.gz kernel_goldelico_gta04-99dcadede42f8898d4c963ef69192ef4b9b76ba8.tar.bz2 |
intel-iommu: Support PCIe hot-plug
To support PCIe hot plug in IOMMU, we register a notifier to respond to device
change action.
When the notifier gets BUS_NOTIFY_UNBOUND_DRIVER, it removes the device
from its DMAR domain.
A hot added device will be added into an IOMMU domain when it first does IOMMU
op. So there is no need to add more code for hot add.
Without the patch, after a hot-remove, a hot-added device on the same
slot will not work.
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
Tested-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/intel-iommu.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 7fe5f79..1840a05 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -3215,6 +3215,33 @@ static int __init init_iommu_sysfs(void) } #endif /* CONFIG_PM */ +/* + * Here we only respond to action of unbound device from driver. + * + * Added device is not attached to its DMAR domain here yet. That will happen + * when mapping the device to iova. + */ +static int device_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct device *dev = data; + struct pci_dev *pdev = to_pci_dev(dev); + struct dmar_domain *domain; + + domain = find_domain(pdev); + if (!domain) + return 0; + + if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) + domain_remove_one_dev_info(domain, pdev); + + return 0; +} + +static struct notifier_block device_nb = { + .notifier_call = device_notifier, +}; + int __init intel_iommu_init(void) { int ret = 0; @@ -3267,6 +3294,8 @@ int __init intel_iommu_init(void) register_iommu(&intel_iommu_ops); + bus_register_notifier(&pci_bus_type, &device_nb); + return 0; } |