From: Lu Baolu <baolu.lu@linux.intel.com>
To: Joerg Roedel <joro@8bytes.org>, Will Deacon <will@kernel.org>,
Robin Murphy <robin.murphy@arm.com>,
Jason Gunthorpe <jgg@ziepe.ca>, Kevin Tian <kevin.tian@intel.com>,
Jean-Philippe Brucker <jean-philippe@linaro.org>,
Nicolin Chen <nicolinc@nvidia.com>
Cc: Yi Liu <yi.l.liu@intel.com>,
Jacob Pan <jacob.jun.pan@linux.intel.com>,
Longfang Liu <liulongfang@huawei.com>,
Yan Zhao <yan.y.zhao@intel.com>,
Joel Granados <j.granados@samsung.com>,
iommu@lists.linux.dev, kvm@vger.kernel.org,
linux-kernel@vger.kernel.org, Lu Baolu <baolu.lu@linux.intel.com>,
Jason Gunthorpe <jgg@nvidia.com>
Subject: [PATCH v13 13/16] iommu: Improve iopf_queue_remove_device()
Date: Mon, 12 Feb 2024 09:22:24 +0800 [thread overview]
Message-ID: <20240212012227.119381-14-baolu.lu@linux.intel.com> (raw)
In-Reply-To: <20240212012227.119381-1-baolu.lu@linux.intel.com>
Convert iopf_queue_remove_device() to return void instead of an error code,
as the return value is never used. This removal helper is designed to be
never-failed, so there's no need for error handling.
Ack all outstanding page requests from the device with the response code of
IOMMU_PAGE_RESP_INVALID, indicating device should not attempt any retry.
Add comments to this helper explaining the steps involved in removing a
device from the iopf queue and disabling its PRI. The individual drivers
are expected to be adjusted accordingly. Here we just define the expected
behaviors of the individual iommu driver from the core's perspective.
Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Tested-by: Yan Zhao <yan.y.zhao@intel.com>
---
include/linux/iommu.h | 5 ++--
drivers/iommu/intel/iommu.c | 7 +----
drivers/iommu/io-pgfault.c | 59 ++++++++++++++++++++++++-------------
3 files changed, 41 insertions(+), 30 deletions(-)
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 99cc55c3137f..7c60692d9cf2 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -1566,7 +1566,7 @@ iommu_sva_domain_alloc(struct device *dev, struct mm_struct *mm)
#ifdef CONFIG_IOMMU_IOPF
int iopf_queue_add_device(struct iopf_queue *queue, struct device *dev);
-int iopf_queue_remove_device(struct iopf_queue *queue, struct device *dev);
+void iopf_queue_remove_device(struct iopf_queue *queue, struct device *dev);
int iopf_queue_flush_dev(struct device *dev);
struct iopf_queue *iopf_queue_alloc(const char *name);
void iopf_queue_free(struct iopf_queue *queue);
@@ -1582,10 +1582,9 @@ iopf_queue_add_device(struct iopf_queue *queue, struct device *dev)
return -ENODEV;
}
-static inline int
+static inline void
iopf_queue_remove_device(struct iopf_queue *queue, struct device *dev)
{
- return -ENODEV;
}
static inline int iopf_queue_flush_dev(struct device *dev)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 29a12f289e2e..a81a2be9b870 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -4455,12 +4455,7 @@ static int intel_iommu_disable_iopf(struct device *dev)
*/
pci_disable_pri(to_pci_dev(dev));
info->pri_enabled = 0;
-
- /*
- * With PRI disabled and outstanding PRQs drained, removing device
- * from iopf queue should never fail.
- */
- WARN_ON(iopf_queue_remove_device(iommu->iopf_queue, dev));
+ iopf_queue_remove_device(iommu->iopf_queue, dev);
return 0;
}
diff --git a/drivers/iommu/io-pgfault.c b/drivers/iommu/io-pgfault.c
index ce7058892b59..ece09552e5cf 100644
--- a/drivers/iommu/io-pgfault.c
+++ b/drivers/iommu/io-pgfault.c
@@ -448,50 +448,67 @@ EXPORT_SYMBOL_GPL(iopf_queue_add_device);
* @queue: IOPF queue
* @dev: device to remove
*
- * Caller makes sure that no more faults are reported for this device.
+ * Removing a device from an iopf_queue. It's recommended to follow these
+ * steps when removing a device:
*
- * Return: 0 on success and <0 on error.
+ * - Disable new PRI reception: Turn off PRI generation in the IOMMU hardware
+ * and flush any hardware page request queues. This should be done before
+ * calling into this helper.
+ * - Acknowledge all outstanding PRQs to the device: Respond to all outstanding
+ * page requests with IOMMU_PAGE_RESP_INVALID, indicating the device should
+ * not retry. This helper function handles this.
+ * - Disable PRI on the device: After calling this helper, the caller could
+ * then disable PRI on the device.
+ *
+ * Calling iopf_queue_remove_device() essentially disassociates the device.
+ * The fault_param might still exist, but iommu_page_response() will do
+ * nothing. The device fault parameter reference count has been properly
+ * passed from iommu_report_device_fault() to the fault handling work, and
+ * will eventually be released after iommu_page_response().
*/
-int iopf_queue_remove_device(struct iopf_queue *queue, struct device *dev)
+void iopf_queue_remove_device(struct iopf_queue *queue, struct device *dev)
{
- int ret = 0;
struct iopf_fault *iopf, *next;
+ struct iommu_page_response resp;
struct dev_iommu *param = dev->iommu;
struct iommu_fault_param *fault_param;
+ const struct iommu_ops *ops = dev_iommu_ops(dev);
mutex_lock(&queue->lock);
mutex_lock(¶m->lock);
fault_param = rcu_dereference_check(param->fault_param,
lockdep_is_held(¶m->lock));
- if (!fault_param) {
- ret = -ENODEV;
- goto unlock;
- }
-
- if (fault_param->queue != queue) {
- ret = -EINVAL;
- goto unlock;
- }
- if (!list_empty(&fault_param->faults)) {
- ret = -EBUSY;
+ if (WARN_ON(!fault_param || fault_param->queue != queue))
goto unlock;
- }
-
- list_del(&fault_param->queue_list);
- /* Just in case some faults are still stuck */
+ mutex_lock(&fault_param->lock);
list_for_each_entry_safe(iopf, next, &fault_param->partial, list)
kfree(iopf);
+ list_for_each_entry_safe(iopf, next, &fault_param->faults, list) {
+ memset(&resp, 0, sizeof(struct iommu_page_response));
+ resp.pasid = iopf->fault.prm.pasid;
+ resp.grpid = iopf->fault.prm.grpid;
+ resp.code = IOMMU_PAGE_RESP_INVALID;
+
+ if (iopf->fault.prm.flags & IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID)
+ resp.flags = IOMMU_PAGE_RESP_PASID_VALID;
+
+ ops->page_response(dev, iopf, &resp);
+ list_del(&iopf->list);
+ kfree(iopf);
+ }
+ mutex_unlock(&fault_param->lock);
+
+ list_del(&fault_param->queue_list);
+
/* dec the ref owned by iopf_queue_add_device() */
rcu_assign_pointer(param->fault_param, NULL);
iopf_put_dev_fault_param(fault_param);
unlock:
mutex_unlock(¶m->lock);
mutex_unlock(&queue->lock);
-
- return ret;
}
EXPORT_SYMBOL_GPL(iopf_queue_remove_device);
--
2.34.1
next prev parent reply other threads:[~2024-02-12 1:29 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-12 1:22 [PATCH v13 00/16] iommu: Prepare to deliver page faults to user space Lu Baolu
2024-02-12 1:22 ` [PATCH v13 01/16] iommu: Move iommu fault data to linux/iommu.h Lu Baolu
2024-02-12 1:22 ` [PATCH v13 02/16] iommu/arm-smmu-v3: Remove unrecoverable faults reporting Lu Baolu
2024-02-12 1:22 ` [PATCH v13 03/16] iommu: Remove unrecoverable fault data Lu Baolu
2024-02-12 1:22 ` [PATCH v13 04/16] iommu: Cleanup iopf data structure definitions Lu Baolu
2024-02-12 1:22 ` [PATCH v13 05/16] iommu: Merge iopf_device_param into iommu_fault_param Lu Baolu
2024-02-12 1:22 ` [PATCH v13 06/16] iommu: Remove iommu_[un]register_device_fault_handler() Lu Baolu
2024-02-12 1:22 ` [PATCH v13 07/16] iommu: Merge iommu_fault_event and iopf_fault Lu Baolu
2024-02-12 1:22 ` [PATCH v13 08/16] iommu: Prepare for separating SVA and IOPF Lu Baolu
2024-02-12 1:22 ` [PATCH v13 09/16] iommu: Make iommu_queue_iopf() more generic Lu Baolu
2024-02-12 1:22 ` [PATCH v13 10/16] iommu: Separate SVA and IOPF Lu Baolu
2024-02-12 1:22 ` [PATCH v13 11/16] iommu: Refine locking for per-device fault data management Lu Baolu
2024-02-12 1:22 ` [PATCH v13 12/16] iommu: Use refcount for fault data access Lu Baolu
2024-02-12 1:22 ` Lu Baolu [this message]
2024-02-12 1:22 ` [PATCH v13 14/16] iommu: Track iopf group instead of last fault Lu Baolu
2024-02-12 1:22 ` [PATCH v13 15/16] iommu: Make iopf_group_response() return void Lu Baolu
2024-02-12 1:22 ` [PATCH v13 16/16] iommu: Make iommu_report_device_fault() " Lu Baolu
2024-02-16 14:20 ` [PATCH v13 00/16] iommu: Prepare to deliver page faults to user space Joerg Roedel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240212012227.119381-14-baolu.lu@linux.intel.com \
--to=baolu.lu@linux.intel.com \
--cc=iommu@lists.linux.dev \
--cc=j.granados@samsung.com \
--cc=jacob.jun.pan@linux.intel.com \
--cc=jean-philippe@linaro.org \
--cc=jgg@nvidia.com \
--cc=jgg@ziepe.ca \
--cc=joro@8bytes.org \
--cc=kevin.tian@intel.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=liulongfang@huawei.com \
--cc=nicolinc@nvidia.com \
--cc=robin.murphy@arm.com \
--cc=will@kernel.org \
--cc=yan.y.zhao@intel.com \
--cc=yi.l.liu@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox