mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-06 05:06:29 +00:00
IOMMU Fixes for Linux v6.10-rc2
Including: - Core: - Make iommu-dma code recognize 'force_aperture' again - Fix for potential NULL-ptr dereference from iommu_sva_bind_device() return value - AMD IOMMU fixes: - Fix lockdep splat for invalid wait context - Add feature bit check before enabling PPR - Make workqueue name fit into buffer - Fix memory leak in sysfs code -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEr9jSbILcajRFYWYyK/BELZcBGuMFAmZiyXsACgkQK/BELZcB GuNHAQ//UtMczjHfRS1XzKuhvXh3Ay2kFp42bMHdaydWdEzRQfrdK9Nj0Zb2VYEV WiX38pteFHVs5ZKkf/vEIqQOV3crbMSIq/k/P3jrglG480yt1xj05nf4+r4ZibMJ aGv9adhn5t9EiFjrj4yirto9MyZHDHynr2QSHILzOhqtfvQsxNIuSW490zvAA9EO gMasRDPx8do1dOi5k3BnB+0URehcM06QP+vTi5KJqBBwXMp11BU1R99iRwgWOGHp shPkOhU+N+sQaYVXXi1n92eBuWfJfHaqTThT4DHGGoyFx0eJIIB92dKbhin+0oiv gFoSMtysoLo+HCzhJQ0NN9Ayv2at4oHZeRKiE5QTSJOTZ801QVR7d8k7lmQewl62 qs1WOKR4lE0IwIk2VjLOqpY+rok5YgY1BgFy7BD5cbsIYIhN+5olzq43AH4UtKQN RIBedWZ/78FffrjFsE8Ut2fPpu67QVy5AqqqJ06zCbhrMBB75+o7itL8+KJhOisd uPXW21aAiPGpOg3BOrFcRKHejn6oqxfhuESbVkcOQttqx5rdPC9lgDnH+xzZsm/P fnIBuvgr2l7I9ulqk6+m9qc2N+n1dRjfKS9GdCGQH+y+o9t9gLeob0aTu+rGC4gN 2mW4cHaet9X1LvJtdACHK04BFzAAboLP2bqclPbsaVkJPD9Ejk8= =67iX -----END PGP SIGNATURE----- Merge tag 'iommu-fixes-v6.10-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu Pull iommu fixes from Joerg Roedel: "Core: - Make iommu-dma code recognize 'force_aperture' again - Fix for potential NULL-ptr dereference from iommu_sva_bind_device() return value AMD IOMMU fixes: - Fix lockdep splat for invalid wait context - Add feature bit check before enabling PPR - Make workqueue name fit into buffer - Fix memory leak in sysfs code" * tag 'iommu-fixes-v6.10-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: iommu/amd: Fix Invalid wait context issue iommu/amd: Check EFR[EPHSup] bit before enabling PPR iommu/amd: Fix workqueue name iommu: Return right value in iommu_sva_bind_device() iommu/dma: Fix domain init iommu/amd: Fix sysfs leak in iommu init
This commit is contained in:
commit
f24b46ea10
@ -129,7 +129,8 @@ static inline int check_feature_gpt_level(void)
|
||||
static inline bool amd_iommu_gt_ppr_supported(void)
|
||||
{
|
||||
return (check_feature(FEATURE_GT) &&
|
||||
check_feature(FEATURE_PPR));
|
||||
check_feature(FEATURE_PPR) &&
|
||||
check_feature(FEATURE_EPHSUP));
|
||||
}
|
||||
|
||||
static inline u64 iommu_virt_to_phys(void *vaddr)
|
||||
|
@ -1626,8 +1626,17 @@ static void __init free_pci_segments(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void __init free_sysfs(struct amd_iommu *iommu)
|
||||
{
|
||||
if (iommu->iommu.dev) {
|
||||
iommu_device_unregister(&iommu->iommu);
|
||||
iommu_device_sysfs_remove(&iommu->iommu);
|
||||
}
|
||||
}
|
||||
|
||||
static void __init free_iommu_one(struct amd_iommu *iommu)
|
||||
{
|
||||
free_sysfs(iommu);
|
||||
free_cwwb_sem(iommu);
|
||||
free_command_buffer(iommu);
|
||||
free_event_buffer(iommu);
|
||||
|
@ -2032,7 +2032,6 @@ static int do_attach(struct iommu_dev_data *dev_data,
|
||||
struct protection_domain *domain)
|
||||
{
|
||||
struct amd_iommu *iommu = get_amd_iommu_from_dev_data(dev_data);
|
||||
struct pci_dev *pdev;
|
||||
int ret = 0;
|
||||
|
||||
/* Update data structures */
|
||||
@ -2047,30 +2046,13 @@ static int do_attach(struct iommu_dev_data *dev_data,
|
||||
domain->dev_iommu[iommu->index] += 1;
|
||||
domain->dev_cnt += 1;
|
||||
|
||||
pdev = dev_is_pci(dev_data->dev) ? to_pci_dev(dev_data->dev) : NULL;
|
||||
/* Setup GCR3 table */
|
||||
if (pdom_is_sva_capable(domain)) {
|
||||
ret = init_gcr3_table(dev_data, domain);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (pdev) {
|
||||
pdev_enable_caps(pdev);
|
||||
|
||||
/*
|
||||
* Device can continue to function even if IOPF
|
||||
* enablement failed. Hence in error path just
|
||||
* disable device PRI support.
|
||||
*/
|
||||
if (amd_iommu_iopf_add_device(iommu, dev_data))
|
||||
pdev_disable_cap_pri(pdev);
|
||||
}
|
||||
} else if (pdev) {
|
||||
pdev_enable_cap_ats(pdev);
|
||||
}
|
||||
|
||||
/* Update device table */
|
||||
amd_iommu_dev_update_dte(dev_data, true);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2163,6 +2145,11 @@ static void detach_device(struct device *dev)
|
||||
|
||||
do_detach(dev_data);
|
||||
|
||||
out:
|
||||
spin_unlock(&dev_data->lock);
|
||||
|
||||
spin_unlock_irqrestore(&domain->lock, flags);
|
||||
|
||||
/* Remove IOPF handler */
|
||||
if (ppr)
|
||||
amd_iommu_iopf_remove_device(iommu, dev_data);
|
||||
@ -2170,10 +2157,6 @@ static void detach_device(struct device *dev)
|
||||
if (dev_is_pci(dev))
|
||||
pdev_disable_caps(to_pci_dev(dev));
|
||||
|
||||
out:
|
||||
spin_unlock(&dev_data->lock);
|
||||
|
||||
spin_unlock_irqrestore(&domain->lock, flags);
|
||||
}
|
||||
|
||||
static struct iommu_device *amd_iommu_probe_device(struct device *dev)
|
||||
@ -2485,6 +2468,7 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
|
||||
struct iommu_dev_data *dev_data = dev_iommu_priv_get(dev);
|
||||
struct protection_domain *domain = to_pdomain(dom);
|
||||
struct amd_iommu *iommu = get_amd_iommu_from_dev(dev);
|
||||
struct pci_dev *pdev;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@ -2517,7 +2501,23 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
|
||||
}
|
||||
#endif
|
||||
|
||||
iommu_completion_wait(iommu);
|
||||
pdev = dev_is_pci(dev_data->dev) ? to_pci_dev(dev_data->dev) : NULL;
|
||||
if (pdev && pdom_is_sva_capable(domain)) {
|
||||
pdev_enable_caps(pdev);
|
||||
|
||||
/*
|
||||
* Device can continue to function even if IOPF
|
||||
* enablement failed. Hence in error path just
|
||||
* disable device PRI support.
|
||||
*/
|
||||
if (amd_iommu_iopf_add_device(iommu, dev_data))
|
||||
pdev_disable_cap_pri(pdev);
|
||||
} else if (pdev) {
|
||||
pdev_enable_cap_ats(pdev);
|
||||
}
|
||||
|
||||
/* Update device table */
|
||||
amd_iommu_dev_update_dte(dev_data, true);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -222,8 +222,7 @@ int amd_iommu_iopf_init(struct amd_iommu *iommu)
|
||||
if (iommu->iopf_queue)
|
||||
return ret;
|
||||
|
||||
snprintf(iommu->iopfq_name, sizeof(iommu->iopfq_name),
|
||||
"amdiommu-%#x-iopfq",
|
||||
snprintf(iommu->iopfq_name, sizeof(iommu->iopfq_name), "amdvi-%#x",
|
||||
PCI_SEG_DEVID_TO_SBDF(iommu->pci_seg->id, iommu->devid));
|
||||
|
||||
iommu->iopf_queue = iopf_queue_alloc(iommu->iopfq_name);
|
||||
@ -249,40 +248,26 @@ void amd_iommu_page_response(struct device *dev, struct iopf_fault *evt,
|
||||
int amd_iommu_iopf_add_device(struct amd_iommu *iommu,
|
||||
struct iommu_dev_data *dev_data)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
if (!dev_data->pri_enabled)
|
||||
return ret;
|
||||
|
||||
raw_spin_lock_irqsave(&iommu->lock, flags);
|
||||
|
||||
if (!iommu->iopf_queue) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (!iommu->iopf_queue)
|
||||
return -EINVAL;
|
||||
|
||||
ret = iopf_queue_add_device(iommu->iopf_queue, dev_data->dev);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
return ret;
|
||||
|
||||
dev_data->ppr = true;
|
||||
|
||||
out_unlock:
|
||||
raw_spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Its assumed that caller has verified that device was added to iopf queue */
|
||||
void amd_iommu_iopf_remove_device(struct amd_iommu *iommu,
|
||||
struct iommu_dev_data *dev_data)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&iommu->lock, flags);
|
||||
|
||||
iopf_queue_remove_device(iommu->iopf_queue, dev_data->dev);
|
||||
dev_data->ppr = false;
|
||||
|
||||
raw_spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
}
|
||||
|
@ -686,15 +686,15 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, struct device *dev
|
||||
|
||||
/* Check the domain allows at least some access to the device... */
|
||||
if (map) {
|
||||
dma_addr_t base = dma_range_map_min(map);
|
||||
if (base > domain->geometry.aperture_end ||
|
||||
if (dma_range_map_min(map) > domain->geometry.aperture_end ||
|
||||
dma_range_map_max(map) < domain->geometry.aperture_start) {
|
||||
pr_warn("specified DMA range outside IOMMU capability\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
/* ...then finally give it a kicking to make sure it fits */
|
||||
base_pfn = max(base, domain->geometry.aperture_start) >> order;
|
||||
}
|
||||
/* ...then finally give it a kicking to make sure it fits */
|
||||
base_pfn = max_t(unsigned long, base_pfn,
|
||||
domain->geometry.aperture_start >> order);
|
||||
|
||||
/* start_pfn is always nonzero for an already-initialised domain */
|
||||
mutex_lock(&cookie->mutex);
|
||||
|
@ -1533,7 +1533,7 @@ struct iommu_domain *iommu_sva_domain_alloc(struct device *dev,
|
||||
static inline struct iommu_sva *
|
||||
iommu_sva_bind_device(struct device *dev, struct mm_struct *mm)
|
||||
{
|
||||
return NULL;
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static inline void iommu_sva_unbind_device(struct iommu_sva *handle)
|
||||
|
Loading…
Reference in New Issue
Block a user