All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/15] dma mapping/iommu: Allow IOMMU IOVA rcache range to be configured
@ 2021-05-10 14:17 ` John Garry
  0 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm,
	sai.praneeth.prakhya, John Garry

For streaming DMA mappings involving an IOMMU and whose IOVA len regularly
exceeds the IOVA rcache upper limit (meaning that they are not cached),
performance can be reduced. 

This is much more pronounced from commit 4e89dce72521 ("iommu/iova: Retry
from last rb tree node if iova search fails"), as discussed at [0].

IOVAs which cannot be cached are highly involved in the IOVA aging issue,
as discussed at [1].

This series allows the IOVA rcache range be configured, so that we may
cache all IOVAs per domain, thus improving performance.

A new IOMMU group sysfs file is added - max_opt_dma_size - which is used
indirectly to configure the IOVA rcache range:
/sys/kernel/iommu_groups/X/max_opt_dma_size

This file is updated same as how the IOMMU group default domain type is
updated, i.e. must unbind the only device in the group first. However, the
IOMMU default domain is reallocated in the device driver reprobe, and not
immediately.

In addition, we keep (from v1 series) the DMA mapping API to allow DMA max
optimised size be set from a LLDD. How it works is a lot different. When
the LLDD calls this during probe, once the value is successfully recorded, we
return -EDEFER_PROBE. In the reprobe, the IOMM group default domain is
reallocated, and the new IOVA domain rcache upper limit is set according
to that DMA max optimised size. As such, we don't operate on a live IOMMU
domain.

Note that the DMA mapping API frontend is not strictly required, but saves
the LLDD calling IOMMU APIs directly, that being not preferred.

Some figures for storage scenario:
v5.13-rc1 baseline:			1200K IOPS
With series:				1800K IOPS

All above are for IOMMU strict mode. Non-strict mode gives ~1800K IOPS in
all scenarios.

Patch breakdown:
1-11: Add support for setting DMA max optimised size via sysfs
12-15: Add support for setting DMA max optimised size from LLDD

[0] https://lore.kernel.org/linux-iommu/20210129092120.1482-1-thunder.leizhen@huawei.com/
[1] https://lore.kernel.org/linux-iommu/1607538189-237944-1-git-send-email-john.garry@huawei.com/

Differences to v1:
- Many
- Change method to not operate on a 'live' IOMMU domain:
	- rather, force device driver to be re-probed once
	  dma_max_opt_size is set, and reconfig a new IOMMU group then
- Add iommu sysfs max_dma_opt_size file, and allow updating same as how
  group type is changed 

John Garry (15):
  iommu: Reactor iommu_group_store_type()
  iova: Allow rcache range upper limit to be flexible
  iommu: Allow max opt DMA len be set for a group via sysfs
  iommu: Add iommu_group_get_max_opt_dma_size()
  iova: Add iova_domain_len_is_cached()
  iommu: Allow iommu_change_dev_def_domain() realloc default domain for
    same type
  iommu: Add iommu_realloc_dev_group()
  dma-iommu: Add iommu_reconfig_dev_group_dma()
  iova: Add init_iova_domain_ext()
  dma-iommu: Use init_iova_domain_ext() for IOVA domain init
  dma-iommu: Reconfig group domain
  iommu: Add iommu_set_dev_dma_opt_size()
  dma-mapping: Add dma_set_max_opt_size()
  dma-iommu: Add iommu_dma_set_opt_size()
  scsi: hisi_sas: Set max optimal DMA size for v3 hw

 drivers/iommu/dma-iommu.c              |  51 +++++-
 drivers/iommu/iommu.c                  | 231 +++++++++++++++++++------
 drivers/iommu/iova.c                   |  61 +++++--
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c |   5 +
 include/linux/dma-iommu.h              |   4 +
 include/linux/dma-map-ops.h            |   1 +
 include/linux/dma-mapping.h            |   8 +
 include/linux/iommu.h                  |  19 ++
 include/linux/iova.h                   |  21 ++-
 kernel/dma/mapping.c                   |  11 ++
 10 files changed, 344 insertions(+), 68 deletions(-)

-- 
2.26.2


^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH v2 00/15] dma mapping/iommu: Allow IOMMU IOVA rcache range to be configured
@ 2021-05-10 14:17 ` John Garry
  0 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: linux-scsi, linuxarm, linux-kernel, sai.praneeth.prakhya, iommu

For streaming DMA mappings involving an IOMMU and whose IOVA len regularly
exceeds the IOVA rcache upper limit (meaning that they are not cached),
performance can be reduced. 

This is much more pronounced from commit 4e89dce72521 ("iommu/iova: Retry
from last rb tree node if iova search fails"), as discussed at [0].

IOVAs which cannot be cached are highly involved in the IOVA aging issue,
as discussed at [1].

This series allows the IOVA rcache range be configured, so that we may
cache all IOVAs per domain, thus improving performance.

A new IOMMU group sysfs file is added - max_opt_dma_size - which is used
indirectly to configure the IOVA rcache range:
/sys/kernel/iommu_groups/X/max_opt_dma_size

This file is updated same as how the IOMMU group default domain type is
updated, i.e. must unbind the only device in the group first. However, the
IOMMU default domain is reallocated in the device driver reprobe, and not
immediately.

In addition, we keep (from v1 series) the DMA mapping API to allow DMA max
optimised size be set from a LLDD. How it works is a lot different. When
the LLDD calls this during probe, once the value is successfully recorded, we
return -EDEFER_PROBE. In the reprobe, the IOMM group default domain is
reallocated, and the new IOVA domain rcache upper limit is set according
to that DMA max optimised size. As such, we don't operate on a live IOMMU
domain.

Note that the DMA mapping API frontend is not strictly required, but saves
the LLDD calling IOMMU APIs directly, that being not preferred.

Some figures for storage scenario:
v5.13-rc1 baseline:			1200K IOPS
With series:				1800K IOPS

All above are for IOMMU strict mode. Non-strict mode gives ~1800K IOPS in
all scenarios.

Patch breakdown:
1-11: Add support for setting DMA max optimised size via sysfs
12-15: Add support for setting DMA max optimised size from LLDD

[0] https://lore.kernel.org/linux-iommu/20210129092120.1482-1-thunder.leizhen@huawei.com/
[1] https://lore.kernel.org/linux-iommu/1607538189-237944-1-git-send-email-john.garry@huawei.com/

Differences to v1:
- Many
- Change method to not operate on a 'live' IOMMU domain:
	- rather, force device driver to be re-probed once
	  dma_max_opt_size is set, and reconfig a new IOMMU group then
- Add iommu sysfs max_dma_opt_size file, and allow updating same as how
  group type is changed 

John Garry (15):
  iommu: Reactor iommu_group_store_type()
  iova: Allow rcache range upper limit to be flexible
  iommu: Allow max opt DMA len be set for a group via sysfs
  iommu: Add iommu_group_get_max_opt_dma_size()
  iova: Add iova_domain_len_is_cached()
  iommu: Allow iommu_change_dev_def_domain() realloc default domain for
    same type
  iommu: Add iommu_realloc_dev_group()
  dma-iommu: Add iommu_reconfig_dev_group_dma()
  iova: Add init_iova_domain_ext()
  dma-iommu: Use init_iova_domain_ext() for IOVA domain init
  dma-iommu: Reconfig group domain
  iommu: Add iommu_set_dev_dma_opt_size()
  dma-mapping: Add dma_set_max_opt_size()
  dma-iommu: Add iommu_dma_set_opt_size()
  scsi: hisi_sas: Set max optimal DMA size for v3 hw

 drivers/iommu/dma-iommu.c              |  51 +++++-
 drivers/iommu/iommu.c                  | 231 +++++++++++++++++++------
 drivers/iommu/iova.c                   |  61 +++++--
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c |   5 +
 include/linux/dma-iommu.h              |   4 +
 include/linux/dma-map-ops.h            |   1 +
 include/linux/dma-mapping.h            |   8 +
 include/linux/iommu.h                  |  19 ++
 include/linux/iova.h                   |  21 ++-
 kernel/dma/mapping.c                   |  11 ++
 10 files changed, 344 insertions(+), 68 deletions(-)

-- 
2.26.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH v2 01/15] iommu: Reactor iommu_group_store_type()
  2021-05-10 14:17 ` John Garry
@ 2021-05-10 14:17   ` John Garry
  -1 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm,
	sai.praneeth.prakhya, John Garry

Function iommu_group_store_type() supports changing the default domain of
an IOMMU group.

Many conditions need to be satisfied and steps taken for this action to be
successful.

Satisfying these conditions and steps will be required for setting other
IOMMU group attributes, so factor into a common part and a part specific
to update the IOMMU group attribute.

No functional change intended.

Some code comments are tidied up also.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/iommu.c | 73 +++++++++++++++++++++++++++----------------
 1 file changed, 46 insertions(+), 27 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 808ab70d5df5..4d12b607918c 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -3169,20 +3169,23 @@ static int iommu_change_dev_def_domain(struct iommu_group *group,
 }
 
 /*
- * Changing the default domain through sysfs requires the users to ubind the
- * drivers from the devices in the iommu group. Return failure if this doesn't
- * meet.
+ * Changing the default domain or any other IOMMU group attribute through sysfs
+ * requires the users to unbind the drivers from the devices in the IOMMU group.
+ * Return failure if this precondition is not met.
  *
  * We need to consider the race between this and the device release path.
  * device_lock(dev) is used here to guarantee that the device release path
  * will not be entered at the same time.
  */
-static ssize_t iommu_group_store_type(struct iommu_group *group,
-				      const char *buf, size_t count)
+static ssize_t iommu_group_store_common(struct iommu_group *group,
+					const char *buf, size_t count,
+					int (*cb)(const char *buf,
+						  struct iommu_group *group,
+						  struct device *dev))
 {
 	struct group_device *grp_dev;
 	struct device *dev;
-	int ret, req_type;
+	int ret;
 
 	if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
 		return -EACCES;
@@ -3190,25 +3193,16 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
 	if (WARN_ON(!group))
 		return -EINVAL;
 
-	if (sysfs_streq(buf, "identity"))
-		req_type = IOMMU_DOMAIN_IDENTITY;
-	else if (sysfs_streq(buf, "DMA"))
-		req_type = IOMMU_DOMAIN_DMA;
-	else if (sysfs_streq(buf, "auto"))
-		req_type = 0;
-	else
-		return -EINVAL;
-
 	/*
 	 * Lock/Unlock the group mutex here before device lock to
-	 * 1. Make sure that the iommu group has only one device (this is a
+	 * 1. Make sure that the IOMMU group has only one device (this is a
 	 *    prerequisite for step 2)
 	 * 2. Get struct *dev which is needed to lock device
 	 */
 	mutex_lock(&group->mutex);
 	if (iommu_group_device_count(group) != 1) {
 		mutex_unlock(&group->mutex);
-		pr_err_ratelimited("Cannot change default domain: Group has more than one device\n");
+		pr_err_ratelimited("Cannot change IOMMU group default domain attribute: Group has more than one device\n");
 		return -EINVAL;
 	}
 
@@ -3220,16 +3214,16 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
 	/*
 	 * Don't hold the group mutex because taking group mutex first and then
 	 * the device lock could potentially cause a deadlock as below. Assume
-	 * two threads T1 and T2. T1 is trying to change default domain of an
-	 * iommu group and T2 is trying to hot unplug a device or release [1] VF
-	 * of a PCIe device which is in the same iommu group. T1 takes group
-	 * mutex and before it could take device lock assume T2 has taken device
-	 * lock and is yet to take group mutex. Now, both the threads will be
-	 * waiting for the other thread to release lock. Below, lock order was
-	 * suggested.
+	 * two threads, T1 and T2. T1 is trying to change default domain
+	 * attribute of an IOMMU group and T2 is trying to hot unplug a device
+	 * or release [1] VF of a PCIe device which is in the same IOMMU group.
+	 * T1 takes the group mutex and before it could take device lock T2 may
+	 * have taken device lock and is yet to take group mutex. Now, both the
+	 * threads will be waiting for the other thread to release lock. Below,
+	 * lock order was suggested.
 	 * device_lock(dev);
 	 *	mutex_lock(&group->mutex);
-	 *		iommu_change_dev_def_domain();
+	 *		cb->iommu_change_dev_def_domain(); [example cb]
 	 *	mutex_unlock(&group->mutex);
 	 * device_unlock(dev);
 	 *
@@ -3243,7 +3237,7 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
 	 */
 	mutex_unlock(&group->mutex);
 
-	/* Check if the device in the group still has a driver bound to it */
+	/* Check if the only device in the group still has a driver bound */
 	device_lock(dev);
 	if (device_is_bound(dev)) {
 		pr_err_ratelimited("Device is still bound to driver\n");
@@ -3251,7 +3245,7 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
 		goto out;
 	}
 
-	ret = iommu_change_dev_def_domain(group, dev, req_type);
+	ret = (cb)(buf, group, dev);
 	ret = ret ?: count;
 
 out:
@@ -3260,3 +3254,28 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
 
 	return ret;
 }
+
+static int iommu_group_store_type_cb(const char *buf,
+				     struct iommu_group *group,
+				     struct device *dev)
+{
+	int type;
+
+	if (sysfs_streq(buf, "identity"))
+		type = IOMMU_DOMAIN_IDENTITY;
+	else if (sysfs_streq(buf, "DMA"))
+		type = IOMMU_DOMAIN_DMA;
+	else if (sysfs_streq(buf, "auto"))
+		type = 0;
+	else
+		return -EINVAL;
+
+	return iommu_change_dev_def_domain(group, dev, type);
+}
+
+static ssize_t iommu_group_store_type(struct iommu_group *group,
+				      const char *buf, size_t count)
+{
+	return iommu_group_store_common(group, buf, count,
+					iommu_group_store_type_cb);
+}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 01/15] iommu: Reactor iommu_group_store_type()
@ 2021-05-10 14:17   ` John Garry
  0 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: linux-scsi, linuxarm, linux-kernel, sai.praneeth.prakhya, iommu

Function iommu_group_store_type() supports changing the default domain of
an IOMMU group.

Many conditions need to be satisfied and steps taken for this action to be
successful.

Satisfying these conditions and steps will be required for setting other
IOMMU group attributes, so factor into a common part and a part specific
to update the IOMMU group attribute.

No functional change intended.

Some code comments are tidied up also.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/iommu.c | 73 +++++++++++++++++++++++++++----------------
 1 file changed, 46 insertions(+), 27 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 808ab70d5df5..4d12b607918c 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -3169,20 +3169,23 @@ static int iommu_change_dev_def_domain(struct iommu_group *group,
 }
 
 /*
- * Changing the default domain through sysfs requires the users to ubind the
- * drivers from the devices in the iommu group. Return failure if this doesn't
- * meet.
+ * Changing the default domain or any other IOMMU group attribute through sysfs
+ * requires the users to unbind the drivers from the devices in the IOMMU group.
+ * Return failure if this precondition is not met.
  *
  * We need to consider the race between this and the device release path.
  * device_lock(dev) is used here to guarantee that the device release path
  * will not be entered at the same time.
  */
-static ssize_t iommu_group_store_type(struct iommu_group *group,
-				      const char *buf, size_t count)
+static ssize_t iommu_group_store_common(struct iommu_group *group,
+					const char *buf, size_t count,
+					int (*cb)(const char *buf,
+						  struct iommu_group *group,
+						  struct device *dev))
 {
 	struct group_device *grp_dev;
 	struct device *dev;
-	int ret, req_type;
+	int ret;
 
 	if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
 		return -EACCES;
@@ -3190,25 +3193,16 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
 	if (WARN_ON(!group))
 		return -EINVAL;
 
-	if (sysfs_streq(buf, "identity"))
-		req_type = IOMMU_DOMAIN_IDENTITY;
-	else if (sysfs_streq(buf, "DMA"))
-		req_type = IOMMU_DOMAIN_DMA;
-	else if (sysfs_streq(buf, "auto"))
-		req_type = 0;
-	else
-		return -EINVAL;
-
 	/*
 	 * Lock/Unlock the group mutex here before device lock to
-	 * 1. Make sure that the iommu group has only one device (this is a
+	 * 1. Make sure that the IOMMU group has only one device (this is a
 	 *    prerequisite for step 2)
 	 * 2. Get struct *dev which is needed to lock device
 	 */
 	mutex_lock(&group->mutex);
 	if (iommu_group_device_count(group) != 1) {
 		mutex_unlock(&group->mutex);
-		pr_err_ratelimited("Cannot change default domain: Group has more than one device\n");
+		pr_err_ratelimited("Cannot change IOMMU group default domain attribute: Group has more than one device\n");
 		return -EINVAL;
 	}
 
@@ -3220,16 +3214,16 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
 	/*
 	 * Don't hold the group mutex because taking group mutex first and then
 	 * the device lock could potentially cause a deadlock as below. Assume
-	 * two threads T1 and T2. T1 is trying to change default domain of an
-	 * iommu group and T2 is trying to hot unplug a device or release [1] VF
-	 * of a PCIe device which is in the same iommu group. T1 takes group
-	 * mutex and before it could take device lock assume T2 has taken device
-	 * lock and is yet to take group mutex. Now, both the threads will be
-	 * waiting for the other thread to release lock. Below, lock order was
-	 * suggested.
+	 * two threads, T1 and T2. T1 is trying to change default domain
+	 * attribute of an IOMMU group and T2 is trying to hot unplug a device
+	 * or release [1] VF of a PCIe device which is in the same IOMMU group.
+	 * T1 takes the group mutex and before it could take device lock T2 may
+	 * have taken device lock and is yet to take group mutex. Now, both the
+	 * threads will be waiting for the other thread to release lock. Below,
+	 * lock order was suggested.
 	 * device_lock(dev);
 	 *	mutex_lock(&group->mutex);
-	 *		iommu_change_dev_def_domain();
+	 *		cb->iommu_change_dev_def_domain(); [example cb]
 	 *	mutex_unlock(&group->mutex);
 	 * device_unlock(dev);
 	 *
@@ -3243,7 +3237,7 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
 	 */
 	mutex_unlock(&group->mutex);
 
-	/* Check if the device in the group still has a driver bound to it */
+	/* Check if the only device in the group still has a driver bound */
 	device_lock(dev);
 	if (device_is_bound(dev)) {
 		pr_err_ratelimited("Device is still bound to driver\n");
@@ -3251,7 +3245,7 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
 		goto out;
 	}
 
-	ret = iommu_change_dev_def_domain(group, dev, req_type);
+	ret = (cb)(buf, group, dev);
 	ret = ret ?: count;
 
 out:
@@ -3260,3 +3254,28 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
 
 	return ret;
 }
+
+static int iommu_group_store_type_cb(const char *buf,
+				     struct iommu_group *group,
+				     struct device *dev)
+{
+	int type;
+
+	if (sysfs_streq(buf, "identity"))
+		type = IOMMU_DOMAIN_IDENTITY;
+	else if (sysfs_streq(buf, "DMA"))
+		type = IOMMU_DOMAIN_DMA;
+	else if (sysfs_streq(buf, "auto"))
+		type = 0;
+	else
+		return -EINVAL;
+
+	return iommu_change_dev_def_domain(group, dev, type);
+}
+
+static ssize_t iommu_group_store_type(struct iommu_group *group,
+				      const char *buf, size_t count)
+{
+	return iommu_group_store_common(group, buf, count,
+					iommu_group_store_type_cb);
+}
-- 
2.26.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 02/15] iova: Allow rcache range upper limit to be flexible
  2021-05-10 14:17 ` John Garry
@ 2021-05-10 14:17   ` John Garry
  -1 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm,
	sai.praneeth.prakhya, John Garry

Some LLDs may request DMA mappings whose IOVA length exceeds that of the
current rcache upper limit.

This means that allocations for those IOVAs will never be cached, and
always must be allocated and freed from the RB tree per DMA mapping cycle.
This has a significant effect on performance, more so since commit
4e89dce72521 ("iommu/iova: Retry from last rb tree node if iova search
fails"), as discussed at [0].

As a first step towards allowing the rcache range upper limit be configured,
hold this value in the IOVA rcache structure, and allocate the rcaches
separately.

[0] https://lore.kernel.org/linux-iommu/20210129092120.1482-1-thunder.leizhen@huawei.com/

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/dma-iommu.c |  2 +-
 drivers/iommu/iova.c      | 23 +++++++++++++++++------
 include/linux/iova.h      |  4 ++--
 3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 7bcdd1205535..f6d3302bb829 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -432,7 +432,7 @@ static dma_addr_t iommu_dma_alloc_iova(struct iommu_domain *domain,
 	 * rounding up anything cacheable to make sure that can't happen. The
 	 * order of the unadjusted size will still match upon freeing.
 	 */
-	if (iova_len < (1 << (IOVA_RANGE_CACHE_MAX_SIZE - 1)))
+	if (iova_len < (1 << (iovad->rcache_max_size - 1)))
 		iova_len = roundup_pow_of_two(iova_len);
 
 	dma_limit = min_not_zero(dma_limit, dev->bus_dma_limit);
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index b7ecd5b08039..0e4c0e55178a 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -15,6 +15,8 @@
 /* The anchor node sits above the top of the usable address space */
 #define IOVA_ANCHOR	~0UL
 
+#define IOVA_RANGE_CACHE_MAX_SIZE 6    /* log of max cached IOVA range size (in pages) */
+
 static bool iova_rcache_insert(struct iova_domain *iovad,
 			       unsigned long pfn,
 			       unsigned long size);
@@ -877,7 +879,14 @@ static void init_iova_rcaches(struct iova_domain *iovad)
 	unsigned int cpu;
 	int i;
 
-	for (i = 0; i < IOVA_RANGE_CACHE_MAX_SIZE; ++i) {
+	iovad->rcache_max_size = IOVA_RANGE_CACHE_MAX_SIZE;
+
+	iovad->rcaches = kcalloc(iovad->rcache_max_size,
+				 sizeof(*iovad->rcaches), GFP_KERNEL);
+	if (!iovad->rcaches)
+		return;
+
+	for (i = 0; i < iovad->rcache_max_size; ++i) {
 		rcache = &iovad->rcaches[i];
 		spin_lock_init(&rcache->lock);
 		rcache->depot_size = 0;
@@ -952,7 +961,7 @@ static bool iova_rcache_insert(struct iova_domain *iovad, unsigned long pfn,
 {
 	unsigned int log_size = order_base_2(size);
 
-	if (log_size >= IOVA_RANGE_CACHE_MAX_SIZE)
+	if (log_size >= iovad->rcache_max_size)
 		return false;
 
 	return __iova_rcache_insert(iovad, &iovad->rcaches[log_size], pfn);
@@ -1008,7 +1017,7 @@ static unsigned long iova_rcache_get(struct iova_domain *iovad,
 {
 	unsigned int log_size = order_base_2(size);
 
-	if (log_size >= IOVA_RANGE_CACHE_MAX_SIZE)
+	if (log_size >= iovad->rcache_max_size)
 		return 0;
 
 	return __iova_rcache_get(&iovad->rcaches[log_size], limit_pfn - size);
@@ -1024,7 +1033,7 @@ static void free_iova_rcaches(struct iova_domain *iovad)
 	unsigned int cpu;
 	int i, j;
 
-	for (i = 0; i < IOVA_RANGE_CACHE_MAX_SIZE; ++i) {
+	for (i = 0; i < iovad->rcache_max_size; ++i) {
 		rcache = &iovad->rcaches[i];
 		for_each_possible_cpu(cpu) {
 			cpu_rcache = per_cpu_ptr(rcache->cpu_rcaches, cpu);
@@ -1035,6 +1044,8 @@ static void free_iova_rcaches(struct iova_domain *iovad)
 		for (j = 0; j < rcache->depot_size; ++j)
 			iova_magazine_free(rcache->depot[j]);
 	}
+
+	kfree(iovad->rcaches);
 }
 
 /*
@@ -1047,7 +1058,7 @@ static void free_cpu_cached_iovas(unsigned int cpu, struct iova_domain *iovad)
 	unsigned long flags;
 	int i;
 
-	for (i = 0; i < IOVA_RANGE_CACHE_MAX_SIZE; ++i) {
+	for (i = 0; i < iovad->rcache_max_size; ++i) {
 		rcache = &iovad->rcaches[i];
 		cpu_rcache = per_cpu_ptr(rcache->cpu_rcaches, cpu);
 		spin_lock_irqsave(&cpu_rcache->lock, flags);
@@ -1066,7 +1077,7 @@ static void free_global_cached_iovas(struct iova_domain *iovad)
 	unsigned long flags;
 	int i, j;
 
-	for (i = 0; i < IOVA_RANGE_CACHE_MAX_SIZE; ++i) {
+	for (i = 0; i < iovad->rcache_max_size; ++i) {
 		rcache = &iovad->rcaches[i];
 		spin_lock_irqsave(&rcache->lock, flags);
 		for (j = 0; j < rcache->depot_size; ++j) {
diff --git a/include/linux/iova.h b/include/linux/iova.h
index 71d8a2de6635..9974e1d3e2bc 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -25,7 +25,6 @@ struct iova {
 struct iova_magazine;
 struct iova_cpu_rcache;
 
-#define IOVA_RANGE_CACHE_MAX_SIZE 6	/* log of max cached IOVA range size (in pages) */
 #define MAX_GLOBAL_MAGS 32	/* magazines per bin */
 
 struct iova_rcache {
@@ -74,6 +73,7 @@ struct iova_domain {
 	unsigned long	start_pfn;	/* Lower limit for this domain */
 	unsigned long	dma_32bit_pfn;
 	unsigned long	max32_alloc_size; /* Size of last failed allocation */
+	unsigned long	rcache_max_size; /* Upper limit of cached IOVA RANGE */
 	struct iova_fq __percpu *fq;	/* Flush Queue */
 
 	atomic64_t	fq_flush_start_cnt;	/* Number of TLB flushes that
@@ -83,7 +83,6 @@ struct iova_domain {
 						   have been finished */
 
 	struct iova	anchor;		/* rbtree lookup anchor */
-	struct iova_rcache rcaches[IOVA_RANGE_CACHE_MAX_SIZE];	/* IOVA range caches */
 
 	iova_flush_cb	flush_cb;	/* Call-Back function to flush IOMMU
 					   TLBs */
@@ -96,6 +95,7 @@ struct iova_domain {
 	atomic_t fq_timer_on;			/* 1 when timer is active, 0
 						   when not */
 	struct hlist_node	cpuhp_dead;
+	struct iova_rcache *rcaches;	/* IOVA range caches */
 };
 
 static inline unsigned long iova_size(struct iova *iova)
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 02/15] iova: Allow rcache range upper limit to be flexible
@ 2021-05-10 14:17   ` John Garry
  0 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: linux-scsi, linuxarm, linux-kernel, sai.praneeth.prakhya, iommu

Some LLDs may request DMA mappings whose IOVA length exceeds that of the
current rcache upper limit.

This means that allocations for those IOVAs will never be cached, and
always must be allocated and freed from the RB tree per DMA mapping cycle.
This has a significant effect on performance, more so since commit
4e89dce72521 ("iommu/iova: Retry from last rb tree node if iova search
fails"), as discussed at [0].

As a first step towards allowing the rcache range upper limit be configured,
hold this value in the IOVA rcache structure, and allocate the rcaches
separately.

[0] https://lore.kernel.org/linux-iommu/20210129092120.1482-1-thunder.leizhen@huawei.com/

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/dma-iommu.c |  2 +-
 drivers/iommu/iova.c      | 23 +++++++++++++++++------
 include/linux/iova.h      |  4 ++--
 3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 7bcdd1205535..f6d3302bb829 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -432,7 +432,7 @@ static dma_addr_t iommu_dma_alloc_iova(struct iommu_domain *domain,
 	 * rounding up anything cacheable to make sure that can't happen. The
 	 * order of the unadjusted size will still match upon freeing.
 	 */
-	if (iova_len < (1 << (IOVA_RANGE_CACHE_MAX_SIZE - 1)))
+	if (iova_len < (1 << (iovad->rcache_max_size - 1)))
 		iova_len = roundup_pow_of_two(iova_len);
 
 	dma_limit = min_not_zero(dma_limit, dev->bus_dma_limit);
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index b7ecd5b08039..0e4c0e55178a 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -15,6 +15,8 @@
 /* The anchor node sits above the top of the usable address space */
 #define IOVA_ANCHOR	~0UL
 
+#define IOVA_RANGE_CACHE_MAX_SIZE 6    /* log of max cached IOVA range size (in pages) */
+
 static bool iova_rcache_insert(struct iova_domain *iovad,
 			       unsigned long pfn,
 			       unsigned long size);
@@ -877,7 +879,14 @@ static void init_iova_rcaches(struct iova_domain *iovad)
 	unsigned int cpu;
 	int i;
 
-	for (i = 0; i < IOVA_RANGE_CACHE_MAX_SIZE; ++i) {
+	iovad->rcache_max_size = IOVA_RANGE_CACHE_MAX_SIZE;
+
+	iovad->rcaches = kcalloc(iovad->rcache_max_size,
+				 sizeof(*iovad->rcaches), GFP_KERNEL);
+	if (!iovad->rcaches)
+		return;
+
+	for (i = 0; i < iovad->rcache_max_size; ++i) {
 		rcache = &iovad->rcaches[i];
 		spin_lock_init(&rcache->lock);
 		rcache->depot_size = 0;
@@ -952,7 +961,7 @@ static bool iova_rcache_insert(struct iova_domain *iovad, unsigned long pfn,
 {
 	unsigned int log_size = order_base_2(size);
 
-	if (log_size >= IOVA_RANGE_CACHE_MAX_SIZE)
+	if (log_size >= iovad->rcache_max_size)
 		return false;
 
 	return __iova_rcache_insert(iovad, &iovad->rcaches[log_size], pfn);
@@ -1008,7 +1017,7 @@ static unsigned long iova_rcache_get(struct iova_domain *iovad,
 {
 	unsigned int log_size = order_base_2(size);
 
-	if (log_size >= IOVA_RANGE_CACHE_MAX_SIZE)
+	if (log_size >= iovad->rcache_max_size)
 		return 0;
 
 	return __iova_rcache_get(&iovad->rcaches[log_size], limit_pfn - size);
@@ -1024,7 +1033,7 @@ static void free_iova_rcaches(struct iova_domain *iovad)
 	unsigned int cpu;
 	int i, j;
 
-	for (i = 0; i < IOVA_RANGE_CACHE_MAX_SIZE; ++i) {
+	for (i = 0; i < iovad->rcache_max_size; ++i) {
 		rcache = &iovad->rcaches[i];
 		for_each_possible_cpu(cpu) {
 			cpu_rcache = per_cpu_ptr(rcache->cpu_rcaches, cpu);
@@ -1035,6 +1044,8 @@ static void free_iova_rcaches(struct iova_domain *iovad)
 		for (j = 0; j < rcache->depot_size; ++j)
 			iova_magazine_free(rcache->depot[j]);
 	}
+
+	kfree(iovad->rcaches);
 }
 
 /*
@@ -1047,7 +1058,7 @@ static void free_cpu_cached_iovas(unsigned int cpu, struct iova_domain *iovad)
 	unsigned long flags;
 	int i;
 
-	for (i = 0; i < IOVA_RANGE_CACHE_MAX_SIZE; ++i) {
+	for (i = 0; i < iovad->rcache_max_size; ++i) {
 		rcache = &iovad->rcaches[i];
 		cpu_rcache = per_cpu_ptr(rcache->cpu_rcaches, cpu);
 		spin_lock_irqsave(&cpu_rcache->lock, flags);
@@ -1066,7 +1077,7 @@ static void free_global_cached_iovas(struct iova_domain *iovad)
 	unsigned long flags;
 	int i, j;
 
-	for (i = 0; i < IOVA_RANGE_CACHE_MAX_SIZE; ++i) {
+	for (i = 0; i < iovad->rcache_max_size; ++i) {
 		rcache = &iovad->rcaches[i];
 		spin_lock_irqsave(&rcache->lock, flags);
 		for (j = 0; j < rcache->depot_size; ++j) {
diff --git a/include/linux/iova.h b/include/linux/iova.h
index 71d8a2de6635..9974e1d3e2bc 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -25,7 +25,6 @@ struct iova {
 struct iova_magazine;
 struct iova_cpu_rcache;
 
-#define IOVA_RANGE_CACHE_MAX_SIZE 6	/* log of max cached IOVA range size (in pages) */
 #define MAX_GLOBAL_MAGS 32	/* magazines per bin */
 
 struct iova_rcache {
@@ -74,6 +73,7 @@ struct iova_domain {
 	unsigned long	start_pfn;	/* Lower limit for this domain */
 	unsigned long	dma_32bit_pfn;
 	unsigned long	max32_alloc_size; /* Size of last failed allocation */
+	unsigned long	rcache_max_size; /* Upper limit of cached IOVA RANGE */
 	struct iova_fq __percpu *fq;	/* Flush Queue */
 
 	atomic64_t	fq_flush_start_cnt;	/* Number of TLB flushes that
@@ -83,7 +83,6 @@ struct iova_domain {
 						   have been finished */
 
 	struct iova	anchor;		/* rbtree lookup anchor */
-	struct iova_rcache rcaches[IOVA_RANGE_CACHE_MAX_SIZE];	/* IOVA range caches */
 
 	iova_flush_cb	flush_cb;	/* Call-Back function to flush IOMMU
 					   TLBs */
@@ -96,6 +95,7 @@ struct iova_domain {
 	atomic_t fq_timer_on;			/* 1 when timer is active, 0
 						   when not */
 	struct hlist_node	cpuhp_dead;
+	struct iova_rcache *rcaches;	/* IOVA range caches */
 };
 
 static inline unsigned long iova_size(struct iova *iova)
-- 
2.26.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 03/15] iommu: Allow max opt DMA len be set for a group via sysfs
  2021-05-10 14:17 ` John Garry
@ 2021-05-10 14:17   ` John Garry
  -1 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm,
	sai.praneeth.prakhya, John Garry

Add support to allow the maximum optimised DMA len be set for an IOMMU
group via sysfs.

This much the same with the method to change the default domain type for a
group.

However, unlike changing the default domain type, the new domains will be
allocated on a member device reprobe path.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/iommu.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 4d12b607918c..63cdfb11ebed 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -45,6 +45,7 @@ struct iommu_group {
 	struct iommu_domain *default_domain;
 	struct iommu_domain *domain;
 	struct list_head entry;
+	size_t max_opt_dma_size;
 };
 
 struct group_device {
@@ -86,6 +87,9 @@ static int iommu_create_device_direct_mappings(struct iommu_group *group,
 static struct iommu_group *iommu_group_get_for_dev(struct device *dev);
 static ssize_t iommu_group_store_type(struct iommu_group *group,
 				      const char *buf, size_t count);
+static ssize_t iommu_group_store_max_opt_dma_size(struct iommu_group *group,
+						  const char *buf,
+						  size_t count);
 
 #define IOMMU_GROUP_ATTR(_name, _mode, _show, _store)		\
 struct iommu_group_attribute iommu_group_attr_##_name =		\
@@ -554,6 +558,12 @@ static ssize_t iommu_group_show_type(struct iommu_group *group,
 	return strlen(type);
 }
 
+static ssize_t iommu_group_show_max_opt_dma_size(struct iommu_group *group,
+				     char *buf)
+{
+	return sprintf(buf, "%zu\n", group->max_opt_dma_size);
+}
+
 static IOMMU_GROUP_ATTR(name, S_IRUGO, iommu_group_show_name, NULL);
 
 static IOMMU_GROUP_ATTR(reserved_regions, 0444,
@@ -562,6 +572,9 @@ static IOMMU_GROUP_ATTR(reserved_regions, 0444,
 static IOMMU_GROUP_ATTR(type, 0644, iommu_group_show_type,
 			iommu_group_store_type);
 
+static IOMMU_GROUP_ATTR(max_opt_dma_size, 0644, iommu_group_show_max_opt_dma_size,
+			iommu_group_store_max_opt_dma_size);
+
 static void iommu_group_release(struct kobject *kobj)
 {
 	struct iommu_group *group = to_iommu_group(kobj);
@@ -648,6 +661,10 @@ struct iommu_group *iommu_group_alloc(void)
 	if (ret)
 		return ERR_PTR(ret);
 
+	ret = iommu_group_create_file(group, &iommu_group_attr_max_opt_dma_size);
+	if (ret)
+		return ERR_PTR(ret);
+
 	pr_debug("Allocated group %d\n", group->id);
 
 	return group;
@@ -3279,3 +3296,29 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
 	return iommu_group_store_common(group, buf, count,
 					iommu_group_store_type_cb);
 }
+
+static int iommu_group_store_max_opt_dma_size_cb(const char *buf,
+						 struct iommu_group *group,
+						 struct device *dev)
+{
+	unsigned long val;
+	char *endp;
+
+	val = simple_strtoul(buf, &endp, 0);
+	if (endp == buf)
+		return -EINVAL;
+
+	mutex_lock(&group->mutex);
+	group->max_opt_dma_size = val;
+	mutex_unlock(&group->mutex);
+
+	return 0;
+}
+
+static ssize_t iommu_group_store_max_opt_dma_size(struct iommu_group *group,
+						  const char *buf,
+						  size_t count)
+{
+	return iommu_group_store_common(group, buf, count,
+					iommu_group_store_max_opt_dma_size_cb);
+}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 03/15] iommu: Allow max opt DMA len be set for a group via sysfs
@ 2021-05-10 14:17   ` John Garry
  0 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: linux-scsi, linuxarm, linux-kernel, sai.praneeth.prakhya, iommu

Add support to allow the maximum optimised DMA len be set for an IOMMU
group via sysfs.

This much the same with the method to change the default domain type for a
group.

However, unlike changing the default domain type, the new domains will be
allocated on a member device reprobe path.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/iommu.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 4d12b607918c..63cdfb11ebed 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -45,6 +45,7 @@ struct iommu_group {
 	struct iommu_domain *default_domain;
 	struct iommu_domain *domain;
 	struct list_head entry;
+	size_t max_opt_dma_size;
 };
 
 struct group_device {
@@ -86,6 +87,9 @@ static int iommu_create_device_direct_mappings(struct iommu_group *group,
 static struct iommu_group *iommu_group_get_for_dev(struct device *dev);
 static ssize_t iommu_group_store_type(struct iommu_group *group,
 				      const char *buf, size_t count);
+static ssize_t iommu_group_store_max_opt_dma_size(struct iommu_group *group,
+						  const char *buf,
+						  size_t count);
 
 #define IOMMU_GROUP_ATTR(_name, _mode, _show, _store)		\
 struct iommu_group_attribute iommu_group_attr_##_name =		\
@@ -554,6 +558,12 @@ static ssize_t iommu_group_show_type(struct iommu_group *group,
 	return strlen(type);
 }
 
+static ssize_t iommu_group_show_max_opt_dma_size(struct iommu_group *group,
+				     char *buf)
+{
+	return sprintf(buf, "%zu\n", group->max_opt_dma_size);
+}
+
 static IOMMU_GROUP_ATTR(name, S_IRUGO, iommu_group_show_name, NULL);
 
 static IOMMU_GROUP_ATTR(reserved_regions, 0444,
@@ -562,6 +572,9 @@ static IOMMU_GROUP_ATTR(reserved_regions, 0444,
 static IOMMU_GROUP_ATTR(type, 0644, iommu_group_show_type,
 			iommu_group_store_type);
 
+static IOMMU_GROUP_ATTR(max_opt_dma_size, 0644, iommu_group_show_max_opt_dma_size,
+			iommu_group_store_max_opt_dma_size);
+
 static void iommu_group_release(struct kobject *kobj)
 {
 	struct iommu_group *group = to_iommu_group(kobj);
@@ -648,6 +661,10 @@ struct iommu_group *iommu_group_alloc(void)
 	if (ret)
 		return ERR_PTR(ret);
 
+	ret = iommu_group_create_file(group, &iommu_group_attr_max_opt_dma_size);
+	if (ret)
+		return ERR_PTR(ret);
+
 	pr_debug("Allocated group %d\n", group->id);
 
 	return group;
@@ -3279,3 +3296,29 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
 	return iommu_group_store_common(group, buf, count,
 					iommu_group_store_type_cb);
 }
+
+static int iommu_group_store_max_opt_dma_size_cb(const char *buf,
+						 struct iommu_group *group,
+						 struct device *dev)
+{
+	unsigned long val;
+	char *endp;
+
+	val = simple_strtoul(buf, &endp, 0);
+	if (endp == buf)
+		return -EINVAL;
+
+	mutex_lock(&group->mutex);
+	group->max_opt_dma_size = val;
+	mutex_unlock(&group->mutex);
+
+	return 0;
+}
+
+static ssize_t iommu_group_store_max_opt_dma_size(struct iommu_group *group,
+						  const char *buf,
+						  size_t count)
+{
+	return iommu_group_store_common(group, buf, count,
+					iommu_group_store_max_opt_dma_size_cb);
+}
-- 
2.26.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 04/15] iommu: Add iommu_group_get_max_opt_dma_size()
  2021-05-10 14:17 ` John Garry
@ 2021-05-10 14:17   ` John Garry
  -1 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm,
	sai.praneeth.prakhya, John Garry

Add a function to return the max optimised DMA size for an IOMMU group.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/iommu.c | 5 +++++
 include/linux/iommu.h | 6 ++++++
 2 files changed, 11 insertions(+)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 63cdfb11ebed..62e4491f32e0 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -2296,6 +2296,11 @@ struct iommu_domain *iommu_get_dma_domain(struct device *dev)
 	return dev->iommu_group->default_domain;
 }
 
+size_t iommu_group_get_max_opt_dma_size(struct iommu_group *group)
+{
+	return group->max_opt_dma_size;
+}
+
 /*
  * IOMMU groups are really the natural working unit of the IOMMU, but
  * the IOMMU API works on domains and devices.  Bridge that gap by
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 32d448050bf7..e26abda94792 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -405,6 +405,7 @@ extern int iommu_sva_unbind_gpasid(struct iommu_domain *domain,
 				   struct device *dev, ioasid_t pasid);
 extern struct iommu_domain *iommu_get_domain_for_dev(struct device *dev);
 extern struct iommu_domain *iommu_get_dma_domain(struct device *dev);
+extern size_t iommu_group_get_max_opt_dma_size(struct iommu_group *group);
 extern int iommu_map(struct iommu_domain *domain, unsigned long iova,
 		     phys_addr_t paddr, size_t size, int prot);
 extern int iommu_map_atomic(struct iommu_domain *domain, unsigned long iova,
@@ -653,6 +654,11 @@ static inline struct iommu_domain *iommu_get_domain_for_dev(struct device *dev)
 	return NULL;
 }
 
+static inline size_t iommu_group_get_max_opt_dma_size(struct iommu_group *group)
+{
+	return 0;
+}
+
 static inline int iommu_map(struct iommu_domain *domain, unsigned long iova,
 			    phys_addr_t paddr, size_t size, int prot)
 {
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 04/15] iommu: Add iommu_group_get_max_opt_dma_size()
@ 2021-05-10 14:17   ` John Garry
  0 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: linux-scsi, linuxarm, linux-kernel, sai.praneeth.prakhya, iommu

Add a function to return the max optimised DMA size for an IOMMU group.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/iommu.c | 5 +++++
 include/linux/iommu.h | 6 ++++++
 2 files changed, 11 insertions(+)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 63cdfb11ebed..62e4491f32e0 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -2296,6 +2296,11 @@ struct iommu_domain *iommu_get_dma_domain(struct device *dev)
 	return dev->iommu_group->default_domain;
 }
 
+size_t iommu_group_get_max_opt_dma_size(struct iommu_group *group)
+{
+	return group->max_opt_dma_size;
+}
+
 /*
  * IOMMU groups are really the natural working unit of the IOMMU, but
  * the IOMMU API works on domains and devices.  Bridge that gap by
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 32d448050bf7..e26abda94792 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -405,6 +405,7 @@ extern int iommu_sva_unbind_gpasid(struct iommu_domain *domain,
 				   struct device *dev, ioasid_t pasid);
 extern struct iommu_domain *iommu_get_domain_for_dev(struct device *dev);
 extern struct iommu_domain *iommu_get_dma_domain(struct device *dev);
+extern size_t iommu_group_get_max_opt_dma_size(struct iommu_group *group);
 extern int iommu_map(struct iommu_domain *domain, unsigned long iova,
 		     phys_addr_t paddr, size_t size, int prot);
 extern int iommu_map_atomic(struct iommu_domain *domain, unsigned long iova,
@@ -653,6 +654,11 @@ static inline struct iommu_domain *iommu_get_domain_for_dev(struct device *dev)
 	return NULL;
 }
 
+static inline size_t iommu_group_get_max_opt_dma_size(struct iommu_group *group)
+{
+	return 0;
+}
+
 static inline int iommu_map(struct iommu_domain *domain, unsigned long iova,
 			    phys_addr_t paddr, size_t size, int prot)
 {
-- 
2.26.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 05/15] iova: Add iova_domain_len_is_cached()
  2021-05-10 14:17 ` John Garry
@ 2021-05-10 14:17   ` John Garry
  -1 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm,
	sai.praneeth.prakhya, John Garry

Add a function to check whether an IOVA domain currently caches a given
upper IOVA len exactly.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/iova.c | 11 +++++++++++
 include/linux/iova.h |  8 +++++++-
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 0e4c0e55178a..95892a0433cc 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -872,6 +872,17 @@ static void iova_magazine_push(struct iova_magazine *mag, unsigned long pfn)
 	mag->pfns[mag->size++] = pfn;
 }
 
+static unsigned long iova_len_to_rcache_max(unsigned long iova_len)
+{
+	return order_base_2(iova_len) + 1;
+}
+
+/* Test if iova_len range cached upper limit matches that of IOVA domain */
+bool iova_domain_len_is_cached(struct iova_domain *iovad, unsigned long iova_len)
+{
+	return iova_len_to_rcache_max(iova_len) == iovad->rcache_max_size;
+}
+
 static void init_iova_rcaches(struct iova_domain *iovad)
 {
 	struct iova_cpu_rcache *cpu_rcache;
diff --git a/include/linux/iova.h b/include/linux/iova.h
index 9974e1d3e2bc..04cc8eb6de38 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -136,7 +136,8 @@ static inline unsigned long iova_pfn(struct iova_domain *iovad, dma_addr_t iova)
 #if IS_ENABLED(CONFIG_IOMMU_IOVA)
 int iova_cache_get(void);
 void iova_cache_put(void);
-
+bool iova_domain_len_is_cached(struct iova_domain *iovad,
+			       unsigned long iova_len);
 void free_iova(struct iova_domain *iovad, unsigned long pfn);
 void __free_iova(struct iova_domain *iovad, struct iova *iova);
 struct iova *alloc_iova(struct iova_domain *iovad, unsigned long size,
@@ -158,6 +159,11 @@ int init_iova_flush_queue(struct iova_domain *iovad,
 struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
 void put_iova_domain(struct iova_domain *iovad);
 #else
+static inline bool iova_domain_len_is_cached(struct iova_domain *iovad,
+					     unsigned long iova_len)
+{
+	return false;
+}
 static inline int iova_cache_get(void)
 {
 	return -ENOTSUPP;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 05/15] iova: Add iova_domain_len_is_cached()
@ 2021-05-10 14:17   ` John Garry
  0 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: linux-scsi, linuxarm, linux-kernel, sai.praneeth.prakhya, iommu

Add a function to check whether an IOVA domain currently caches a given
upper IOVA len exactly.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/iova.c | 11 +++++++++++
 include/linux/iova.h |  8 +++++++-
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 0e4c0e55178a..95892a0433cc 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -872,6 +872,17 @@ static void iova_magazine_push(struct iova_magazine *mag, unsigned long pfn)
 	mag->pfns[mag->size++] = pfn;
 }
 
+static unsigned long iova_len_to_rcache_max(unsigned long iova_len)
+{
+	return order_base_2(iova_len) + 1;
+}
+
+/* Test if iova_len range cached upper limit matches that of IOVA domain */
+bool iova_domain_len_is_cached(struct iova_domain *iovad, unsigned long iova_len)
+{
+	return iova_len_to_rcache_max(iova_len) == iovad->rcache_max_size;
+}
+
 static void init_iova_rcaches(struct iova_domain *iovad)
 {
 	struct iova_cpu_rcache *cpu_rcache;
diff --git a/include/linux/iova.h b/include/linux/iova.h
index 9974e1d3e2bc..04cc8eb6de38 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -136,7 +136,8 @@ static inline unsigned long iova_pfn(struct iova_domain *iovad, dma_addr_t iova)
 #if IS_ENABLED(CONFIG_IOMMU_IOVA)
 int iova_cache_get(void);
 void iova_cache_put(void);
-
+bool iova_domain_len_is_cached(struct iova_domain *iovad,
+			       unsigned long iova_len);
 void free_iova(struct iova_domain *iovad, unsigned long pfn);
 void __free_iova(struct iova_domain *iovad, struct iova *iova);
 struct iova *alloc_iova(struct iova_domain *iovad, unsigned long size,
@@ -158,6 +159,11 @@ int init_iova_flush_queue(struct iova_domain *iovad,
 struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
 void put_iova_domain(struct iova_domain *iovad);
 #else
+static inline bool iova_domain_len_is_cached(struct iova_domain *iovad,
+					     unsigned long iova_len)
+{
+	return false;
+}
 static inline int iova_cache_get(void)
 {
 	return -ENOTSUPP;
-- 
2.26.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 06/15] iommu: Allow iommu_change_dev_def_domain() realloc default domain for same type
  2021-05-10 14:17 ` John Garry
@ 2021-05-10 14:17   ` John Garry
  -1 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm,
	sai.praneeth.prakhya, John Garry

Allow iommu_change_dev_def_domain() to create a new default domain, keeping
the same as current in case type argument is not set.

Also remove comment about function purpose, which will become stale.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/iommu.c | 53 ++++++++++++++++++++++---------------------
 1 file changed, 27 insertions(+), 26 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 62e4491f32e0..f7253a973ab9 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -3065,16 +3065,13 @@ EXPORT_SYMBOL_GPL(iommu_sva_get_pasid);
  * @prev_dev: The device in the group (this is used to make sure that the device
  *	 hasn't changed after the caller has called this function)
  * @type: The type of the new default domain that gets associated with the group
+ * @new: Allocate new default domain, keeping same type when no type passed
  *
  * Returns 0 on success and error code on failure
  *
- * Note:
- * 1. Presently, this function is called only when user requests to change the
- *    group's default domain type through /sys/kernel/iommu_groups/<grp_id>/type
- *    Please take a closer look if intended to use for other purposes.
  */
 static int iommu_change_dev_def_domain(struct iommu_group *group,
-				       struct device *prev_dev, int type)
+				       struct device *prev_dev, int type, bool new)
 {
 	struct iommu_domain *prev_dom;
 	struct group_device *grp_dev;
@@ -3127,28 +3124,32 @@ static int iommu_change_dev_def_domain(struct iommu_group *group,
 		goto out;
 	}
 
-	dev_def_dom = iommu_get_def_domain_type(dev);
-	if (!type) {
+	if (new && !type) {
+		type = prev_dom->type;
+	} else {
+		dev_def_dom = iommu_get_def_domain_type(dev);
+		if (!type) {
+			/*
+			 * If the user hasn't requested any specific type of domain and
+			 * if the device supports both the domains, then default to the
+			 * domain the device was booted with
+			 */
+			type = dev_def_dom ? : iommu_def_domain_type;
+		} else if (dev_def_dom && type != dev_def_dom) {
+			dev_err_ratelimited(prev_dev, "Device cannot be in %s domain\n",
+					    iommu_domain_type_str(type));
+			ret = -EINVAL;
+			goto out;
+		}
+
 		/*
-		 * If the user hasn't requested any specific type of domain and
-		 * if the device supports both the domains, then default to the
-		 * domain the device was booted with
+		 * Switch to a new domain only if the requested domain type is different
+		 * from the existing default domain type
 		 */
-		type = dev_def_dom ? : iommu_def_domain_type;
-	} else if (dev_def_dom && type != dev_def_dom) {
-		dev_err_ratelimited(prev_dev, "Device cannot be in %s domain\n",
-				    iommu_domain_type_str(type));
-		ret = -EINVAL;
-		goto out;
-	}
-
-	/*
-	 * Switch to a new domain only if the requested domain type is different
-	 * from the existing default domain type
-	 */
-	if (prev_dom->type == type) {
-		ret = 0;
-		goto out;
+		if (prev_dom->type == type) {
+			ret = 0;
+			goto out;
+		}
 	}
 
 	/* Sets group->default_domain to the newly allocated domain */
@@ -3292,7 +3293,7 @@ static int iommu_group_store_type_cb(const char *buf,
 	else
 		return -EINVAL;
 
-	return iommu_change_dev_def_domain(group, dev, type);
+	return iommu_change_dev_def_domain(group, dev, type, false);
 }
 
 static ssize_t iommu_group_store_type(struct iommu_group *group,
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 06/15] iommu: Allow iommu_change_dev_def_domain() realloc default domain for same type
@ 2021-05-10 14:17   ` John Garry
  0 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: linux-scsi, linuxarm, linux-kernel, sai.praneeth.prakhya, iommu

Allow iommu_change_dev_def_domain() to create a new default domain, keeping
the same as current in case type argument is not set.

Also remove comment about function purpose, which will become stale.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/iommu.c | 53 ++++++++++++++++++++++---------------------
 1 file changed, 27 insertions(+), 26 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 62e4491f32e0..f7253a973ab9 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -3065,16 +3065,13 @@ EXPORT_SYMBOL_GPL(iommu_sva_get_pasid);
  * @prev_dev: The device in the group (this is used to make sure that the device
  *	 hasn't changed after the caller has called this function)
  * @type: The type of the new default domain that gets associated with the group
+ * @new: Allocate new default domain, keeping same type when no type passed
  *
  * Returns 0 on success and error code on failure
  *
- * Note:
- * 1. Presently, this function is called only when user requests to change the
- *    group's default domain type through /sys/kernel/iommu_groups/<grp_id>/type
- *    Please take a closer look if intended to use for other purposes.
  */
 static int iommu_change_dev_def_domain(struct iommu_group *group,
-				       struct device *prev_dev, int type)
+				       struct device *prev_dev, int type, bool new)
 {
 	struct iommu_domain *prev_dom;
 	struct group_device *grp_dev;
@@ -3127,28 +3124,32 @@ static int iommu_change_dev_def_domain(struct iommu_group *group,
 		goto out;
 	}
 
-	dev_def_dom = iommu_get_def_domain_type(dev);
-	if (!type) {
+	if (new && !type) {
+		type = prev_dom->type;
+	} else {
+		dev_def_dom = iommu_get_def_domain_type(dev);
+		if (!type) {
+			/*
+			 * If the user hasn't requested any specific type of domain and
+			 * if the device supports both the domains, then default to the
+			 * domain the device was booted with
+			 */
+			type = dev_def_dom ? : iommu_def_domain_type;
+		} else if (dev_def_dom && type != dev_def_dom) {
+			dev_err_ratelimited(prev_dev, "Device cannot be in %s domain\n",
+					    iommu_domain_type_str(type));
+			ret = -EINVAL;
+			goto out;
+		}
+
 		/*
-		 * If the user hasn't requested any specific type of domain and
-		 * if the device supports both the domains, then default to the
-		 * domain the device was booted with
+		 * Switch to a new domain only if the requested domain type is different
+		 * from the existing default domain type
 		 */
-		type = dev_def_dom ? : iommu_def_domain_type;
-	} else if (dev_def_dom && type != dev_def_dom) {
-		dev_err_ratelimited(prev_dev, "Device cannot be in %s domain\n",
-				    iommu_domain_type_str(type));
-		ret = -EINVAL;
-		goto out;
-	}
-
-	/*
-	 * Switch to a new domain only if the requested domain type is different
-	 * from the existing default domain type
-	 */
-	if (prev_dom->type == type) {
-		ret = 0;
-		goto out;
+		if (prev_dom->type == type) {
+			ret = 0;
+			goto out;
+		}
 	}
 
 	/* Sets group->default_domain to the newly allocated domain */
@@ -3292,7 +3293,7 @@ static int iommu_group_store_type_cb(const char *buf,
 	else
 		return -EINVAL;
 
-	return iommu_change_dev_def_domain(group, dev, type);
+	return iommu_change_dev_def_domain(group, dev, type, false);
 }
 
 static ssize_t iommu_group_store_type(struct iommu_group *group,
-- 
2.26.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 07/15] iommu: Add iommu_realloc_dev_group()
  2021-05-10 14:17 ` John Garry
@ 2021-05-10 14:17   ` John Garry
  -1 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm,
	sai.praneeth.prakhya, John Garry

Add a function to re-alloc IOMMU group default domain.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/iommu.c | 12 ++++++++++++
 include/linux/iommu.h |  6 ++++++
 2 files changed, 18 insertions(+)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index f7253a973ab9..bdb9aa47dfca 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -3191,6 +3191,18 @@ static int iommu_change_dev_def_domain(struct iommu_group *group,
 	return ret;
 }
 
+int iommu_realloc_dev_group(struct device *dev)
+{
+	struct iommu_group *group;
+	int ret;
+
+	group = iommu_group_get(dev);
+	ret = iommu_change_dev_def_domain(group, dev, 0, true);
+	iommu_group_put(group);
+
+	return ret;
+}
+
 /*
  * Changing the default domain or any other IOMMU group attribute through sysfs
  * requires the users to unbind the drivers from the devices in the IOMMU group.
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index e26abda94792..6e187746af0f 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -482,6 +482,7 @@ bool iommu_get_dma_strict(struct iommu_domain *domain);
 
 extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
 			      unsigned long iova, int flags);
+extern int iommu_realloc_dev_group(struct device *dev);
 
 static inline void iommu_flush_iotlb_all(struct iommu_domain *domain)
 {
@@ -699,6 +700,11 @@ static inline size_t iommu_map_sg_atomic(struct iommu_domain *domain,
 	return 0;
 }
 
+static inline int iommu_realloc_dev_group(struct device *dev)
+{
+	return -ENODEV;
+}
+
 static inline void iommu_flush_iotlb_all(struct iommu_domain *domain)
 {
 }
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 07/15] iommu: Add iommu_realloc_dev_group()
@ 2021-05-10 14:17   ` John Garry
  0 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: linux-scsi, linuxarm, linux-kernel, sai.praneeth.prakhya, iommu

Add a function to re-alloc IOMMU group default domain.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/iommu.c | 12 ++++++++++++
 include/linux/iommu.h |  6 ++++++
 2 files changed, 18 insertions(+)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index f7253a973ab9..bdb9aa47dfca 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -3191,6 +3191,18 @@ static int iommu_change_dev_def_domain(struct iommu_group *group,
 	return ret;
 }
 
+int iommu_realloc_dev_group(struct device *dev)
+{
+	struct iommu_group *group;
+	int ret;
+
+	group = iommu_group_get(dev);
+	ret = iommu_change_dev_def_domain(group, dev, 0, true);
+	iommu_group_put(group);
+
+	return ret;
+}
+
 /*
  * Changing the default domain or any other IOMMU group attribute through sysfs
  * requires the users to unbind the drivers from the devices in the IOMMU group.
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index e26abda94792..6e187746af0f 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -482,6 +482,7 @@ bool iommu_get_dma_strict(struct iommu_domain *domain);
 
 extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
 			      unsigned long iova, int flags);
+extern int iommu_realloc_dev_group(struct device *dev);
 
 static inline void iommu_flush_iotlb_all(struct iommu_domain *domain)
 {
@@ -699,6 +700,11 @@ static inline size_t iommu_map_sg_atomic(struct iommu_domain *domain,
 	return 0;
 }
 
+static inline int iommu_realloc_dev_group(struct device *dev)
+{
+	return -ENODEV;
+}
+
 static inline void iommu_flush_iotlb_all(struct iommu_domain *domain)
 {
 }
-- 
2.26.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 08/15] dma-iommu: Add iommu_reconfig_dev_group_dma()
  2021-05-10 14:17 ` John Garry
@ 2021-05-10 14:17   ` John Garry
  -1 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm,
	sai.praneeth.prakhya, John Garry

Add a function to reconfigure the IOMMU group for a device, if necessary.

IOVAs are cached in power-of-2 granules, so there is no point in allocating
a new IOMMU domain if the current range is suitable.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/dma-iommu.c | 25 +++++++++++++++++++++++++
 include/linux/dma-iommu.h |  4 ++++
 2 files changed, 29 insertions(+)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index f6d3302bb829..4fb82c554ede 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -315,6 +315,31 @@ static bool dev_is_untrusted(struct device *dev)
 	return dev_is_pci(dev) && to_pci_dev(dev)->untrusted;
 }
 
+void iommu_reconfig_dev_group_dma(struct device *dev)
+{
+	struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
+	struct iommu_dma_cookie *cookie = domain->iova_cookie;
+	unsigned long shift, iova_len;
+	struct iova_domain *iovad;
+	size_t max_opt_dma_size;
+
+	if (!cookie || cookie->type != IOMMU_DMA_IOVA_COOKIE)
+		return;
+
+	max_opt_dma_size = iommu_group_get_max_opt_dma_size(dev->iommu_group);
+	if (!max_opt_dma_size)
+		return;
+
+	iovad = &cookie->iovad;
+	shift = iova_shift(iovad);
+	iova_len = max_opt_dma_size >> shift;
+
+	if (iova_domain_len_is_cached(iovad, iova_len))
+		return;
+
+	iommu_realloc_dev_group(dev);
+}
+
 /**
  * iommu_dma_init_domain - Initialise a DMA mapping domain
  * @domain: IOMMU domain previously prepared by iommu_get_dma_cookie()
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
index 6e75a2d689b4..097398b76dcc 100644
--- a/include/linux/dma-iommu.h
+++ b/include/linux/dma-iommu.h
@@ -20,6 +20,7 @@ void iommu_put_dma_cookie(struct iommu_domain *domain);
 
 /* Setup call for arch DMA mapping code */
 void iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size);
+void iommu_reconfig_dev_group_dma(struct device *dev);
 
 /* The DMA API isn't _quite_ the whole story, though... */
 /*
@@ -53,6 +54,9 @@ static inline void iommu_setup_dma_ops(struct device *dev, u64 dma_base,
 		u64 size)
 {
 }
+static inline void iommu_reconfig_dev_group_dma(struct device *dev)
+{
+}
 
 static inline int iommu_get_dma_cookie(struct iommu_domain *domain)
 {
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 08/15] dma-iommu: Add iommu_reconfig_dev_group_dma()
@ 2021-05-10 14:17   ` John Garry
  0 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: linux-scsi, linuxarm, linux-kernel, sai.praneeth.prakhya, iommu

Add a function to reconfigure the IOMMU group for a device, if necessary.

IOVAs are cached in power-of-2 granules, so there is no point in allocating
a new IOMMU domain if the current range is suitable.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/dma-iommu.c | 25 +++++++++++++++++++++++++
 include/linux/dma-iommu.h |  4 ++++
 2 files changed, 29 insertions(+)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index f6d3302bb829..4fb82c554ede 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -315,6 +315,31 @@ static bool dev_is_untrusted(struct device *dev)
 	return dev_is_pci(dev) && to_pci_dev(dev)->untrusted;
 }
 
+void iommu_reconfig_dev_group_dma(struct device *dev)
+{
+	struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
+	struct iommu_dma_cookie *cookie = domain->iova_cookie;
+	unsigned long shift, iova_len;
+	struct iova_domain *iovad;
+	size_t max_opt_dma_size;
+
+	if (!cookie || cookie->type != IOMMU_DMA_IOVA_COOKIE)
+		return;
+
+	max_opt_dma_size = iommu_group_get_max_opt_dma_size(dev->iommu_group);
+	if (!max_opt_dma_size)
+		return;
+
+	iovad = &cookie->iovad;
+	shift = iova_shift(iovad);
+	iova_len = max_opt_dma_size >> shift;
+
+	if (iova_domain_len_is_cached(iovad, iova_len))
+		return;
+
+	iommu_realloc_dev_group(dev);
+}
+
 /**
  * iommu_dma_init_domain - Initialise a DMA mapping domain
  * @domain: IOMMU domain previously prepared by iommu_get_dma_cookie()
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
index 6e75a2d689b4..097398b76dcc 100644
--- a/include/linux/dma-iommu.h
+++ b/include/linux/dma-iommu.h
@@ -20,6 +20,7 @@ void iommu_put_dma_cookie(struct iommu_domain *domain);
 
 /* Setup call for arch DMA mapping code */
 void iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size);
+void iommu_reconfig_dev_group_dma(struct device *dev);
 
 /* The DMA API isn't _quite_ the whole story, though... */
 /*
@@ -53,6 +54,9 @@ static inline void iommu_setup_dma_ops(struct device *dev, u64 dma_base,
 		u64 size)
 {
 }
+static inline void iommu_reconfig_dev_group_dma(struct device *dev)
+{
+}
 
 static inline int iommu_get_dma_cookie(struct iommu_domain *domain)
 {
-- 
2.26.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 09/15] iova: Add init_iova_domain_ext()
  2021-05-10 14:17 ` John Garry
@ 2021-05-10 14:17   ` John Garry
  -1 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm,
	sai.praneeth.prakhya, John Garry

Add extended version of init_iova_domain() which accepts an max opt
iova length argument, and use it to set the rcaches range.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/iova.c | 29 +++++++++++++++++++++++------
 include/linux/iova.h |  9 +++++++++
 2 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 95892a0433cc..273a689006c3 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -23,7 +23,7 @@ static bool iova_rcache_insert(struct iova_domain *iovad,
 static unsigned long iova_rcache_get(struct iova_domain *iovad,
 				     unsigned long size,
 				     unsigned long limit_pfn);
-static void init_iova_rcaches(struct iova_domain *iovad);
+static void init_iova_rcaches(struct iova_domain *iovad, unsigned long iova_len);
 static void free_cpu_cached_iovas(unsigned int cpu, struct iova_domain *iovad);
 static void free_iova_rcaches(struct iova_domain *iovad);
 static void fq_destroy_all_entries(struct iova_domain *iovad);
@@ -47,8 +47,8 @@ static struct iova *to_iova(struct rb_node *node)
 }
 
 void
-init_iova_domain(struct iova_domain *iovad, unsigned long granule,
-	unsigned long start_pfn)
+__init_iova_domain(struct iova_domain *iovad, unsigned long granule,
+	unsigned long start_pfn, unsigned long iova_len)
 {
 	/*
 	 * IOVA granularity will normally be equal to the smallest
@@ -71,7 +71,21 @@ init_iova_domain(struct iova_domain *iovad, unsigned long granule,
 	rb_link_node(&iovad->anchor.node, NULL, &iovad->rbroot.rb_node);
 	rb_insert_color(&iovad->anchor.node, &iovad->rbroot);
 	cpuhp_state_add_instance_nocalls(CPUHP_IOMMU_IOVA_DEAD, &iovad->cpuhp_dead);
-	init_iova_rcaches(iovad);
+	init_iova_rcaches(iovad, iova_len);
+}
+
+void
+init_iova_domain_ext(struct iova_domain *iovad, unsigned long granule,
+	unsigned long start_pfn, unsigned long iova_len)
+{
+	__init_iova_domain(iovad, granule, start_pfn, iova_len);
+}
+
+void
+init_iova_domain(struct iova_domain *iovad, unsigned long granule,
+	unsigned long start_pfn)
+{
+	__init_iova_domain(iovad, granule, start_pfn, 0);
 }
 EXPORT_SYMBOL_GPL(init_iova_domain);
 
@@ -883,14 +897,17 @@ bool iova_domain_len_is_cached(struct iova_domain *iovad, unsigned long iova_len
 	return iova_len_to_rcache_max(iova_len) == iovad->rcache_max_size;
 }
 
-static void init_iova_rcaches(struct iova_domain *iovad)
+static void init_iova_rcaches(struct iova_domain *iovad, unsigned long iova_len)
 {
 	struct iova_cpu_rcache *cpu_rcache;
 	struct iova_rcache *rcache;
 	unsigned int cpu;
 	int i;
 
-	iovad->rcache_max_size = IOVA_RANGE_CACHE_MAX_SIZE;
+	if (iova_len)
+		iovad->rcache_max_size = iova_len_to_rcache_max(iova_len);
+	else
+		iovad->rcache_max_size = IOVA_RANGE_CACHE_MAX_SIZE;
 
 	iovad->rcaches = kcalloc(iovad->rcache_max_size,
 				 sizeof(*iovad->rcaches), GFP_KERNEL);
diff --git a/include/linux/iova.h b/include/linux/iova.h
index 04cc8eb6de38..cfe416b6a8c7 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -154,6 +154,8 @@ struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
 	unsigned long pfn_hi);
 void init_iova_domain(struct iova_domain *iovad, unsigned long granule,
 	unsigned long start_pfn);
+void init_iova_domain_ext(struct iova_domain *iovad, unsigned long granule,
+	unsigned long start_pfn, unsigned long iova_len);
 int init_iova_flush_queue(struct iova_domain *iovad,
 			  iova_flush_cb flush_cb, iova_entry_dtor entry_dtor);
 struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
@@ -222,6 +224,13 @@ static inline void init_iova_domain(struct iova_domain *iovad,
 {
 }
 
+static inline void init_iova_domain_ext(struct iova_domain *iovad,
+				    unsigned long granule,
+				    unsigned long start_pfn,
+				    unsigned long iova_len)
+{
+}
+
 static inline int init_iova_flush_queue(struct iova_domain *iovad,
 					iova_flush_cb flush_cb,
 					iova_entry_dtor entry_dtor)
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 09/15] iova: Add init_iova_domain_ext()
@ 2021-05-10 14:17   ` John Garry
  0 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: linux-scsi, linuxarm, linux-kernel, sai.praneeth.prakhya, iommu

Add extended version of init_iova_domain() which accepts an max opt
iova length argument, and use it to set the rcaches range.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/iova.c | 29 +++++++++++++++++++++++------
 include/linux/iova.h |  9 +++++++++
 2 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 95892a0433cc..273a689006c3 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -23,7 +23,7 @@ static bool iova_rcache_insert(struct iova_domain *iovad,
 static unsigned long iova_rcache_get(struct iova_domain *iovad,
 				     unsigned long size,
 				     unsigned long limit_pfn);
-static void init_iova_rcaches(struct iova_domain *iovad);
+static void init_iova_rcaches(struct iova_domain *iovad, unsigned long iova_len);
 static void free_cpu_cached_iovas(unsigned int cpu, struct iova_domain *iovad);
 static void free_iova_rcaches(struct iova_domain *iovad);
 static void fq_destroy_all_entries(struct iova_domain *iovad);
@@ -47,8 +47,8 @@ static struct iova *to_iova(struct rb_node *node)
 }
 
 void
-init_iova_domain(struct iova_domain *iovad, unsigned long granule,
-	unsigned long start_pfn)
+__init_iova_domain(struct iova_domain *iovad, unsigned long granule,
+	unsigned long start_pfn, unsigned long iova_len)
 {
 	/*
 	 * IOVA granularity will normally be equal to the smallest
@@ -71,7 +71,21 @@ init_iova_domain(struct iova_domain *iovad, unsigned long granule,
 	rb_link_node(&iovad->anchor.node, NULL, &iovad->rbroot.rb_node);
 	rb_insert_color(&iovad->anchor.node, &iovad->rbroot);
 	cpuhp_state_add_instance_nocalls(CPUHP_IOMMU_IOVA_DEAD, &iovad->cpuhp_dead);
-	init_iova_rcaches(iovad);
+	init_iova_rcaches(iovad, iova_len);
+}
+
+void
+init_iova_domain_ext(struct iova_domain *iovad, unsigned long granule,
+	unsigned long start_pfn, unsigned long iova_len)
+{
+	__init_iova_domain(iovad, granule, start_pfn, iova_len);
+}
+
+void
+init_iova_domain(struct iova_domain *iovad, unsigned long granule,
+	unsigned long start_pfn)
+{
+	__init_iova_domain(iovad, granule, start_pfn, 0);
 }
 EXPORT_SYMBOL_GPL(init_iova_domain);
 
@@ -883,14 +897,17 @@ bool iova_domain_len_is_cached(struct iova_domain *iovad, unsigned long iova_len
 	return iova_len_to_rcache_max(iova_len) == iovad->rcache_max_size;
 }
 
-static void init_iova_rcaches(struct iova_domain *iovad)
+static void init_iova_rcaches(struct iova_domain *iovad, unsigned long iova_len)
 {
 	struct iova_cpu_rcache *cpu_rcache;
 	struct iova_rcache *rcache;
 	unsigned int cpu;
 	int i;
 
-	iovad->rcache_max_size = IOVA_RANGE_CACHE_MAX_SIZE;
+	if (iova_len)
+		iovad->rcache_max_size = iova_len_to_rcache_max(iova_len);
+	else
+		iovad->rcache_max_size = IOVA_RANGE_CACHE_MAX_SIZE;
 
 	iovad->rcaches = kcalloc(iovad->rcache_max_size,
 				 sizeof(*iovad->rcaches), GFP_KERNEL);
diff --git a/include/linux/iova.h b/include/linux/iova.h
index 04cc8eb6de38..cfe416b6a8c7 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -154,6 +154,8 @@ struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
 	unsigned long pfn_hi);
 void init_iova_domain(struct iova_domain *iovad, unsigned long granule,
 	unsigned long start_pfn);
+void init_iova_domain_ext(struct iova_domain *iovad, unsigned long granule,
+	unsigned long start_pfn, unsigned long iova_len);
 int init_iova_flush_queue(struct iova_domain *iovad,
 			  iova_flush_cb flush_cb, iova_entry_dtor entry_dtor);
 struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
@@ -222,6 +224,13 @@ static inline void init_iova_domain(struct iova_domain *iovad,
 {
 }
 
+static inline void init_iova_domain_ext(struct iova_domain *iovad,
+				    unsigned long granule,
+				    unsigned long start_pfn,
+				    unsigned long iova_len)
+{
+}
+
 static inline int init_iova_flush_queue(struct iova_domain *iovad,
 					iova_flush_cb flush_cb,
 					iova_entry_dtor entry_dtor)
-- 
2.26.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 10/15] dma-iommu: Use init_iova_domain_ext() for IOVA domain init
  2021-05-10 14:17 ` John Garry
@ 2021-05-10 14:17   ` John Garry
  -1 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm,
	sai.praneeth.prakhya, John Garry

Pass the max opt iova len to init the IOVA domain, if set.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/dma-iommu.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 4fb82c554ede..574d7a901fd2 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -358,6 +358,8 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
 	struct iommu_dma_cookie *cookie = domain->iova_cookie;
 	unsigned long order, base_pfn;
 	struct iova_domain *iovad;
+	size_t max_opt_dma_size;
+	unsigned long iova_len;
 
 	if (!cookie || cookie->type != IOMMU_DMA_IOVA_COOKIE)
 		return -EINVAL;
@@ -391,7 +393,18 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
 		return 0;
 	}
 
-	init_iova_domain(iovad, 1UL << order, base_pfn);
+	max_opt_dma_size = iommu_group_get_max_opt_dma_size(dev->iommu_group);
+
+	if (max_opt_dma_size) {
+		unsigned long shift = __ffs(1UL << order);
+
+		iova_len = max_opt_dma_size >> shift;
+		iova_len = roundup_pow_of_two(iova_len);
+	} else {
+		iova_len = 0;
+	}
+
+	init_iova_domain_ext(iovad, 1UL << order, base_pfn, iova_len);
 
 	if (!cookie->fq_domain && (!dev || !dev_is_untrusted(dev)) &&
 	    domain->ops->flush_iotlb_all && !iommu_get_dma_strict(domain)) {
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 10/15] dma-iommu: Use init_iova_domain_ext() for IOVA domain init
@ 2021-05-10 14:17   ` John Garry
  0 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: linux-scsi, linuxarm, linux-kernel, sai.praneeth.prakhya, iommu

Pass the max opt iova len to init the IOVA domain, if set.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/dma-iommu.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 4fb82c554ede..574d7a901fd2 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -358,6 +358,8 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
 	struct iommu_dma_cookie *cookie = domain->iova_cookie;
 	unsigned long order, base_pfn;
 	struct iova_domain *iovad;
+	size_t max_opt_dma_size;
+	unsigned long iova_len;
 
 	if (!cookie || cookie->type != IOMMU_DMA_IOVA_COOKIE)
 		return -EINVAL;
@@ -391,7 +393,18 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
 		return 0;
 	}
 
-	init_iova_domain(iovad, 1UL << order, base_pfn);
+	max_opt_dma_size = iommu_group_get_max_opt_dma_size(dev->iommu_group);
+
+	if (max_opt_dma_size) {
+		unsigned long shift = __ffs(1UL << order);
+
+		iova_len = max_opt_dma_size >> shift;
+		iova_len = roundup_pow_of_two(iova_len);
+	} else {
+		iova_len = 0;
+	}
+
+	init_iova_domain_ext(iovad, 1UL << order, base_pfn, iova_len);
 
 	if (!cookie->fq_domain && (!dev || !dev_is_untrusted(dev)) &&
 	    domain->ops->flush_iotlb_all && !iommu_get_dma_strict(domain)) {
-- 
2.26.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 11/15] dma-iommu: Reconfig group domain
  2021-05-10 14:17 ` John Garry
@ 2021-05-10 14:17   ` John Garry
  -1 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm,
	sai.praneeth.prakhya, John Garry

Call iommu_reconfig_dev_group_dma() from iommu_setup_dma_ops() to reconfig
the group domain, if necessary.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/dma-iommu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 574d7a901fd2..1d58c7a2d85d 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -1358,6 +1358,9 @@ void iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size)
 	 * underlying IOMMU driver needs to support via the dma-iommu layer.
 	 */
 	if (domain->type == IOMMU_DOMAIN_DMA) {
+		iommu_reconfig_dev_group_dma(dev);
+		/* domain may be stale ... */
+		domain = iommu_get_domain_for_dev(dev);
 		if (iommu_dma_init_domain(domain, dma_base, size, dev))
 			goto out_err;
 		dev->dma_ops = &iommu_dma_ops;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 11/15] dma-iommu: Reconfig group domain
@ 2021-05-10 14:17   ` John Garry
  0 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: linux-scsi, linuxarm, linux-kernel, sai.praneeth.prakhya, iommu

Call iommu_reconfig_dev_group_dma() from iommu_setup_dma_ops() to reconfig
the group domain, if necessary.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/dma-iommu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 574d7a901fd2..1d58c7a2d85d 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -1358,6 +1358,9 @@ void iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size)
 	 * underlying IOMMU driver needs to support via the dma-iommu layer.
 	 */
 	if (domain->type == IOMMU_DOMAIN_DMA) {
+		iommu_reconfig_dev_group_dma(dev);
+		/* domain may be stale ... */
+		domain = iommu_get_domain_for_dev(dev);
 		if (iommu_dma_init_domain(domain, dma_base, size, dev))
 			goto out_err;
 		dev->dma_ops = &iommu_dma_ops;
-- 
2.26.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 12/15] iommu: Add iommu_set_dev_dma_opt_size()
  2021-05-10 14:17 ` John Garry
@ 2021-05-10 14:17   ` John Garry
  -1 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm,
	sai.praneeth.prakhya, John Garry

Add a function which allows the max optimised IOMMU DMA size to be set.

When set successfully, return -EPROBE_DEFER to inform the caller that the
device driver needs to be reprobed to take effect.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/iommu.c | 47 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/iommu.h |  7 +++++++
 2 files changed, 54 insertions(+)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index bdb9aa47dfca..263d78e26c48 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -3058,6 +3058,53 @@ u32 iommu_sva_get_pasid(struct iommu_sva *handle)
 }
 EXPORT_SYMBOL_GPL(iommu_sva_get_pasid);
 
+int iommu_set_dev_dma_opt_size(struct device *dev, size_t size)
+{
+	struct iommu_group *group = iommu_group_get(dev);
+	struct group_device *grp_dev;
+	struct device *_dev;
+	int ret, group_count;
+
+	if (!group)
+		return 0;
+
+	mutex_lock(&group->mutex);
+
+	/*
+	 * If already set, then ignore. We may have been set via sysfs, so
+	 * honour that.
+	 */
+	if (group->max_opt_dma_size) {
+		ret = 0;
+		goto out;
+	}
+
+	group_count = iommu_group_device_count(group);
+	if (group_count != 1) {
+		dev_err_ratelimited(dev, "Cannot change DMA opt size: Group has more than one device group_count=%d\n",
+				    group_count);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Since group has only one device */
+	grp_dev = list_first_entry(&group->devices, struct group_device, list);
+	_dev = grp_dev->dev;
+
+	if (_dev != dev) {
+		dev_err_ratelimited(dev, "Cannot set DMA max opt size - device has changed\n");
+		ret = -EBUSY;
+		goto out;
+	}
+
+	group->max_opt_dma_size = size;
+	ret = -EPROBE_DEFER;
+out:
+	mutex_unlock(&group->mutex);
+	iommu_group_put(group);
+	return ret;
+}
+
 /*
  * Changes the default domain of an iommu group that has *only* one device
  *
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 6e187746af0f..36871e8ae636 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -428,6 +428,7 @@ extern void iommu_get_resv_regions(struct device *dev, struct list_head *list);
 extern void iommu_put_resv_regions(struct device *dev, struct list_head *list);
 extern void generic_iommu_put_resv_regions(struct device *dev,
 					   struct list_head *list);
+extern int iommu_set_dev_dma_opt_size(struct device *dev, size_t size);
 extern void iommu_set_default_passthrough(bool cmd_line);
 extern void iommu_set_default_translated(bool cmd_line);
 extern bool iommu_default_passthrough(void);
@@ -740,6 +741,12 @@ static inline int iommu_get_group_resv_regions(struct iommu_group *group,
 	return -ENODEV;
 }
 
+static inline int iommu_set_dev_dma_opt_size(struct device *dev,
+						 size_t size)
+{
+	return -ENODEV;
+}
+
 static inline void iommu_set_default_passthrough(bool cmd_line)
 {
 }
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 12/15] iommu: Add iommu_set_dev_dma_opt_size()
@ 2021-05-10 14:17   ` John Garry
  0 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: linux-scsi, linuxarm, linux-kernel, sai.praneeth.prakhya, iommu

Add a function which allows the max optimised IOMMU DMA size to be set.

When set successfully, return -EPROBE_DEFER to inform the caller that the
device driver needs to be reprobed to take effect.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/iommu.c | 47 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/iommu.h |  7 +++++++
 2 files changed, 54 insertions(+)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index bdb9aa47dfca..263d78e26c48 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -3058,6 +3058,53 @@ u32 iommu_sva_get_pasid(struct iommu_sva *handle)
 }
 EXPORT_SYMBOL_GPL(iommu_sva_get_pasid);
 
+int iommu_set_dev_dma_opt_size(struct device *dev, size_t size)
+{
+	struct iommu_group *group = iommu_group_get(dev);
+	struct group_device *grp_dev;
+	struct device *_dev;
+	int ret, group_count;
+
+	if (!group)
+		return 0;
+
+	mutex_lock(&group->mutex);
+
+	/*
+	 * If already set, then ignore. We may have been set via sysfs, so
+	 * honour that.
+	 */
+	if (group->max_opt_dma_size) {
+		ret = 0;
+		goto out;
+	}
+
+	group_count = iommu_group_device_count(group);
+	if (group_count != 1) {
+		dev_err_ratelimited(dev, "Cannot change DMA opt size: Group has more than one device group_count=%d\n",
+				    group_count);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Since group has only one device */
+	grp_dev = list_first_entry(&group->devices, struct group_device, list);
+	_dev = grp_dev->dev;
+
+	if (_dev != dev) {
+		dev_err_ratelimited(dev, "Cannot set DMA max opt size - device has changed\n");
+		ret = -EBUSY;
+		goto out;
+	}
+
+	group->max_opt_dma_size = size;
+	ret = -EPROBE_DEFER;
+out:
+	mutex_unlock(&group->mutex);
+	iommu_group_put(group);
+	return ret;
+}
+
 /*
  * Changes the default domain of an iommu group that has *only* one device
  *
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 6e187746af0f..36871e8ae636 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -428,6 +428,7 @@ extern void iommu_get_resv_regions(struct device *dev, struct list_head *list);
 extern void iommu_put_resv_regions(struct device *dev, struct list_head *list);
 extern void generic_iommu_put_resv_regions(struct device *dev,
 					   struct list_head *list);
+extern int iommu_set_dev_dma_opt_size(struct device *dev, size_t size);
 extern void iommu_set_default_passthrough(bool cmd_line);
 extern void iommu_set_default_translated(bool cmd_line);
 extern bool iommu_default_passthrough(void);
@@ -740,6 +741,12 @@ static inline int iommu_get_group_resv_regions(struct iommu_group *group,
 	return -ENODEV;
 }
 
+static inline int iommu_set_dev_dma_opt_size(struct device *dev,
+						 size_t size)
+{
+	return -ENODEV;
+}
+
 static inline void iommu_set_default_passthrough(bool cmd_line)
 {
 }
-- 
2.26.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 13/15] dma-mapping: Add dma_set_max_opt_size()
  2021-05-10 14:17 ` John Garry
@ 2021-05-10 14:17   ` John Garry
  -1 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm,
	sai.praneeth.prakhya, John Garry

Add a function to allow the max size which we want to optimise DMA mappings
for.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 include/linux/dma-map-ops.h |  1 +
 include/linux/dma-mapping.h |  8 ++++++++
 kernel/dma/mapping.c        | 11 +++++++++++
 3 files changed, 20 insertions(+)

diff --git a/include/linux/dma-map-ops.h b/include/linux/dma-map-ops.h
index 0d53a96a3d64..7f9857da87d8 100644
--- a/include/linux/dma-map-ops.h
+++ b/include/linux/dma-map-ops.h
@@ -69,6 +69,7 @@ struct dma_map_ops {
 	u64 (*get_required_mask)(struct device *dev);
 	size_t (*max_mapping_size)(struct device *dev);
 	unsigned long (*get_merge_boundary)(struct device *dev);
+	int (*set_max_opt_size)(struct device *dev, size_t size);
 };
 
 #ifdef CONFIG_DMA_OPS
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 183e7103a66d..41681db93580 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -153,6 +153,7 @@ void *dma_vmap_noncontiguous(struct device *dev, size_t size,
 void dma_vunmap_noncontiguous(struct device *dev, void *vaddr);
 int dma_mmap_noncontiguous(struct device *dev, struct vm_area_struct *vma,
 		size_t size, struct sg_table *sgt);
+int dma_set_max_opt_size(struct device *dev, size_t size);
 #else /* CONFIG_HAS_DMA */
 static inline dma_addr_t dma_map_page_attrs(struct device *dev,
 		struct page *page, size_t offset, size_t size,
@@ -266,6 +267,7 @@ static inline unsigned long dma_get_merge_boundary(struct device *dev)
 {
 	return 0;
 }
+
 static inline struct sg_table *dma_alloc_noncontiguous(struct device *dev,
 		size_t size, enum dma_data_direction dir, gfp_t gfp,
 		unsigned long attrs)
@@ -289,6 +291,12 @@ static inline int dma_mmap_noncontiguous(struct device *dev,
 {
 	return -EINVAL;
 }
+
+static inline int dma_set_max_opt_size(struct device *dev, size_t size)
+{
+	return -EINVAL;
+}
+
 #endif /* CONFIG_HAS_DMA */
 
 struct page *dma_alloc_pages(struct device *dev, size_t size,
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index 2b06a809d0b9..1e4820b08f7e 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -736,3 +736,14 @@ unsigned long dma_get_merge_boundary(struct device *dev)
 	return ops->get_merge_boundary(dev);
 }
 EXPORT_SYMBOL_GPL(dma_get_merge_boundary);
+
+int dma_set_max_opt_size(struct device *dev, size_t size)
+{
+	const struct dma_map_ops *ops = get_dma_ops(dev);
+
+	if (!ops || !ops->set_max_opt_size)
+		return 0;
+
+	return ops->set_max_opt_size(dev, size);
+}
+EXPORT_SYMBOL_GPL(dma_set_max_opt_size);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 13/15] dma-mapping: Add dma_set_max_opt_size()
@ 2021-05-10 14:17   ` John Garry
  0 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: linux-scsi, linuxarm, linux-kernel, sai.praneeth.prakhya, iommu

Add a function to allow the max size which we want to optimise DMA mappings
for.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 include/linux/dma-map-ops.h |  1 +
 include/linux/dma-mapping.h |  8 ++++++++
 kernel/dma/mapping.c        | 11 +++++++++++
 3 files changed, 20 insertions(+)

diff --git a/include/linux/dma-map-ops.h b/include/linux/dma-map-ops.h
index 0d53a96a3d64..7f9857da87d8 100644
--- a/include/linux/dma-map-ops.h
+++ b/include/linux/dma-map-ops.h
@@ -69,6 +69,7 @@ struct dma_map_ops {
 	u64 (*get_required_mask)(struct device *dev);
 	size_t (*max_mapping_size)(struct device *dev);
 	unsigned long (*get_merge_boundary)(struct device *dev);
+	int (*set_max_opt_size)(struct device *dev, size_t size);
 };
 
 #ifdef CONFIG_DMA_OPS
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 183e7103a66d..41681db93580 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -153,6 +153,7 @@ void *dma_vmap_noncontiguous(struct device *dev, size_t size,
 void dma_vunmap_noncontiguous(struct device *dev, void *vaddr);
 int dma_mmap_noncontiguous(struct device *dev, struct vm_area_struct *vma,
 		size_t size, struct sg_table *sgt);
+int dma_set_max_opt_size(struct device *dev, size_t size);
 #else /* CONFIG_HAS_DMA */
 static inline dma_addr_t dma_map_page_attrs(struct device *dev,
 		struct page *page, size_t offset, size_t size,
@@ -266,6 +267,7 @@ static inline unsigned long dma_get_merge_boundary(struct device *dev)
 {
 	return 0;
 }
+
 static inline struct sg_table *dma_alloc_noncontiguous(struct device *dev,
 		size_t size, enum dma_data_direction dir, gfp_t gfp,
 		unsigned long attrs)
@@ -289,6 +291,12 @@ static inline int dma_mmap_noncontiguous(struct device *dev,
 {
 	return -EINVAL;
 }
+
+static inline int dma_set_max_opt_size(struct device *dev, size_t size)
+{
+	return -EINVAL;
+}
+
 #endif /* CONFIG_HAS_DMA */
 
 struct page *dma_alloc_pages(struct device *dev, size_t size,
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index 2b06a809d0b9..1e4820b08f7e 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -736,3 +736,14 @@ unsigned long dma_get_merge_boundary(struct device *dev)
 	return ops->get_merge_boundary(dev);
 }
 EXPORT_SYMBOL_GPL(dma_get_merge_boundary);
+
+int dma_set_max_opt_size(struct device *dev, size_t size)
+{
+	const struct dma_map_ops *ops = get_dma_ops(dev);
+
+	if (!ops || !ops->set_max_opt_size)
+		return 0;
+
+	return ops->set_max_opt_size(dev, size);
+}
+EXPORT_SYMBOL_GPL(dma_set_max_opt_size);
-- 
2.26.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 14/15] dma-iommu: Add iommu_dma_set_opt_size()
  2021-05-10 14:17 ` John Garry
@ 2021-05-10 14:17   ` John Garry
  -1 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm,
	sai.praneeth.prakhya, John Garry

Add iommu_dma_set_opt_size(), which is a frontend for
iommu_set_dev_dma_opt_size().

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/dma-iommu.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 1d58c7a2d85d..fd62afe7c7d0 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -490,6 +490,11 @@ static dma_addr_t iommu_dma_alloc_iova(struct iommu_domain *domain,
 	return (dma_addr_t)iova << shift;
 }
 
+static int iommu_dma_set_opt_size(struct device *dev, size_t size)
+{
+	return iommu_set_dev_dma_opt_size(dev, size);
+}
+
 static void iommu_dma_free_iova(struct iommu_dma_cookie *cookie,
 		dma_addr_t iova, size_t size, struct page *freelist)
 {
@@ -1340,6 +1345,7 @@ static const struct dma_map_ops iommu_dma_ops = {
 	.map_resource		= iommu_dma_map_resource,
 	.unmap_resource		= iommu_dma_unmap_resource,
 	.get_merge_boundary	= iommu_dma_get_merge_boundary,
+	.set_max_opt_size	= iommu_dma_set_opt_size,
 };
 
 /*
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 14/15] dma-iommu: Add iommu_dma_set_opt_size()
@ 2021-05-10 14:17   ` John Garry
  0 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: linux-scsi, linuxarm, linux-kernel, sai.praneeth.prakhya, iommu

Add iommu_dma_set_opt_size(), which is a frontend for
iommu_set_dev_dma_opt_size().

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/iommu/dma-iommu.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 1d58c7a2d85d..fd62afe7c7d0 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -490,6 +490,11 @@ static dma_addr_t iommu_dma_alloc_iova(struct iommu_domain *domain,
 	return (dma_addr_t)iova << shift;
 }
 
+static int iommu_dma_set_opt_size(struct device *dev, size_t size)
+{
+	return iommu_set_dev_dma_opt_size(dev, size);
+}
+
 static void iommu_dma_free_iova(struct iommu_dma_cookie *cookie,
 		dma_addr_t iova, size_t size, struct page *freelist)
 {
@@ -1340,6 +1345,7 @@ static const struct dma_map_ops iommu_dma_ops = {
 	.map_resource		= iommu_dma_map_resource,
 	.unmap_resource		= iommu_dma_unmap_resource,
 	.get_merge_boundary	= iommu_dma_get_merge_boundary,
+	.set_max_opt_size	= iommu_dma_set_opt_size,
 };
 
 /*
-- 
2.26.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 15/15] scsi: hisi_sas: Set max optimal DMA size for v3 hw
  2021-05-10 14:17 ` John Garry
@ 2021-05-10 14:17   ` John Garry
  -1 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm,
	sai.praneeth.prakhya, John Garry

For IOMMU strict mode, gives a big performance boost in some scenarios.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 499c770d405c..365fc9de4be2 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -4675,6 +4675,11 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	struct sas_ha_struct *sha;
 	int rc, phy_nr, port_nr, i;
 
+	rc = dma_set_max_opt_size(dev, PAGE_SIZE * HISI_SAS_SGE_PAGE_CNT);
+	/* We can live with other errors */
+	if (rc == -EPROBE_DEFER)
+		return rc;
+
 	rc = pci_enable_device(pdev);
 	if (rc)
 		goto err_out;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 15/15] scsi: hisi_sas: Set max optimal DMA size for v3 hw
@ 2021-05-10 14:17   ` John Garry
  0 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-10 14:17 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: linux-scsi, linuxarm, linux-kernel, sai.praneeth.prakhya, iommu

For IOMMU strict mode, gives a big performance boost in some scenarios.

Signed-off-by: John Garry <john.garry@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 499c770d405c..365fc9de4be2 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -4675,6 +4675,11 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	struct sas_ha_struct *sha;
 	int rc, phy_nr, port_nr, i;
 
+	rc = dma_set_max_opt_size(dev, PAGE_SIZE * HISI_SAS_SGE_PAGE_CNT);
+	/* We can live with other errors */
+	if (rc == -EPROBE_DEFER)
+		return rc;
+
 	rc = pci_enable_device(pdev);
 	if (rc)
 		goto err_out;
-- 
2.26.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 09/15] iova: Add init_iova_domain_ext()
  2021-05-10 14:17   ` John Garry
  (?)
@ 2021-05-10 17:50     ` kernel test robot
  -1 siblings, 0 replies; 40+ messages in thread
From: kernel test robot @ 2021-05-10 17:50 UTC (permalink / raw)
  To: John Garry, joro, will, robin.murphy, hch, m.szyprowski
  Cc: kbuild-all, iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm

[-- Attachment #1: Type: text/plain, Size: 3323 bytes --]

Hi John,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.13-rc1 next-20210510]
[cannot apply to iommu/next mkp-scsi/for-next scsi/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/John-Garry/dma-mapping-iommu-Allow-IOMMU-IOVA-rcache-range-to-be-configured/20210510-222805
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 6efb943b8616ec53a5e444193dccf1af9ad627b5
config: i386-randconfig-s002-20210510 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.3-341-g8af24329-dirty
        # https://github.com/0day-ci/linux/commit/d9a8e3a4ac0070cd3094af3b41e9c6277faf3ea6
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review John-Garry/dma-mapping-iommu-Allow-IOMMU-IOVA-rcache-range-to-be-configured/20210510-222805
        git checkout d9a8e3a4ac0070cd3094af3b41e9c6277faf3ea6
        # save the attached .config to linux build tree
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/iommu/iova.c:50:1: warning: no previous prototype for '__init_iova_domain' [-Wmissing-prototypes]
      50 | __init_iova_domain(struct iova_domain *iovad, unsigned long granule,
         | ^~~~~~~~~~~~~~~~~~


sparse warnings: (new ones prefixed by >>)
>> drivers/iommu/iova.c:50:1: sparse: sparse: symbol '__init_iova_domain' was not declared. Should it be static?

Please review and possibly fold the followup patch.

vim +/__init_iova_domain +50 drivers/iommu/iova.c

    48	
    49	void
  > 50	__init_iova_domain(struct iova_domain *iovad, unsigned long granule,
    51		unsigned long start_pfn, unsigned long iova_len)
    52	{
    53		/*
    54		 * IOVA granularity will normally be equal to the smallest
    55		 * supported IOMMU page size; both *must* be capable of
    56		 * representing individual CPU pages exactly.
    57		 */
    58		BUG_ON((granule > PAGE_SIZE) || !is_power_of_2(granule));
    59	
    60		spin_lock_init(&iovad->iova_rbtree_lock);
    61		iovad->rbroot = RB_ROOT;
    62		iovad->cached_node = &iovad->anchor.node;
    63		iovad->cached32_node = &iovad->anchor.node;
    64		iovad->granule = granule;
    65		iovad->start_pfn = start_pfn;
    66		iovad->dma_32bit_pfn = 1UL << (32 - iova_shift(iovad));
    67		iovad->max32_alloc_size = iovad->dma_32bit_pfn;
    68		iovad->flush_cb = NULL;
    69		iovad->fq = NULL;
    70		iovad->anchor.pfn_lo = iovad->anchor.pfn_hi = IOVA_ANCHOR;
    71		rb_link_node(&iovad->anchor.node, NULL, &iovad->rbroot.rb_node);
    72		rb_insert_color(&iovad->anchor.node, &iovad->rbroot);
    73		cpuhp_state_add_instance_nocalls(CPUHP_IOMMU_IOVA_DEAD, &iovad->cpuhp_dead);
    74		init_iova_rcaches(iovad, iova_len);
    75	}
    76	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 34105 bytes --]

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 09/15] iova: Add init_iova_domain_ext()
@ 2021-05-10 17:50     ` kernel test robot
  0 siblings, 0 replies; 40+ messages in thread
From: kernel test robot @ 2021-05-10 17:50 UTC (permalink / raw)
  To: John Garry, joro, will, robin.murphy, hch, m.szyprowski
  Cc: kbuild-all, linux-scsi, linuxarm, linux-kernel, iommu

[-- Attachment #1: Type: text/plain, Size: 3323 bytes --]

Hi John,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.13-rc1 next-20210510]
[cannot apply to iommu/next mkp-scsi/for-next scsi/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/John-Garry/dma-mapping-iommu-Allow-IOMMU-IOVA-rcache-range-to-be-configured/20210510-222805
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 6efb943b8616ec53a5e444193dccf1af9ad627b5
config: i386-randconfig-s002-20210510 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.3-341-g8af24329-dirty
        # https://github.com/0day-ci/linux/commit/d9a8e3a4ac0070cd3094af3b41e9c6277faf3ea6
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review John-Garry/dma-mapping-iommu-Allow-IOMMU-IOVA-rcache-range-to-be-configured/20210510-222805
        git checkout d9a8e3a4ac0070cd3094af3b41e9c6277faf3ea6
        # save the attached .config to linux build tree
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/iommu/iova.c:50:1: warning: no previous prototype for '__init_iova_domain' [-Wmissing-prototypes]
      50 | __init_iova_domain(struct iova_domain *iovad, unsigned long granule,
         | ^~~~~~~~~~~~~~~~~~


sparse warnings: (new ones prefixed by >>)
>> drivers/iommu/iova.c:50:1: sparse: sparse: symbol '__init_iova_domain' was not declared. Should it be static?

Please review and possibly fold the followup patch.

vim +/__init_iova_domain +50 drivers/iommu/iova.c

    48	
    49	void
  > 50	__init_iova_domain(struct iova_domain *iovad, unsigned long granule,
    51		unsigned long start_pfn, unsigned long iova_len)
    52	{
    53		/*
    54		 * IOVA granularity will normally be equal to the smallest
    55		 * supported IOMMU page size; both *must* be capable of
    56		 * representing individual CPU pages exactly.
    57		 */
    58		BUG_ON((granule > PAGE_SIZE) || !is_power_of_2(granule));
    59	
    60		spin_lock_init(&iovad->iova_rbtree_lock);
    61		iovad->rbroot = RB_ROOT;
    62		iovad->cached_node = &iovad->anchor.node;
    63		iovad->cached32_node = &iovad->anchor.node;
    64		iovad->granule = granule;
    65		iovad->start_pfn = start_pfn;
    66		iovad->dma_32bit_pfn = 1UL << (32 - iova_shift(iovad));
    67		iovad->max32_alloc_size = iovad->dma_32bit_pfn;
    68		iovad->flush_cb = NULL;
    69		iovad->fq = NULL;
    70		iovad->anchor.pfn_lo = iovad->anchor.pfn_hi = IOVA_ANCHOR;
    71		rb_link_node(&iovad->anchor.node, NULL, &iovad->rbroot.rb_node);
    72		rb_insert_color(&iovad->anchor.node, &iovad->rbroot);
    73		cpuhp_state_add_instance_nocalls(CPUHP_IOMMU_IOVA_DEAD, &iovad->cpuhp_dead);
    74		init_iova_rcaches(iovad, iova_len);
    75	}
    76	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 34105 bytes --]

[-- Attachment #3: Type: text/plain, Size: 156 bytes --]

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 09/15] iova: Add init_iova_domain_ext()
@ 2021-05-10 17:50     ` kernel test robot
  0 siblings, 0 replies; 40+ messages in thread
From: kernel test robot @ 2021-05-10 17:50 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 3400 bytes --]

Hi John,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.13-rc1 next-20210510]
[cannot apply to iommu/next mkp-scsi/for-next scsi/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/John-Garry/dma-mapping-iommu-Allow-IOMMU-IOVA-rcache-range-to-be-configured/20210510-222805
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 6efb943b8616ec53a5e444193dccf1af9ad627b5
config: i386-randconfig-s002-20210510 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.3-341-g8af24329-dirty
        # https://github.com/0day-ci/linux/commit/d9a8e3a4ac0070cd3094af3b41e9c6277faf3ea6
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review John-Garry/dma-mapping-iommu-Allow-IOMMU-IOVA-rcache-range-to-be-configured/20210510-222805
        git checkout d9a8e3a4ac0070cd3094af3b41e9c6277faf3ea6
        # save the attached .config to linux build tree
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/iommu/iova.c:50:1: warning: no previous prototype for '__init_iova_domain' [-Wmissing-prototypes]
      50 | __init_iova_domain(struct iova_domain *iovad, unsigned long granule,
         | ^~~~~~~~~~~~~~~~~~


sparse warnings: (new ones prefixed by >>)
>> drivers/iommu/iova.c:50:1: sparse: sparse: symbol '__init_iova_domain' was not declared. Should it be static?

Please review and possibly fold the followup patch.

vim +/__init_iova_domain +50 drivers/iommu/iova.c

    48	
    49	void
  > 50	__init_iova_domain(struct iova_domain *iovad, unsigned long granule,
    51		unsigned long start_pfn, unsigned long iova_len)
    52	{
    53		/*
    54		 * IOVA granularity will normally be equal to the smallest
    55		 * supported IOMMU page size; both *must* be capable of
    56		 * representing individual CPU pages exactly.
    57		 */
    58		BUG_ON((granule > PAGE_SIZE) || !is_power_of_2(granule));
    59	
    60		spin_lock_init(&iovad->iova_rbtree_lock);
    61		iovad->rbroot = RB_ROOT;
    62		iovad->cached_node = &iovad->anchor.node;
    63		iovad->cached32_node = &iovad->anchor.node;
    64		iovad->granule = granule;
    65		iovad->start_pfn = start_pfn;
    66		iovad->dma_32bit_pfn = 1UL << (32 - iova_shift(iovad));
    67		iovad->max32_alloc_size = iovad->dma_32bit_pfn;
    68		iovad->flush_cb = NULL;
    69		iovad->fq = NULL;
    70		iovad->anchor.pfn_lo = iovad->anchor.pfn_hi = IOVA_ANCHOR;
    71		rb_link_node(&iovad->anchor.node, NULL, &iovad->rbroot.rb_node);
    72		rb_insert_color(&iovad->anchor.node, &iovad->rbroot);
    73		cpuhp_state_add_instance_nocalls(CPUHP_IOMMU_IOVA_DEAD, &iovad->cpuhp_dead);
    74		init_iova_rcaches(iovad, iova_len);
    75	}
    76	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 34105 bytes --]

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [RFC PATCH] iova: __init_iova_domain can be static
  2021-05-10 14:17   ` John Garry
  (?)
@ 2021-05-10 17:50     ` kernel test robot
  -1 siblings, 0 replies; 40+ messages in thread
From: kernel test robot @ 2021-05-10 17:50 UTC (permalink / raw)
  To: John Garry, joro, will, robin.murphy, hch, m.szyprowski
  Cc: kbuild-all, iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm

drivers/iommu/iova.c:50:1: warning: symbol '__init_iova_domain' was not declared. Should it be static?

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: kernel test robot <lkp@intel.com>
---
 iova.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 273a689006c36..ae4901073a98a 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -46,7 +46,7 @@ static struct iova *to_iova(struct rb_node *node)
 	return rb_entry(node, struct iova, node);
 }
 
-void
+static void
 __init_iova_domain(struct iova_domain *iovad, unsigned long granule,
 	unsigned long start_pfn, unsigned long iova_len)
 {

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC PATCH] iova: __init_iova_domain can be static
@ 2021-05-10 17:50     ` kernel test robot
  0 siblings, 0 replies; 40+ messages in thread
From: kernel test robot @ 2021-05-10 17:50 UTC (permalink / raw)
  To: John Garry, joro, will, robin.murphy, hch, m.szyprowski
  Cc: kbuild-all, linux-scsi, linuxarm, linux-kernel, iommu

drivers/iommu/iova.c:50:1: warning: symbol '__init_iova_domain' was not declared. Should it be static?

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: kernel test robot <lkp@intel.com>
---
 iova.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 273a689006c36..ae4901073a98a 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -46,7 +46,7 @@ static struct iova *to_iova(struct rb_node *node)
 	return rb_entry(node, struct iova, node);
 }
 
-void
+static void
 __init_iova_domain(struct iova_domain *iovad, unsigned long granule,
 	unsigned long start_pfn, unsigned long iova_len)
 {
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC PATCH] iova: __init_iova_domain can be static
@ 2021-05-10 17:50     ` kernel test robot
  0 siblings, 0 replies; 40+ messages in thread
From: kernel test robot @ 2021-05-10 17:50 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 702 bytes --]

drivers/iommu/iova.c:50:1: warning: symbol '__init_iova_domain' was not declared. Should it be static?

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: kernel test robot <lkp@intel.com>
---
 iova.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 273a689006c36..ae4901073a98a 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -46,7 +46,7 @@ static struct iova *to_iova(struct rb_node *node)
 	return rb_entry(node, struct iova, node);
 }
 
-void
+static void
 __init_iova_domain(struct iova_domain *iovad, unsigned long granule,
 	unsigned long start_pfn, unsigned long iova_len)
 {

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 00/15] dma mapping/iommu: Allow IOMMU IOVA rcache range to be configured
  2021-05-10 14:17 ` John Garry
@ 2021-05-20  8:28   ` John Garry
  -1 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-20  8:28 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: iommu, baolu.lu, linux-kernel, linux-scsi, linuxarm

On 10/05/2021 15:17, John Garry wrote:

Hi Robin, guys,

A friendly reminder on this one...

Thanks

> For streaming DMA mappings involving an IOMMU and whose IOVA len regularly
> exceeds the IOVA rcache upper limit (meaning that they are not cached),
> performance can be reduced.
> 
> This is much more pronounced from commit 4e89dce72521 ("iommu/iova: Retry
> from last rb tree node if iova search fails"), as discussed at [0].
> 
> IOVAs which cannot be cached are highly involved in the IOVA aging issue,
> as discussed at [1].
> 
> This series allows the IOVA rcache range be configured, so that we may
> cache all IOVAs per domain, thus improving performance.
> 
> A new IOMMU group sysfs file is added - max_opt_dma_size - which is used
> indirectly to configure the IOVA rcache range:
> /sys/kernel/iommu_groups/X/max_opt_dma_size
> 
> This file is updated same as how the IOMMU group default domain type is
> updated, i.e. must unbind the only device in the group first. However, the
> IOMMU default domain is reallocated in the device driver reprobe, and not
> immediately.
> 
> In addition, we keep (from v1 series) the DMA mapping API to allow DMA max
> optimised size be set from a LLDD. How it works is a lot different. When
> the LLDD calls this during probe, once the value is successfully recorded, we
> return -EDEFER_PROBE. In the reprobe, the IOMM group default domain is
> reallocated, and the new IOVA domain rcache upper limit is set according
> to that DMA max optimised size. As such, we don't operate on a live IOMMU
> domain.
> 
> Note that the DMA mapping API frontend is not strictly required, but saves
> the LLDD calling IOMMU APIs directly, that being not preferred.
> 
> Some figures for storage scenario:
> v5.13-rc1 baseline:			1200K IOPS
> With series:				1800K IOPS
> 
> All above are for IOMMU strict mode. Non-strict mode gives ~1800K IOPS in
> all scenarios.
> 
> Patch breakdown:
> 1-11: Add support for setting DMA max optimised size via sysfs
> 12-15: Add support for setting DMA max optimised size from LLDD
> 
> [0] https://lore.kernel.org/linux-iommu/20210129092120.1482-1-thunder.leizhen@huawei.com/
> [1] https://lore.kernel.org/linux-iommu/1607538189-237944-1-git-send-email-john.garry@huawei.com/
> 
> Differences to v1:
> - Many
> - Change method to not operate on a 'live' IOMMU domain:
> 	- rather, force device driver to be re-probed once
> 	  dma_max_opt_size is set, and reconfig a new IOMMU group then
> - Add iommu sysfs max_dma_opt_size file, and allow updating same as how
>    group type is changed
> 
> John Garry (15):
>    iommu: Reactor iommu_group_store_type()
>    iova: Allow rcache range upper limit to be flexible
>    iommu: Allow max opt DMA len be set for a group via sysfs
>    iommu: Add iommu_group_get_max_opt_dma_size()
>    iova: Add iova_domain_len_is_cached()
>    iommu: Allow iommu_change_dev_def_domain() realloc default domain for
>      same type
>    iommu: Add iommu_realloc_dev_group()
>    dma-iommu: Add iommu_reconfig_dev_group_dma()
>    iova: Add init_iova_domain_ext()
>    dma-iommu: Use init_iova_domain_ext() for IOVA domain init
>    dma-iommu: Reconfig group domain
>    iommu: Add iommu_set_dev_dma_opt_size()
>    dma-mapping: Add dma_set_max_opt_size()
>    dma-iommu: Add iommu_dma_set_opt_size()
>    scsi: hisi_sas: Set max optimal DMA size for v3 hw
> 
>   drivers/iommu/dma-iommu.c              |  51 +++++-
>   drivers/iommu/iommu.c                  | 231 +++++++++++++++++++------
>   drivers/iommu/iova.c                   |  61 +++++--
>   drivers/scsi/hisi_sas/hisi_sas_v3_hw.c |   5 +
>   include/linux/dma-iommu.h              |   4 +
>   include/linux/dma-map-ops.h            |   1 +
>   include/linux/dma-mapping.h            |   8 +
>   include/linux/iommu.h                  |  19 ++
>   include/linux/iova.h                   |  21 ++-
>   kernel/dma/mapping.c                   |  11 ++
>   10 files changed, 344 insertions(+), 68 deletions(-)
> 


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 00/15] dma mapping/iommu: Allow IOMMU IOVA rcache range to be configured
@ 2021-05-20  8:28   ` John Garry
  0 siblings, 0 replies; 40+ messages in thread
From: John Garry @ 2021-05-20  8:28 UTC (permalink / raw)
  To: joro, will, robin.murphy, hch, m.szyprowski
  Cc: iommu, linuxarm, linux-kernel, linux-scsi

On 10/05/2021 15:17, John Garry wrote:

Hi Robin, guys,

A friendly reminder on this one...

Thanks

> For streaming DMA mappings involving an IOMMU and whose IOVA len regularly
> exceeds the IOVA rcache upper limit (meaning that they are not cached),
> performance can be reduced.
> 
> This is much more pronounced from commit 4e89dce72521 ("iommu/iova: Retry
> from last rb tree node if iova search fails"), as discussed at [0].
> 
> IOVAs which cannot be cached are highly involved in the IOVA aging issue,
> as discussed at [1].
> 
> This series allows the IOVA rcache range be configured, so that we may
> cache all IOVAs per domain, thus improving performance.
> 
> A new IOMMU group sysfs file is added - max_opt_dma_size - which is used
> indirectly to configure the IOVA rcache range:
> /sys/kernel/iommu_groups/X/max_opt_dma_size
> 
> This file is updated same as how the IOMMU group default domain type is
> updated, i.e. must unbind the only device in the group first. However, the
> IOMMU default domain is reallocated in the device driver reprobe, and not
> immediately.
> 
> In addition, we keep (from v1 series) the DMA mapping API to allow DMA max
> optimised size be set from a LLDD. How it works is a lot different. When
> the LLDD calls this during probe, once the value is successfully recorded, we
> return -EDEFER_PROBE. In the reprobe, the IOMM group default domain is
> reallocated, and the new IOVA domain rcache upper limit is set according
> to that DMA max optimised size. As such, we don't operate on a live IOMMU
> domain.
> 
> Note that the DMA mapping API frontend is not strictly required, but saves
> the LLDD calling IOMMU APIs directly, that being not preferred.
> 
> Some figures for storage scenario:
> v5.13-rc1 baseline:			1200K IOPS
> With series:				1800K IOPS
> 
> All above are for IOMMU strict mode. Non-strict mode gives ~1800K IOPS in
> all scenarios.
> 
> Patch breakdown:
> 1-11: Add support for setting DMA max optimised size via sysfs
> 12-15: Add support for setting DMA max optimised size from LLDD
> 
> [0] https://lore.kernel.org/linux-iommu/20210129092120.1482-1-thunder.leizhen@huawei.com/
> [1] https://lore.kernel.org/linux-iommu/1607538189-237944-1-git-send-email-john.garry@huawei.com/
> 
> Differences to v1:
> - Many
> - Change method to not operate on a 'live' IOMMU domain:
> 	- rather, force device driver to be re-probed once
> 	  dma_max_opt_size is set, and reconfig a new IOMMU group then
> - Add iommu sysfs max_dma_opt_size file, and allow updating same as how
>    group type is changed
> 
> John Garry (15):
>    iommu: Reactor iommu_group_store_type()
>    iova: Allow rcache range upper limit to be flexible
>    iommu: Allow max opt DMA len be set for a group via sysfs
>    iommu: Add iommu_group_get_max_opt_dma_size()
>    iova: Add iova_domain_len_is_cached()
>    iommu: Allow iommu_change_dev_def_domain() realloc default domain for
>      same type
>    iommu: Add iommu_realloc_dev_group()
>    dma-iommu: Add iommu_reconfig_dev_group_dma()
>    iova: Add init_iova_domain_ext()
>    dma-iommu: Use init_iova_domain_ext() for IOVA domain init
>    dma-iommu: Reconfig group domain
>    iommu: Add iommu_set_dev_dma_opt_size()
>    dma-mapping: Add dma_set_max_opt_size()
>    dma-iommu: Add iommu_dma_set_opt_size()
>    scsi: hisi_sas: Set max optimal DMA size for v3 hw
> 
>   drivers/iommu/dma-iommu.c              |  51 +++++-
>   drivers/iommu/iommu.c                  | 231 +++++++++++++++++++------
>   drivers/iommu/iova.c                   |  61 +++++--
>   drivers/scsi/hisi_sas/hisi_sas_v3_hw.c |   5 +
>   include/linux/dma-iommu.h              |   4 +
>   include/linux/dma-map-ops.h            |   1 +
>   include/linux/dma-mapping.h            |   8 +
>   include/linux/iommu.h                  |  19 ++
>   include/linux/iova.h                   |  21 ++-
>   kernel/dma/mapping.c                   |  11 ++
>   10 files changed, 344 insertions(+), 68 deletions(-)
> 

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2021-05-20  8:29 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-10 14:17 [PATCH v2 00/15] dma mapping/iommu: Allow IOMMU IOVA rcache range to be configured John Garry
2021-05-10 14:17 ` John Garry
2021-05-10 14:17 ` [PATCH v2 01/15] iommu: Reactor iommu_group_store_type() John Garry
2021-05-10 14:17   ` John Garry
2021-05-10 14:17 ` [PATCH v2 02/15] iova: Allow rcache range upper limit to be flexible John Garry
2021-05-10 14:17   ` John Garry
2021-05-10 14:17 ` [PATCH v2 03/15] iommu: Allow max opt DMA len be set for a group via sysfs John Garry
2021-05-10 14:17   ` John Garry
2021-05-10 14:17 ` [PATCH v2 04/15] iommu: Add iommu_group_get_max_opt_dma_size() John Garry
2021-05-10 14:17   ` John Garry
2021-05-10 14:17 ` [PATCH v2 05/15] iova: Add iova_domain_len_is_cached() John Garry
2021-05-10 14:17   ` John Garry
2021-05-10 14:17 ` [PATCH v2 06/15] iommu: Allow iommu_change_dev_def_domain() realloc default domain for same type John Garry
2021-05-10 14:17   ` John Garry
2021-05-10 14:17 ` [PATCH v2 07/15] iommu: Add iommu_realloc_dev_group() John Garry
2021-05-10 14:17   ` John Garry
2021-05-10 14:17 ` [PATCH v2 08/15] dma-iommu: Add iommu_reconfig_dev_group_dma() John Garry
2021-05-10 14:17   ` John Garry
2021-05-10 14:17 ` [PATCH v2 09/15] iova: Add init_iova_domain_ext() John Garry
2021-05-10 14:17   ` John Garry
2021-05-10 17:50   ` kernel test robot
2021-05-10 17:50     ` kernel test robot
2021-05-10 17:50     ` kernel test robot
2021-05-10 17:50   ` [RFC PATCH] iova: __init_iova_domain can be static kernel test robot
2021-05-10 17:50     ` kernel test robot
2021-05-10 17:50     ` kernel test robot
2021-05-10 14:17 ` [PATCH v2 10/15] dma-iommu: Use init_iova_domain_ext() for IOVA domain init John Garry
2021-05-10 14:17   ` John Garry
2021-05-10 14:17 ` [PATCH v2 11/15] dma-iommu: Reconfig group domain John Garry
2021-05-10 14:17   ` John Garry
2021-05-10 14:17 ` [PATCH v2 12/15] iommu: Add iommu_set_dev_dma_opt_size() John Garry
2021-05-10 14:17   ` John Garry
2021-05-10 14:17 ` [PATCH v2 13/15] dma-mapping: Add dma_set_max_opt_size() John Garry
2021-05-10 14:17   ` John Garry
2021-05-10 14:17 ` [PATCH v2 14/15] dma-iommu: Add iommu_dma_set_opt_size() John Garry
2021-05-10 14:17   ` John Garry
2021-05-10 14:17 ` [PATCH v2 15/15] scsi: hisi_sas: Set max optimal DMA size for v3 hw John Garry
2021-05-10 14:17   ` John Garry
2021-05-20  8:28 ` [PATCH v2 00/15] dma mapping/iommu: Allow IOMMU IOVA rcache range to be configured John Garry
2021-05-20  8:28   ` John Garry

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.