Commit 15478623 authored by Lu Baolu's avatar Lu Baolu Committed by Joerg Roedel

iommu/vt-d: Make prq draining code generic

Currently draining page requests and responses for a pasid is part of SVA
implementation. This is because the driver only supports attaching an SVA
domain to a device pasid. As we are about to support attaching other types
of domains to a device pasid, the prq draining code becomes generic.
Signed-off-by: default avatarLu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: default avatarJacob Pan <jacob.jun.pan@linux.intel.com>
Reviewed-by: default avatarKevin Tian <kevin.tian@intel.com>
Link: https://lore.kernel.org/r/20230802212427.1497170-6-jacob.jun.pan@linux.intel.comSigned-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent b6170188
...@@ -4727,21 +4727,29 @@ static void intel_iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid) ...@@ -4727,21 +4727,29 @@ static void intel_iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid)
struct intel_iommu *iommu = device_to_iommu(dev, NULL, NULL); struct intel_iommu *iommu = device_to_iommu(dev, NULL, NULL);
struct iommu_domain *domain; struct iommu_domain *domain;
/* Domain type specific cleanup: */
domain = iommu_get_domain_for_dev_pasid(dev, pasid, 0); domain = iommu_get_domain_for_dev_pasid(dev, pasid, 0);
if (domain) { if (WARN_ON_ONCE(!domain))
switch (domain->type) { goto out_tear_down;
case IOMMU_DOMAIN_SVA:
intel_svm_remove_dev_pasid(dev, pasid); /*
break; * The SVA implementation needs to handle its own stuffs like the mm
default: * notification. Before consolidating that code into iommu core, let
/* should never reach here */ * the intel sva code handle it.
WARN_ON(1); */
break; if (domain->type == IOMMU_DOMAIN_SVA) {
} intel_svm_remove_dev_pasid(dev, pasid);
goto out_tear_down;
} }
/*
* Should never reach here until we add support for attaching
* non-SVA domain to a pasid.
*/
WARN_ON(1);
out_tear_down:
intel_pasid_tear_down_entry(iommu, dev, pasid, false); intel_pasid_tear_down_entry(iommu, dev, pasid, false);
intel_drain_pasid_prq(dev, pasid);
} }
const struct iommu_ops intel_iommu_ops = { const struct iommu_ops intel_iommu_ops = {
......
...@@ -844,6 +844,7 @@ int intel_svm_page_response(struct device *dev, struct iommu_fault_event *evt, ...@@ -844,6 +844,7 @@ int intel_svm_page_response(struct device *dev, struct iommu_fault_event *evt,
struct iommu_page_response *msg); struct iommu_page_response *msg);
struct iommu_domain *intel_svm_domain_alloc(void); struct iommu_domain *intel_svm_domain_alloc(void);
void intel_svm_remove_dev_pasid(struct device *dev, ioasid_t pasid); void intel_svm_remove_dev_pasid(struct device *dev, ioasid_t pasid);
void intel_drain_pasid_prq(struct device *dev, u32 pasid);
struct intel_svm_dev { struct intel_svm_dev {
struct list_head list; struct list_head list;
...@@ -862,6 +863,7 @@ struct intel_svm { ...@@ -862,6 +863,7 @@ struct intel_svm {
}; };
#else #else
static inline void intel_svm_check(struct intel_iommu *iommu) {} static inline void intel_svm_check(struct intel_iommu *iommu) {}
static inline void intel_drain_pasid_prq(struct device *dev, u32 pasid) {}
static inline struct iommu_domain *intel_svm_domain_alloc(void) static inline struct iommu_domain *intel_svm_domain_alloc(void)
{ {
return NULL; return NULL;
......
...@@ -26,8 +26,6 @@ ...@@ -26,8 +26,6 @@
#include "trace.h" #include "trace.h"
static irqreturn_t prq_event_thread(int irq, void *d); static irqreturn_t prq_event_thread(int irq, void *d);
static void intel_svm_drain_prq(struct device *dev, u32 pasid);
#define to_intel_svm_dev(handle) container_of(handle, struct intel_svm_dev, sva)
static DEFINE_XARRAY_ALLOC(pasid_private_array); static DEFINE_XARRAY_ALLOC(pasid_private_array);
static int pasid_private_add(ioasid_t pasid, void *priv) static int pasid_private_add(ioasid_t pasid, void *priv)
...@@ -382,17 +380,6 @@ void intel_svm_remove_dev_pasid(struct device *dev, u32 pasid) ...@@ -382,17 +380,6 @@ void intel_svm_remove_dev_pasid(struct device *dev, u32 pasid)
if (sdev) { if (sdev) {
list_del_rcu(&sdev->list); list_del_rcu(&sdev->list);
/*
* Flush the PASID cache and IOTLB for this device.
* Note that we do depend on the hardware *not* using
* the PASID any more. Just as we depend on other
* devices never using PASIDs that they have no right
* to use. We have a *shared* PASID table, because it's
* large and has to be physically contiguous. So it's
* hard to be as defensive as we might like.
*/
intel_pasid_tear_down_entry(iommu, dev, svm->pasid, false);
intel_svm_drain_prq(dev, svm->pasid);
kfree_rcu(sdev, rcu); kfree_rcu(sdev, rcu);
if (list_empty(&svm->devs)) { if (list_empty(&svm->devs)) {
...@@ -449,7 +436,7 @@ static bool is_canonical_address(u64 addr) ...@@ -449,7 +436,7 @@ static bool is_canonical_address(u64 addr)
} }
/** /**
* intel_svm_drain_prq - Drain page requests and responses for a pasid * intel_drain_pasid_prq - Drain page requests and responses for a pasid
* @dev: target device * @dev: target device
* @pasid: pasid for draining * @pasid: pasid for draining
* *
...@@ -463,7 +450,7 @@ static bool is_canonical_address(u64 addr) ...@@ -463,7 +450,7 @@ static bool is_canonical_address(u64 addr)
* described in VT-d spec CH7.10 to drain all page requests and page * described in VT-d spec CH7.10 to drain all page requests and page
* responses pending in the hardware. * responses pending in the hardware.
*/ */
static void intel_svm_drain_prq(struct device *dev, u32 pasid) void intel_drain_pasid_prq(struct device *dev, u32 pasid)
{ {
struct device_domain_info *info; struct device_domain_info *info;
struct dmar_domain *domain; struct dmar_domain *domain;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment