Skip to content

Commit c4cb231

Browse files
hegdevasantjoergroedel
authored andcommitted
iommu/amd: Add support for enable/disable IOPF
Return success from enable_feature(IOPF) path as this interface is going away. Instead we will enable/disable IOPF support in attach/detach device path. In attach device path, if device is capable of PRI, then we will add it to per IOMMU IOPF queue and enable PPR support in IOMMU. Also it will attach device to domain even if it fails to enable PRI or add device to IOPF queue as device can continue to work without PRI support. In detach device patch it follows following sequence: - Flush the queue for the given device - Disable PPR support in DTE[devid] - Remove device from IOPF queue - Disable device PRI Also add IOMMU_IOPF as dependency to AMD_IOMMU driver. Co-developed-by: Suravee Suthikulpanit <[email protected]> Signed-off-by: Suravee Suthikulpanit <[email protected]> Signed-off-by: Vasant Hegde <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 978d626 commit c4cb231

File tree

4 files changed

+77
-8
lines changed

4 files changed

+77
-8
lines changed

drivers/iommu/amd/Kconfig

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ config AMD_IOMMU
1010
select IOMMU_API
1111
select IOMMU_IOVA
1212
select IOMMU_IO_PGTABLE
13+
select IOMMU_IOPF
1314
select IOMMUFD_DRIVER if IOMMUFD
1415
depends on X86_64 && PCI && ACPI && HAVE_CMPXCHG_DOUBLE
1516
help

drivers/iommu/amd/amd_iommu.h

+4
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ int amd_iommu_iopf_init(struct amd_iommu *iommu);
5151
void amd_iommu_iopf_uninit(struct amd_iommu *iommu);
5252
void amd_iommu_page_response(struct device *dev, struct iopf_fault *evt,
5353
struct iommu_page_response *resp);
54+
int amd_iommu_iopf_add_device(struct amd_iommu *iommu,
55+
struct iommu_dev_data *dev_data);
56+
void amd_iommu_iopf_remove_device(struct amd_iommu *iommu,
57+
struct iommu_dev_data *dev_data);
5458

5559
/* GCR3 setup */
5660
int amd_iommu_set_gcr3(struct iommu_dev_data *dev_data,

drivers/iommu/amd/iommu.c

+31-8
Original file line numberDiff line numberDiff line change
@@ -2057,8 +2057,17 @@ static int do_attach(struct iommu_dev_data *dev_data,
20572057
if (ret)
20582058
return ret;
20592059

2060-
if (pdev)
2060+
if (pdev) {
20612061
pdev_enable_caps(pdev);
2062+
2063+
/*
2064+
* Device can continue to function even if IOPF
2065+
* enablement failed. Hence in error path just
2066+
* disable device PRI support.
2067+
*/
2068+
if (amd_iommu_iopf_add_device(iommu, dev_data))
2069+
pdev_disable_cap_pri(pdev);
2070+
}
20622071
} else if (pdev) {
20632072
pdev_enable_cap_ats(pdev);
20642073
}
@@ -2130,12 +2139,11 @@ static int attach_device(struct device *dev,
21302139
*/
21312140
static void detach_device(struct device *dev)
21322141
{
2133-
struct protection_domain *domain;
2134-
struct iommu_dev_data *dev_data;
2142+
struct iommu_dev_data *dev_data = dev_iommu_priv_get(dev);
2143+
struct protection_domain *domain = dev_data->domain;
2144+
struct amd_iommu *iommu = get_amd_iommu_from_dev_data(dev_data);
21352145
unsigned long flags;
2136-
2137-
dev_data = dev_iommu_priv_get(dev);
2138-
domain = dev_data->domain;
2146+
bool ppr = dev_data->ppr;
21392147

21402148
spin_lock_irqsave(&domain->lock, flags);
21412149

@@ -2150,8 +2158,19 @@ static void detach_device(struct device *dev)
21502158
if (WARN_ON(!dev_data->domain))
21512159
goto out;
21522160

2161+
if (ppr) {
2162+
iopf_queue_flush_dev(dev);
2163+
2164+
/* Updated here so that it gets reflected in DTE */
2165+
dev_data->ppr = false;
2166+
}
2167+
21532168
do_detach(dev_data);
21542169

2170+
/* Remove IOPF handler */
2171+
if (ppr)
2172+
amd_iommu_iopf_remove_device(iommu, dev_data);
2173+
21552174
if (dev_is_pci(dev))
21562175
pdev_disable_caps(to_pci_dev(dev));
21572176

@@ -2814,9 +2833,11 @@ static const struct iommu_dirty_ops amd_dirty_ops = {
28142833
static int amd_iommu_dev_enable_feature(struct device *dev,
28152834
enum iommu_dev_features feat)
28162835
{
2817-
int ret;
2836+
int ret = 0;
28182837

28192838
switch (feat) {
2839+
case IOMMU_DEV_FEAT_IOPF:
2840+
break;
28202841
default:
28212842
ret = -EINVAL;
28222843
break;
@@ -2827,9 +2848,11 @@ static int amd_iommu_dev_enable_feature(struct device *dev,
28272848
static int amd_iommu_dev_disable_feature(struct device *dev,
28282849
enum iommu_dev_features feat)
28292850
{
2830-
int ret;
2851+
int ret = 0;
28312852

28322853
switch (feat) {
2854+
case IOMMU_DEV_FEAT_IOPF:
2855+
break;
28332856
default:
28342857
ret = -EINVAL;
28352858
break;

drivers/iommu/amd/ppr.c

+41
Original file line numberDiff line numberDiff line change
@@ -243,3 +243,44 @@ void amd_iommu_page_response(struct device *dev, struct iopf_fault *evt,
243243
{
244244
amd_iommu_complete_ppr(dev, resp->pasid, resp->code, resp->grpid);
245245
}
246+
247+
int amd_iommu_iopf_add_device(struct amd_iommu *iommu,
248+
struct iommu_dev_data *dev_data)
249+
{
250+
unsigned long flags;
251+
int ret = 0;
252+
253+
if (!dev_data->pri_enabled)
254+
return ret;
255+
256+
raw_spin_lock_irqsave(&iommu->lock, flags);
257+
258+
if (!iommu->iopf_queue) {
259+
ret = -EINVAL;
260+
goto out_unlock;
261+
}
262+
263+
ret = iopf_queue_add_device(iommu->iopf_queue, dev_data->dev);
264+
if (ret)
265+
goto out_unlock;
266+
267+
dev_data->ppr = true;
268+
269+
out_unlock:
270+
raw_spin_unlock_irqrestore(&iommu->lock, flags);
271+
return ret;
272+
}
273+
274+
/* Its assumed that caller has verified that device was added to iopf queue */
275+
void amd_iommu_iopf_remove_device(struct amd_iommu *iommu,
276+
struct iommu_dev_data *dev_data)
277+
{
278+
unsigned long flags;
279+
280+
raw_spin_lock_irqsave(&iommu->lock, flags);
281+
282+
iopf_queue_remove_device(iommu->iopf_queue, dev_data->dev);
283+
dev_data->ppr = false;
284+
285+
raw_spin_unlock_irqrestore(&iommu->lock, flags);
286+
}

0 commit comments

Comments
 (0)