diff options
author | Lu Baolu <baolu.lu@linux.intel.com> | 2019-05-25 01:41:32 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2019-05-28 04:19:11 -0400 |
commit | 8af46c784ecfe8929f66b5eaae987f6874953226 (patch) | |
tree | 6f4bbaec5617602575cb02e97f9c8e32f432da6a /drivers/iommu/intel-iommu.c | |
parent | fa212a97f3a366adcb2046c565e7c978ab067c73 (diff) |
iommu/vt-d: Implement is_attach_deferred iommu ops entry
As a domain is now attached to a device earlier, we should
implement the is_attach_deferred call-back and use it to
defer the domain attach from iommu driver init to device
driver init when iommu is pre-enabled in kdump kernel.
Suggested-by: Tom Murphy <tmurphy@arista.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/intel-iommu.c')
-rw-r--r-- | drivers/iommu/intel-iommu.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 0bae0b73076c..c8b73802f0e0 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
@@ -353,6 +353,8 @@ static void domain_context_clear(struct intel_iommu *iommu, | |||
353 | static int domain_detach_iommu(struct dmar_domain *domain, | 353 | static int domain_detach_iommu(struct dmar_domain *domain, |
354 | struct intel_iommu *iommu); | 354 | struct intel_iommu *iommu); |
355 | static bool device_is_rmrr_locked(struct device *dev); | 355 | static bool device_is_rmrr_locked(struct device *dev); |
356 | static int intel_iommu_attach_device(struct iommu_domain *domain, | ||
357 | struct device *dev); | ||
356 | 358 | ||
357 | #ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON | 359 | #ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON |
358 | int dmar_disabled = 0; | 360 | int dmar_disabled = 0; |
@@ -378,6 +380,7 @@ int intel_iommu_gfx_mapped; | |||
378 | EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped); | 380 | EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped); |
379 | 381 | ||
380 | #define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1)) | 382 | #define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1)) |
383 | #define DEFER_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-2)) | ||
381 | static DEFINE_SPINLOCK(device_domain_lock); | 384 | static DEFINE_SPINLOCK(device_domain_lock); |
382 | static LIST_HEAD(device_domain_list); | 385 | static LIST_HEAD(device_domain_list); |
383 | 386 | ||
@@ -2408,8 +2411,18 @@ static struct dmar_domain *find_domain(struct device *dev) | |||
2408 | { | 2411 | { |
2409 | struct device_domain_info *info; | 2412 | struct device_domain_info *info; |
2410 | 2413 | ||
2414 | if (unlikely(dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO)) { | ||
2415 | struct iommu_domain *domain; | ||
2416 | |||
2417 | dev->archdata.iommu = NULL; | ||
2418 | domain = iommu_get_domain_for_dev(dev); | ||
2419 | if (domain) | ||
2420 | intel_iommu_attach_device(domain, dev); | ||
2421 | } | ||
2422 | |||
2411 | /* No lock here, assumes no domain exit in normal case */ | 2423 | /* No lock here, assumes no domain exit in normal case */ |
2412 | info = dev->archdata.iommu; | 2424 | info = dev->archdata.iommu; |
2425 | |||
2413 | if (likely(info)) | 2426 | if (likely(info)) |
2414 | return info->domain; | 2427 | return info->domain; |
2415 | return NULL; | 2428 | return NULL; |
@@ -5504,6 +5517,9 @@ static int intel_iommu_add_device(struct device *dev) | |||
5504 | 5517 | ||
5505 | iommu_device_link(&iommu->iommu, dev); | 5518 | iommu_device_link(&iommu->iommu, dev); |
5506 | 5519 | ||
5520 | if (translation_pre_enabled(iommu)) | ||
5521 | dev->archdata.iommu = DEFER_DEVICE_DOMAIN_INFO; | ||
5522 | |||
5507 | group = iommu_group_get_for_dev(dev); | 5523 | group = iommu_group_get_for_dev(dev); |
5508 | 5524 | ||
5509 | if (IS_ERR(group)) | 5525 | if (IS_ERR(group)) |
@@ -5828,6 +5844,12 @@ intel_iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev) | |||
5828 | dmar_domain->default_pasid : -EINVAL; | 5844 | dmar_domain->default_pasid : -EINVAL; |
5829 | } | 5845 | } |
5830 | 5846 | ||
5847 | static bool intel_iommu_is_attach_deferred(struct iommu_domain *domain, | ||
5848 | struct device *dev) | ||
5849 | { | ||
5850 | return dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO; | ||
5851 | } | ||
5852 | |||
5831 | const struct iommu_ops intel_iommu_ops = { | 5853 | const struct iommu_ops intel_iommu_ops = { |
5832 | .capable = intel_iommu_capable, | 5854 | .capable = intel_iommu_capable, |
5833 | .domain_alloc = intel_iommu_domain_alloc, | 5855 | .domain_alloc = intel_iommu_domain_alloc, |
@@ -5850,6 +5872,7 @@ const struct iommu_ops intel_iommu_ops = { | |||
5850 | .dev_feat_enabled = intel_iommu_dev_feat_enabled, | 5872 | .dev_feat_enabled = intel_iommu_dev_feat_enabled, |
5851 | .dev_enable_feat = intel_iommu_dev_enable_feat, | 5873 | .dev_enable_feat = intel_iommu_dev_enable_feat, |
5852 | .dev_disable_feat = intel_iommu_dev_disable_feat, | 5874 | .dev_disable_feat = intel_iommu_dev_disable_feat, |
5875 | .is_attach_deferred = intel_iommu_is_attach_deferred, | ||
5853 | .pgsize_bitmap = INTEL_IOMMU_PGSIZES, | 5876 | .pgsize_bitmap = INTEL_IOMMU_PGSIZES, |
5854 | }; | 5877 | }; |
5855 | 5878 | ||