Skip to content

Commit 3753311

Browse files
LuBaoluwilldeacon
authored andcommitted
iommu/vt-d: Refactor PCI PRI enabling/disabling callbacks
Commit 0095bf8 ("iommu: Improve iopf_queue_remove_device()") specified the flow for disabling the PRI on a device. Refactor the PRI callbacks in the intel iommu driver to better manage PRI enabling and disabling and align it with the device queue interfaces in the iommu core. Signed-off-by: Lu Baolu <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Link: https://lore.kernel.org/r/[email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent f90584f commit 3753311

File tree

3 files changed

+61
-7
lines changed

3 files changed

+61
-7
lines changed

drivers/iommu/intel/iommu.c

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4244,6 +4244,37 @@ static int intel_iommu_enable_sva(struct device *dev)
42444244
return 0;
42454245
}
42464246

4247+
static int context_flip_pri(struct device_domain_info *info, bool enable)
4248+
{
4249+
struct intel_iommu *iommu = info->iommu;
4250+
u8 bus = info->bus, devfn = info->devfn;
4251+
struct context_entry *context;
4252+
4253+
spin_lock(&iommu->lock);
4254+
if (context_copied(iommu, bus, devfn)) {
4255+
spin_unlock(&iommu->lock);
4256+
return -EINVAL;
4257+
}
4258+
4259+
context = iommu_context_addr(iommu, bus, devfn, false);
4260+
if (!context || !context_present(context)) {
4261+
spin_unlock(&iommu->lock);
4262+
return -ENODEV;
4263+
}
4264+
4265+
if (enable)
4266+
context_set_sm_pre(context);
4267+
else
4268+
context_clear_sm_pre(context);
4269+
4270+
if (!ecap_coherent(iommu->ecap))
4271+
clflush_cache_range(context, sizeof(*context));
4272+
intel_context_flush_present(info, context, true);
4273+
spin_unlock(&iommu->lock);
4274+
4275+
return 0;
4276+
}
4277+
42474278
static int intel_iommu_enable_iopf(struct device *dev)
42484279
{
42494280
struct pci_dev *pdev = dev_is_pci(dev) ? to_pci_dev(dev) : NULL;
@@ -4273,15 +4304,23 @@ static int intel_iommu_enable_iopf(struct device *dev)
42734304
if (ret)
42744305
return ret;
42754306

4307+
ret = context_flip_pri(info, true);
4308+
if (ret)
4309+
goto err_remove_device;
4310+
42764311
ret = pci_enable_pri(pdev, PRQ_DEPTH);
4277-
if (ret) {
4278-
iopf_queue_remove_device(iommu->iopf_queue, dev);
4279-
return ret;
4280-
}
4312+
if (ret)
4313+
goto err_clear_pri;
42814314

42824315
info->pri_enabled = 1;
42834316

42844317
return 0;
4318+
err_clear_pri:
4319+
context_flip_pri(info, false);
4320+
err_remove_device:
4321+
iopf_queue_remove_device(iommu->iopf_queue, dev);
4322+
4323+
return ret;
42854324
}
42864325

42874326
static int intel_iommu_disable_iopf(struct device *dev)
@@ -4292,6 +4331,15 @@ static int intel_iommu_disable_iopf(struct device *dev)
42924331
if (!info->pri_enabled)
42934332
return -EINVAL;
42944333

4334+
/* Disable new PRI reception: */
4335+
context_flip_pri(info, false);
4336+
4337+
/*
4338+
* Remove device from fault queue and acknowledge all outstanding
4339+
* PRQs to the device:
4340+
*/
4341+
iopf_queue_remove_device(iommu->iopf_queue, dev);
4342+
42954343
/*
42964344
* PCIe spec states that by clearing PRI enable bit, the Page
42974345
* Request Interface will not issue new page requests, but has
@@ -4302,7 +4350,6 @@ static int intel_iommu_disable_iopf(struct device *dev)
43024350
*/
43034351
pci_disable_pri(to_pci_dev(dev));
43044352
info->pri_enabled = 0;
4305-
iopf_queue_remove_device(iommu->iopf_queue, dev);
43064353

43074354
return 0;
43084355
}

drivers/iommu/intel/iommu.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,15 @@ static inline void context_set_sm_pre(struct context_entry *context)
10451045
context->lo |= BIT_ULL(4);
10461046
}
10471047

1048+
/*
1049+
* Clear the PRE(Page Request Enable) field of a scalable mode context
1050+
* entry.
1051+
*/
1052+
static inline void context_clear_sm_pre(struct context_entry *context)
1053+
{
1054+
context->lo &= ~BIT_ULL(4);
1055+
}
1056+
10481057
/* Returns a number of VTD pages, but aligned to MM page size */
10491058
static inline unsigned long aligned_nrpages(unsigned long host_addr, size_t size)
10501059
{

drivers/iommu/intel/pasid.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -752,8 +752,6 @@ static int context_entry_set_pasid_table(struct context_entry *context,
752752

753753
if (info->ats_supported)
754754
context_set_sm_dte(context);
755-
if (info->pri_supported)
756-
context_set_sm_pre(context);
757755
if (info->pasid_supported)
758756
context_set_pasid(context);
759757

0 commit comments

Comments
 (0)