All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/11] iommu: refactor flush queues into iommu-dma
@ 2021-12-10 17:54 ` Robin Murphy
  0 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel,
	john.garry, linux-mm

v1: https://lore.kernel.org/linux-iommu/cover.1637671820.git.robin.murphy@arm.com/

Hi all,

Just a minor update, pulling in Xiongfeng's fix as a basis for the
subsequent patches moving that code around, and the Tegra DRM patch
previously posted separately. Plus commenting the subtlety in the AMD
pagetable code so it's hopefully easier to remember in future.

Given that no major issues have surfaced so far, hopefully this is on
track for 5.17 in parallel with the slab rework.

Thanks,
Robin.


Matthew Wilcox (Oracle) (2):
  iommu/amd: Use put_pages_list
  iommu/vt-d: Use put_pages_list

Robin Murphy (8):
  gpu: host1x: Add missing DMA API include
  drm/tegra: vic: Fix DMA API misuse
  iommu/iova: Squash entry_dtor abstraction
  iommu/iova: Squash flush_cb abstraction
  iommu/amd: Simplify pagetable freeing
  iommu/iova: Consolidate flush queue code
  iommu/iova: Move flush queue code to iommu-dma
  iommu: Move flush queue data into iommu_dma_cookie

Xiongfeng Wang (1):
  iommu/iova: Fix race between FQ timeout and teardown

 drivers/gpu/drm/tegra/vic.c    |   7 +-
 drivers/gpu/host1x/bus.c       |   1 +
 drivers/iommu/amd/io_pgtable.c | 120 ++++++---------
 drivers/iommu/dma-iommu.c      | 268 +++++++++++++++++++++++++++------
 drivers/iommu/intel/iommu.c    |  89 ++++-------
 drivers/iommu/iova.c           | 200 ------------------------
 include/linux/iommu.h          |   3 +-
 include/linux/iova.h           |  69 +--------
 8 files changed, 303 insertions(+), 454 deletions(-)

-- 
2.28.0.dirty


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

* [PATCH v2 00/11] iommu: refactor flush queues into iommu-dma
@ 2021-12-10 17:54 ` Robin Murphy
  0 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will; +Cc: linux-kernel, willy, linux-mm, iommu

v1: https://lore.kernel.org/linux-iommu/cover.1637671820.git.robin.murphy@arm.com/

Hi all,

Just a minor update, pulling in Xiongfeng's fix as a basis for the
subsequent patches moving that code around, and the Tegra DRM patch
previously posted separately. Plus commenting the subtlety in the AMD
pagetable code so it's hopefully easier to remember in future.

Given that no major issues have surfaced so far, hopefully this is on
track for 5.17 in parallel with the slab rework.

Thanks,
Robin.


Matthew Wilcox (Oracle) (2):
  iommu/amd: Use put_pages_list
  iommu/vt-d: Use put_pages_list

Robin Murphy (8):
  gpu: host1x: Add missing DMA API include
  drm/tegra: vic: Fix DMA API misuse
  iommu/iova: Squash entry_dtor abstraction
  iommu/iova: Squash flush_cb abstraction
  iommu/amd: Simplify pagetable freeing
  iommu/iova: Consolidate flush queue code
  iommu/iova: Move flush queue code to iommu-dma
  iommu: Move flush queue data into iommu_dma_cookie

Xiongfeng Wang (1):
  iommu/iova: Fix race between FQ timeout and teardown

 drivers/gpu/drm/tegra/vic.c    |   7 +-
 drivers/gpu/host1x/bus.c       |   1 +
 drivers/iommu/amd/io_pgtable.c | 120 ++++++---------
 drivers/iommu/dma-iommu.c      | 268 +++++++++++++++++++++++++++------
 drivers/iommu/intel/iommu.c    |  89 ++++-------
 drivers/iommu/iova.c           | 200 ------------------------
 include/linux/iommu.h          |   3 +-
 include/linux/iova.h           |  69 +--------
 8 files changed, 303 insertions(+), 454 deletions(-)

-- 
2.28.0.dirty

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

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

* [PATCH v2 01/11] iommu/iova: Fix race between FQ timeout and teardown
  2021-12-10 17:54 ` Robin Murphy
@ 2021-12-10 17:54   ` Robin Murphy
  -1 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel,
	john.garry, linux-mm, Xiongfeng Wang

From: Xiongfeng Wang <wangxiongfeng2@huawei.com>

It turns out to be possible for hotplugging out a device to reach the
stage of tearing down the device's group and default domain before the
domain's flush queue has drained naturally. At this point, it is then
possible for the timeout to expire just *before* the del_timer() call
from free_iova_flush_queue(), such that we then proceed to free the FQ
resources while fq_flush_timeout() is still accessing them on another
CPU. Crashes due to this have been observed in the wild while removing
NVMe devices.

Close the race window by using del_timer_sync() to safely wait for any
active timeout handler to finish before we start to free things. We
already avoid any locking in free_iova_flush_queue() since the FQ is
supposed to be inactive anyway, so the potential deadlock scenario does
not apply.

Fixes: 9a005a800ae8 ("iommu/iova: Add flush timer")
Signed-off-by: Xiongfeng Wang <wangxiongfeng2@huawei.com>
[ rm: rewrite commit message ]
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: New to this series, picked up from:

https://lore.kernel.org/linux-iommu/1564219269-14346-1-git-send-email-wangxiongfeng2@huawei.com/

 drivers/iommu/iova.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 9e8bc802ac05..920fcc27c9a1 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -83,8 +83,7 @@ static void free_iova_flush_queue(struct iova_domain *iovad)
 	if (!has_iova_flush_queue(iovad))
 		return;
 
-	if (timer_pending(&iovad->fq_timer))
-		del_timer(&iovad->fq_timer);
+	del_timer_sync(&iovad->fq_timer);
 
 	fq_destroy_all_entries(iovad);
 
-- 
2.28.0.dirty


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

* [PATCH v2 01/11] iommu/iova: Fix race between FQ timeout and teardown
@ 2021-12-10 17:54   ` Robin Murphy
  0 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will; +Cc: linux-kernel, willy, linux-mm, iommu, Xiongfeng Wang

From: Xiongfeng Wang <wangxiongfeng2@huawei.com>

It turns out to be possible for hotplugging out a device to reach the
stage of tearing down the device's group and default domain before the
domain's flush queue has drained naturally. At this point, it is then
possible for the timeout to expire just *before* the del_timer() call
from free_iova_flush_queue(), such that we then proceed to free the FQ
resources while fq_flush_timeout() is still accessing them on another
CPU. Crashes due to this have been observed in the wild while removing
NVMe devices.

Close the race window by using del_timer_sync() to safely wait for any
active timeout handler to finish before we start to free things. We
already avoid any locking in free_iova_flush_queue() since the FQ is
supposed to be inactive anyway, so the potential deadlock scenario does
not apply.

Fixes: 9a005a800ae8 ("iommu/iova: Add flush timer")
Signed-off-by: Xiongfeng Wang <wangxiongfeng2@huawei.com>
[ rm: rewrite commit message ]
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: New to this series, picked up from:

https://lore.kernel.org/linux-iommu/1564219269-14346-1-git-send-email-wangxiongfeng2@huawei.com/

 drivers/iommu/iova.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 9e8bc802ac05..920fcc27c9a1 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -83,8 +83,7 @@ static void free_iova_flush_queue(struct iova_domain *iovad)
 	if (!has_iova_flush_queue(iovad))
 		return;
 
-	if (timer_pending(&iovad->fq_timer))
-		del_timer(&iovad->fq_timer);
+	del_timer_sync(&iovad->fq_timer);
 
 	fq_destroy_all_entries(iovad);
 
-- 
2.28.0.dirty

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

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

* [PATCH v2 02/11] gpu: host1x: Add missing DMA API include
  2021-12-10 17:54 ` Robin Murphy
  (?)
@ 2021-12-10 17:54   ` Robin Murphy
  -1 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel,
	john.garry, linux-mm, Thierry Reding, Mikko Perttunen, dri-devel

Host1x seems to be relying on picking up dma-mapping.h transitively from
iova.h, which has no reason to include it in the first place. Fix the
former issue before we totally break things by fixing the latter one.

CC: Thierry Reding <thierry.reding@gmail.com>
CC: Mikko Perttunen <mperttunen@nvidia.com>
CC: dri-devel@lists.freedesktop.org
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: No change

 drivers/gpu/host1x/bus.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c
index 218e3718fd68..881fad5c3307 100644
--- a/drivers/gpu/host1x/bus.c
+++ b/drivers/gpu/host1x/bus.c
@@ -5,6 +5,7 @@
  */
 
 #include <linux/debugfs.h>
+#include <linux/dma-mapping.h>
 #include <linux/host1x.h>
 #include <linux/of.h>
 #include <linux/seq_file.h>
-- 
2.28.0.dirty


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

* [PATCH v2 02/11] gpu: host1x: Add missing DMA API include
@ 2021-12-10 17:54   ` Robin Murphy
  0 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will
  Cc: linux-kernel, willy, Mikko Perttunen, linux-mm, iommu,
	Thierry Reding, dri-devel

Host1x seems to be relying on picking up dma-mapping.h transitively from
iova.h, which has no reason to include it in the first place. Fix the
former issue before we totally break things by fixing the latter one.

CC: Thierry Reding <thierry.reding@gmail.com>
CC: Mikko Perttunen <mperttunen@nvidia.com>
CC: dri-devel@lists.freedesktop.org
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: No change

 drivers/gpu/host1x/bus.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c
index 218e3718fd68..881fad5c3307 100644
--- a/drivers/gpu/host1x/bus.c
+++ b/drivers/gpu/host1x/bus.c
@@ -5,6 +5,7 @@
  */
 
 #include <linux/debugfs.h>
+#include <linux/dma-mapping.h>
 #include <linux/host1x.h>
 #include <linux/of.h>
 #include <linux/seq_file.h>
-- 
2.28.0.dirty

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

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

* [PATCH v2 02/11] gpu: host1x: Add missing DMA API include
@ 2021-12-10 17:54   ` Robin Murphy
  0 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will
  Cc: john.garry, linux-kernel, willy, Mikko Perttunen, linux-mm,
	iommu, Thierry Reding, dri-devel, suravee.suthikulpanit,
	baolu.lu

Host1x seems to be relying on picking up dma-mapping.h transitively from
iova.h, which has no reason to include it in the first place. Fix the
former issue before we totally break things by fixing the latter one.

CC: Thierry Reding <thierry.reding@gmail.com>
CC: Mikko Perttunen <mperttunen@nvidia.com>
CC: dri-devel@lists.freedesktop.org
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: No change

 drivers/gpu/host1x/bus.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c
index 218e3718fd68..881fad5c3307 100644
--- a/drivers/gpu/host1x/bus.c
+++ b/drivers/gpu/host1x/bus.c
@@ -5,6 +5,7 @@
  */
 
 #include <linux/debugfs.h>
+#include <linux/dma-mapping.h>
 #include <linux/host1x.h>
 #include <linux/of.h>
 #include <linux/seq_file.h>
-- 
2.28.0.dirty


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

* [PATCH v2 03/11] drm/tegra: vic: Fix DMA API misuse
  2021-12-10 17:54 ` Robin Murphy
  (?)
@ 2021-12-10 17:54   ` Robin Murphy
  -1 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel,
	john.garry, linux-mm, Thierry Reding, Mikko Perttunen, dri-devel

Upon failure, dma_alloc_coherent() returns NULL. If that does happen,
passing some uninitialised stack contents to dma_mapping_error() - which
belongs to a different API in the first place - has precious little
chance of detecting it.

Also include the correct header, because the fragile transitive
inclusion currently providing it is going to break soon.

Fixes: 20e7dce255e9 ("drm/tegra: Remove memory allocation from Falcon library")
CC: Thierry Reding <thierry.reding@gmail.com>
CC: Mikko Perttunen <mperttunen@nvidia.com>
CC: dri-devel@lists.freedesktop.org
Signed-off-by: Robin Murphy <robin.murphy@arm.com>

---

It also doesn't appear to handle failure of the tegra_drm_alloc() path
either, but that's a loose thread I have no desire to pull on... ;)

v2: Resend as part of the series, originally posted separately here:

https://lore.kernel.org/dri-devel/2703882439344010e33bf21ecd63cf9e5e6dc00d.1637781007.git.robin.murphy@arm.com/

 drivers/gpu/drm/tegra/vic.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
index c02010ff2b7f..da4af5371991 100644
--- a/drivers/gpu/drm/tegra/vic.c
+++ b/drivers/gpu/drm/tegra/vic.c
@@ -5,6 +5,7 @@
 
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 #include <linux/host1x.h>
 #include <linux/iommu.h>
 #include <linux/module.h>
@@ -232,10 +233,8 @@ static int vic_load_firmware(struct vic *vic)
 
 	if (!client->group) {
 		virt = dma_alloc_coherent(vic->dev, size, &iova, GFP_KERNEL);
-
-		err = dma_mapping_error(vic->dev, iova);
-		if (err < 0)
-			return err;
+		if (!virt)
+			return -ENOMEM;
 	} else {
 		virt = tegra_drm_alloc(tegra, size, &iova);
 	}
-- 
2.28.0.dirty


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

* [PATCH v2 03/11] drm/tegra: vic: Fix DMA API misuse
@ 2021-12-10 17:54   ` Robin Murphy
  0 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will
  Cc: linux-kernel, willy, Mikko Perttunen, linux-mm, iommu,
	Thierry Reding, dri-devel

Upon failure, dma_alloc_coherent() returns NULL. If that does happen,
passing some uninitialised stack contents to dma_mapping_error() - which
belongs to a different API in the first place - has precious little
chance of detecting it.

Also include the correct header, because the fragile transitive
inclusion currently providing it is going to break soon.

Fixes: 20e7dce255e9 ("drm/tegra: Remove memory allocation from Falcon library")
CC: Thierry Reding <thierry.reding@gmail.com>
CC: Mikko Perttunen <mperttunen@nvidia.com>
CC: dri-devel@lists.freedesktop.org
Signed-off-by: Robin Murphy <robin.murphy@arm.com>

---

It also doesn't appear to handle failure of the tegra_drm_alloc() path
either, but that's a loose thread I have no desire to pull on... ;)

v2: Resend as part of the series, originally posted separately here:

https://lore.kernel.org/dri-devel/2703882439344010e33bf21ecd63cf9e5e6dc00d.1637781007.git.robin.murphy@arm.com/

 drivers/gpu/drm/tegra/vic.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
index c02010ff2b7f..da4af5371991 100644
--- a/drivers/gpu/drm/tegra/vic.c
+++ b/drivers/gpu/drm/tegra/vic.c
@@ -5,6 +5,7 @@
 
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 #include <linux/host1x.h>
 #include <linux/iommu.h>
 #include <linux/module.h>
@@ -232,10 +233,8 @@ static int vic_load_firmware(struct vic *vic)
 
 	if (!client->group) {
 		virt = dma_alloc_coherent(vic->dev, size, &iova, GFP_KERNEL);
-
-		err = dma_mapping_error(vic->dev, iova);
-		if (err < 0)
-			return err;
+		if (!virt)
+			return -ENOMEM;
 	} else {
 		virt = tegra_drm_alloc(tegra, size, &iova);
 	}
-- 
2.28.0.dirty

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

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

* [PATCH v2 03/11] drm/tegra: vic: Fix DMA API misuse
@ 2021-12-10 17:54   ` Robin Murphy
  0 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will
  Cc: john.garry, linux-kernel, willy, Mikko Perttunen, linux-mm,
	iommu, Thierry Reding, dri-devel, suravee.suthikulpanit,
	baolu.lu

Upon failure, dma_alloc_coherent() returns NULL. If that does happen,
passing some uninitialised stack contents to dma_mapping_error() - which
belongs to a different API in the first place - has precious little
chance of detecting it.

Also include the correct header, because the fragile transitive
inclusion currently providing it is going to break soon.

Fixes: 20e7dce255e9 ("drm/tegra: Remove memory allocation from Falcon library")
CC: Thierry Reding <thierry.reding@gmail.com>
CC: Mikko Perttunen <mperttunen@nvidia.com>
CC: dri-devel@lists.freedesktop.org
Signed-off-by: Robin Murphy <robin.murphy@arm.com>

---

It also doesn't appear to handle failure of the tegra_drm_alloc() path
either, but that's a loose thread I have no desire to pull on... ;)

v2: Resend as part of the series, originally posted separately here:

https://lore.kernel.org/dri-devel/2703882439344010e33bf21ecd63cf9e5e6dc00d.1637781007.git.robin.murphy@arm.com/

 drivers/gpu/drm/tegra/vic.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
index c02010ff2b7f..da4af5371991 100644
--- a/drivers/gpu/drm/tegra/vic.c
+++ b/drivers/gpu/drm/tegra/vic.c
@@ -5,6 +5,7 @@
 
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 #include <linux/host1x.h>
 #include <linux/iommu.h>
 #include <linux/module.h>
@@ -232,10 +233,8 @@ static int vic_load_firmware(struct vic *vic)
 
 	if (!client->group) {
 		virt = dma_alloc_coherent(vic->dev, size, &iova, GFP_KERNEL);
-
-		err = dma_mapping_error(vic->dev, iova);
-		if (err < 0)
-			return err;
+		if (!virt)
+			return -ENOMEM;
 	} else {
 		virt = tegra_drm_alloc(tegra, size, &iova);
 	}
-- 
2.28.0.dirty


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

* [PATCH v2 04/11] iommu/iova: Squash entry_dtor abstraction
  2021-12-10 17:54 ` Robin Murphy
@ 2021-12-10 17:54   ` Robin Murphy
  -1 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel,
	john.garry, linux-mm

All flush queues are driven by iommu-dma now, so there is no need to
abstract entry_dtor or its data any more. Squash the now-canonical
implementation directly into the IOVA code to get it out of the way.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: No change

 drivers/iommu/dma-iommu.c | 17 ++---------------
 drivers/iommu/iova.c      | 28 +++++++++++++++-------------
 include/linux/iova.h      | 26 +++-----------------------
 3 files changed, 20 insertions(+), 51 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index b42e38a0dbe2..fa21b9141b71 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -64,18 +64,6 @@ static int __init iommu_dma_forcedac_setup(char *str)
 }
 early_param("iommu.forcedac", iommu_dma_forcedac_setup);
 
-static void iommu_dma_entry_dtor(unsigned long data)
-{
-	struct page *freelist = (struct page *)data;
-
-	while (freelist) {
-		unsigned long p = (unsigned long)page_address(freelist);
-
-		freelist = freelist->freelist;
-		free_page(p);
-	}
-}
-
 static inline size_t cookie_msi_granule(struct iommu_dma_cookie *cookie)
 {
 	if (cookie->type == IOMMU_DMA_IOVA_COOKIE)
@@ -324,8 +312,7 @@ int iommu_dma_init_fq(struct iommu_domain *domain)
 	if (cookie->fq_domain)
 		return 0;
 
-	ret = init_iova_flush_queue(&cookie->iovad, iommu_dma_flush_iotlb_all,
-				    iommu_dma_entry_dtor);
+	ret = init_iova_flush_queue(&cookie->iovad, iommu_dma_flush_iotlb_all);
 	if (ret) {
 		pr_warn("iova flush queue initialization failed\n");
 		return ret;
@@ -479,7 +466,7 @@ static void iommu_dma_free_iova(struct iommu_dma_cookie *cookie,
 	else if (gather && gather->queued)
 		queue_iova(iovad, iova_pfn(iovad, iova),
 				size >> iova_shift(iovad),
-				(unsigned long)gather->freelist);
+				gather->freelist);
 	else
 		free_iova_fast(iovad, iova_pfn(iovad, iova),
 				size >> iova_shift(iovad));
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 920fcc27c9a1..280dd0c7fe1b 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -91,11 +91,9 @@ static void free_iova_flush_queue(struct iova_domain *iovad)
 
 	iovad->fq         = NULL;
 	iovad->flush_cb   = NULL;
-	iovad->entry_dtor = NULL;
 }
 
-int init_iova_flush_queue(struct iova_domain *iovad,
-			  iova_flush_cb flush_cb, iova_entry_dtor entry_dtor)
+int init_iova_flush_queue(struct iova_domain *iovad, iova_flush_cb flush_cb)
 {
 	struct iova_fq __percpu *queue;
 	int cpu;
@@ -108,7 +106,6 @@ int init_iova_flush_queue(struct iova_domain *iovad,
 		return -ENOMEM;
 
 	iovad->flush_cb   = flush_cb;
-	iovad->entry_dtor = entry_dtor;
 
 	for_each_possible_cpu(cpu) {
 		struct iova_fq *fq;
@@ -538,6 +535,16 @@ free_iova_fast(struct iova_domain *iovad, unsigned long pfn, unsigned long size)
 }
 EXPORT_SYMBOL_GPL(free_iova_fast);
 
+static void fq_entry_dtor(struct page *freelist)
+{
+	while (freelist) {
+		unsigned long p = (unsigned long)page_address(freelist);
+
+		freelist = freelist->freelist;
+		free_page(p);
+	}
+}
+
 #define fq_ring_for_each(i, fq) \
 	for ((i) = (fq)->head; (i) != (fq)->tail; (i) = ((i) + 1) % IOVA_FQ_SIZE)
 
@@ -570,9 +577,7 @@ static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
 		if (fq->entries[idx].counter >= counter)
 			break;
 
-		if (iovad->entry_dtor)
-			iovad->entry_dtor(fq->entries[idx].data);
-
+		fq_entry_dtor(fq->entries[idx].freelist);
 		free_iova_fast(iovad,
 			       fq->entries[idx].iova_pfn,
 			       fq->entries[idx].pages);
@@ -597,15 +602,12 @@ static void fq_destroy_all_entries(struct iova_domain *iovad)
 	 * bother to free iovas, just call the entry_dtor on all remaining
 	 * entries.
 	 */
-	if (!iovad->entry_dtor)
-		return;
-
 	for_each_possible_cpu(cpu) {
 		struct iova_fq *fq = per_cpu_ptr(iovad->fq, cpu);
 		int idx;
 
 		fq_ring_for_each(idx, fq)
-			iovad->entry_dtor(fq->entries[idx].data);
+			fq_entry_dtor(fq->entries[idx].freelist);
 	}
 }
 
@@ -630,7 +632,7 @@ static void fq_flush_timeout(struct timer_list *t)
 
 void queue_iova(struct iova_domain *iovad,
 		unsigned long pfn, unsigned long pages,
-		unsigned long data)
+		struct page *freelist)
 {
 	struct iova_fq *fq;
 	unsigned long flags;
@@ -664,7 +666,7 @@ void queue_iova(struct iova_domain *iovad,
 
 	fq->entries[idx].iova_pfn = pfn;
 	fq->entries[idx].pages    = pages;
-	fq->entries[idx].data     = data;
+	fq->entries[idx].freelist = freelist;
 	fq->entries[idx].counter  = atomic64_read(&iovad->fq_flush_start_cnt);
 
 	spin_unlock_irqrestore(&fq->lock, flags);
diff --git a/include/linux/iova.h b/include/linux/iova.h
index 71d8a2de6635..e746d8e41449 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -40,9 +40,6 @@ struct iova_domain;
 /* Call-Back from IOVA code into IOMMU drivers */
 typedef void (* iova_flush_cb)(struct iova_domain *domain);
 
-/* Destructor for per-entry data */
-typedef void (* iova_entry_dtor)(unsigned long data);
-
 /* Number of entries per Flush Queue */
 #define IOVA_FQ_SIZE	256
 
@@ -53,7 +50,7 @@ typedef void (* iova_entry_dtor)(unsigned long data);
 struct iova_fq_entry {
 	unsigned long iova_pfn;
 	unsigned long pages;
-	unsigned long data;
+	struct page *freelist;
 	u64 counter; /* Flush counter when this entrie was added */
 };
 
@@ -88,9 +85,6 @@ struct iova_domain {
 	iova_flush_cb	flush_cb;	/* Call-Back function to flush IOMMU
 					   TLBs */
 
-	iova_entry_dtor entry_dtor;	/* IOMMU driver specific destructor for
-					   iova entry */
-
 	struct timer_list fq_timer;		/* Timer to regularily empty the
 						   flush-queues */
 	atomic_t fq_timer_on;			/* 1 when timer is active, 0
@@ -146,15 +140,14 @@ void free_iova_fast(struct iova_domain *iovad, unsigned long pfn,
 		    unsigned long size);
 void queue_iova(struct iova_domain *iovad,
 		unsigned long pfn, unsigned long pages,
-		unsigned long data);
+		struct page *freelist);
 unsigned long alloc_iova_fast(struct iova_domain *iovad, unsigned long size,
 			      unsigned long limit_pfn, bool flush_rcache);
 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);
-int init_iova_flush_queue(struct iova_domain *iovad,
-			  iova_flush_cb flush_cb, iova_entry_dtor entry_dtor);
+int init_iova_flush_queue(struct iova_domain *iovad, iova_flush_cb flush_cb);
 struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
 void put_iova_domain(struct iova_domain *iovad);
 #else
@@ -189,12 +182,6 @@ static inline void free_iova_fast(struct iova_domain *iovad,
 {
 }
 
-static inline void queue_iova(struct iova_domain *iovad,
-			      unsigned long pfn, unsigned long pages,
-			      unsigned long data)
-{
-}
-
 static inline unsigned long alloc_iova_fast(struct iova_domain *iovad,
 					    unsigned long size,
 					    unsigned long limit_pfn,
@@ -216,13 +203,6 @@ static inline void init_iova_domain(struct iova_domain *iovad,
 {
 }
 
-static inline int init_iova_flush_queue(struct iova_domain *iovad,
-					iova_flush_cb flush_cb,
-					iova_entry_dtor entry_dtor)
-{
-	return -ENODEV;
-}
-
 static inline struct iova *find_iova(struct iova_domain *iovad,
 				     unsigned long pfn)
 {
-- 
2.28.0.dirty


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

* [PATCH v2 04/11] iommu/iova: Squash entry_dtor abstraction
@ 2021-12-10 17:54   ` Robin Murphy
  0 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will; +Cc: linux-kernel, willy, linux-mm, iommu

All flush queues are driven by iommu-dma now, so there is no need to
abstract entry_dtor or its data any more. Squash the now-canonical
implementation directly into the IOVA code to get it out of the way.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: No change

 drivers/iommu/dma-iommu.c | 17 ++---------------
 drivers/iommu/iova.c      | 28 +++++++++++++++-------------
 include/linux/iova.h      | 26 +++-----------------------
 3 files changed, 20 insertions(+), 51 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index b42e38a0dbe2..fa21b9141b71 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -64,18 +64,6 @@ static int __init iommu_dma_forcedac_setup(char *str)
 }
 early_param("iommu.forcedac", iommu_dma_forcedac_setup);
 
-static void iommu_dma_entry_dtor(unsigned long data)
-{
-	struct page *freelist = (struct page *)data;
-
-	while (freelist) {
-		unsigned long p = (unsigned long)page_address(freelist);
-
-		freelist = freelist->freelist;
-		free_page(p);
-	}
-}
-
 static inline size_t cookie_msi_granule(struct iommu_dma_cookie *cookie)
 {
 	if (cookie->type == IOMMU_DMA_IOVA_COOKIE)
@@ -324,8 +312,7 @@ int iommu_dma_init_fq(struct iommu_domain *domain)
 	if (cookie->fq_domain)
 		return 0;
 
-	ret = init_iova_flush_queue(&cookie->iovad, iommu_dma_flush_iotlb_all,
-				    iommu_dma_entry_dtor);
+	ret = init_iova_flush_queue(&cookie->iovad, iommu_dma_flush_iotlb_all);
 	if (ret) {
 		pr_warn("iova flush queue initialization failed\n");
 		return ret;
@@ -479,7 +466,7 @@ static void iommu_dma_free_iova(struct iommu_dma_cookie *cookie,
 	else if (gather && gather->queued)
 		queue_iova(iovad, iova_pfn(iovad, iova),
 				size >> iova_shift(iovad),
-				(unsigned long)gather->freelist);
+				gather->freelist);
 	else
 		free_iova_fast(iovad, iova_pfn(iovad, iova),
 				size >> iova_shift(iovad));
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 920fcc27c9a1..280dd0c7fe1b 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -91,11 +91,9 @@ static void free_iova_flush_queue(struct iova_domain *iovad)
 
 	iovad->fq         = NULL;
 	iovad->flush_cb   = NULL;
-	iovad->entry_dtor = NULL;
 }
 
-int init_iova_flush_queue(struct iova_domain *iovad,
-			  iova_flush_cb flush_cb, iova_entry_dtor entry_dtor)
+int init_iova_flush_queue(struct iova_domain *iovad, iova_flush_cb flush_cb)
 {
 	struct iova_fq __percpu *queue;
 	int cpu;
@@ -108,7 +106,6 @@ int init_iova_flush_queue(struct iova_domain *iovad,
 		return -ENOMEM;
 
 	iovad->flush_cb   = flush_cb;
-	iovad->entry_dtor = entry_dtor;
 
 	for_each_possible_cpu(cpu) {
 		struct iova_fq *fq;
@@ -538,6 +535,16 @@ free_iova_fast(struct iova_domain *iovad, unsigned long pfn, unsigned long size)
 }
 EXPORT_SYMBOL_GPL(free_iova_fast);
 
+static void fq_entry_dtor(struct page *freelist)
+{
+	while (freelist) {
+		unsigned long p = (unsigned long)page_address(freelist);
+
+		freelist = freelist->freelist;
+		free_page(p);
+	}
+}
+
 #define fq_ring_for_each(i, fq) \
 	for ((i) = (fq)->head; (i) != (fq)->tail; (i) = ((i) + 1) % IOVA_FQ_SIZE)
 
@@ -570,9 +577,7 @@ static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
 		if (fq->entries[idx].counter >= counter)
 			break;
 
-		if (iovad->entry_dtor)
-			iovad->entry_dtor(fq->entries[idx].data);
-
+		fq_entry_dtor(fq->entries[idx].freelist);
 		free_iova_fast(iovad,
 			       fq->entries[idx].iova_pfn,
 			       fq->entries[idx].pages);
@@ -597,15 +602,12 @@ static void fq_destroy_all_entries(struct iova_domain *iovad)
 	 * bother to free iovas, just call the entry_dtor on all remaining
 	 * entries.
 	 */
-	if (!iovad->entry_dtor)
-		return;
-
 	for_each_possible_cpu(cpu) {
 		struct iova_fq *fq = per_cpu_ptr(iovad->fq, cpu);
 		int idx;
 
 		fq_ring_for_each(idx, fq)
-			iovad->entry_dtor(fq->entries[idx].data);
+			fq_entry_dtor(fq->entries[idx].freelist);
 	}
 }
 
@@ -630,7 +632,7 @@ static void fq_flush_timeout(struct timer_list *t)
 
 void queue_iova(struct iova_domain *iovad,
 		unsigned long pfn, unsigned long pages,
-		unsigned long data)
+		struct page *freelist)
 {
 	struct iova_fq *fq;
 	unsigned long flags;
@@ -664,7 +666,7 @@ void queue_iova(struct iova_domain *iovad,
 
 	fq->entries[idx].iova_pfn = pfn;
 	fq->entries[idx].pages    = pages;
-	fq->entries[idx].data     = data;
+	fq->entries[idx].freelist = freelist;
 	fq->entries[idx].counter  = atomic64_read(&iovad->fq_flush_start_cnt);
 
 	spin_unlock_irqrestore(&fq->lock, flags);
diff --git a/include/linux/iova.h b/include/linux/iova.h
index 71d8a2de6635..e746d8e41449 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -40,9 +40,6 @@ struct iova_domain;
 /* Call-Back from IOVA code into IOMMU drivers */
 typedef void (* iova_flush_cb)(struct iova_domain *domain);
 
-/* Destructor for per-entry data */
-typedef void (* iova_entry_dtor)(unsigned long data);
-
 /* Number of entries per Flush Queue */
 #define IOVA_FQ_SIZE	256
 
@@ -53,7 +50,7 @@ typedef void (* iova_entry_dtor)(unsigned long data);
 struct iova_fq_entry {
 	unsigned long iova_pfn;
 	unsigned long pages;
-	unsigned long data;
+	struct page *freelist;
 	u64 counter; /* Flush counter when this entrie was added */
 };
 
@@ -88,9 +85,6 @@ struct iova_domain {
 	iova_flush_cb	flush_cb;	/* Call-Back function to flush IOMMU
 					   TLBs */
 
-	iova_entry_dtor entry_dtor;	/* IOMMU driver specific destructor for
-					   iova entry */
-
 	struct timer_list fq_timer;		/* Timer to regularily empty the
 						   flush-queues */
 	atomic_t fq_timer_on;			/* 1 when timer is active, 0
@@ -146,15 +140,14 @@ void free_iova_fast(struct iova_domain *iovad, unsigned long pfn,
 		    unsigned long size);
 void queue_iova(struct iova_domain *iovad,
 		unsigned long pfn, unsigned long pages,
-		unsigned long data);
+		struct page *freelist);
 unsigned long alloc_iova_fast(struct iova_domain *iovad, unsigned long size,
 			      unsigned long limit_pfn, bool flush_rcache);
 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);
-int init_iova_flush_queue(struct iova_domain *iovad,
-			  iova_flush_cb flush_cb, iova_entry_dtor entry_dtor);
+int init_iova_flush_queue(struct iova_domain *iovad, iova_flush_cb flush_cb);
 struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
 void put_iova_domain(struct iova_domain *iovad);
 #else
@@ -189,12 +182,6 @@ static inline void free_iova_fast(struct iova_domain *iovad,
 {
 }
 
-static inline void queue_iova(struct iova_domain *iovad,
-			      unsigned long pfn, unsigned long pages,
-			      unsigned long data)
-{
-}
-
 static inline unsigned long alloc_iova_fast(struct iova_domain *iovad,
 					    unsigned long size,
 					    unsigned long limit_pfn,
@@ -216,13 +203,6 @@ static inline void init_iova_domain(struct iova_domain *iovad,
 {
 }
 
-static inline int init_iova_flush_queue(struct iova_domain *iovad,
-					iova_flush_cb flush_cb,
-					iova_entry_dtor entry_dtor)
-{
-	return -ENODEV;
-}
-
 static inline struct iova *find_iova(struct iova_domain *iovad,
 				     unsigned long pfn)
 {
-- 
2.28.0.dirty

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

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

* [PATCH v2 05/11] iommu/iova: Squash flush_cb abstraction
  2021-12-10 17:54 ` Robin Murphy
@ 2021-12-10 17:54   ` Robin Murphy
  -1 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel,
	john.garry, linux-mm

Once again, with iommu-dma now being the only flush queue user, we no
longer need the extra level of indirection through flush_cb. Squash that
and let the flush queue code call the domain method directly.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: No change

 drivers/iommu/dma-iommu.c | 13 +------------
 drivers/iommu/iova.c      | 11 +++++------
 include/linux/iova.h      | 11 +++--------
 3 files changed, 9 insertions(+), 26 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index fa21b9141b71..cde887530549 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -282,17 +282,6 @@ static int iova_reserve_iommu_regions(struct device *dev,
 	return ret;
 }
 
-static void iommu_dma_flush_iotlb_all(struct iova_domain *iovad)
-{
-	struct iommu_dma_cookie *cookie;
-	struct iommu_domain *domain;
-
-	cookie = container_of(iovad, struct iommu_dma_cookie, iovad);
-	domain = cookie->fq_domain;
-
-	domain->ops->flush_iotlb_all(domain);
-}
-
 static bool dev_is_untrusted(struct device *dev)
 {
 	return dev_is_pci(dev) && to_pci_dev(dev)->untrusted;
@@ -312,7 +301,7 @@ int iommu_dma_init_fq(struct iommu_domain *domain)
 	if (cookie->fq_domain)
 		return 0;
 
-	ret = init_iova_flush_queue(&cookie->iovad, iommu_dma_flush_iotlb_all);
+	ret = init_iova_flush_queue(&cookie->iovad, domain);
 	if (ret) {
 		pr_warn("iova flush queue initialization failed\n");
 		return ret;
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 280dd0c7fe1b..76bc6f39fac7 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -63,7 +63,7 @@ init_iova_domain(struct iova_domain *iovad, unsigned long granule,
 	iovad->start_pfn = start_pfn;
 	iovad->dma_32bit_pfn = 1UL << (32 - iova_shift(iovad));
 	iovad->max32_alloc_size = iovad->dma_32bit_pfn;
-	iovad->flush_cb = NULL;
+	iovad->fq_domain = NULL;
 	iovad->fq = NULL;
 	iovad->anchor.pfn_lo = iovad->anchor.pfn_hi = IOVA_ANCHOR;
 	rb_link_node(&iovad->anchor.node, NULL, &iovad->rbroot.rb_node);
@@ -90,10 +90,10 @@ static void free_iova_flush_queue(struct iova_domain *iovad)
 	free_percpu(iovad->fq);
 
 	iovad->fq         = NULL;
-	iovad->flush_cb   = NULL;
+	iovad->fq_domain  = NULL;
 }
 
-int init_iova_flush_queue(struct iova_domain *iovad, iova_flush_cb flush_cb)
+int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain)
 {
 	struct iova_fq __percpu *queue;
 	int cpu;
@@ -105,8 +105,6 @@ int init_iova_flush_queue(struct iova_domain *iovad, iova_flush_cb flush_cb)
 	if (!queue)
 		return -ENOMEM;
 
-	iovad->flush_cb   = flush_cb;
-
 	for_each_possible_cpu(cpu) {
 		struct iova_fq *fq;
 
@@ -117,6 +115,7 @@ int init_iova_flush_queue(struct iova_domain *iovad, iova_flush_cb flush_cb)
 		spin_lock_init(&fq->lock);
 	}
 
+	iovad->fq_domain = fq_domain;
 	iovad->fq = queue;
 
 	timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
@@ -589,7 +588,7 @@ static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
 static void iova_domain_flush(struct iova_domain *iovad)
 {
 	atomic64_inc(&iovad->fq_flush_start_cnt);
-	iovad->flush_cb(iovad);
+	iovad->fq_domain->ops->flush_iotlb_all(iovad->fq_domain);
 	atomic64_inc(&iovad->fq_flush_finish_cnt);
 }
 
diff --git a/include/linux/iova.h b/include/linux/iova.h
index e746d8e41449..99be4fcea4f3 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -14,6 +14,7 @@
 #include <linux/rbtree.h>
 #include <linux/atomic.h>
 #include <linux/dma-mapping.h>
+#include <linux/iommu.h>
 
 /* iova structure */
 struct iova {
@@ -35,11 +36,6 @@ struct iova_rcache {
 	struct iova_cpu_rcache __percpu *cpu_rcaches;
 };
 
-struct iova_domain;
-
-/* Call-Back from IOVA code into IOMMU drivers */
-typedef void (* iova_flush_cb)(struct iova_domain *domain);
-
 /* Number of entries per Flush Queue */
 #define IOVA_FQ_SIZE	256
 
@@ -82,8 +78,7 @@ struct iova_domain {
 	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 */
+	struct iommu_domain *fq_domain;
 
 	struct timer_list fq_timer;		/* Timer to regularily empty the
 						   flush-queues */
@@ -147,7 +142,7 @@ 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);
-int init_iova_flush_queue(struct iova_domain *iovad, iova_flush_cb flush_cb);
+int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain);
 struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
 void put_iova_domain(struct iova_domain *iovad);
 #else
-- 
2.28.0.dirty


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

* [PATCH v2 05/11] iommu/iova: Squash flush_cb abstraction
@ 2021-12-10 17:54   ` Robin Murphy
  0 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will; +Cc: linux-kernel, willy, linux-mm, iommu

Once again, with iommu-dma now being the only flush queue user, we no
longer need the extra level of indirection through flush_cb. Squash that
and let the flush queue code call the domain method directly.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: No change

 drivers/iommu/dma-iommu.c | 13 +------------
 drivers/iommu/iova.c      | 11 +++++------
 include/linux/iova.h      | 11 +++--------
 3 files changed, 9 insertions(+), 26 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index fa21b9141b71..cde887530549 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -282,17 +282,6 @@ static int iova_reserve_iommu_regions(struct device *dev,
 	return ret;
 }
 
-static void iommu_dma_flush_iotlb_all(struct iova_domain *iovad)
-{
-	struct iommu_dma_cookie *cookie;
-	struct iommu_domain *domain;
-
-	cookie = container_of(iovad, struct iommu_dma_cookie, iovad);
-	domain = cookie->fq_domain;
-
-	domain->ops->flush_iotlb_all(domain);
-}
-
 static bool dev_is_untrusted(struct device *dev)
 {
 	return dev_is_pci(dev) && to_pci_dev(dev)->untrusted;
@@ -312,7 +301,7 @@ int iommu_dma_init_fq(struct iommu_domain *domain)
 	if (cookie->fq_domain)
 		return 0;
 
-	ret = init_iova_flush_queue(&cookie->iovad, iommu_dma_flush_iotlb_all);
+	ret = init_iova_flush_queue(&cookie->iovad, domain);
 	if (ret) {
 		pr_warn("iova flush queue initialization failed\n");
 		return ret;
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 280dd0c7fe1b..76bc6f39fac7 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -63,7 +63,7 @@ init_iova_domain(struct iova_domain *iovad, unsigned long granule,
 	iovad->start_pfn = start_pfn;
 	iovad->dma_32bit_pfn = 1UL << (32 - iova_shift(iovad));
 	iovad->max32_alloc_size = iovad->dma_32bit_pfn;
-	iovad->flush_cb = NULL;
+	iovad->fq_domain = NULL;
 	iovad->fq = NULL;
 	iovad->anchor.pfn_lo = iovad->anchor.pfn_hi = IOVA_ANCHOR;
 	rb_link_node(&iovad->anchor.node, NULL, &iovad->rbroot.rb_node);
@@ -90,10 +90,10 @@ static void free_iova_flush_queue(struct iova_domain *iovad)
 	free_percpu(iovad->fq);
 
 	iovad->fq         = NULL;
-	iovad->flush_cb   = NULL;
+	iovad->fq_domain  = NULL;
 }
 
-int init_iova_flush_queue(struct iova_domain *iovad, iova_flush_cb flush_cb)
+int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain)
 {
 	struct iova_fq __percpu *queue;
 	int cpu;
@@ -105,8 +105,6 @@ int init_iova_flush_queue(struct iova_domain *iovad, iova_flush_cb flush_cb)
 	if (!queue)
 		return -ENOMEM;
 
-	iovad->flush_cb   = flush_cb;
-
 	for_each_possible_cpu(cpu) {
 		struct iova_fq *fq;
 
@@ -117,6 +115,7 @@ int init_iova_flush_queue(struct iova_domain *iovad, iova_flush_cb flush_cb)
 		spin_lock_init(&fq->lock);
 	}
 
+	iovad->fq_domain = fq_domain;
 	iovad->fq = queue;
 
 	timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
@@ -589,7 +588,7 @@ static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
 static void iova_domain_flush(struct iova_domain *iovad)
 {
 	atomic64_inc(&iovad->fq_flush_start_cnt);
-	iovad->flush_cb(iovad);
+	iovad->fq_domain->ops->flush_iotlb_all(iovad->fq_domain);
 	atomic64_inc(&iovad->fq_flush_finish_cnt);
 }
 
diff --git a/include/linux/iova.h b/include/linux/iova.h
index e746d8e41449..99be4fcea4f3 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -14,6 +14,7 @@
 #include <linux/rbtree.h>
 #include <linux/atomic.h>
 #include <linux/dma-mapping.h>
+#include <linux/iommu.h>
 
 /* iova structure */
 struct iova {
@@ -35,11 +36,6 @@ struct iova_rcache {
 	struct iova_cpu_rcache __percpu *cpu_rcaches;
 };
 
-struct iova_domain;
-
-/* Call-Back from IOVA code into IOMMU drivers */
-typedef void (* iova_flush_cb)(struct iova_domain *domain);
-
 /* Number of entries per Flush Queue */
 #define IOVA_FQ_SIZE	256
 
@@ -82,8 +78,7 @@ struct iova_domain {
 	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 */
+	struct iommu_domain *fq_domain;
 
 	struct timer_list fq_timer;		/* Timer to regularily empty the
 						   flush-queues */
@@ -147,7 +142,7 @@ 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);
-int init_iova_flush_queue(struct iova_domain *iovad, iova_flush_cb flush_cb);
+int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain);
 struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
 void put_iova_domain(struct iova_domain *iovad);
 #else
-- 
2.28.0.dirty

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

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

* [PATCH v2 06/11] iommu/amd: Simplify pagetable freeing
  2021-12-10 17:54 ` Robin Murphy
@ 2021-12-10 17:54   ` Robin Murphy
  -1 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel,
	john.garry, linux-mm

For reasons unclear, pagetable freeing is an effectively recursive
method implemented via an elaborate system of templated functions that
turns out to account for 25% of the object file size. Implementing it
using regular straightforward recursion makes the code simpler, and
seems like a good thing to do before we work on it further. As part of
that, also fix the types to avoid all the needless casting back and
forth which just gets in the way.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: Comment the (pre-existing) level 2 optimisation logic

 drivers/iommu/amd/io_pgtable.c | 82 ++++++++++++++--------------------
 1 file changed, 34 insertions(+), 48 deletions(-)

diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c
index 182c93a43efd..4165e1372b6e 100644
--- a/drivers/iommu/amd/io_pgtable.c
+++ b/drivers/iommu/amd/io_pgtable.c
@@ -84,49 +84,45 @@ static void free_page_list(struct page *freelist)
 	}
 }
 
-static struct page *free_pt_page(unsigned long pt, struct page *freelist)
+static struct page *free_pt_page(u64 *pt, struct page *freelist)
 {
-	struct page *p = virt_to_page((void *)pt);
+	struct page *p = virt_to_page(pt);
 
 	p->freelist = freelist;
 
 	return p;
 }
 
-#define DEFINE_FREE_PT_FN(LVL, FN)						\
-static struct page *free_pt_##LVL (unsigned long __pt, struct page *freelist)	\
-{										\
-	unsigned long p;							\
-	u64 *pt;								\
-	int i;									\
-										\
-	pt = (u64 *)__pt;							\
-										\
-	for (i = 0; i < 512; ++i) {						\
-		/* PTE present? */						\
-		if (!IOMMU_PTE_PRESENT(pt[i]))					\
-			continue;						\
-										\
-		/* Large PTE? */						\
-		if (PM_PTE_LEVEL(pt[i]) == 0 ||					\
-		    PM_PTE_LEVEL(pt[i]) == 7)					\
-			continue;						\
-										\
-		p = (unsigned long)IOMMU_PTE_PAGE(pt[i]);			\
-		freelist = FN(p, freelist);					\
-	}									\
-										\
-	return free_pt_page((unsigned long)pt, freelist);			\
+static struct page *free_pt_lvl(u64 *pt, struct page *freelist, int lvl)
+{
+	u64 *p;
+	int i;
+
+	for (i = 0; i < 512; ++i) {
+		/* PTE present? */
+		if (!IOMMU_PTE_PRESENT(pt[i]))
+			continue;
+
+		/* Large PTE? */
+		if (PM_PTE_LEVEL(pt[i]) == 0 ||
+		    PM_PTE_LEVEL(pt[i]) == 7)
+			continue;
+
+		/*
+		 * Free the next level. No need to look at l1 tables here since
+		 * they can only contain leaf PTEs; just free them directly.
+		 */
+		p = IOMMU_PTE_PAGE(pt[i]);
+		if (lvl > 2)
+			freelist = free_pt_lvl(p, freelist, lvl - 1);
+		else
+			freelist = free_pt_page(p, freelist);
+	}
+
+	return free_pt_page(pt, freelist);
 }
 
-DEFINE_FREE_PT_FN(l2, free_pt_page)
-DEFINE_FREE_PT_FN(l3, free_pt_l2)
-DEFINE_FREE_PT_FN(l4, free_pt_l3)
-DEFINE_FREE_PT_FN(l5, free_pt_l4)
-DEFINE_FREE_PT_FN(l6, free_pt_l5)
-
-static struct page *free_sub_pt(unsigned long root, int mode,
-				struct page *freelist)
+static struct page *free_sub_pt(u64 *root, int mode, struct page *freelist)
 {
 	switch (mode) {
 	case PAGE_MODE_NONE:
@@ -136,19 +132,11 @@ static struct page *free_sub_pt(unsigned long root, int mode,
 		freelist = free_pt_page(root, freelist);
 		break;
 	case PAGE_MODE_2_LEVEL:
-		freelist = free_pt_l2(root, freelist);
-		break;
 	case PAGE_MODE_3_LEVEL:
-		freelist = free_pt_l3(root, freelist);
-		break;
 	case PAGE_MODE_4_LEVEL:
-		freelist = free_pt_l4(root, freelist);
-		break;
 	case PAGE_MODE_5_LEVEL:
-		freelist = free_pt_l5(root, freelist);
-		break;
 	case PAGE_MODE_6_LEVEL:
-		freelist = free_pt_l6(root, freelist);
+		free_pt_lvl(root, freelist, mode);
 		break;
 	default:
 		BUG();
@@ -364,7 +352,7 @@ static u64 *fetch_pte(struct amd_io_pgtable *pgtable,
 
 static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist)
 {
-	unsigned long pt;
+	u64 *pt;
 	int mode;
 
 	while (cmpxchg64(pte, pteval, 0) != pteval) {
@@ -375,7 +363,7 @@ static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist)
 	if (!IOMMU_PTE_PRESENT(pteval))
 		return freelist;
 
-	pt   = (unsigned long)IOMMU_PTE_PAGE(pteval);
+	pt   = IOMMU_PTE_PAGE(pteval);
 	mode = IOMMU_PTE_MODE(pteval);
 
 	return free_sub_pt(pt, mode, freelist);
@@ -512,7 +500,6 @@ static void v1_free_pgtable(struct io_pgtable *iop)
 	struct amd_io_pgtable *pgtable = container_of(iop, struct amd_io_pgtable, iop);
 	struct protection_domain *dom;
 	struct page *freelist = NULL;
-	unsigned long root;
 
 	if (pgtable->mode == PAGE_MODE_NONE)
 		return;
@@ -529,8 +516,7 @@ static void v1_free_pgtable(struct io_pgtable *iop)
 	BUG_ON(pgtable->mode < PAGE_MODE_NONE ||
 	       pgtable->mode > PAGE_MODE_6_LEVEL);
 
-	root = (unsigned long)pgtable->root;
-	freelist = free_sub_pt(root, pgtable->mode, freelist);
+	freelist = free_sub_pt(pgtable->root, pgtable->mode, freelist);
 
 	free_page_list(freelist);
 }
-- 
2.28.0.dirty


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

* [PATCH v2 06/11] iommu/amd: Simplify pagetable freeing
@ 2021-12-10 17:54   ` Robin Murphy
  0 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will; +Cc: linux-kernel, willy, linux-mm, iommu

For reasons unclear, pagetable freeing is an effectively recursive
method implemented via an elaborate system of templated functions that
turns out to account for 25% of the object file size. Implementing it
using regular straightforward recursion makes the code simpler, and
seems like a good thing to do before we work on it further. As part of
that, also fix the types to avoid all the needless casting back and
forth which just gets in the way.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: Comment the (pre-existing) level 2 optimisation logic

 drivers/iommu/amd/io_pgtable.c | 82 ++++++++++++++--------------------
 1 file changed, 34 insertions(+), 48 deletions(-)

diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c
index 182c93a43efd..4165e1372b6e 100644
--- a/drivers/iommu/amd/io_pgtable.c
+++ b/drivers/iommu/amd/io_pgtable.c
@@ -84,49 +84,45 @@ static void free_page_list(struct page *freelist)
 	}
 }
 
-static struct page *free_pt_page(unsigned long pt, struct page *freelist)
+static struct page *free_pt_page(u64 *pt, struct page *freelist)
 {
-	struct page *p = virt_to_page((void *)pt);
+	struct page *p = virt_to_page(pt);
 
 	p->freelist = freelist;
 
 	return p;
 }
 
-#define DEFINE_FREE_PT_FN(LVL, FN)						\
-static struct page *free_pt_##LVL (unsigned long __pt, struct page *freelist)	\
-{										\
-	unsigned long p;							\
-	u64 *pt;								\
-	int i;									\
-										\
-	pt = (u64 *)__pt;							\
-										\
-	for (i = 0; i < 512; ++i) {						\
-		/* PTE present? */						\
-		if (!IOMMU_PTE_PRESENT(pt[i]))					\
-			continue;						\
-										\
-		/* Large PTE? */						\
-		if (PM_PTE_LEVEL(pt[i]) == 0 ||					\
-		    PM_PTE_LEVEL(pt[i]) == 7)					\
-			continue;						\
-										\
-		p = (unsigned long)IOMMU_PTE_PAGE(pt[i]);			\
-		freelist = FN(p, freelist);					\
-	}									\
-										\
-	return free_pt_page((unsigned long)pt, freelist);			\
+static struct page *free_pt_lvl(u64 *pt, struct page *freelist, int lvl)
+{
+	u64 *p;
+	int i;
+
+	for (i = 0; i < 512; ++i) {
+		/* PTE present? */
+		if (!IOMMU_PTE_PRESENT(pt[i]))
+			continue;
+
+		/* Large PTE? */
+		if (PM_PTE_LEVEL(pt[i]) == 0 ||
+		    PM_PTE_LEVEL(pt[i]) == 7)
+			continue;
+
+		/*
+		 * Free the next level. No need to look at l1 tables here since
+		 * they can only contain leaf PTEs; just free them directly.
+		 */
+		p = IOMMU_PTE_PAGE(pt[i]);
+		if (lvl > 2)
+			freelist = free_pt_lvl(p, freelist, lvl - 1);
+		else
+			freelist = free_pt_page(p, freelist);
+	}
+
+	return free_pt_page(pt, freelist);
 }
 
-DEFINE_FREE_PT_FN(l2, free_pt_page)
-DEFINE_FREE_PT_FN(l3, free_pt_l2)
-DEFINE_FREE_PT_FN(l4, free_pt_l3)
-DEFINE_FREE_PT_FN(l5, free_pt_l4)
-DEFINE_FREE_PT_FN(l6, free_pt_l5)
-
-static struct page *free_sub_pt(unsigned long root, int mode,
-				struct page *freelist)
+static struct page *free_sub_pt(u64 *root, int mode, struct page *freelist)
 {
 	switch (mode) {
 	case PAGE_MODE_NONE:
@@ -136,19 +132,11 @@ static struct page *free_sub_pt(unsigned long root, int mode,
 		freelist = free_pt_page(root, freelist);
 		break;
 	case PAGE_MODE_2_LEVEL:
-		freelist = free_pt_l2(root, freelist);
-		break;
 	case PAGE_MODE_3_LEVEL:
-		freelist = free_pt_l3(root, freelist);
-		break;
 	case PAGE_MODE_4_LEVEL:
-		freelist = free_pt_l4(root, freelist);
-		break;
 	case PAGE_MODE_5_LEVEL:
-		freelist = free_pt_l5(root, freelist);
-		break;
 	case PAGE_MODE_6_LEVEL:
-		freelist = free_pt_l6(root, freelist);
+		free_pt_lvl(root, freelist, mode);
 		break;
 	default:
 		BUG();
@@ -364,7 +352,7 @@ static u64 *fetch_pte(struct amd_io_pgtable *pgtable,
 
 static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist)
 {
-	unsigned long pt;
+	u64 *pt;
 	int mode;
 
 	while (cmpxchg64(pte, pteval, 0) != pteval) {
@@ -375,7 +363,7 @@ static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist)
 	if (!IOMMU_PTE_PRESENT(pteval))
 		return freelist;
 
-	pt   = (unsigned long)IOMMU_PTE_PAGE(pteval);
+	pt   = IOMMU_PTE_PAGE(pteval);
 	mode = IOMMU_PTE_MODE(pteval);
 
 	return free_sub_pt(pt, mode, freelist);
@@ -512,7 +500,6 @@ static void v1_free_pgtable(struct io_pgtable *iop)
 	struct amd_io_pgtable *pgtable = container_of(iop, struct amd_io_pgtable, iop);
 	struct protection_domain *dom;
 	struct page *freelist = NULL;
-	unsigned long root;
 
 	if (pgtable->mode == PAGE_MODE_NONE)
 		return;
@@ -529,8 +516,7 @@ static void v1_free_pgtable(struct io_pgtable *iop)
 	BUG_ON(pgtable->mode < PAGE_MODE_NONE ||
 	       pgtable->mode > PAGE_MODE_6_LEVEL);
 
-	root = (unsigned long)pgtable->root;
-	freelist = free_sub_pt(root, pgtable->mode, freelist);
+	freelist = free_sub_pt(pgtable->root, pgtable->mode, freelist);
 
 	free_page_list(freelist);
 }
-- 
2.28.0.dirty

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

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

* [PATCH v2 07/11] iommu/amd: Use put_pages_list
  2021-12-10 17:54 ` Robin Murphy
@ 2021-12-10 17:54   ` Robin Murphy
  -1 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel,
	john.garry, linux-mm

From: "Matthew Wilcox (Oracle)" <willy@infradead.org>

page->freelist is for the use of slab.  We already have the ability
to free a list of pages in the core mm, but it requires the use of a
list_head and for the pages to be chained together through page->lru.
Switch the AMD IOMMU code over to using free_pages_list().

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
[rm: split from original patch, cosmetic tweaks]
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: No change

 drivers/iommu/amd/io_pgtable.c | 50 ++++++++++++----------------------
 1 file changed, 18 insertions(+), 32 deletions(-)

diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c
index 4165e1372b6e..b1bf4125b0f7 100644
--- a/drivers/iommu/amd/io_pgtable.c
+++ b/drivers/iommu/amd/io_pgtable.c
@@ -74,26 +74,14 @@ static u64 *first_pte_l7(u64 *pte, unsigned long *page_size,
  *
  ****************************************************************************/
 
-static void free_page_list(struct page *freelist)
-{
-	while (freelist != NULL) {
-		unsigned long p = (unsigned long)page_address(freelist);
-
-		freelist = freelist->freelist;
-		free_page(p);
-	}
-}
-
-static struct page *free_pt_page(u64 *pt, struct page *freelist)
+static void free_pt_page(u64 *pt, struct list_head *freelist)
 {
 	struct page *p = virt_to_page(pt);
 
-	p->freelist = freelist;
-
-	return p;
+	list_add_tail(&p->lru, freelist);
 }
 
-static struct page *free_pt_lvl(u64 *pt, struct page *freelist, int lvl)
+static void free_pt_lvl(u64 *pt, struct list_head *freelist, int lvl)
 {
 	u64 *p;
 	int i;
@@ -114,22 +102,22 @@ static struct page *free_pt_lvl(u64 *pt, struct page *freelist, int lvl)
 		 */
 		p = IOMMU_PTE_PAGE(pt[i]);
 		if (lvl > 2)
-			freelist = free_pt_lvl(p, freelist, lvl - 1);
+			free_pt_lvl(p, freelist, lvl - 1);
 		else
-			freelist = free_pt_page(p, freelist);
+			free_pt_page(p, freelist);
 	}
 
-	return free_pt_page(pt, freelist);
+	free_pt_page(pt, freelist);
 }
 
-static struct page *free_sub_pt(u64 *root, int mode, struct page *freelist)
+static void free_sub_pt(u64 *root, int mode, struct list_head *freelist)
 {
 	switch (mode) {
 	case PAGE_MODE_NONE:
 	case PAGE_MODE_7_LEVEL:
 		break;
 	case PAGE_MODE_1_LEVEL:
-		freelist = free_pt_page(root, freelist);
+		free_pt_page(root, freelist);
 		break;
 	case PAGE_MODE_2_LEVEL:
 	case PAGE_MODE_3_LEVEL:
@@ -141,8 +129,6 @@ static struct page *free_sub_pt(u64 *root, int mode, struct page *freelist)
 	default:
 		BUG();
 	}
-
-	return freelist;
 }
 
 void amd_iommu_domain_set_pgtable(struct protection_domain *domain,
@@ -350,7 +336,7 @@ static u64 *fetch_pte(struct amd_io_pgtable *pgtable,
 	return pte;
 }
 
-static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist)
+static void free_clear_pte(u64 *pte, u64 pteval, struct list_head *freelist)
 {
 	u64 *pt;
 	int mode;
@@ -361,12 +347,12 @@ static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist)
 	}
 
 	if (!IOMMU_PTE_PRESENT(pteval))
-		return freelist;
+		return;
 
 	pt   = IOMMU_PTE_PAGE(pteval);
 	mode = IOMMU_PTE_MODE(pteval);
 
-	return free_sub_pt(pt, mode, freelist);
+	free_sub_pt(pt, mode, freelist);
 }
 
 /*
@@ -380,7 +366,7 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova,
 			  phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
 {
 	struct protection_domain *dom = io_pgtable_ops_to_domain(ops);
-	struct page *freelist = NULL;
+	LIST_HEAD(freelist);
 	bool updated = false;
 	u64 __pte, *pte;
 	int ret, i, count;
@@ -400,9 +386,9 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova,
 		goto out;
 
 	for (i = 0; i < count; ++i)
-		freelist = free_clear_pte(&pte[i], pte[i], freelist);
+		free_clear_pte(&pte[i], pte[i], &freelist);
 
-	if (freelist != NULL)
+	if (!list_empty(&freelist))
 		updated = true;
 
 	if (count > 1) {
@@ -437,7 +423,7 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova,
 	}
 
 	/* Everything flushed out, free pages now */
-	free_page_list(freelist);
+	put_pages_list(&freelist);
 
 	return ret;
 }
@@ -499,7 +485,7 @@ static void v1_free_pgtable(struct io_pgtable *iop)
 {
 	struct amd_io_pgtable *pgtable = container_of(iop, struct amd_io_pgtable, iop);
 	struct protection_domain *dom;
-	struct page *freelist = NULL;
+	LIST_HEAD(freelist);
 
 	if (pgtable->mode == PAGE_MODE_NONE)
 		return;
@@ -516,9 +502,9 @@ static void v1_free_pgtable(struct io_pgtable *iop)
 	BUG_ON(pgtable->mode < PAGE_MODE_NONE ||
 	       pgtable->mode > PAGE_MODE_6_LEVEL);
 
-	freelist = free_sub_pt(pgtable->root, pgtable->mode, freelist);
+	free_sub_pt(pgtable->root, pgtable->mode, &freelist);
 
-	free_page_list(freelist);
+	put_pages_list(&freelist);
 }
 
 static struct io_pgtable *v1_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
-- 
2.28.0.dirty


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

* [PATCH v2 07/11] iommu/amd: Use put_pages_list
@ 2021-12-10 17:54   ` Robin Murphy
  0 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will; +Cc: linux-kernel, willy, linux-mm, iommu

From: "Matthew Wilcox (Oracle)" <willy@infradead.org>

page->freelist is for the use of slab.  We already have the ability
to free a list of pages in the core mm, but it requires the use of a
list_head and for the pages to be chained together through page->lru.
Switch the AMD IOMMU code over to using free_pages_list().

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
[rm: split from original patch, cosmetic tweaks]
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: No change

 drivers/iommu/amd/io_pgtable.c | 50 ++++++++++++----------------------
 1 file changed, 18 insertions(+), 32 deletions(-)

diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c
index 4165e1372b6e..b1bf4125b0f7 100644
--- a/drivers/iommu/amd/io_pgtable.c
+++ b/drivers/iommu/amd/io_pgtable.c
@@ -74,26 +74,14 @@ static u64 *first_pte_l7(u64 *pte, unsigned long *page_size,
  *
  ****************************************************************************/
 
-static void free_page_list(struct page *freelist)
-{
-	while (freelist != NULL) {
-		unsigned long p = (unsigned long)page_address(freelist);
-
-		freelist = freelist->freelist;
-		free_page(p);
-	}
-}
-
-static struct page *free_pt_page(u64 *pt, struct page *freelist)
+static void free_pt_page(u64 *pt, struct list_head *freelist)
 {
 	struct page *p = virt_to_page(pt);
 
-	p->freelist = freelist;
-
-	return p;
+	list_add_tail(&p->lru, freelist);
 }
 
-static struct page *free_pt_lvl(u64 *pt, struct page *freelist, int lvl)
+static void free_pt_lvl(u64 *pt, struct list_head *freelist, int lvl)
 {
 	u64 *p;
 	int i;
@@ -114,22 +102,22 @@ static struct page *free_pt_lvl(u64 *pt, struct page *freelist, int lvl)
 		 */
 		p = IOMMU_PTE_PAGE(pt[i]);
 		if (lvl > 2)
-			freelist = free_pt_lvl(p, freelist, lvl - 1);
+			free_pt_lvl(p, freelist, lvl - 1);
 		else
-			freelist = free_pt_page(p, freelist);
+			free_pt_page(p, freelist);
 	}
 
-	return free_pt_page(pt, freelist);
+	free_pt_page(pt, freelist);
 }
 
-static struct page *free_sub_pt(u64 *root, int mode, struct page *freelist)
+static void free_sub_pt(u64 *root, int mode, struct list_head *freelist)
 {
 	switch (mode) {
 	case PAGE_MODE_NONE:
 	case PAGE_MODE_7_LEVEL:
 		break;
 	case PAGE_MODE_1_LEVEL:
-		freelist = free_pt_page(root, freelist);
+		free_pt_page(root, freelist);
 		break;
 	case PAGE_MODE_2_LEVEL:
 	case PAGE_MODE_3_LEVEL:
@@ -141,8 +129,6 @@ static struct page *free_sub_pt(u64 *root, int mode, struct page *freelist)
 	default:
 		BUG();
 	}
-
-	return freelist;
 }
 
 void amd_iommu_domain_set_pgtable(struct protection_domain *domain,
@@ -350,7 +336,7 @@ static u64 *fetch_pte(struct amd_io_pgtable *pgtable,
 	return pte;
 }
 
-static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist)
+static void free_clear_pte(u64 *pte, u64 pteval, struct list_head *freelist)
 {
 	u64 *pt;
 	int mode;
@@ -361,12 +347,12 @@ static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist)
 	}
 
 	if (!IOMMU_PTE_PRESENT(pteval))
-		return freelist;
+		return;
 
 	pt   = IOMMU_PTE_PAGE(pteval);
 	mode = IOMMU_PTE_MODE(pteval);
 
-	return free_sub_pt(pt, mode, freelist);
+	free_sub_pt(pt, mode, freelist);
 }
 
 /*
@@ -380,7 +366,7 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova,
 			  phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
 {
 	struct protection_domain *dom = io_pgtable_ops_to_domain(ops);
-	struct page *freelist = NULL;
+	LIST_HEAD(freelist);
 	bool updated = false;
 	u64 __pte, *pte;
 	int ret, i, count;
@@ -400,9 +386,9 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova,
 		goto out;
 
 	for (i = 0; i < count; ++i)
-		freelist = free_clear_pte(&pte[i], pte[i], freelist);
+		free_clear_pte(&pte[i], pte[i], &freelist);
 
-	if (freelist != NULL)
+	if (!list_empty(&freelist))
 		updated = true;
 
 	if (count > 1) {
@@ -437,7 +423,7 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova,
 	}
 
 	/* Everything flushed out, free pages now */
-	free_page_list(freelist);
+	put_pages_list(&freelist);
 
 	return ret;
 }
@@ -499,7 +485,7 @@ static void v1_free_pgtable(struct io_pgtable *iop)
 {
 	struct amd_io_pgtable *pgtable = container_of(iop, struct amd_io_pgtable, iop);
 	struct protection_domain *dom;
-	struct page *freelist = NULL;
+	LIST_HEAD(freelist);
 
 	if (pgtable->mode == PAGE_MODE_NONE)
 		return;
@@ -516,9 +502,9 @@ static void v1_free_pgtable(struct io_pgtable *iop)
 	BUG_ON(pgtable->mode < PAGE_MODE_NONE ||
 	       pgtable->mode > PAGE_MODE_6_LEVEL);
 
-	freelist = free_sub_pt(pgtable->root, pgtable->mode, freelist);
+	free_sub_pt(pgtable->root, pgtable->mode, &freelist);
 
-	free_page_list(freelist);
+	put_pages_list(&freelist);
 }
 
 static struct io_pgtable *v1_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
-- 
2.28.0.dirty

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

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

* [PATCH v2 08/11] iommu/vt-d: Use put_pages_list
  2021-12-10 17:54 ` Robin Murphy
@ 2021-12-10 17:54   ` Robin Murphy
  -1 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel,
	john.garry, linux-mm

From: "Matthew Wilcox (Oracle)" <willy@infradead.org>

page->freelist is for the use of slab.  We already have the ability
to free a list of pages in the core mm, but it requires the use of a
list_head and for the pages to be chained together through page->lru.
Switch the Intel IOMMU and IOVA code over to using free_pages_list().

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
[rm: split from original patch, cosmetic tweaks, fix fq entries]
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: No change

 drivers/iommu/dma-iommu.c   |  2 +-
 drivers/iommu/intel/iommu.c | 89 +++++++++++++------------------------
 drivers/iommu/iova.c        | 26 ++++-------
 include/linux/iommu.h       |  3 +-
 include/linux/iova.h        |  4 +-
 5 files changed, 45 insertions(+), 79 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index cde887530549..f139b77caee0 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -455,7 +455,7 @@ static void iommu_dma_free_iova(struct iommu_dma_cookie *cookie,
 	else if (gather && gather->queued)
 		queue_iova(iovad, iova_pfn(iovad, iova),
 				size >> iova_shift(iovad),
-				gather->freelist);
+				&gather->freelist);
 	else
 		free_iova_fast(iovad, iova_pfn(iovad, iova),
 				size >> iova_shift(iovad));
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index b6a8f3282411..17b3d97111f3 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -1303,35 +1303,30 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain,
    know the hardware page-walk will no longer touch them.
    The 'pte' argument is the *parent* PTE, pointing to the page that is to
    be freed. */
-static struct page *dma_pte_list_pagetables(struct dmar_domain *domain,
-					    int level, struct dma_pte *pte,
-					    struct page *freelist)
+static void dma_pte_list_pagetables(struct dmar_domain *domain,
+				    int level, struct dma_pte *pte,
+				    struct list_head *freelist)
 {
 	struct page *pg;
 
 	pg = pfn_to_page(dma_pte_addr(pte) >> PAGE_SHIFT);
-	pg->freelist = freelist;
-	freelist = pg;
+	list_add_tail(&pg->lru, freelist);
 
 	if (level == 1)
-		return freelist;
+		return;
 
 	pte = page_address(pg);
 	do {
 		if (dma_pte_present(pte) && !dma_pte_superpage(pte))
-			freelist = dma_pte_list_pagetables(domain, level - 1,
-							   pte, freelist);
+			dma_pte_list_pagetables(domain, level - 1, pte, freelist);
 		pte++;
 	} while (!first_pte_in_page(pte));
-
-	return freelist;
 }
 
-static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
-					struct dma_pte *pte, unsigned long pfn,
-					unsigned long start_pfn,
-					unsigned long last_pfn,
-					struct page *freelist)
+static void dma_pte_clear_level(struct dmar_domain *domain, int level,
+				struct dma_pte *pte, unsigned long pfn,
+				unsigned long start_pfn, unsigned long last_pfn,
+				struct list_head *freelist)
 {
 	struct dma_pte *first_pte = NULL, *last_pte = NULL;
 
@@ -1350,7 +1345,7 @@ static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
 			/* These suborbinate page tables are going away entirely. Don't
 			   bother to clear them; we're just going to *free* them. */
 			if (level > 1 && !dma_pte_superpage(pte))
-				freelist = dma_pte_list_pagetables(domain, level - 1, pte, freelist);
+				dma_pte_list_pagetables(domain, level - 1, pte, freelist);
 
 			dma_clear_pte(pte);
 			if (!first_pte)
@@ -1358,10 +1353,10 @@ static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
 			last_pte = pte;
 		} else if (level > 1) {
 			/* Recurse down into a level that isn't *entirely* obsolete */
-			freelist = dma_pte_clear_level(domain, level - 1,
-						       phys_to_virt(dma_pte_addr(pte)),
-						       level_pfn, start_pfn, last_pfn,
-						       freelist);
+			dma_pte_clear_level(domain, level - 1,
+					    phys_to_virt(dma_pte_addr(pte)),
+					    level_pfn, start_pfn, last_pfn,
+					    freelist);
 		}
 next:
 		pfn = level_pfn + level_size(level);
@@ -1370,47 +1365,28 @@ static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
 	if (first_pte)
 		domain_flush_cache(domain, first_pte,
 				   (void *)++last_pte - (void *)first_pte);
-
-	return freelist;
 }
 
 /* We can't just free the pages because the IOMMU may still be walking
    the page tables, and may have cached the intermediate levels. The
    pages can only be freed after the IOTLB flush has been done. */
-static struct page *domain_unmap(struct dmar_domain *domain,
-				 unsigned long start_pfn,
-				 unsigned long last_pfn,
-				 struct page *freelist)
+static void domain_unmap(struct dmar_domain *domain, unsigned long start_pfn,
+			 unsigned long last_pfn, struct list_head *freelist)
 {
 	BUG_ON(!domain_pfn_supported(domain, start_pfn));
 	BUG_ON(!domain_pfn_supported(domain, last_pfn));
 	BUG_ON(start_pfn > last_pfn);
 
 	/* we don't need lock here; nobody else touches the iova range */
-	freelist = dma_pte_clear_level(domain, agaw_to_level(domain->agaw),
-				       domain->pgd, 0, start_pfn, last_pfn,
-				       freelist);
+	dma_pte_clear_level(domain, agaw_to_level(domain->agaw),
+			    domain->pgd, 0, start_pfn, last_pfn, freelist);
 
 	/* free pgd */
 	if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
 		struct page *pgd_page = virt_to_page(domain->pgd);
-		pgd_page->freelist = freelist;
-		freelist = pgd_page;
-
+		list_add_tail(&pgd_page->lru, freelist);
 		domain->pgd = NULL;
 	}
-
-	return freelist;
-}
-
-static void dma_free_pagelist(struct page *freelist)
-{
-	struct page *pg;
-
-	while ((pg = freelist)) {
-		freelist = pg->freelist;
-		free_pgtable_page(page_address(pg));
-	}
 }
 
 /* iommu handling */
@@ -2095,11 +2071,10 @@ static void domain_exit(struct dmar_domain *domain)
 	domain_remove_dev_info(domain);
 
 	if (domain->pgd) {
-		struct page *freelist;
+		LIST_HEAD(freelist);
 
-		freelist = domain_unmap(domain, 0,
-					DOMAIN_MAX_PFN(domain->gaw), NULL);
-		dma_free_pagelist(freelist);
+		domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw), &freelist);
+		put_pages_list(&freelist);
 	}
 
 	free_domain_mem(domain);
@@ -4192,19 +4167,17 @@ static int intel_iommu_memory_notifier(struct notifier_block *nb,
 		{
 			struct dmar_drhd_unit *drhd;
 			struct intel_iommu *iommu;
-			struct page *freelist;
+			LIST_HEAD(freelist);
 
-			freelist = domain_unmap(si_domain,
-						start_vpfn, last_vpfn,
-						NULL);
+			domain_unmap(si_domain, start_vpfn, last_vpfn, &freelist);
 
 			rcu_read_lock();
 			for_each_active_iommu(iommu, drhd)
 				iommu_flush_iotlb_psi(iommu, si_domain,
 					start_vpfn, mhp->nr_pages,
-					!freelist, 0);
+					list_empty(&freelist), 0);
 			rcu_read_unlock();
-			dma_free_pagelist(freelist);
+			put_pages_list(&freelist);
 		}
 		break;
 	}
@@ -5211,8 +5184,7 @@ static size_t intel_iommu_unmap(struct iommu_domain *domain,
 	start_pfn = iova >> VTD_PAGE_SHIFT;
 	last_pfn = (iova + size - 1) >> VTD_PAGE_SHIFT;
 
-	gather->freelist = domain_unmap(dmar_domain, start_pfn,
-					last_pfn, gather->freelist);
+	domain_unmap(dmar_domain, start_pfn, last_pfn, &gather->freelist);
 
 	if (dmar_domain->max_addr == iova + size)
 		dmar_domain->max_addr = iova;
@@ -5248,9 +5220,10 @@ static void intel_iommu_tlb_sync(struct iommu_domain *domain,
 
 	for_each_domain_iommu(iommu_id, dmar_domain)
 		iommu_flush_iotlb_psi(g_iommus[iommu_id], dmar_domain,
-				      start_pfn, nrpages, !gather->freelist, 0);
+				      start_pfn, nrpages,
+				      list_empty(&gather->freelist), 0);
 
-	dma_free_pagelist(gather->freelist);
+	put_pages_list(&gather->freelist);
 }
 
 static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 76bc6f39fac7..a0250cebcdcf 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -96,7 +96,7 @@ static void free_iova_flush_queue(struct iova_domain *iovad)
 int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain)
 {
 	struct iova_fq __percpu *queue;
-	int cpu;
+	int i, cpu;
 
 	atomic64_set(&iovad->fq_flush_start_cnt,  0);
 	atomic64_set(&iovad->fq_flush_finish_cnt, 0);
@@ -113,6 +113,9 @@ int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_dom
 		fq->tail = 0;
 
 		spin_lock_init(&fq->lock);
+
+		for (i = 0; i < IOVA_FQ_SIZE; i++)
+			INIT_LIST_HEAD(&fq->entries[i].freelist);
 	}
 
 	iovad->fq_domain = fq_domain;
@@ -534,16 +537,6 @@ free_iova_fast(struct iova_domain *iovad, unsigned long pfn, unsigned long size)
 }
 EXPORT_SYMBOL_GPL(free_iova_fast);
 
-static void fq_entry_dtor(struct page *freelist)
-{
-	while (freelist) {
-		unsigned long p = (unsigned long)page_address(freelist);
-
-		freelist = freelist->freelist;
-		free_page(p);
-	}
-}
-
 #define fq_ring_for_each(i, fq) \
 	for ((i) = (fq)->head; (i) != (fq)->tail; (i) = ((i) + 1) % IOVA_FQ_SIZE)
 
@@ -576,7 +569,7 @@ static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
 		if (fq->entries[idx].counter >= counter)
 			break;
 
-		fq_entry_dtor(fq->entries[idx].freelist);
+		put_pages_list(&fq->entries[idx].freelist);
 		free_iova_fast(iovad,
 			       fq->entries[idx].iova_pfn,
 			       fq->entries[idx].pages);
@@ -598,15 +591,14 @@ static void fq_destroy_all_entries(struct iova_domain *iovad)
 
 	/*
 	 * This code runs when the iova_domain is being detroyed, so don't
-	 * bother to free iovas, just call the entry_dtor on all remaining
-	 * entries.
+	 * bother to free iovas, just free any remaining pagetable pages.
 	 */
 	for_each_possible_cpu(cpu) {
 		struct iova_fq *fq = per_cpu_ptr(iovad->fq, cpu);
 		int idx;
 
 		fq_ring_for_each(idx, fq)
-			fq_entry_dtor(fq->entries[idx].freelist);
+			put_pages_list(&fq->entries[idx].freelist);
 	}
 }
 
@@ -631,7 +623,7 @@ static void fq_flush_timeout(struct timer_list *t)
 
 void queue_iova(struct iova_domain *iovad,
 		unsigned long pfn, unsigned long pages,
-		struct page *freelist)
+		struct list_head *freelist)
 {
 	struct iova_fq *fq;
 	unsigned long flags;
@@ -665,8 +657,8 @@ void queue_iova(struct iova_domain *iovad,
 
 	fq->entries[idx].iova_pfn = pfn;
 	fq->entries[idx].pages    = pages;
-	fq->entries[idx].freelist = freelist;
 	fq->entries[idx].counter  = atomic64_read(&iovad->fq_flush_start_cnt);
+	list_splice(freelist, &fq->entries[idx].freelist);
 
 	spin_unlock_irqrestore(&fq->lock, flags);
 
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index d2f3435e7d17..de0c57a567c8 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -186,7 +186,7 @@ struct iommu_iotlb_gather {
 	unsigned long		start;
 	unsigned long		end;
 	size_t			pgsize;
-	struct page		*freelist;
+	struct list_head	freelist;
 	bool			queued;
 };
 
@@ -399,6 +399,7 @@ static inline void iommu_iotlb_gather_init(struct iommu_iotlb_gather *gather)
 {
 	*gather = (struct iommu_iotlb_gather) {
 		.start	= ULONG_MAX,
+		.freelist = LIST_HEAD_INIT(gather->freelist),
 	};
 }
 
diff --git a/include/linux/iova.h b/include/linux/iova.h
index 99be4fcea4f3..072a09c06e8a 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -46,7 +46,7 @@ struct iova_rcache {
 struct iova_fq_entry {
 	unsigned long iova_pfn;
 	unsigned long pages;
-	struct page *freelist;
+	struct list_head freelist;
 	u64 counter; /* Flush counter when this entrie was added */
 };
 
@@ -135,7 +135,7 @@ void free_iova_fast(struct iova_domain *iovad, unsigned long pfn,
 		    unsigned long size);
 void queue_iova(struct iova_domain *iovad,
 		unsigned long pfn, unsigned long pages,
-		struct page *freelist);
+		struct list_head *freelist);
 unsigned long alloc_iova_fast(struct iova_domain *iovad, unsigned long size,
 			      unsigned long limit_pfn, bool flush_rcache);
 struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
-- 
2.28.0.dirty


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

* [PATCH v2 08/11] iommu/vt-d: Use put_pages_list
@ 2021-12-10 17:54   ` Robin Murphy
  0 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will; +Cc: linux-kernel, willy, linux-mm, iommu

From: "Matthew Wilcox (Oracle)" <willy@infradead.org>

page->freelist is for the use of slab.  We already have the ability
to free a list of pages in the core mm, but it requires the use of a
list_head and for the pages to be chained together through page->lru.
Switch the Intel IOMMU and IOVA code over to using free_pages_list().

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
[rm: split from original patch, cosmetic tweaks, fix fq entries]
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: No change

 drivers/iommu/dma-iommu.c   |  2 +-
 drivers/iommu/intel/iommu.c | 89 +++++++++++++------------------------
 drivers/iommu/iova.c        | 26 ++++-------
 include/linux/iommu.h       |  3 +-
 include/linux/iova.h        |  4 +-
 5 files changed, 45 insertions(+), 79 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index cde887530549..f139b77caee0 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -455,7 +455,7 @@ static void iommu_dma_free_iova(struct iommu_dma_cookie *cookie,
 	else if (gather && gather->queued)
 		queue_iova(iovad, iova_pfn(iovad, iova),
 				size >> iova_shift(iovad),
-				gather->freelist);
+				&gather->freelist);
 	else
 		free_iova_fast(iovad, iova_pfn(iovad, iova),
 				size >> iova_shift(iovad));
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index b6a8f3282411..17b3d97111f3 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -1303,35 +1303,30 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain,
    know the hardware page-walk will no longer touch them.
    The 'pte' argument is the *parent* PTE, pointing to the page that is to
    be freed. */
-static struct page *dma_pte_list_pagetables(struct dmar_domain *domain,
-					    int level, struct dma_pte *pte,
-					    struct page *freelist)
+static void dma_pte_list_pagetables(struct dmar_domain *domain,
+				    int level, struct dma_pte *pte,
+				    struct list_head *freelist)
 {
 	struct page *pg;
 
 	pg = pfn_to_page(dma_pte_addr(pte) >> PAGE_SHIFT);
-	pg->freelist = freelist;
-	freelist = pg;
+	list_add_tail(&pg->lru, freelist);
 
 	if (level == 1)
-		return freelist;
+		return;
 
 	pte = page_address(pg);
 	do {
 		if (dma_pte_present(pte) && !dma_pte_superpage(pte))
-			freelist = dma_pte_list_pagetables(domain, level - 1,
-							   pte, freelist);
+			dma_pte_list_pagetables(domain, level - 1, pte, freelist);
 		pte++;
 	} while (!first_pte_in_page(pte));
-
-	return freelist;
 }
 
-static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
-					struct dma_pte *pte, unsigned long pfn,
-					unsigned long start_pfn,
-					unsigned long last_pfn,
-					struct page *freelist)
+static void dma_pte_clear_level(struct dmar_domain *domain, int level,
+				struct dma_pte *pte, unsigned long pfn,
+				unsigned long start_pfn, unsigned long last_pfn,
+				struct list_head *freelist)
 {
 	struct dma_pte *first_pte = NULL, *last_pte = NULL;
 
@@ -1350,7 +1345,7 @@ static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
 			/* These suborbinate page tables are going away entirely. Don't
 			   bother to clear them; we're just going to *free* them. */
 			if (level > 1 && !dma_pte_superpage(pte))
-				freelist = dma_pte_list_pagetables(domain, level - 1, pte, freelist);
+				dma_pte_list_pagetables(domain, level - 1, pte, freelist);
 
 			dma_clear_pte(pte);
 			if (!first_pte)
@@ -1358,10 +1353,10 @@ static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
 			last_pte = pte;
 		} else if (level > 1) {
 			/* Recurse down into a level that isn't *entirely* obsolete */
-			freelist = dma_pte_clear_level(domain, level - 1,
-						       phys_to_virt(dma_pte_addr(pte)),
-						       level_pfn, start_pfn, last_pfn,
-						       freelist);
+			dma_pte_clear_level(domain, level - 1,
+					    phys_to_virt(dma_pte_addr(pte)),
+					    level_pfn, start_pfn, last_pfn,
+					    freelist);
 		}
 next:
 		pfn = level_pfn + level_size(level);
@@ -1370,47 +1365,28 @@ static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
 	if (first_pte)
 		domain_flush_cache(domain, first_pte,
 				   (void *)++last_pte - (void *)first_pte);
-
-	return freelist;
 }
 
 /* We can't just free the pages because the IOMMU may still be walking
    the page tables, and may have cached the intermediate levels. The
    pages can only be freed after the IOTLB flush has been done. */
-static struct page *domain_unmap(struct dmar_domain *domain,
-				 unsigned long start_pfn,
-				 unsigned long last_pfn,
-				 struct page *freelist)
+static void domain_unmap(struct dmar_domain *domain, unsigned long start_pfn,
+			 unsigned long last_pfn, struct list_head *freelist)
 {
 	BUG_ON(!domain_pfn_supported(domain, start_pfn));
 	BUG_ON(!domain_pfn_supported(domain, last_pfn));
 	BUG_ON(start_pfn > last_pfn);
 
 	/* we don't need lock here; nobody else touches the iova range */
-	freelist = dma_pte_clear_level(domain, agaw_to_level(domain->agaw),
-				       domain->pgd, 0, start_pfn, last_pfn,
-				       freelist);
+	dma_pte_clear_level(domain, agaw_to_level(domain->agaw),
+			    domain->pgd, 0, start_pfn, last_pfn, freelist);
 
 	/* free pgd */
 	if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
 		struct page *pgd_page = virt_to_page(domain->pgd);
-		pgd_page->freelist = freelist;
-		freelist = pgd_page;
-
+		list_add_tail(&pgd_page->lru, freelist);
 		domain->pgd = NULL;
 	}
-
-	return freelist;
-}
-
-static void dma_free_pagelist(struct page *freelist)
-{
-	struct page *pg;
-
-	while ((pg = freelist)) {
-		freelist = pg->freelist;
-		free_pgtable_page(page_address(pg));
-	}
 }
 
 /* iommu handling */
@@ -2095,11 +2071,10 @@ static void domain_exit(struct dmar_domain *domain)
 	domain_remove_dev_info(domain);
 
 	if (domain->pgd) {
-		struct page *freelist;
+		LIST_HEAD(freelist);
 
-		freelist = domain_unmap(domain, 0,
-					DOMAIN_MAX_PFN(domain->gaw), NULL);
-		dma_free_pagelist(freelist);
+		domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw), &freelist);
+		put_pages_list(&freelist);
 	}
 
 	free_domain_mem(domain);
@@ -4192,19 +4167,17 @@ static int intel_iommu_memory_notifier(struct notifier_block *nb,
 		{
 			struct dmar_drhd_unit *drhd;
 			struct intel_iommu *iommu;
-			struct page *freelist;
+			LIST_HEAD(freelist);
 
-			freelist = domain_unmap(si_domain,
-						start_vpfn, last_vpfn,
-						NULL);
+			domain_unmap(si_domain, start_vpfn, last_vpfn, &freelist);
 
 			rcu_read_lock();
 			for_each_active_iommu(iommu, drhd)
 				iommu_flush_iotlb_psi(iommu, si_domain,
 					start_vpfn, mhp->nr_pages,
-					!freelist, 0);
+					list_empty(&freelist), 0);
 			rcu_read_unlock();
-			dma_free_pagelist(freelist);
+			put_pages_list(&freelist);
 		}
 		break;
 	}
@@ -5211,8 +5184,7 @@ static size_t intel_iommu_unmap(struct iommu_domain *domain,
 	start_pfn = iova >> VTD_PAGE_SHIFT;
 	last_pfn = (iova + size - 1) >> VTD_PAGE_SHIFT;
 
-	gather->freelist = domain_unmap(dmar_domain, start_pfn,
-					last_pfn, gather->freelist);
+	domain_unmap(dmar_domain, start_pfn, last_pfn, &gather->freelist);
 
 	if (dmar_domain->max_addr == iova + size)
 		dmar_domain->max_addr = iova;
@@ -5248,9 +5220,10 @@ static void intel_iommu_tlb_sync(struct iommu_domain *domain,
 
 	for_each_domain_iommu(iommu_id, dmar_domain)
 		iommu_flush_iotlb_psi(g_iommus[iommu_id], dmar_domain,
-				      start_pfn, nrpages, !gather->freelist, 0);
+				      start_pfn, nrpages,
+				      list_empty(&gather->freelist), 0);
 
-	dma_free_pagelist(gather->freelist);
+	put_pages_list(&gather->freelist);
 }
 
 static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 76bc6f39fac7..a0250cebcdcf 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -96,7 +96,7 @@ static void free_iova_flush_queue(struct iova_domain *iovad)
 int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain)
 {
 	struct iova_fq __percpu *queue;
-	int cpu;
+	int i, cpu;
 
 	atomic64_set(&iovad->fq_flush_start_cnt,  0);
 	atomic64_set(&iovad->fq_flush_finish_cnt, 0);
@@ -113,6 +113,9 @@ int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_dom
 		fq->tail = 0;
 
 		spin_lock_init(&fq->lock);
+
+		for (i = 0; i < IOVA_FQ_SIZE; i++)
+			INIT_LIST_HEAD(&fq->entries[i].freelist);
 	}
 
 	iovad->fq_domain = fq_domain;
@@ -534,16 +537,6 @@ free_iova_fast(struct iova_domain *iovad, unsigned long pfn, unsigned long size)
 }
 EXPORT_SYMBOL_GPL(free_iova_fast);
 
-static void fq_entry_dtor(struct page *freelist)
-{
-	while (freelist) {
-		unsigned long p = (unsigned long)page_address(freelist);
-
-		freelist = freelist->freelist;
-		free_page(p);
-	}
-}
-
 #define fq_ring_for_each(i, fq) \
 	for ((i) = (fq)->head; (i) != (fq)->tail; (i) = ((i) + 1) % IOVA_FQ_SIZE)
 
@@ -576,7 +569,7 @@ static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
 		if (fq->entries[idx].counter >= counter)
 			break;
 
-		fq_entry_dtor(fq->entries[idx].freelist);
+		put_pages_list(&fq->entries[idx].freelist);
 		free_iova_fast(iovad,
 			       fq->entries[idx].iova_pfn,
 			       fq->entries[idx].pages);
@@ -598,15 +591,14 @@ static void fq_destroy_all_entries(struct iova_domain *iovad)
 
 	/*
 	 * This code runs when the iova_domain is being detroyed, so don't
-	 * bother to free iovas, just call the entry_dtor on all remaining
-	 * entries.
+	 * bother to free iovas, just free any remaining pagetable pages.
 	 */
 	for_each_possible_cpu(cpu) {
 		struct iova_fq *fq = per_cpu_ptr(iovad->fq, cpu);
 		int idx;
 
 		fq_ring_for_each(idx, fq)
-			fq_entry_dtor(fq->entries[idx].freelist);
+			put_pages_list(&fq->entries[idx].freelist);
 	}
 }
 
@@ -631,7 +623,7 @@ static void fq_flush_timeout(struct timer_list *t)
 
 void queue_iova(struct iova_domain *iovad,
 		unsigned long pfn, unsigned long pages,
-		struct page *freelist)
+		struct list_head *freelist)
 {
 	struct iova_fq *fq;
 	unsigned long flags;
@@ -665,8 +657,8 @@ void queue_iova(struct iova_domain *iovad,
 
 	fq->entries[idx].iova_pfn = pfn;
 	fq->entries[idx].pages    = pages;
-	fq->entries[idx].freelist = freelist;
 	fq->entries[idx].counter  = atomic64_read(&iovad->fq_flush_start_cnt);
+	list_splice(freelist, &fq->entries[idx].freelist);
 
 	spin_unlock_irqrestore(&fq->lock, flags);
 
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index d2f3435e7d17..de0c57a567c8 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -186,7 +186,7 @@ struct iommu_iotlb_gather {
 	unsigned long		start;
 	unsigned long		end;
 	size_t			pgsize;
-	struct page		*freelist;
+	struct list_head	freelist;
 	bool			queued;
 };
 
@@ -399,6 +399,7 @@ static inline void iommu_iotlb_gather_init(struct iommu_iotlb_gather *gather)
 {
 	*gather = (struct iommu_iotlb_gather) {
 		.start	= ULONG_MAX,
+		.freelist = LIST_HEAD_INIT(gather->freelist),
 	};
 }
 
diff --git a/include/linux/iova.h b/include/linux/iova.h
index 99be4fcea4f3..072a09c06e8a 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -46,7 +46,7 @@ struct iova_rcache {
 struct iova_fq_entry {
 	unsigned long iova_pfn;
 	unsigned long pages;
-	struct page *freelist;
+	struct list_head freelist;
 	u64 counter; /* Flush counter when this entrie was added */
 };
 
@@ -135,7 +135,7 @@ void free_iova_fast(struct iova_domain *iovad, unsigned long pfn,
 		    unsigned long size);
 void queue_iova(struct iova_domain *iovad,
 		unsigned long pfn, unsigned long pages,
-		struct page *freelist);
+		struct list_head *freelist);
 unsigned long alloc_iova_fast(struct iova_domain *iovad, unsigned long size,
 			      unsigned long limit_pfn, bool flush_rcache);
 struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
-- 
2.28.0.dirty

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

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

* [PATCH v2 09/11] iommu/iova: Consolidate flush queue code
  2021-12-10 17:54 ` Robin Murphy
@ 2021-12-10 17:54   ` Robin Murphy
  -1 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel,
	john.garry, linux-mm

Squash and simplify some of the freeing code, and move the init
and free routines down into the rest of the flush queue code to
obviate the forward declarations.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: Rebase with del_timer_sync() change

 drivers/iommu/iova.c | 131 +++++++++++++++++++------------------------
 1 file changed, 58 insertions(+), 73 deletions(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index a0250cebcdcf..c19f9a749070 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -24,8 +24,6 @@ static unsigned long iova_rcache_get(struct iova_domain *iovad,
 static void init_iova_rcaches(struct iova_domain *iovad);
 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);
-static void fq_flush_timeout(struct timer_list *t);
 
 static int iova_cpuhp_dead(unsigned int cpu, struct hlist_node *node)
 {
@@ -73,60 +71,6 @@ init_iova_domain(struct iova_domain *iovad, unsigned long granule,
 }
 EXPORT_SYMBOL_GPL(init_iova_domain);
 
-static bool has_iova_flush_queue(struct iova_domain *iovad)
-{
-	return !!iovad->fq;
-}
-
-static void free_iova_flush_queue(struct iova_domain *iovad)
-{
-	if (!has_iova_flush_queue(iovad))
-		return;
-
-	del_timer_sync(&iovad->fq_timer);
-
-	fq_destroy_all_entries(iovad);
-
-	free_percpu(iovad->fq);
-
-	iovad->fq         = NULL;
-	iovad->fq_domain  = NULL;
-}
-
-int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain)
-{
-	struct iova_fq __percpu *queue;
-	int i, cpu;
-
-	atomic64_set(&iovad->fq_flush_start_cnt,  0);
-	atomic64_set(&iovad->fq_flush_finish_cnt, 0);
-
-	queue = alloc_percpu(struct iova_fq);
-	if (!queue)
-		return -ENOMEM;
-
-	for_each_possible_cpu(cpu) {
-		struct iova_fq *fq;
-
-		fq = per_cpu_ptr(queue, cpu);
-		fq->head = 0;
-		fq->tail = 0;
-
-		spin_lock_init(&fq->lock);
-
-		for (i = 0; i < IOVA_FQ_SIZE; i++)
-			INIT_LIST_HEAD(&fq->entries[i].freelist);
-	}
-
-	iovad->fq_domain = fq_domain;
-	iovad->fq = queue;
-
-	timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
-	atomic_set(&iovad->fq_timer_on, 0);
-
-	return 0;
-}
-
 static struct rb_node *
 __get_cached_rbnode(struct iova_domain *iovad, unsigned long limit_pfn)
 {
@@ -585,23 +529,6 @@ static void iova_domain_flush(struct iova_domain *iovad)
 	atomic64_inc(&iovad->fq_flush_finish_cnt);
 }
 
-static void fq_destroy_all_entries(struct iova_domain *iovad)
-{
-	int cpu;
-
-	/*
-	 * This code runs when the iova_domain is being detroyed, so don't
-	 * bother to free iovas, just free any remaining pagetable pages.
-	 */
-	for_each_possible_cpu(cpu) {
-		struct iova_fq *fq = per_cpu_ptr(iovad->fq, cpu);
-		int idx;
-
-		fq_ring_for_each(idx, fq)
-			put_pages_list(&fq->entries[idx].freelist);
-	}
-}
-
 static void fq_flush_timeout(struct timer_list *t)
 {
 	struct iova_domain *iovad = from_timer(iovad, t, fq_timer);
@@ -669,6 +596,64 @@ void queue_iova(struct iova_domain *iovad,
 			  jiffies + msecs_to_jiffies(IOVA_FQ_TIMEOUT));
 }
 
+static void free_iova_flush_queue(struct iova_domain *iovad)
+{
+	int cpu, idx;
+
+	if (!iovad->fq)
+		return;
+
+	del_timer_sync(&iovad->fq_timer);
+	/*
+	 * This code runs when the iova_domain is being detroyed, so don't
+	 * bother to free iovas, just free any remaining pagetable pages.
+	 */
+	for_each_possible_cpu(cpu) {
+		struct iova_fq *fq = per_cpu_ptr(iovad->fq, cpu);
+
+		fq_ring_for_each(idx, fq)
+			put_pages_list(&fq->entries[idx].freelist);
+	}
+
+	free_percpu(iovad->fq);
+
+	iovad->fq = NULL;
+	iovad->fq_domain = NULL;
+}
+
+int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain)
+{
+	struct iova_fq __percpu *queue;
+	int i, cpu;
+
+	atomic64_set(&iovad->fq_flush_start_cnt,  0);
+	atomic64_set(&iovad->fq_flush_finish_cnt, 0);
+
+	queue = alloc_percpu(struct iova_fq);
+	if (!queue)
+		return -ENOMEM;
+
+	for_each_possible_cpu(cpu) {
+		struct iova_fq *fq = per_cpu_ptr(queue, cpu);
+
+		fq->head = 0;
+		fq->tail = 0;
+
+		spin_lock_init(&fq->lock);
+
+		for (i = 0; i < IOVA_FQ_SIZE; i++)
+			INIT_LIST_HEAD(&fq->entries[i].freelist);
+	}
+
+	iovad->fq_domain = fq_domain;
+	iovad->fq = queue;
+
+	timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
+	atomic_set(&iovad->fq_timer_on, 0);
+
+	return 0;
+}
+
 /**
  * put_iova_domain - destroys the iova domain
  * @iovad: - iova domain in question.
-- 
2.28.0.dirty


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

* [PATCH v2 09/11] iommu/iova: Consolidate flush queue code
@ 2021-12-10 17:54   ` Robin Murphy
  0 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will; +Cc: linux-kernel, willy, linux-mm, iommu

Squash and simplify some of the freeing code, and move the init
and free routines down into the rest of the flush queue code to
obviate the forward declarations.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: Rebase with del_timer_sync() change

 drivers/iommu/iova.c | 131 +++++++++++++++++++------------------------
 1 file changed, 58 insertions(+), 73 deletions(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index a0250cebcdcf..c19f9a749070 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -24,8 +24,6 @@ static unsigned long iova_rcache_get(struct iova_domain *iovad,
 static void init_iova_rcaches(struct iova_domain *iovad);
 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);
-static void fq_flush_timeout(struct timer_list *t);
 
 static int iova_cpuhp_dead(unsigned int cpu, struct hlist_node *node)
 {
@@ -73,60 +71,6 @@ init_iova_domain(struct iova_domain *iovad, unsigned long granule,
 }
 EXPORT_SYMBOL_GPL(init_iova_domain);
 
-static bool has_iova_flush_queue(struct iova_domain *iovad)
-{
-	return !!iovad->fq;
-}
-
-static void free_iova_flush_queue(struct iova_domain *iovad)
-{
-	if (!has_iova_flush_queue(iovad))
-		return;
-
-	del_timer_sync(&iovad->fq_timer);
-
-	fq_destroy_all_entries(iovad);
-
-	free_percpu(iovad->fq);
-
-	iovad->fq         = NULL;
-	iovad->fq_domain  = NULL;
-}
-
-int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain)
-{
-	struct iova_fq __percpu *queue;
-	int i, cpu;
-
-	atomic64_set(&iovad->fq_flush_start_cnt,  0);
-	atomic64_set(&iovad->fq_flush_finish_cnt, 0);
-
-	queue = alloc_percpu(struct iova_fq);
-	if (!queue)
-		return -ENOMEM;
-
-	for_each_possible_cpu(cpu) {
-		struct iova_fq *fq;
-
-		fq = per_cpu_ptr(queue, cpu);
-		fq->head = 0;
-		fq->tail = 0;
-
-		spin_lock_init(&fq->lock);
-
-		for (i = 0; i < IOVA_FQ_SIZE; i++)
-			INIT_LIST_HEAD(&fq->entries[i].freelist);
-	}
-
-	iovad->fq_domain = fq_domain;
-	iovad->fq = queue;
-
-	timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
-	atomic_set(&iovad->fq_timer_on, 0);
-
-	return 0;
-}
-
 static struct rb_node *
 __get_cached_rbnode(struct iova_domain *iovad, unsigned long limit_pfn)
 {
@@ -585,23 +529,6 @@ static void iova_domain_flush(struct iova_domain *iovad)
 	atomic64_inc(&iovad->fq_flush_finish_cnt);
 }
 
-static void fq_destroy_all_entries(struct iova_domain *iovad)
-{
-	int cpu;
-
-	/*
-	 * This code runs when the iova_domain is being detroyed, so don't
-	 * bother to free iovas, just free any remaining pagetable pages.
-	 */
-	for_each_possible_cpu(cpu) {
-		struct iova_fq *fq = per_cpu_ptr(iovad->fq, cpu);
-		int idx;
-
-		fq_ring_for_each(idx, fq)
-			put_pages_list(&fq->entries[idx].freelist);
-	}
-}
-
 static void fq_flush_timeout(struct timer_list *t)
 {
 	struct iova_domain *iovad = from_timer(iovad, t, fq_timer);
@@ -669,6 +596,64 @@ void queue_iova(struct iova_domain *iovad,
 			  jiffies + msecs_to_jiffies(IOVA_FQ_TIMEOUT));
 }
 
+static void free_iova_flush_queue(struct iova_domain *iovad)
+{
+	int cpu, idx;
+
+	if (!iovad->fq)
+		return;
+
+	del_timer_sync(&iovad->fq_timer);
+	/*
+	 * This code runs when the iova_domain is being detroyed, so don't
+	 * bother to free iovas, just free any remaining pagetable pages.
+	 */
+	for_each_possible_cpu(cpu) {
+		struct iova_fq *fq = per_cpu_ptr(iovad->fq, cpu);
+
+		fq_ring_for_each(idx, fq)
+			put_pages_list(&fq->entries[idx].freelist);
+	}
+
+	free_percpu(iovad->fq);
+
+	iovad->fq = NULL;
+	iovad->fq_domain = NULL;
+}
+
+int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain)
+{
+	struct iova_fq __percpu *queue;
+	int i, cpu;
+
+	atomic64_set(&iovad->fq_flush_start_cnt,  0);
+	atomic64_set(&iovad->fq_flush_finish_cnt, 0);
+
+	queue = alloc_percpu(struct iova_fq);
+	if (!queue)
+		return -ENOMEM;
+
+	for_each_possible_cpu(cpu) {
+		struct iova_fq *fq = per_cpu_ptr(queue, cpu);
+
+		fq->head = 0;
+		fq->tail = 0;
+
+		spin_lock_init(&fq->lock);
+
+		for (i = 0; i < IOVA_FQ_SIZE; i++)
+			INIT_LIST_HEAD(&fq->entries[i].freelist);
+	}
+
+	iovad->fq_domain = fq_domain;
+	iovad->fq = queue;
+
+	timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
+	atomic_set(&iovad->fq_timer_on, 0);
+
+	return 0;
+}
+
 /**
  * put_iova_domain - destroys the iova domain
  * @iovad: - iova domain in question.
-- 
2.28.0.dirty

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

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

* [PATCH v2 10/11] iommu/iova: Move flush queue code to iommu-dma
  2021-12-10 17:54 ` Robin Murphy
@ 2021-12-10 17:54   ` Robin Murphy
  -1 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel,
	john.garry, linux-mm

Flush queues are specific to DMA ops, which are now handled exclusively
by iommu-dma. As such, now that the historical artefacts from being
shared directly with drivers have been cleaned up, move the flush queue
code into iommu-dma itself to get it out of the way of other IOVA users.

This is pure code movement with no functional change; refactoring to
clean up the headers and definitions will follow.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: Rebase with del_timer_sync() change

 drivers/iommu/dma-iommu.c | 179 +++++++++++++++++++++++++++++++++++++-
 drivers/iommu/iova.c      | 175 -------------------------------------
 2 files changed, 178 insertions(+), 176 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index f139b77caee0..ab8818965b2f 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -64,6 +64,181 @@ static int __init iommu_dma_forcedac_setup(char *str)
 }
 early_param("iommu.forcedac", iommu_dma_forcedac_setup);
 
+
+#define fq_ring_for_each(i, fq) \
+	for ((i) = (fq)->head; (i) != (fq)->tail; (i) = ((i) + 1) % IOVA_FQ_SIZE)
+
+static inline bool fq_full(struct iova_fq *fq)
+{
+	assert_spin_locked(&fq->lock);
+	return (((fq->tail + 1) % IOVA_FQ_SIZE) == fq->head);
+}
+
+static inline unsigned fq_ring_add(struct iova_fq *fq)
+{
+	unsigned idx = fq->tail;
+
+	assert_spin_locked(&fq->lock);
+
+	fq->tail = (idx + 1) % IOVA_FQ_SIZE;
+
+	return idx;
+}
+
+static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
+{
+	u64 counter = atomic64_read(&iovad->fq_flush_finish_cnt);
+	unsigned idx;
+
+	assert_spin_locked(&fq->lock);
+
+	fq_ring_for_each(idx, fq) {
+
+		if (fq->entries[idx].counter >= counter)
+			break;
+
+		put_pages_list(&fq->entries[idx].freelist);
+		free_iova_fast(iovad,
+			       fq->entries[idx].iova_pfn,
+			       fq->entries[idx].pages);
+
+		fq->head = (fq->head + 1) % IOVA_FQ_SIZE;
+	}
+}
+
+static void iova_domain_flush(struct iova_domain *iovad)
+{
+	atomic64_inc(&iovad->fq_flush_start_cnt);
+	iovad->fq_domain->ops->flush_iotlb_all(iovad->fq_domain);
+	atomic64_inc(&iovad->fq_flush_finish_cnt);
+}
+
+static void fq_flush_timeout(struct timer_list *t)
+{
+	struct iova_domain *iovad = from_timer(iovad, t, fq_timer);
+	int cpu;
+
+	atomic_set(&iovad->fq_timer_on, 0);
+	iova_domain_flush(iovad);
+
+	for_each_possible_cpu(cpu) {
+		unsigned long flags;
+		struct iova_fq *fq;
+
+		fq = per_cpu_ptr(iovad->fq, cpu);
+		spin_lock_irqsave(&fq->lock, flags);
+		fq_ring_free(iovad, fq);
+		spin_unlock_irqrestore(&fq->lock, flags);
+	}
+}
+
+void queue_iova(struct iova_domain *iovad,
+		unsigned long pfn, unsigned long pages,
+		struct list_head *freelist)
+{
+	struct iova_fq *fq;
+	unsigned long flags;
+	unsigned idx;
+
+	/*
+	 * Order against the IOMMU driver's pagetable update from unmapping
+	 * @pte, to guarantee that iova_domain_flush() observes that if called
+	 * from a different CPU before we release the lock below. Full barrier
+	 * so it also pairs with iommu_dma_init_fq() to avoid seeing partially
+	 * written fq state here.
+	 */
+	smp_mb();
+
+	fq = raw_cpu_ptr(iovad->fq);
+	spin_lock_irqsave(&fq->lock, flags);
+
+	/*
+	 * First remove all entries from the flush queue that have already been
+	 * flushed out on another CPU. This makes the fq_full() check below less
+	 * likely to be true.
+	 */
+	fq_ring_free(iovad, fq);
+
+	if (fq_full(fq)) {
+		iova_domain_flush(iovad);
+		fq_ring_free(iovad, fq);
+	}
+
+	idx = fq_ring_add(fq);
+
+	fq->entries[idx].iova_pfn = pfn;
+	fq->entries[idx].pages    = pages;
+	fq->entries[idx].counter  = atomic64_read(&iovad->fq_flush_start_cnt);
+	list_splice(freelist, &fq->entries[idx].freelist);
+
+	spin_unlock_irqrestore(&fq->lock, flags);
+
+	/* Avoid false sharing as much as possible. */
+	if (!atomic_read(&iovad->fq_timer_on) &&
+	    !atomic_xchg(&iovad->fq_timer_on, 1))
+		mod_timer(&iovad->fq_timer,
+			  jiffies + msecs_to_jiffies(IOVA_FQ_TIMEOUT));
+}
+
+static void free_iova_flush_queue(struct iova_domain *iovad)
+{
+	int cpu, idx;
+
+	if (!iovad->fq)
+		return;
+
+	del_timer_sync(&iovad->fq_timer);
+	/*
+	 * This code runs when the iova_domain is being detroyed, so don't
+	 * bother to free iovas, just free any remaining pagetable pages.
+	 */
+	for_each_possible_cpu(cpu) {
+		struct iova_fq *fq = per_cpu_ptr(iovad->fq, cpu);
+
+		fq_ring_for_each(idx, fq)
+			put_pages_list(&fq->entries[idx].freelist);
+	}
+
+	free_percpu(iovad->fq);
+
+	iovad->fq = NULL;
+	iovad->fq_domain = NULL;
+}
+
+int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain)
+{
+	struct iova_fq __percpu *queue;
+	int i, cpu;
+
+	atomic64_set(&iovad->fq_flush_start_cnt,  0);
+	atomic64_set(&iovad->fq_flush_finish_cnt, 0);
+
+	queue = alloc_percpu(struct iova_fq);
+	if (!queue)
+		return -ENOMEM;
+
+	for_each_possible_cpu(cpu) {
+		struct iova_fq *fq = per_cpu_ptr(queue, cpu);
+
+		fq->head = 0;
+		fq->tail = 0;
+
+		spin_lock_init(&fq->lock);
+
+		for (i = 0; i < IOVA_FQ_SIZE; i++)
+			INIT_LIST_HEAD(&fq->entries[i].freelist);
+	}
+
+	iovad->fq_domain = fq_domain;
+	iovad->fq = queue;
+
+	timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
+	atomic_set(&iovad->fq_timer_on, 0);
+
+	return 0;
+}
+
+
 static inline size_t cookie_msi_granule(struct iommu_dma_cookie *cookie)
 {
 	if (cookie->type == IOMMU_DMA_IOVA_COOKIE)
@@ -144,8 +319,10 @@ void iommu_put_dma_cookie(struct iommu_domain *domain)
 	if (!cookie)
 		return;
 
-	if (cookie->type == IOMMU_DMA_IOVA_COOKIE && cookie->iovad.granule)
+	if (cookie->type == IOMMU_DMA_IOVA_COOKIE && cookie->iovad.granule) {
+		free_iova_flush_queue(&cookie->iovad);
 		put_iova_domain(&cookie->iovad);
+	}
 
 	list_for_each_entry_safe(msi, tmp, &cookie->msi_page_list, list) {
 		list_del(&msi->list);
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index c19f9a749070..6673dfa8e7c5 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -481,179 +481,6 @@ free_iova_fast(struct iova_domain *iovad, unsigned long pfn, unsigned long size)
 }
 EXPORT_SYMBOL_GPL(free_iova_fast);
 
-#define fq_ring_for_each(i, fq) \
-	for ((i) = (fq)->head; (i) != (fq)->tail; (i) = ((i) + 1) % IOVA_FQ_SIZE)
-
-static inline bool fq_full(struct iova_fq *fq)
-{
-	assert_spin_locked(&fq->lock);
-	return (((fq->tail + 1) % IOVA_FQ_SIZE) == fq->head);
-}
-
-static inline unsigned fq_ring_add(struct iova_fq *fq)
-{
-	unsigned idx = fq->tail;
-
-	assert_spin_locked(&fq->lock);
-
-	fq->tail = (idx + 1) % IOVA_FQ_SIZE;
-
-	return idx;
-}
-
-static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
-{
-	u64 counter = atomic64_read(&iovad->fq_flush_finish_cnt);
-	unsigned idx;
-
-	assert_spin_locked(&fq->lock);
-
-	fq_ring_for_each(idx, fq) {
-
-		if (fq->entries[idx].counter >= counter)
-			break;
-
-		put_pages_list(&fq->entries[idx].freelist);
-		free_iova_fast(iovad,
-			       fq->entries[idx].iova_pfn,
-			       fq->entries[idx].pages);
-
-		fq->head = (fq->head + 1) % IOVA_FQ_SIZE;
-	}
-}
-
-static void iova_domain_flush(struct iova_domain *iovad)
-{
-	atomic64_inc(&iovad->fq_flush_start_cnt);
-	iovad->fq_domain->ops->flush_iotlb_all(iovad->fq_domain);
-	atomic64_inc(&iovad->fq_flush_finish_cnt);
-}
-
-static void fq_flush_timeout(struct timer_list *t)
-{
-	struct iova_domain *iovad = from_timer(iovad, t, fq_timer);
-	int cpu;
-
-	atomic_set(&iovad->fq_timer_on, 0);
-	iova_domain_flush(iovad);
-
-	for_each_possible_cpu(cpu) {
-		unsigned long flags;
-		struct iova_fq *fq;
-
-		fq = per_cpu_ptr(iovad->fq, cpu);
-		spin_lock_irqsave(&fq->lock, flags);
-		fq_ring_free(iovad, fq);
-		spin_unlock_irqrestore(&fq->lock, flags);
-	}
-}
-
-void queue_iova(struct iova_domain *iovad,
-		unsigned long pfn, unsigned long pages,
-		struct list_head *freelist)
-{
-	struct iova_fq *fq;
-	unsigned long flags;
-	unsigned idx;
-
-	/*
-	 * Order against the IOMMU driver's pagetable update from unmapping
-	 * @pte, to guarantee that iova_domain_flush() observes that if called
-	 * from a different CPU before we release the lock below. Full barrier
-	 * so it also pairs with iommu_dma_init_fq() to avoid seeing partially
-	 * written fq state here.
-	 */
-	smp_mb();
-
-	fq = raw_cpu_ptr(iovad->fq);
-	spin_lock_irqsave(&fq->lock, flags);
-
-	/*
-	 * First remove all entries from the flush queue that have already been
-	 * flushed out on another CPU. This makes the fq_full() check below less
-	 * likely to be true.
-	 */
-	fq_ring_free(iovad, fq);
-
-	if (fq_full(fq)) {
-		iova_domain_flush(iovad);
-		fq_ring_free(iovad, fq);
-	}
-
-	idx = fq_ring_add(fq);
-
-	fq->entries[idx].iova_pfn = pfn;
-	fq->entries[idx].pages    = pages;
-	fq->entries[idx].counter  = atomic64_read(&iovad->fq_flush_start_cnt);
-	list_splice(freelist, &fq->entries[idx].freelist);
-
-	spin_unlock_irqrestore(&fq->lock, flags);
-
-	/* Avoid false sharing as much as possible. */
-	if (!atomic_read(&iovad->fq_timer_on) &&
-	    !atomic_xchg(&iovad->fq_timer_on, 1))
-		mod_timer(&iovad->fq_timer,
-			  jiffies + msecs_to_jiffies(IOVA_FQ_TIMEOUT));
-}
-
-static void free_iova_flush_queue(struct iova_domain *iovad)
-{
-	int cpu, idx;
-
-	if (!iovad->fq)
-		return;
-
-	del_timer_sync(&iovad->fq_timer);
-	/*
-	 * This code runs when the iova_domain is being detroyed, so don't
-	 * bother to free iovas, just free any remaining pagetable pages.
-	 */
-	for_each_possible_cpu(cpu) {
-		struct iova_fq *fq = per_cpu_ptr(iovad->fq, cpu);
-
-		fq_ring_for_each(idx, fq)
-			put_pages_list(&fq->entries[idx].freelist);
-	}
-
-	free_percpu(iovad->fq);
-
-	iovad->fq = NULL;
-	iovad->fq_domain = NULL;
-}
-
-int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain)
-{
-	struct iova_fq __percpu *queue;
-	int i, cpu;
-
-	atomic64_set(&iovad->fq_flush_start_cnt,  0);
-	atomic64_set(&iovad->fq_flush_finish_cnt, 0);
-
-	queue = alloc_percpu(struct iova_fq);
-	if (!queue)
-		return -ENOMEM;
-
-	for_each_possible_cpu(cpu) {
-		struct iova_fq *fq = per_cpu_ptr(queue, cpu);
-
-		fq->head = 0;
-		fq->tail = 0;
-
-		spin_lock_init(&fq->lock);
-
-		for (i = 0; i < IOVA_FQ_SIZE; i++)
-			INIT_LIST_HEAD(&fq->entries[i].freelist);
-	}
-
-	iovad->fq_domain = fq_domain;
-	iovad->fq = queue;
-
-	timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
-	atomic_set(&iovad->fq_timer_on, 0);
-
-	return 0;
-}
-
 /**
  * put_iova_domain - destroys the iova domain
  * @iovad: - iova domain in question.
@@ -665,8 +492,6 @@ void put_iova_domain(struct iova_domain *iovad)
 
 	cpuhp_state_remove_instance_nocalls(CPUHP_IOMMU_IOVA_DEAD,
 					    &iovad->cpuhp_dead);
-
-	free_iova_flush_queue(iovad);
 	free_iova_rcaches(iovad);
 	rbtree_postorder_for_each_entry_safe(iova, tmp, &iovad->rbroot, node)
 		free_iova_mem(iova);
-- 
2.28.0.dirty


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

* [PATCH v2 10/11] iommu/iova: Move flush queue code to iommu-dma
@ 2021-12-10 17:54   ` Robin Murphy
  0 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will; +Cc: linux-kernel, willy, linux-mm, iommu

Flush queues are specific to DMA ops, which are now handled exclusively
by iommu-dma. As such, now that the historical artefacts from being
shared directly with drivers have been cleaned up, move the flush queue
code into iommu-dma itself to get it out of the way of other IOVA users.

This is pure code movement with no functional change; refactoring to
clean up the headers and definitions will follow.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: Rebase with del_timer_sync() change

 drivers/iommu/dma-iommu.c | 179 +++++++++++++++++++++++++++++++++++++-
 drivers/iommu/iova.c      | 175 -------------------------------------
 2 files changed, 178 insertions(+), 176 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index f139b77caee0..ab8818965b2f 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -64,6 +64,181 @@ static int __init iommu_dma_forcedac_setup(char *str)
 }
 early_param("iommu.forcedac", iommu_dma_forcedac_setup);
 
+
+#define fq_ring_for_each(i, fq) \
+	for ((i) = (fq)->head; (i) != (fq)->tail; (i) = ((i) + 1) % IOVA_FQ_SIZE)
+
+static inline bool fq_full(struct iova_fq *fq)
+{
+	assert_spin_locked(&fq->lock);
+	return (((fq->tail + 1) % IOVA_FQ_SIZE) == fq->head);
+}
+
+static inline unsigned fq_ring_add(struct iova_fq *fq)
+{
+	unsigned idx = fq->tail;
+
+	assert_spin_locked(&fq->lock);
+
+	fq->tail = (idx + 1) % IOVA_FQ_SIZE;
+
+	return idx;
+}
+
+static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
+{
+	u64 counter = atomic64_read(&iovad->fq_flush_finish_cnt);
+	unsigned idx;
+
+	assert_spin_locked(&fq->lock);
+
+	fq_ring_for_each(idx, fq) {
+
+		if (fq->entries[idx].counter >= counter)
+			break;
+
+		put_pages_list(&fq->entries[idx].freelist);
+		free_iova_fast(iovad,
+			       fq->entries[idx].iova_pfn,
+			       fq->entries[idx].pages);
+
+		fq->head = (fq->head + 1) % IOVA_FQ_SIZE;
+	}
+}
+
+static void iova_domain_flush(struct iova_domain *iovad)
+{
+	atomic64_inc(&iovad->fq_flush_start_cnt);
+	iovad->fq_domain->ops->flush_iotlb_all(iovad->fq_domain);
+	atomic64_inc(&iovad->fq_flush_finish_cnt);
+}
+
+static void fq_flush_timeout(struct timer_list *t)
+{
+	struct iova_domain *iovad = from_timer(iovad, t, fq_timer);
+	int cpu;
+
+	atomic_set(&iovad->fq_timer_on, 0);
+	iova_domain_flush(iovad);
+
+	for_each_possible_cpu(cpu) {
+		unsigned long flags;
+		struct iova_fq *fq;
+
+		fq = per_cpu_ptr(iovad->fq, cpu);
+		spin_lock_irqsave(&fq->lock, flags);
+		fq_ring_free(iovad, fq);
+		spin_unlock_irqrestore(&fq->lock, flags);
+	}
+}
+
+void queue_iova(struct iova_domain *iovad,
+		unsigned long pfn, unsigned long pages,
+		struct list_head *freelist)
+{
+	struct iova_fq *fq;
+	unsigned long flags;
+	unsigned idx;
+
+	/*
+	 * Order against the IOMMU driver's pagetable update from unmapping
+	 * @pte, to guarantee that iova_domain_flush() observes that if called
+	 * from a different CPU before we release the lock below. Full barrier
+	 * so it also pairs with iommu_dma_init_fq() to avoid seeing partially
+	 * written fq state here.
+	 */
+	smp_mb();
+
+	fq = raw_cpu_ptr(iovad->fq);
+	spin_lock_irqsave(&fq->lock, flags);
+
+	/*
+	 * First remove all entries from the flush queue that have already been
+	 * flushed out on another CPU. This makes the fq_full() check below less
+	 * likely to be true.
+	 */
+	fq_ring_free(iovad, fq);
+
+	if (fq_full(fq)) {
+		iova_domain_flush(iovad);
+		fq_ring_free(iovad, fq);
+	}
+
+	idx = fq_ring_add(fq);
+
+	fq->entries[idx].iova_pfn = pfn;
+	fq->entries[idx].pages    = pages;
+	fq->entries[idx].counter  = atomic64_read(&iovad->fq_flush_start_cnt);
+	list_splice(freelist, &fq->entries[idx].freelist);
+
+	spin_unlock_irqrestore(&fq->lock, flags);
+
+	/* Avoid false sharing as much as possible. */
+	if (!atomic_read(&iovad->fq_timer_on) &&
+	    !atomic_xchg(&iovad->fq_timer_on, 1))
+		mod_timer(&iovad->fq_timer,
+			  jiffies + msecs_to_jiffies(IOVA_FQ_TIMEOUT));
+}
+
+static void free_iova_flush_queue(struct iova_domain *iovad)
+{
+	int cpu, idx;
+
+	if (!iovad->fq)
+		return;
+
+	del_timer_sync(&iovad->fq_timer);
+	/*
+	 * This code runs when the iova_domain is being detroyed, so don't
+	 * bother to free iovas, just free any remaining pagetable pages.
+	 */
+	for_each_possible_cpu(cpu) {
+		struct iova_fq *fq = per_cpu_ptr(iovad->fq, cpu);
+
+		fq_ring_for_each(idx, fq)
+			put_pages_list(&fq->entries[idx].freelist);
+	}
+
+	free_percpu(iovad->fq);
+
+	iovad->fq = NULL;
+	iovad->fq_domain = NULL;
+}
+
+int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain)
+{
+	struct iova_fq __percpu *queue;
+	int i, cpu;
+
+	atomic64_set(&iovad->fq_flush_start_cnt,  0);
+	atomic64_set(&iovad->fq_flush_finish_cnt, 0);
+
+	queue = alloc_percpu(struct iova_fq);
+	if (!queue)
+		return -ENOMEM;
+
+	for_each_possible_cpu(cpu) {
+		struct iova_fq *fq = per_cpu_ptr(queue, cpu);
+
+		fq->head = 0;
+		fq->tail = 0;
+
+		spin_lock_init(&fq->lock);
+
+		for (i = 0; i < IOVA_FQ_SIZE; i++)
+			INIT_LIST_HEAD(&fq->entries[i].freelist);
+	}
+
+	iovad->fq_domain = fq_domain;
+	iovad->fq = queue;
+
+	timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
+	atomic_set(&iovad->fq_timer_on, 0);
+
+	return 0;
+}
+
+
 static inline size_t cookie_msi_granule(struct iommu_dma_cookie *cookie)
 {
 	if (cookie->type == IOMMU_DMA_IOVA_COOKIE)
@@ -144,8 +319,10 @@ void iommu_put_dma_cookie(struct iommu_domain *domain)
 	if (!cookie)
 		return;
 
-	if (cookie->type == IOMMU_DMA_IOVA_COOKIE && cookie->iovad.granule)
+	if (cookie->type == IOMMU_DMA_IOVA_COOKIE && cookie->iovad.granule) {
+		free_iova_flush_queue(&cookie->iovad);
 		put_iova_domain(&cookie->iovad);
+	}
 
 	list_for_each_entry_safe(msi, tmp, &cookie->msi_page_list, list) {
 		list_del(&msi->list);
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index c19f9a749070..6673dfa8e7c5 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -481,179 +481,6 @@ free_iova_fast(struct iova_domain *iovad, unsigned long pfn, unsigned long size)
 }
 EXPORT_SYMBOL_GPL(free_iova_fast);
 
-#define fq_ring_for_each(i, fq) \
-	for ((i) = (fq)->head; (i) != (fq)->tail; (i) = ((i) + 1) % IOVA_FQ_SIZE)
-
-static inline bool fq_full(struct iova_fq *fq)
-{
-	assert_spin_locked(&fq->lock);
-	return (((fq->tail + 1) % IOVA_FQ_SIZE) == fq->head);
-}
-
-static inline unsigned fq_ring_add(struct iova_fq *fq)
-{
-	unsigned idx = fq->tail;
-
-	assert_spin_locked(&fq->lock);
-
-	fq->tail = (idx + 1) % IOVA_FQ_SIZE;
-
-	return idx;
-}
-
-static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
-{
-	u64 counter = atomic64_read(&iovad->fq_flush_finish_cnt);
-	unsigned idx;
-
-	assert_spin_locked(&fq->lock);
-
-	fq_ring_for_each(idx, fq) {
-
-		if (fq->entries[idx].counter >= counter)
-			break;
-
-		put_pages_list(&fq->entries[idx].freelist);
-		free_iova_fast(iovad,
-			       fq->entries[idx].iova_pfn,
-			       fq->entries[idx].pages);
-
-		fq->head = (fq->head + 1) % IOVA_FQ_SIZE;
-	}
-}
-
-static void iova_domain_flush(struct iova_domain *iovad)
-{
-	atomic64_inc(&iovad->fq_flush_start_cnt);
-	iovad->fq_domain->ops->flush_iotlb_all(iovad->fq_domain);
-	atomic64_inc(&iovad->fq_flush_finish_cnt);
-}
-
-static void fq_flush_timeout(struct timer_list *t)
-{
-	struct iova_domain *iovad = from_timer(iovad, t, fq_timer);
-	int cpu;
-
-	atomic_set(&iovad->fq_timer_on, 0);
-	iova_domain_flush(iovad);
-
-	for_each_possible_cpu(cpu) {
-		unsigned long flags;
-		struct iova_fq *fq;
-
-		fq = per_cpu_ptr(iovad->fq, cpu);
-		spin_lock_irqsave(&fq->lock, flags);
-		fq_ring_free(iovad, fq);
-		spin_unlock_irqrestore(&fq->lock, flags);
-	}
-}
-
-void queue_iova(struct iova_domain *iovad,
-		unsigned long pfn, unsigned long pages,
-		struct list_head *freelist)
-{
-	struct iova_fq *fq;
-	unsigned long flags;
-	unsigned idx;
-
-	/*
-	 * Order against the IOMMU driver's pagetable update from unmapping
-	 * @pte, to guarantee that iova_domain_flush() observes that if called
-	 * from a different CPU before we release the lock below. Full barrier
-	 * so it also pairs with iommu_dma_init_fq() to avoid seeing partially
-	 * written fq state here.
-	 */
-	smp_mb();
-
-	fq = raw_cpu_ptr(iovad->fq);
-	spin_lock_irqsave(&fq->lock, flags);
-
-	/*
-	 * First remove all entries from the flush queue that have already been
-	 * flushed out on another CPU. This makes the fq_full() check below less
-	 * likely to be true.
-	 */
-	fq_ring_free(iovad, fq);
-
-	if (fq_full(fq)) {
-		iova_domain_flush(iovad);
-		fq_ring_free(iovad, fq);
-	}
-
-	idx = fq_ring_add(fq);
-
-	fq->entries[idx].iova_pfn = pfn;
-	fq->entries[idx].pages    = pages;
-	fq->entries[idx].counter  = atomic64_read(&iovad->fq_flush_start_cnt);
-	list_splice(freelist, &fq->entries[idx].freelist);
-
-	spin_unlock_irqrestore(&fq->lock, flags);
-
-	/* Avoid false sharing as much as possible. */
-	if (!atomic_read(&iovad->fq_timer_on) &&
-	    !atomic_xchg(&iovad->fq_timer_on, 1))
-		mod_timer(&iovad->fq_timer,
-			  jiffies + msecs_to_jiffies(IOVA_FQ_TIMEOUT));
-}
-
-static void free_iova_flush_queue(struct iova_domain *iovad)
-{
-	int cpu, idx;
-
-	if (!iovad->fq)
-		return;
-
-	del_timer_sync(&iovad->fq_timer);
-	/*
-	 * This code runs when the iova_domain is being detroyed, so don't
-	 * bother to free iovas, just free any remaining pagetable pages.
-	 */
-	for_each_possible_cpu(cpu) {
-		struct iova_fq *fq = per_cpu_ptr(iovad->fq, cpu);
-
-		fq_ring_for_each(idx, fq)
-			put_pages_list(&fq->entries[idx].freelist);
-	}
-
-	free_percpu(iovad->fq);
-
-	iovad->fq = NULL;
-	iovad->fq_domain = NULL;
-}
-
-int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain)
-{
-	struct iova_fq __percpu *queue;
-	int i, cpu;
-
-	atomic64_set(&iovad->fq_flush_start_cnt,  0);
-	atomic64_set(&iovad->fq_flush_finish_cnt, 0);
-
-	queue = alloc_percpu(struct iova_fq);
-	if (!queue)
-		return -ENOMEM;
-
-	for_each_possible_cpu(cpu) {
-		struct iova_fq *fq = per_cpu_ptr(queue, cpu);
-
-		fq->head = 0;
-		fq->tail = 0;
-
-		spin_lock_init(&fq->lock);
-
-		for (i = 0; i < IOVA_FQ_SIZE; i++)
-			INIT_LIST_HEAD(&fq->entries[i].freelist);
-	}
-
-	iovad->fq_domain = fq_domain;
-	iovad->fq = queue;
-
-	timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
-	atomic_set(&iovad->fq_timer_on, 0);
-
-	return 0;
-}
-
 /**
  * put_iova_domain - destroys the iova domain
  * @iovad: - iova domain in question.
@@ -665,8 +492,6 @@ void put_iova_domain(struct iova_domain *iovad)
 
 	cpuhp_state_remove_instance_nocalls(CPUHP_IOMMU_IOVA_DEAD,
 					    &iovad->cpuhp_dead);
-
-	free_iova_flush_queue(iovad);
 	free_iova_rcaches(iovad);
 	rbtree_postorder_for_each_entry_safe(iova, tmp, &iovad->rbroot, node)
 		free_iova_mem(iova);
-- 
2.28.0.dirty

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

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

* [PATCH v2 11/11] iommu: Move flush queue data into iommu_dma_cookie
  2021-12-10 17:54 ` Robin Murphy
@ 2021-12-10 17:54   ` Robin Murphy
  -1 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel,
	john.garry, linux-mm

Complete the move into iommu-dma by refactoring the flush queues
themselves to belong to the DMA cookie rather than the IOVA domain.

The refactoring may as well extend to some minor cosmetic aspects
too, to help us stay one step ahead of the style police.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: Rebase with del_timer_sync() change

 drivers/iommu/dma-iommu.c | 171 +++++++++++++++++++++-----------------
 drivers/iommu/iova.c      |   2 -
 include/linux/iova.h      |  44 +---------
 3 files changed, 95 insertions(+), 122 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index ab8818965b2f..a7cd3a875481 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -9,9 +9,12 @@
  */
 
 #include <linux/acpi_iort.h>
+#include <linux/atomic.h>
+#include <linux/crash_dump.h>
 #include <linux/device.h>
-#include <linux/dma-map-ops.h>
+#include <linux/dma-direct.h>
 #include <linux/dma-iommu.h>
+#include <linux/dma-map-ops.h>
 #include <linux/gfp.h>
 #include <linux/huge_mm.h>
 #include <linux/iommu.h>
@@ -20,11 +23,10 @@
 #include <linux/mm.h>
 #include <linux/mutex.h>
 #include <linux/pci.h>
-#include <linux/swiotlb.h>
 #include <linux/scatterlist.h>
+#include <linux/spinlock.h>
+#include <linux/swiotlb.h>
 #include <linux/vmalloc.h>
-#include <linux/crash_dump.h>
-#include <linux/dma-direct.h>
 
 struct iommu_dma_msi_page {
 	struct list_head	list;
@@ -41,7 +43,19 @@ struct iommu_dma_cookie {
 	enum iommu_dma_cookie_type	type;
 	union {
 		/* Full allocator for IOMMU_DMA_IOVA_COOKIE */
-		struct iova_domain	iovad;
+		struct {
+			struct iova_domain	iovad;
+
+			struct iova_fq __percpu *fq;	/* Flush queue */
+			/* Number of TLB flushes that have been started */
+			atomic64_t		fq_flush_start_cnt;
+			/* Number of TLB flushes that have been finished */
+			atomic64_t		fq_flush_finish_cnt;
+			/* Timer to regularily empty the flush queues */
+			struct timer_list	fq_timer;
+			/* 1 when timer is active, 0 when not */
+			atomic_t		fq_timer_on;
+		};
 		/* Trivial linear page allocator for IOMMU_DMA_MSI_COOKIE */
 		dma_addr_t		msi_iova;
 	};
@@ -65,6 +79,27 @@ static int __init iommu_dma_forcedac_setup(char *str)
 early_param("iommu.forcedac", iommu_dma_forcedac_setup);
 
 
+/* Number of entries per flush queue */
+#define IOVA_FQ_SIZE	256
+
+/* Timeout (in ms) after which entries are flushed from the queue */
+#define IOVA_FQ_TIMEOUT	10
+
+/* Flush queue entry for deferred flushing */
+struct iova_fq_entry {
+	unsigned long iova_pfn;
+	unsigned long pages;
+	struct list_head freelist;
+	u64 counter; /* Flush counter when this entry was added */
+};
+
+/* Per-CPU flush queue structure */
+struct iova_fq {
+	struct iova_fq_entry entries[IOVA_FQ_SIZE];
+	unsigned int head, tail;
+	spinlock_t lock;
+};
+
 #define fq_ring_for_each(i, fq) \
 	for ((i) = (fq)->head; (i) != (fq)->tail; (i) = ((i) + 1) % IOVA_FQ_SIZE)
 
@@ -74,9 +109,9 @@ static inline bool fq_full(struct iova_fq *fq)
 	return (((fq->tail + 1) % IOVA_FQ_SIZE) == fq->head);
 }
 
-static inline unsigned fq_ring_add(struct iova_fq *fq)
+static inline unsigned int fq_ring_add(struct iova_fq *fq)
 {
-	unsigned idx = fq->tail;
+	unsigned int idx = fq->tail;
 
 	assert_spin_locked(&fq->lock);
 
@@ -85,10 +120,10 @@ static inline unsigned fq_ring_add(struct iova_fq *fq)
 	return idx;
 }
 
-static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
+static void fq_ring_free(struct iommu_dma_cookie *cookie, struct iova_fq *fq)
 {
-	u64 counter = atomic64_read(&iovad->fq_flush_finish_cnt);
-	unsigned idx;
+	u64 counter = atomic64_read(&cookie->fq_flush_finish_cnt);
+	unsigned int idx;
 
 	assert_spin_locked(&fq->lock);
 
@@ -98,7 +133,7 @@ static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
 			break;
 
 		put_pages_list(&fq->entries[idx].freelist);
-		free_iova_fast(iovad,
+		free_iova_fast(&cookie->iovad,
 			       fq->entries[idx].iova_pfn,
 			       fq->entries[idx].pages);
 
@@ -106,50 +141,50 @@ static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
 	}
 }
 
-static void iova_domain_flush(struct iova_domain *iovad)
+static void fq_flush_iotlb(struct iommu_dma_cookie *cookie)
 {
-	atomic64_inc(&iovad->fq_flush_start_cnt);
-	iovad->fq_domain->ops->flush_iotlb_all(iovad->fq_domain);
-	atomic64_inc(&iovad->fq_flush_finish_cnt);
+	atomic64_inc(&cookie->fq_flush_start_cnt);
+	cookie->fq_domain->ops->flush_iotlb_all(cookie->fq_domain);
+	atomic64_inc(&cookie->fq_flush_finish_cnt);
 }
 
 static void fq_flush_timeout(struct timer_list *t)
 {
-	struct iova_domain *iovad = from_timer(iovad, t, fq_timer);
+	struct iommu_dma_cookie *cookie = from_timer(cookie, t, fq_timer);
 	int cpu;
 
-	atomic_set(&iovad->fq_timer_on, 0);
-	iova_domain_flush(iovad);
+	atomic_set(&cookie->fq_timer_on, 0);
+	fq_flush_iotlb(cookie);
 
 	for_each_possible_cpu(cpu) {
 		unsigned long flags;
 		struct iova_fq *fq;
 
-		fq = per_cpu_ptr(iovad->fq, cpu);
+		fq = per_cpu_ptr(cookie->fq, cpu);
 		spin_lock_irqsave(&fq->lock, flags);
-		fq_ring_free(iovad, fq);
+		fq_ring_free(cookie, fq);
 		spin_unlock_irqrestore(&fq->lock, flags);
 	}
 }
 
-void queue_iova(struct iova_domain *iovad,
+static void queue_iova(struct iommu_dma_cookie *cookie,
 		unsigned long pfn, unsigned long pages,
 		struct list_head *freelist)
 {
 	struct iova_fq *fq;
 	unsigned long flags;
-	unsigned idx;
+	unsigned int idx;
 
 	/*
 	 * Order against the IOMMU driver's pagetable update from unmapping
-	 * @pte, to guarantee that iova_domain_flush() observes that if called
+	 * @pte, to guarantee that fq_flush_iotlb() observes that if called
 	 * from a different CPU before we release the lock below. Full barrier
 	 * so it also pairs with iommu_dma_init_fq() to avoid seeing partially
 	 * written fq state here.
 	 */
 	smp_mb();
 
-	fq = raw_cpu_ptr(iovad->fq);
+	fq = raw_cpu_ptr(cookie->fq);
 	spin_lock_irqsave(&fq->lock, flags);
 
 	/*
@@ -157,65 +192,66 @@ void queue_iova(struct iova_domain *iovad,
 	 * flushed out on another CPU. This makes the fq_full() check below less
 	 * likely to be true.
 	 */
-	fq_ring_free(iovad, fq);
+	fq_ring_free(cookie, fq);
 
 	if (fq_full(fq)) {
-		iova_domain_flush(iovad);
-		fq_ring_free(iovad, fq);
+		fq_flush_iotlb(cookie);
+		fq_ring_free(cookie, fq);
 	}
 
 	idx = fq_ring_add(fq);
 
 	fq->entries[idx].iova_pfn = pfn;
 	fq->entries[idx].pages    = pages;
-	fq->entries[idx].counter  = atomic64_read(&iovad->fq_flush_start_cnt);
+	fq->entries[idx].counter  = atomic64_read(&cookie->fq_flush_start_cnt);
 	list_splice(freelist, &fq->entries[idx].freelist);
 
 	spin_unlock_irqrestore(&fq->lock, flags);
 
 	/* Avoid false sharing as much as possible. */
-	if (!atomic_read(&iovad->fq_timer_on) &&
-	    !atomic_xchg(&iovad->fq_timer_on, 1))
-		mod_timer(&iovad->fq_timer,
+	if (!atomic_read(&cookie->fq_timer_on) &&
+	    !atomic_xchg(&cookie->fq_timer_on, 1))
+		mod_timer(&cookie->fq_timer,
 			  jiffies + msecs_to_jiffies(IOVA_FQ_TIMEOUT));
 }
 
-static void free_iova_flush_queue(struct iova_domain *iovad)
+static void iommu_dma_free_fq(struct iommu_dma_cookie *cookie)
 {
 	int cpu, idx;
 
-	if (!iovad->fq)
+	if (!cookie->fq)
 		return;
 
-	del_timer_sync(&iovad->fq_timer);
-	/*
-	 * This code runs when the iova_domain is being detroyed, so don't
-	 * bother to free iovas, just free any remaining pagetable pages.
-	 */
+	del_timer_sync(&cookie->fq_timer);
+	/* The IOVAs will be torn down separately, so just free our queued pages */
 	for_each_possible_cpu(cpu) {
-		struct iova_fq *fq = per_cpu_ptr(iovad->fq, cpu);
+		struct iova_fq *fq = per_cpu_ptr(cookie->fq, cpu);
 
 		fq_ring_for_each(idx, fq)
 			put_pages_list(&fq->entries[idx].freelist);
 	}
 
-	free_percpu(iovad->fq);
-
-	iovad->fq = NULL;
-	iovad->fq_domain = NULL;
+	free_percpu(cookie->fq);
 }
 
-int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain)
+/* sysfs updates are serialised by the mutex of the group owning @domain */
+int iommu_dma_init_fq(struct iommu_domain *domain)
 {
+	struct iommu_dma_cookie *cookie = domain->iova_cookie;
 	struct iova_fq __percpu *queue;
 	int i, cpu;
 
-	atomic64_set(&iovad->fq_flush_start_cnt,  0);
-	atomic64_set(&iovad->fq_flush_finish_cnt, 0);
+	if (cookie->fq_domain)
+		return 0;
+
+	atomic64_set(&cookie->fq_flush_start_cnt,  0);
+	atomic64_set(&cookie->fq_flush_finish_cnt, 0);
 
 	queue = alloc_percpu(struct iova_fq);
-	if (!queue)
+	if (!queue) {
+		pr_warn("iova flush queue initialization failed\n");
 		return -ENOMEM;
+	}
 
 	for_each_possible_cpu(cpu) {
 		struct iova_fq *fq = per_cpu_ptr(queue, cpu);
@@ -229,12 +265,16 @@ int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_dom
 			INIT_LIST_HEAD(&fq->entries[i].freelist);
 	}
 
-	iovad->fq_domain = fq_domain;
-	iovad->fq = queue;
-
-	timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
-	atomic_set(&iovad->fq_timer_on, 0);
+	cookie->fq = queue;
 
+	timer_setup(&cookie->fq_timer, fq_flush_timeout, 0);
+	atomic_set(&cookie->fq_timer_on, 0);
+	/*
+	 * Prevent incomplete fq state being observable. Pairs with path from
+	 * __iommu_dma_unmap() through iommu_dma_free_iova() to queue_iova()
+	 */
+	smp_wmb();
+	WRITE_ONCE(cookie->fq_domain, domain);
 	return 0;
 }
 
@@ -320,7 +360,7 @@ void iommu_put_dma_cookie(struct iommu_domain *domain)
 		return;
 
 	if (cookie->type == IOMMU_DMA_IOVA_COOKIE && cookie->iovad.granule) {
-		free_iova_flush_queue(&cookie->iovad);
+		iommu_dma_free_fq(cookie);
 		put_iova_domain(&cookie->iovad);
 	}
 
@@ -469,29 +509,6 @@ static bool dev_use_swiotlb(struct device *dev)
 	return IS_ENABLED(CONFIG_SWIOTLB) && dev_is_untrusted(dev);
 }
 
-/* sysfs updates are serialised by the mutex of the group owning @domain */
-int iommu_dma_init_fq(struct iommu_domain *domain)
-{
-	struct iommu_dma_cookie *cookie = domain->iova_cookie;
-	int ret;
-
-	if (cookie->fq_domain)
-		return 0;
-
-	ret = init_iova_flush_queue(&cookie->iovad, domain);
-	if (ret) {
-		pr_warn("iova flush queue initialization failed\n");
-		return ret;
-	}
-	/*
-	 * Prevent incomplete iovad->fq being observable. Pairs with path from
-	 * __iommu_dma_unmap() through iommu_dma_free_iova() to queue_iova()
-	 */
-	smp_wmb();
-	WRITE_ONCE(cookie->fq_domain, domain);
-	return 0;
-}
-
 /**
  * iommu_dma_init_domain - Initialise a DMA mapping domain
  * @domain: IOMMU domain previously prepared by iommu_get_dma_cookie()
@@ -630,7 +647,7 @@ static void iommu_dma_free_iova(struct iommu_dma_cookie *cookie,
 	if (cookie->type == IOMMU_DMA_MSI_COOKIE)
 		cookie->msi_iova -= size;
 	else if (gather && gather->queued)
-		queue_iova(iovad, iova_pfn(iovad, iova),
+		queue_iova(cookie, iova_pfn(iovad, iova),
 				size >> iova_shift(iovad),
 				&gather->freelist);
 	else
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 6673dfa8e7c5..72ac25831584 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -61,8 +61,6 @@ init_iova_domain(struct iova_domain *iovad, unsigned long granule,
 	iovad->start_pfn = start_pfn;
 	iovad->dma_32bit_pfn = 1UL << (32 - iova_shift(iovad));
 	iovad->max32_alloc_size = iovad->dma_32bit_pfn;
-	iovad->fq_domain = NULL;
-	iovad->fq = NULL;
 	iovad->anchor.pfn_lo = iovad->anchor.pfn_hi = IOVA_ANCHOR;
 	rb_link_node(&iovad->anchor.node, NULL, &iovad->rbroot.rb_node);
 	rb_insert_color(&iovad->anchor.node, &iovad->rbroot);
diff --git a/include/linux/iova.h b/include/linux/iova.h
index 072a09c06e8a..0abd48c5e622 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -12,9 +12,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/rbtree.h>
-#include <linux/atomic.h>
-#include <linux/dma-mapping.h>
-#include <linux/iommu.h>
 
 /* iova structure */
 struct iova {
@@ -36,27 +33,6 @@ struct iova_rcache {
 	struct iova_cpu_rcache __percpu *cpu_rcaches;
 };
 
-/* Number of entries per Flush Queue */
-#define IOVA_FQ_SIZE	256
-
-/* Timeout (in ms) after which entries are flushed from the Flush-Queue */
-#define IOVA_FQ_TIMEOUT	10
-
-/* Flush Queue entry for defered flushing */
-struct iova_fq_entry {
-	unsigned long iova_pfn;
-	unsigned long pages;
-	struct list_head freelist;
-	u64 counter; /* Flush counter when this entrie was added */
-};
-
-/* Per-CPU Flush Queue structure */
-struct iova_fq {
-	struct iova_fq_entry entries[IOVA_FQ_SIZE];
-	unsigned head, tail;
-	spinlock_t lock;
-};
-
 /* holds all the iova translations for a domain */
 struct iova_domain {
 	spinlock_t	iova_rbtree_lock; /* Lock to protect update of rbtree */
@@ -67,23 +43,9 @@ 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 */
-	struct iova_fq __percpu *fq;	/* Flush Queue */
-
-	atomic64_t	fq_flush_start_cnt;	/* Number of TLB flushes that
-						   have been started */
-
-	atomic64_t	fq_flush_finish_cnt;	/* Number of TLB flushes that
-						   have been finished */
-
 	struct iova	anchor;		/* rbtree lookup anchor */
+
 	struct iova_rcache rcaches[IOVA_RANGE_CACHE_MAX_SIZE];	/* IOVA range caches */
-
-	struct iommu_domain *fq_domain;
-
-	struct timer_list fq_timer;		/* Timer to regularily empty the
-						   flush-queues */
-	atomic_t fq_timer_on;			/* 1 when timer is active, 0
-						   when not */
 	struct hlist_node	cpuhp_dead;
 };
 
@@ -133,16 +95,12 @@ struct iova *alloc_iova(struct iova_domain *iovad, unsigned long size,
 	bool size_aligned);
 void free_iova_fast(struct iova_domain *iovad, unsigned long pfn,
 		    unsigned long size);
-void queue_iova(struct iova_domain *iovad,
-		unsigned long pfn, unsigned long pages,
-		struct list_head *freelist);
 unsigned long alloc_iova_fast(struct iova_domain *iovad, unsigned long size,
 			      unsigned long limit_pfn, bool flush_rcache);
 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);
-int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain);
 struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
 void put_iova_domain(struct iova_domain *iovad);
 #else
-- 
2.28.0.dirty


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

* [PATCH v2 11/11] iommu: Move flush queue data into iommu_dma_cookie
@ 2021-12-10 17:54   ` Robin Murphy
  0 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 17:54 UTC (permalink / raw)
  To: joro, will; +Cc: linux-kernel, willy, linux-mm, iommu

Complete the move into iommu-dma by refactoring the flush queues
themselves to belong to the DMA cookie rather than the IOVA domain.

The refactoring may as well extend to some minor cosmetic aspects
too, to help us stay one step ahead of the style police.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---

v2: Rebase with del_timer_sync() change

 drivers/iommu/dma-iommu.c | 171 +++++++++++++++++++++-----------------
 drivers/iommu/iova.c      |   2 -
 include/linux/iova.h      |  44 +---------
 3 files changed, 95 insertions(+), 122 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index ab8818965b2f..a7cd3a875481 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -9,9 +9,12 @@
  */
 
 #include <linux/acpi_iort.h>
+#include <linux/atomic.h>
+#include <linux/crash_dump.h>
 #include <linux/device.h>
-#include <linux/dma-map-ops.h>
+#include <linux/dma-direct.h>
 #include <linux/dma-iommu.h>
+#include <linux/dma-map-ops.h>
 #include <linux/gfp.h>
 #include <linux/huge_mm.h>
 #include <linux/iommu.h>
@@ -20,11 +23,10 @@
 #include <linux/mm.h>
 #include <linux/mutex.h>
 #include <linux/pci.h>
-#include <linux/swiotlb.h>
 #include <linux/scatterlist.h>
+#include <linux/spinlock.h>
+#include <linux/swiotlb.h>
 #include <linux/vmalloc.h>
-#include <linux/crash_dump.h>
-#include <linux/dma-direct.h>
 
 struct iommu_dma_msi_page {
 	struct list_head	list;
@@ -41,7 +43,19 @@ struct iommu_dma_cookie {
 	enum iommu_dma_cookie_type	type;
 	union {
 		/* Full allocator for IOMMU_DMA_IOVA_COOKIE */
-		struct iova_domain	iovad;
+		struct {
+			struct iova_domain	iovad;
+
+			struct iova_fq __percpu *fq;	/* Flush queue */
+			/* Number of TLB flushes that have been started */
+			atomic64_t		fq_flush_start_cnt;
+			/* Number of TLB flushes that have been finished */
+			atomic64_t		fq_flush_finish_cnt;
+			/* Timer to regularily empty the flush queues */
+			struct timer_list	fq_timer;
+			/* 1 when timer is active, 0 when not */
+			atomic_t		fq_timer_on;
+		};
 		/* Trivial linear page allocator for IOMMU_DMA_MSI_COOKIE */
 		dma_addr_t		msi_iova;
 	};
@@ -65,6 +79,27 @@ static int __init iommu_dma_forcedac_setup(char *str)
 early_param("iommu.forcedac", iommu_dma_forcedac_setup);
 
 
+/* Number of entries per flush queue */
+#define IOVA_FQ_SIZE	256
+
+/* Timeout (in ms) after which entries are flushed from the queue */
+#define IOVA_FQ_TIMEOUT	10
+
+/* Flush queue entry for deferred flushing */
+struct iova_fq_entry {
+	unsigned long iova_pfn;
+	unsigned long pages;
+	struct list_head freelist;
+	u64 counter; /* Flush counter when this entry was added */
+};
+
+/* Per-CPU flush queue structure */
+struct iova_fq {
+	struct iova_fq_entry entries[IOVA_FQ_SIZE];
+	unsigned int head, tail;
+	spinlock_t lock;
+};
+
 #define fq_ring_for_each(i, fq) \
 	for ((i) = (fq)->head; (i) != (fq)->tail; (i) = ((i) + 1) % IOVA_FQ_SIZE)
 
@@ -74,9 +109,9 @@ static inline bool fq_full(struct iova_fq *fq)
 	return (((fq->tail + 1) % IOVA_FQ_SIZE) == fq->head);
 }
 
-static inline unsigned fq_ring_add(struct iova_fq *fq)
+static inline unsigned int fq_ring_add(struct iova_fq *fq)
 {
-	unsigned idx = fq->tail;
+	unsigned int idx = fq->tail;
 
 	assert_spin_locked(&fq->lock);
 
@@ -85,10 +120,10 @@ static inline unsigned fq_ring_add(struct iova_fq *fq)
 	return idx;
 }
 
-static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
+static void fq_ring_free(struct iommu_dma_cookie *cookie, struct iova_fq *fq)
 {
-	u64 counter = atomic64_read(&iovad->fq_flush_finish_cnt);
-	unsigned idx;
+	u64 counter = atomic64_read(&cookie->fq_flush_finish_cnt);
+	unsigned int idx;
 
 	assert_spin_locked(&fq->lock);
 
@@ -98,7 +133,7 @@ static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
 			break;
 
 		put_pages_list(&fq->entries[idx].freelist);
-		free_iova_fast(iovad,
+		free_iova_fast(&cookie->iovad,
 			       fq->entries[idx].iova_pfn,
 			       fq->entries[idx].pages);
 
@@ -106,50 +141,50 @@ static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
 	}
 }
 
-static void iova_domain_flush(struct iova_domain *iovad)
+static void fq_flush_iotlb(struct iommu_dma_cookie *cookie)
 {
-	atomic64_inc(&iovad->fq_flush_start_cnt);
-	iovad->fq_domain->ops->flush_iotlb_all(iovad->fq_domain);
-	atomic64_inc(&iovad->fq_flush_finish_cnt);
+	atomic64_inc(&cookie->fq_flush_start_cnt);
+	cookie->fq_domain->ops->flush_iotlb_all(cookie->fq_domain);
+	atomic64_inc(&cookie->fq_flush_finish_cnt);
 }
 
 static void fq_flush_timeout(struct timer_list *t)
 {
-	struct iova_domain *iovad = from_timer(iovad, t, fq_timer);
+	struct iommu_dma_cookie *cookie = from_timer(cookie, t, fq_timer);
 	int cpu;
 
-	atomic_set(&iovad->fq_timer_on, 0);
-	iova_domain_flush(iovad);
+	atomic_set(&cookie->fq_timer_on, 0);
+	fq_flush_iotlb(cookie);
 
 	for_each_possible_cpu(cpu) {
 		unsigned long flags;
 		struct iova_fq *fq;
 
-		fq = per_cpu_ptr(iovad->fq, cpu);
+		fq = per_cpu_ptr(cookie->fq, cpu);
 		spin_lock_irqsave(&fq->lock, flags);
-		fq_ring_free(iovad, fq);
+		fq_ring_free(cookie, fq);
 		spin_unlock_irqrestore(&fq->lock, flags);
 	}
 }
 
-void queue_iova(struct iova_domain *iovad,
+static void queue_iova(struct iommu_dma_cookie *cookie,
 		unsigned long pfn, unsigned long pages,
 		struct list_head *freelist)
 {
 	struct iova_fq *fq;
 	unsigned long flags;
-	unsigned idx;
+	unsigned int idx;
 
 	/*
 	 * Order against the IOMMU driver's pagetable update from unmapping
-	 * @pte, to guarantee that iova_domain_flush() observes that if called
+	 * @pte, to guarantee that fq_flush_iotlb() observes that if called
 	 * from a different CPU before we release the lock below. Full barrier
 	 * so it also pairs with iommu_dma_init_fq() to avoid seeing partially
 	 * written fq state here.
 	 */
 	smp_mb();
 
-	fq = raw_cpu_ptr(iovad->fq);
+	fq = raw_cpu_ptr(cookie->fq);
 	spin_lock_irqsave(&fq->lock, flags);
 
 	/*
@@ -157,65 +192,66 @@ void queue_iova(struct iova_domain *iovad,
 	 * flushed out on another CPU. This makes the fq_full() check below less
 	 * likely to be true.
 	 */
-	fq_ring_free(iovad, fq);
+	fq_ring_free(cookie, fq);
 
 	if (fq_full(fq)) {
-		iova_domain_flush(iovad);
-		fq_ring_free(iovad, fq);
+		fq_flush_iotlb(cookie);
+		fq_ring_free(cookie, fq);
 	}
 
 	idx = fq_ring_add(fq);
 
 	fq->entries[idx].iova_pfn = pfn;
 	fq->entries[idx].pages    = pages;
-	fq->entries[idx].counter  = atomic64_read(&iovad->fq_flush_start_cnt);
+	fq->entries[idx].counter  = atomic64_read(&cookie->fq_flush_start_cnt);
 	list_splice(freelist, &fq->entries[idx].freelist);
 
 	spin_unlock_irqrestore(&fq->lock, flags);
 
 	/* Avoid false sharing as much as possible. */
-	if (!atomic_read(&iovad->fq_timer_on) &&
-	    !atomic_xchg(&iovad->fq_timer_on, 1))
-		mod_timer(&iovad->fq_timer,
+	if (!atomic_read(&cookie->fq_timer_on) &&
+	    !atomic_xchg(&cookie->fq_timer_on, 1))
+		mod_timer(&cookie->fq_timer,
 			  jiffies + msecs_to_jiffies(IOVA_FQ_TIMEOUT));
 }
 
-static void free_iova_flush_queue(struct iova_domain *iovad)
+static void iommu_dma_free_fq(struct iommu_dma_cookie *cookie)
 {
 	int cpu, idx;
 
-	if (!iovad->fq)
+	if (!cookie->fq)
 		return;
 
-	del_timer_sync(&iovad->fq_timer);
-	/*
-	 * This code runs when the iova_domain is being detroyed, so don't
-	 * bother to free iovas, just free any remaining pagetable pages.
-	 */
+	del_timer_sync(&cookie->fq_timer);
+	/* The IOVAs will be torn down separately, so just free our queued pages */
 	for_each_possible_cpu(cpu) {
-		struct iova_fq *fq = per_cpu_ptr(iovad->fq, cpu);
+		struct iova_fq *fq = per_cpu_ptr(cookie->fq, cpu);
 
 		fq_ring_for_each(idx, fq)
 			put_pages_list(&fq->entries[idx].freelist);
 	}
 
-	free_percpu(iovad->fq);
-
-	iovad->fq = NULL;
-	iovad->fq_domain = NULL;
+	free_percpu(cookie->fq);
 }
 
-int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain)
+/* sysfs updates are serialised by the mutex of the group owning @domain */
+int iommu_dma_init_fq(struct iommu_domain *domain)
 {
+	struct iommu_dma_cookie *cookie = domain->iova_cookie;
 	struct iova_fq __percpu *queue;
 	int i, cpu;
 
-	atomic64_set(&iovad->fq_flush_start_cnt,  0);
-	atomic64_set(&iovad->fq_flush_finish_cnt, 0);
+	if (cookie->fq_domain)
+		return 0;
+
+	atomic64_set(&cookie->fq_flush_start_cnt,  0);
+	atomic64_set(&cookie->fq_flush_finish_cnt, 0);
 
 	queue = alloc_percpu(struct iova_fq);
-	if (!queue)
+	if (!queue) {
+		pr_warn("iova flush queue initialization failed\n");
 		return -ENOMEM;
+	}
 
 	for_each_possible_cpu(cpu) {
 		struct iova_fq *fq = per_cpu_ptr(queue, cpu);
@@ -229,12 +265,16 @@ int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_dom
 			INIT_LIST_HEAD(&fq->entries[i].freelist);
 	}
 
-	iovad->fq_domain = fq_domain;
-	iovad->fq = queue;
-
-	timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
-	atomic_set(&iovad->fq_timer_on, 0);
+	cookie->fq = queue;
 
+	timer_setup(&cookie->fq_timer, fq_flush_timeout, 0);
+	atomic_set(&cookie->fq_timer_on, 0);
+	/*
+	 * Prevent incomplete fq state being observable. Pairs with path from
+	 * __iommu_dma_unmap() through iommu_dma_free_iova() to queue_iova()
+	 */
+	smp_wmb();
+	WRITE_ONCE(cookie->fq_domain, domain);
 	return 0;
 }
 
@@ -320,7 +360,7 @@ void iommu_put_dma_cookie(struct iommu_domain *domain)
 		return;
 
 	if (cookie->type == IOMMU_DMA_IOVA_COOKIE && cookie->iovad.granule) {
-		free_iova_flush_queue(&cookie->iovad);
+		iommu_dma_free_fq(cookie);
 		put_iova_domain(&cookie->iovad);
 	}
 
@@ -469,29 +509,6 @@ static bool dev_use_swiotlb(struct device *dev)
 	return IS_ENABLED(CONFIG_SWIOTLB) && dev_is_untrusted(dev);
 }
 
-/* sysfs updates are serialised by the mutex of the group owning @domain */
-int iommu_dma_init_fq(struct iommu_domain *domain)
-{
-	struct iommu_dma_cookie *cookie = domain->iova_cookie;
-	int ret;
-
-	if (cookie->fq_domain)
-		return 0;
-
-	ret = init_iova_flush_queue(&cookie->iovad, domain);
-	if (ret) {
-		pr_warn("iova flush queue initialization failed\n");
-		return ret;
-	}
-	/*
-	 * Prevent incomplete iovad->fq being observable. Pairs with path from
-	 * __iommu_dma_unmap() through iommu_dma_free_iova() to queue_iova()
-	 */
-	smp_wmb();
-	WRITE_ONCE(cookie->fq_domain, domain);
-	return 0;
-}
-
 /**
  * iommu_dma_init_domain - Initialise a DMA mapping domain
  * @domain: IOMMU domain previously prepared by iommu_get_dma_cookie()
@@ -630,7 +647,7 @@ static void iommu_dma_free_iova(struct iommu_dma_cookie *cookie,
 	if (cookie->type == IOMMU_DMA_MSI_COOKIE)
 		cookie->msi_iova -= size;
 	else if (gather && gather->queued)
-		queue_iova(iovad, iova_pfn(iovad, iova),
+		queue_iova(cookie, iova_pfn(iovad, iova),
 				size >> iova_shift(iovad),
 				&gather->freelist);
 	else
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 6673dfa8e7c5..72ac25831584 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -61,8 +61,6 @@ init_iova_domain(struct iova_domain *iovad, unsigned long granule,
 	iovad->start_pfn = start_pfn;
 	iovad->dma_32bit_pfn = 1UL << (32 - iova_shift(iovad));
 	iovad->max32_alloc_size = iovad->dma_32bit_pfn;
-	iovad->fq_domain = NULL;
-	iovad->fq = NULL;
 	iovad->anchor.pfn_lo = iovad->anchor.pfn_hi = IOVA_ANCHOR;
 	rb_link_node(&iovad->anchor.node, NULL, &iovad->rbroot.rb_node);
 	rb_insert_color(&iovad->anchor.node, &iovad->rbroot);
diff --git a/include/linux/iova.h b/include/linux/iova.h
index 072a09c06e8a..0abd48c5e622 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -12,9 +12,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/rbtree.h>
-#include <linux/atomic.h>
-#include <linux/dma-mapping.h>
-#include <linux/iommu.h>
 
 /* iova structure */
 struct iova {
@@ -36,27 +33,6 @@ struct iova_rcache {
 	struct iova_cpu_rcache __percpu *cpu_rcaches;
 };
 
-/* Number of entries per Flush Queue */
-#define IOVA_FQ_SIZE	256
-
-/* Timeout (in ms) after which entries are flushed from the Flush-Queue */
-#define IOVA_FQ_TIMEOUT	10
-
-/* Flush Queue entry for defered flushing */
-struct iova_fq_entry {
-	unsigned long iova_pfn;
-	unsigned long pages;
-	struct list_head freelist;
-	u64 counter; /* Flush counter when this entrie was added */
-};
-
-/* Per-CPU Flush Queue structure */
-struct iova_fq {
-	struct iova_fq_entry entries[IOVA_FQ_SIZE];
-	unsigned head, tail;
-	spinlock_t lock;
-};
-
 /* holds all the iova translations for a domain */
 struct iova_domain {
 	spinlock_t	iova_rbtree_lock; /* Lock to protect update of rbtree */
@@ -67,23 +43,9 @@ 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 */
-	struct iova_fq __percpu *fq;	/* Flush Queue */
-
-	atomic64_t	fq_flush_start_cnt;	/* Number of TLB flushes that
-						   have been started */
-
-	atomic64_t	fq_flush_finish_cnt;	/* Number of TLB flushes that
-						   have been finished */
-
 	struct iova	anchor;		/* rbtree lookup anchor */
+
 	struct iova_rcache rcaches[IOVA_RANGE_CACHE_MAX_SIZE];	/* IOVA range caches */
-
-	struct iommu_domain *fq_domain;
-
-	struct timer_list fq_timer;		/* Timer to regularily empty the
-						   flush-queues */
-	atomic_t fq_timer_on;			/* 1 when timer is active, 0
-						   when not */
 	struct hlist_node	cpuhp_dead;
 };
 
@@ -133,16 +95,12 @@ struct iova *alloc_iova(struct iova_domain *iovad, unsigned long size,
 	bool size_aligned);
 void free_iova_fast(struct iova_domain *iovad, unsigned long pfn,
 		    unsigned long size);
-void queue_iova(struct iova_domain *iovad,
-		unsigned long pfn, unsigned long pages,
-		struct list_head *freelist);
 unsigned long alloc_iova_fast(struct iova_domain *iovad, unsigned long size,
 			      unsigned long limit_pfn, bool flush_rcache);
 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);
-int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain);
 struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
 void put_iova_domain(struct iova_domain *iovad);
 #else
-- 
2.28.0.dirty

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

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

* Re: [PATCH v2 01/11] iommu/iova: Fix race between FQ timeout and teardown
  2021-12-10 17:54   ` Robin Murphy
@ 2021-12-10 18:04     ` John Garry via iommu
  -1 siblings, 0 replies; 66+ messages in thread
From: John Garry @ 2021-12-10 18:04 UTC (permalink / raw)
  To: Robin Murphy, joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel,
	linux-mm, Xiongfeng Wang

On 10/12/2021 17:54, Robin Murphy wrote:
> From: Xiongfeng Wang<wangxiongfeng2@huawei.com>
> 
> It turns out to be possible for hotplugging out a device to reach the
> stage of tearing down the device's group and default domain before the
> domain's flush queue has drained naturally. At this point, it is then
> possible for the timeout to expire just*before*  the del_timer() call

super nit: "just*before*  the" - needs a whitespace before "before" :)

> from free_iova_flush_queue(), such that we then proceed to free the FQ
> resources while fq_flush_timeout() is still accessing them on another
> CPU. Crashes due to this have been observed in the wild while removing
> NVMe devices.
> 
> Close the race window by using del_timer_sync() to safely wait for any
> active timeout handler to finish before we start to free things. We
> already avoid any locking in free_iova_flush_queue() since the FQ is
> supposed to be inactive anyway, so the potential deadlock scenario does
> not apply.
> 
> Fixes: 9a005a800ae8 ("iommu/iova: Add flush timer")
> Signed-off-by: Xiongfeng Wang<wangxiongfeng2@huawei.com>
> [ rm: rewrite commit message ]
> Signed-off-by: Robin Murphy<robin.murphy@arm.com>

FWIW,

Reviewed-by: John Garry <john.garry@huawei.com>

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

* Re: [PATCH v2 01/11] iommu/iova: Fix race between FQ timeout and teardown
@ 2021-12-10 18:04     ` John Garry via iommu
  0 siblings, 0 replies; 66+ messages in thread
From: John Garry via iommu @ 2021-12-10 18:04 UTC (permalink / raw)
  To: Robin Murphy, joro, will
  Cc: linux-kernel, willy, linux-mm, iommu, Xiongfeng Wang

On 10/12/2021 17:54, Robin Murphy wrote:
> From: Xiongfeng Wang<wangxiongfeng2@huawei.com>
> 
> It turns out to be possible for hotplugging out a device to reach the
> stage of tearing down the device's group and default domain before the
> domain's flush queue has drained naturally. At this point, it is then
> possible for the timeout to expire just*before*  the del_timer() call

super nit: "just*before*  the" - needs a whitespace before "before" :)

> from free_iova_flush_queue(), such that we then proceed to free the FQ
> resources while fq_flush_timeout() is still accessing them on another
> CPU. Crashes due to this have been observed in the wild while removing
> NVMe devices.
> 
> Close the race window by using del_timer_sync() to safely wait for any
> active timeout handler to finish before we start to free things. We
> already avoid any locking in free_iova_flush_queue() since the FQ is
> supposed to be inactive anyway, so the potential deadlock scenario does
> not apply.
> 
> Fixes: 9a005a800ae8 ("iommu/iova: Add flush timer")
> Signed-off-by: Xiongfeng Wang<wangxiongfeng2@huawei.com>
> [ rm: rewrite commit message ]
> Signed-off-by: Robin Murphy<robin.murphy@arm.com>

FWIW,

Reviewed-by: John Garry <john.garry@huawei.com>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

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

* Re: [PATCH v2 01/11] iommu/iova: Fix race between FQ timeout and teardown
  2021-12-10 18:04     ` John Garry via iommu
@ 2021-12-10 18:13       ` Robin Murphy
  -1 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 18:13 UTC (permalink / raw)
  To: John Garry, joro, will
  Cc: linux-kernel, willy, linux-mm, iommu, Xiongfeng Wang

On 2021-12-10 18:04, John Garry via iommu wrote:
> On 10/12/2021 17:54, Robin Murphy wrote:
>> From: Xiongfeng Wang<wangxiongfeng2@huawei.com>
>>
>> It turns out to be possible for hotplugging out a device to reach the
>> stage of tearing down the device's group and default domain before the
>> domain's flush queue has drained naturally. At this point, it is then
>> possible for the timeout to expire just*before*  the del_timer() call
> 
> super nit: "just*before*  the" - needs a whitespace before "before" :)

Weird... the original patch file here and the copy received by lore via 
linux-iommu look fine, gremlins in your MUA or delivery path perhaps?

>> from free_iova_flush_queue(), such that we then proceed to free the FQ
>> resources while fq_flush_timeout() is still accessing them on another
>> CPU. Crashes due to this have been observed in the wild while removing
>> NVMe devices.
>>
>> Close the race window by using del_timer_sync() to safely wait for any
>> active timeout handler to finish before we start to free things. We
>> already avoid any locking in free_iova_flush_queue() since the FQ is
>> supposed to be inactive anyway, so the potential deadlock scenario does
>> not apply.
>>
>> Fixes: 9a005a800ae8 ("iommu/iova: Add flush timer")
>> Signed-off-by: Xiongfeng Wang<wangxiongfeng2@huawei.com>
>> [ rm: rewrite commit message ]
>> Signed-off-by: Robin Murphy<robin.murphy@arm.com>
> 
> FWIW,
> 
> Reviewed-by: John Garry <john.garry@huawei.com>

Thanks John!

Robin.

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

* Re: [PATCH v2 01/11] iommu/iova: Fix race between FQ timeout and teardown
@ 2021-12-10 18:13       ` Robin Murphy
  0 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-10 18:13 UTC (permalink / raw)
  To: John Garry, joro, will
  Cc: linux-mm, iommu, linux-kernel, willy, Xiongfeng Wang

On 2021-12-10 18:04, John Garry via iommu wrote:
> On 10/12/2021 17:54, Robin Murphy wrote:
>> From: Xiongfeng Wang<wangxiongfeng2@huawei.com>
>>
>> It turns out to be possible for hotplugging out a device to reach the
>> stage of tearing down the device's group and default domain before the
>> domain's flush queue has drained naturally. At this point, it is then
>> possible for the timeout to expire just*before*  the del_timer() call
> 
> super nit: "just*before*  the" - needs a whitespace before "before" :)

Weird... the original patch file here and the copy received by lore via 
linux-iommu look fine, gremlins in your MUA or delivery path perhaps?

>> from free_iova_flush_queue(), such that we then proceed to free the FQ
>> resources while fq_flush_timeout() is still accessing them on another
>> CPU. Crashes due to this have been observed in the wild while removing
>> NVMe devices.
>>
>> Close the race window by using del_timer_sync() to safely wait for any
>> active timeout handler to finish before we start to free things. We
>> already avoid any locking in free_iova_flush_queue() since the FQ is
>> supposed to be inactive anyway, so the potential deadlock scenario does
>> not apply.
>>
>> Fixes: 9a005a800ae8 ("iommu/iova: Add flush timer")
>> Signed-off-by: Xiongfeng Wang<wangxiongfeng2@huawei.com>
>> [ rm: rewrite commit message ]
>> Signed-off-by: Robin Murphy<robin.murphy@arm.com>
> 
> FWIW,
> 
> Reviewed-by: John Garry <john.garry@huawei.com>

Thanks John!

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

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

* Re: [PATCH v2 01/11] iommu/iova: Fix race between FQ timeout and teardown
  2021-12-10 18:13       ` Robin Murphy
@ 2021-12-10 19:19         ` John Garry via iommu
  -1 siblings, 0 replies; 66+ messages in thread
From: John Garry @ 2021-12-10 19:19 UTC (permalink / raw)
  To: Robin Murphy, joro, will
  Cc: linux-kernel, willy, linux-mm, iommu, Xiongfeng Wang

On 10/12/2021 18:13, Robin Murphy wrote:
>>> possible for the timeout to expire just*before*  the del_timer() call
>>
>> super nit: "just*before*  the" - needs a whitespace before "before" :)
> 
> Weird... the original patch file here and the copy received by lore via 
> linux-iommu look fine, gremlins in your MUA or delivery path perhaps?

Right, apologies for that. I did receive it ok, but my replying seemed 
to mangle it. Not sure why..

Thanks,
John

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

* Re: [PATCH v2 01/11] iommu/iova: Fix race between FQ timeout and teardown
@ 2021-12-10 19:19         ` John Garry via iommu
  0 siblings, 0 replies; 66+ messages in thread
From: John Garry via iommu @ 2021-12-10 19:19 UTC (permalink / raw)
  To: Robin Murphy, joro, will
  Cc: linux-mm, iommu, linux-kernel, willy, Xiongfeng Wang

On 10/12/2021 18:13, Robin Murphy wrote:
>>> possible for the timeout to expire just*before*  the del_timer() call
>>
>> super nit: "just*before*  the" - needs a whitespace before "before" :)
> 
> Weird... the original patch file here and the copy received by lore via 
> linux-iommu look fine, gremlins in your MUA or delivery path perhaps?

Right, apologies for that. I did receive it ok, but my replying seemed 
to mangle it. Not sure why..

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

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

* Re: [PATCH v2 11/11] iommu: Move flush queue data into iommu_dma_cookie
  2021-12-10 17:54   ` Robin Murphy
  (?)
@ 2021-12-10 23:30     ` kernel test robot
  -1 siblings, 0 replies; 66+ messages in thread
From: kernel test robot @ 2021-12-10 23:30 UTC (permalink / raw)
  To: Robin Murphy, joro, will
  Cc: kbuild-all, iommu, suravee.suthikulpanit, baolu.lu, willy,
	linux-kernel, john.garry, linux-mm

Hi Robin,

I love your patch! Yet something to improve:

[auto build test ERROR on joro-iommu/next]
[also build test ERROR on tegra/for-next v5.16-rc4]
[cannot apply to tegra-drm/drm/tegra/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/Robin-Murphy/iommu-refactor-flush-queues-into-iommu-dma/20211211-015635
base:   https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next
config: arm-randconfig-r013-20211210 (https://download.01.org/0day-ci/archive/20211211/202112110753.vYbSlMnq-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/3b6adb4a8ec42d7b5c1b3b1af2c857a2375fd7e1
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Robin-Murphy/iommu-refactor-flush-queues-into-iommu-dma/20211211-015635
        git checkout 3b6adb4a8ec42d7b5c1b3b1af2c857a2375fd7e1
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=arm SHELL=/bin/bash drivers/gpu/drm/tegra/ drivers/iommu/

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

All errors (new ones prefixed by >>):

   drivers/gpu/drm/tegra/hub.c: In function 'tegra_display_hub_probe':
>> drivers/gpu/drm/tegra/hub.c:1043:24: error: implicit declaration of function 'dma_get_mask'; did you mean 'xa_get_mark'? [-Werror=implicit-function-declaration]
    1043 |         u64 dma_mask = dma_get_mask(pdev->dev.parent);
         |                        ^~~~~~~~~~~~
         |                        xa_get_mark
>> drivers/gpu/drm/tegra/hub.c:1050:15: error: implicit declaration of function 'dma_coerce_mask_and_coherent' [-Werror=implicit-function-declaration]
    1050 |         err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
         |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
   drivers/gpu/drm/tegra/plane.c: In function 'tegra_plane_reset':
>> drivers/gpu/drm/tegra/plane.c:46:42: error: 'DMA_MAPPING_ERROR' undeclared (first use in this function)
      46 |                         state->iova[i] = DMA_MAPPING_ERROR;
         |                                          ^~~~~~~~~~~~~~~~~
   drivers/gpu/drm/tegra/plane.c:46:42: note: each undeclared identifier is reported only once for each function it appears in
   drivers/gpu/drm/tegra/plane.c: In function 'tegra_plane_atomic_duplicate_state':
   drivers/gpu/drm/tegra/plane.c:76:33: error: 'DMA_MAPPING_ERROR' undeclared (first use in this function)
      76 |                 copy->iova[i] = DMA_MAPPING_ERROR;
         |                                 ^~~~~~~~~~~~~~~~~
   drivers/gpu/drm/tegra/plane.c: In function 'tegra_dc_pin':
>> drivers/gpu/drm/tegra/plane.c:170:31: error: implicit declaration of function 'dma_map_sgtable'; did you mean 'iommu_map_sgtable'? [-Werror=implicit-function-declaration]
     170 |                         err = dma_map_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
         |                               ^~~~~~~~~~~~~~~
         |                               iommu_map_sgtable
>> drivers/gpu/drm/tegra/plane.c:170:61: error: 'DMA_TO_DEVICE' undeclared (first use in this function); did you mean 'MT_DEVICE'?
     170 |                         err = dma_map_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
         |                                                             ^~~~~~~~~~~~~
         |                                                             MT_DEVICE
>> drivers/gpu/drm/tegra/plane.c:202:25: error: implicit declaration of function 'dma_unmap_sgtable'; did you mean 'iommu_map_sgtable'? [-Werror=implicit-function-declaration]
     202 |                         dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
         |                         ^~~~~~~~~~~~~~~~~
         |                         iommu_map_sgtable
   drivers/gpu/drm/tegra/plane.c:205:34: error: 'DMA_MAPPING_ERROR' undeclared (first use in this function)
     205 |                 state->iova[i] = DMA_MAPPING_ERROR;
         |                                  ^~~~~~~~~~~~~~~~~
   drivers/gpu/drm/tegra/plane.c: In function 'tegra_dc_unpin':
   drivers/gpu/drm/tegra/plane.c:221:57: error: 'DMA_TO_DEVICE' undeclared (first use in this function); did you mean 'MT_DEVICE'?
     221 |                         dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
         |                                                         ^~~~~~~~~~~~~
         |                                                         MT_DEVICE
   drivers/gpu/drm/tegra/plane.c:224:34: error: 'DMA_MAPPING_ERROR' undeclared (first use in this function)
     224 |                 state->iova[i] = DMA_MAPPING_ERROR;
         |                                  ^~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
   drivers/gpu/drm/tegra/dc.c: In function 'tegra_crtc_calculate_memory_bandwidth':
   drivers/gpu/drm/tegra/dc.c:2225:38: warning: variable 'old_state' set but not used [-Wunused-but-set-variable]
    2225 |         const struct drm_crtc_state *old_state;
         |                                      ^~~~~~~~~
   drivers/gpu/drm/tegra/dc.c: In function 'tegra_dc_probe':
>> drivers/gpu/drm/tegra/dc.c:2978:24: error: implicit declaration of function 'dma_get_mask'; did you mean 'xa_get_mark'? [-Werror=implicit-function-declaration]
    2978 |         u64 dma_mask = dma_get_mask(pdev->dev.parent);
         |                        ^~~~~~~~~~~~
         |                        xa_get_mark
>> drivers/gpu/drm/tegra/dc.c:2982:15: error: implicit declaration of function 'dma_coerce_mask_and_coherent' [-Werror=implicit-function-declaration]
    2982 |         err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
         |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors


vim +1043 drivers/gpu/drm/tegra/hub.c

c4755fb9064f64 Thierry Reding 2017-11-13  1040  
c4755fb9064f64 Thierry Reding 2017-11-13  1041  static int tegra_display_hub_probe(struct platform_device *pdev)
c4755fb9064f64 Thierry Reding 2017-11-13  1042  {
86044e749be77a Thierry Reding 2021-03-26 @1043  	u64 dma_mask = dma_get_mask(pdev->dev.parent);
0cffbde2e318cc Thierry Reding 2018-11-29  1044  	struct device_node *child = NULL;
c4755fb9064f64 Thierry Reding 2017-11-13  1045  	struct tegra_display_hub *hub;
0cffbde2e318cc Thierry Reding 2018-11-29  1046  	struct clk *clk;
c4755fb9064f64 Thierry Reding 2017-11-13  1047  	unsigned int i;
c4755fb9064f64 Thierry Reding 2017-11-13  1048  	int err;
c4755fb9064f64 Thierry Reding 2017-11-13  1049  
86044e749be77a Thierry Reding 2021-03-26 @1050  	err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
86044e749be77a Thierry Reding 2021-03-26  1051  	if (err < 0) {
86044e749be77a Thierry Reding 2021-03-26  1052  		dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err);
86044e749be77a Thierry Reding 2021-03-26  1053  		return err;
86044e749be77a Thierry Reding 2021-03-26  1054  	}
86044e749be77a Thierry Reding 2021-03-26  1055  
c4755fb9064f64 Thierry Reding 2017-11-13  1056  	hub = devm_kzalloc(&pdev->dev, sizeof(*hub), GFP_KERNEL);
c4755fb9064f64 Thierry Reding 2017-11-13  1057  	if (!hub)
c4755fb9064f64 Thierry Reding 2017-11-13  1058  		return -ENOMEM;
c4755fb9064f64 Thierry Reding 2017-11-13  1059  
c4755fb9064f64 Thierry Reding 2017-11-13  1060  	hub->soc = of_device_get_match_data(&pdev->dev);
c4755fb9064f64 Thierry Reding 2017-11-13  1061  
c4755fb9064f64 Thierry Reding 2017-11-13  1062  	hub->clk_disp = devm_clk_get(&pdev->dev, "disp");
c4755fb9064f64 Thierry Reding 2017-11-13  1063  	if (IS_ERR(hub->clk_disp)) {
c4755fb9064f64 Thierry Reding 2017-11-13  1064  		err = PTR_ERR(hub->clk_disp);
c4755fb9064f64 Thierry Reding 2017-11-13  1065  		return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1066  	}
c4755fb9064f64 Thierry Reding 2017-11-13  1067  
5725daaab55ca0 Thierry Reding 2018-09-21  1068  	if (hub->soc->supports_dsc) {
c4755fb9064f64 Thierry Reding 2017-11-13  1069  		hub->clk_dsc = devm_clk_get(&pdev->dev, "dsc");
c4755fb9064f64 Thierry Reding 2017-11-13  1070  		if (IS_ERR(hub->clk_dsc)) {
c4755fb9064f64 Thierry Reding 2017-11-13  1071  			err = PTR_ERR(hub->clk_dsc);
c4755fb9064f64 Thierry Reding 2017-11-13  1072  			return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1073  		}
5725daaab55ca0 Thierry Reding 2018-09-21  1074  	}
c4755fb9064f64 Thierry Reding 2017-11-13  1075  
c4755fb9064f64 Thierry Reding 2017-11-13  1076  	hub->clk_hub = devm_clk_get(&pdev->dev, "hub");
c4755fb9064f64 Thierry Reding 2017-11-13  1077  	if (IS_ERR(hub->clk_hub)) {
c4755fb9064f64 Thierry Reding 2017-11-13  1078  		err = PTR_ERR(hub->clk_hub);
c4755fb9064f64 Thierry Reding 2017-11-13  1079  		return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1080  	}
c4755fb9064f64 Thierry Reding 2017-11-13  1081  
c4755fb9064f64 Thierry Reding 2017-11-13  1082  	hub->rst = devm_reset_control_get(&pdev->dev, "misc");
c4755fb9064f64 Thierry Reding 2017-11-13  1083  	if (IS_ERR(hub->rst)) {
c4755fb9064f64 Thierry Reding 2017-11-13  1084  		err = PTR_ERR(hub->rst);
c4755fb9064f64 Thierry Reding 2017-11-13  1085  		return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1086  	}
c4755fb9064f64 Thierry Reding 2017-11-13  1087  
c4755fb9064f64 Thierry Reding 2017-11-13  1088  	hub->wgrps = devm_kcalloc(&pdev->dev, hub->soc->num_wgrps,
c4755fb9064f64 Thierry Reding 2017-11-13  1089  				  sizeof(*hub->wgrps), GFP_KERNEL);
c4755fb9064f64 Thierry Reding 2017-11-13  1090  	if (!hub->wgrps)
c4755fb9064f64 Thierry Reding 2017-11-13  1091  		return -ENOMEM;
c4755fb9064f64 Thierry Reding 2017-11-13  1092  
c4755fb9064f64 Thierry Reding 2017-11-13  1093  	for (i = 0; i < hub->soc->num_wgrps; i++) {
c4755fb9064f64 Thierry Reding 2017-11-13  1094  		struct tegra_windowgroup *wgrp = &hub->wgrps[i];
c4755fb9064f64 Thierry Reding 2017-11-13  1095  		char id[8];
c4755fb9064f64 Thierry Reding 2017-11-13  1096  
c4755fb9064f64 Thierry Reding 2017-11-13  1097  		snprintf(id, sizeof(id), "wgrp%u", i);
c4755fb9064f64 Thierry Reding 2017-11-13  1098  		mutex_init(&wgrp->lock);
c4755fb9064f64 Thierry Reding 2017-11-13  1099  		wgrp->usecount = 0;
c4755fb9064f64 Thierry Reding 2017-11-13  1100  		wgrp->index = i;
c4755fb9064f64 Thierry Reding 2017-11-13  1101  
c4755fb9064f64 Thierry Reding 2017-11-13  1102  		wgrp->rst = devm_reset_control_get(&pdev->dev, id);
c4755fb9064f64 Thierry Reding 2017-11-13  1103  		if (IS_ERR(wgrp->rst))
c4755fb9064f64 Thierry Reding 2017-11-13  1104  			return PTR_ERR(wgrp->rst);
c4755fb9064f64 Thierry Reding 2017-11-13  1105  
c4755fb9064f64 Thierry Reding 2017-11-13  1106  		err = reset_control_assert(wgrp->rst);
c4755fb9064f64 Thierry Reding 2017-11-13  1107  		if (err < 0)
c4755fb9064f64 Thierry Reding 2017-11-13  1108  			return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1109  	}
c4755fb9064f64 Thierry Reding 2017-11-13  1110  
0cffbde2e318cc Thierry Reding 2018-11-29  1111  	hub->num_heads = of_get_child_count(pdev->dev.of_node);
0cffbde2e318cc Thierry Reding 2018-11-29  1112  
0cffbde2e318cc Thierry Reding 2018-11-29  1113  	hub->clk_heads = devm_kcalloc(&pdev->dev, hub->num_heads, sizeof(clk),
0cffbde2e318cc Thierry Reding 2018-11-29  1114  				      GFP_KERNEL);
0cffbde2e318cc Thierry Reding 2018-11-29  1115  	if (!hub->clk_heads)
0cffbde2e318cc Thierry Reding 2018-11-29  1116  		return -ENOMEM;
0cffbde2e318cc Thierry Reding 2018-11-29  1117  
0cffbde2e318cc Thierry Reding 2018-11-29  1118  	for (i = 0; i < hub->num_heads; i++) {
0cffbde2e318cc Thierry Reding 2018-11-29  1119  		child = of_get_next_child(pdev->dev.of_node, child);
0cffbde2e318cc Thierry Reding 2018-11-29  1120  		if (!child) {
0cffbde2e318cc Thierry Reding 2018-11-29  1121  			dev_err(&pdev->dev, "failed to find node for head %u\n",
0cffbde2e318cc Thierry Reding 2018-11-29  1122  				i);
0cffbde2e318cc Thierry Reding 2018-11-29  1123  			return -ENODEV;
0cffbde2e318cc Thierry Reding 2018-11-29  1124  		}
0cffbde2e318cc Thierry Reding 2018-11-29  1125  
0cffbde2e318cc Thierry Reding 2018-11-29  1126  		clk = devm_get_clk_from_child(&pdev->dev, child, "dc");
0cffbde2e318cc Thierry Reding 2018-11-29  1127  		if (IS_ERR(clk)) {
0cffbde2e318cc Thierry Reding 2018-11-29  1128  			dev_err(&pdev->dev, "failed to get clock for head %u\n",
0cffbde2e318cc Thierry Reding 2018-11-29  1129  				i);
0cffbde2e318cc Thierry Reding 2018-11-29  1130  			of_node_put(child);
0cffbde2e318cc Thierry Reding 2018-11-29  1131  			return PTR_ERR(clk);
0cffbde2e318cc Thierry Reding 2018-11-29  1132  		}
0cffbde2e318cc Thierry Reding 2018-11-29  1133  
0cffbde2e318cc Thierry Reding 2018-11-29  1134  		hub->clk_heads[i] = clk;
0cffbde2e318cc Thierry Reding 2018-11-29  1135  	}
0cffbde2e318cc Thierry Reding 2018-11-29  1136  
0cffbde2e318cc Thierry Reding 2018-11-29  1137  	of_node_put(child);
0cffbde2e318cc Thierry Reding 2018-11-29  1138  
c4755fb9064f64 Thierry Reding 2017-11-13  1139  	/* XXX: enable clock across reset? */
c4755fb9064f64 Thierry Reding 2017-11-13  1140  	err = reset_control_assert(hub->rst);
c4755fb9064f64 Thierry Reding 2017-11-13  1141  	if (err < 0)
c4755fb9064f64 Thierry Reding 2017-11-13  1142  		return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1143  
c4755fb9064f64 Thierry Reding 2017-11-13  1144  	platform_set_drvdata(pdev, hub);
c4755fb9064f64 Thierry Reding 2017-11-13  1145  	pm_runtime_enable(&pdev->dev);
c4755fb9064f64 Thierry Reding 2017-11-13  1146  
c4755fb9064f64 Thierry Reding 2017-11-13  1147  	INIT_LIST_HEAD(&hub->client.list);
c4755fb9064f64 Thierry Reding 2017-11-13  1148  	hub->client.ops = &tegra_display_hub_ops;
c4755fb9064f64 Thierry Reding 2017-11-13  1149  	hub->client.dev = &pdev->dev;
c4755fb9064f64 Thierry Reding 2017-11-13  1150  
c4755fb9064f64 Thierry Reding 2017-11-13  1151  	err = host1x_client_register(&hub->client);
c4755fb9064f64 Thierry Reding 2017-11-13  1152  	if (err < 0)
c4755fb9064f64 Thierry Reding 2017-11-13  1153  		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
c4755fb9064f64 Thierry Reding 2017-11-13  1154  			err);
c4755fb9064f64 Thierry Reding 2017-11-13  1155  
a101e3dad8a90a Thierry Reding 2020-06-12  1156  	err = devm_of_platform_populate(&pdev->dev);
a101e3dad8a90a Thierry Reding 2020-06-12  1157  	if (err < 0)
a101e3dad8a90a Thierry Reding 2020-06-12  1158  		goto unregister;
a101e3dad8a90a Thierry Reding 2020-06-12  1159  
a101e3dad8a90a Thierry Reding 2020-06-12  1160  	return err;
a101e3dad8a90a Thierry Reding 2020-06-12  1161  
a101e3dad8a90a Thierry Reding 2020-06-12  1162  unregister:
a101e3dad8a90a Thierry Reding 2020-06-12  1163  	host1x_client_unregister(&hub->client);
a101e3dad8a90a Thierry Reding 2020-06-12  1164  	pm_runtime_disable(&pdev->dev);
c4755fb9064f64 Thierry Reding 2017-11-13  1165  	return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1166  }
c4755fb9064f64 Thierry Reding 2017-11-13  1167  

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

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

* Re: [PATCH v2 11/11] iommu: Move flush queue data into iommu_dma_cookie
@ 2021-12-10 23:30     ` kernel test robot
  0 siblings, 0 replies; 66+ messages in thread
From: kernel test robot @ 2021-12-10 23:30 UTC (permalink / raw)
  To: Robin Murphy, joro, will; +Cc: kbuild-all, linux-kernel, willy, linux-mm, iommu

Hi Robin,

I love your patch! Yet something to improve:

[auto build test ERROR on joro-iommu/next]
[also build test ERROR on tegra/for-next v5.16-rc4]
[cannot apply to tegra-drm/drm/tegra/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/Robin-Murphy/iommu-refactor-flush-queues-into-iommu-dma/20211211-015635
base:   https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next
config: arm-randconfig-r013-20211210 (https://download.01.org/0day-ci/archive/20211211/202112110753.vYbSlMnq-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/3b6adb4a8ec42d7b5c1b3b1af2c857a2375fd7e1
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Robin-Murphy/iommu-refactor-flush-queues-into-iommu-dma/20211211-015635
        git checkout 3b6adb4a8ec42d7b5c1b3b1af2c857a2375fd7e1
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=arm SHELL=/bin/bash drivers/gpu/drm/tegra/ drivers/iommu/

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

All errors (new ones prefixed by >>):

   drivers/gpu/drm/tegra/hub.c: In function 'tegra_display_hub_probe':
>> drivers/gpu/drm/tegra/hub.c:1043:24: error: implicit declaration of function 'dma_get_mask'; did you mean 'xa_get_mark'? [-Werror=implicit-function-declaration]
    1043 |         u64 dma_mask = dma_get_mask(pdev->dev.parent);
         |                        ^~~~~~~~~~~~
         |                        xa_get_mark
>> drivers/gpu/drm/tegra/hub.c:1050:15: error: implicit declaration of function 'dma_coerce_mask_and_coherent' [-Werror=implicit-function-declaration]
    1050 |         err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
         |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
   drivers/gpu/drm/tegra/plane.c: In function 'tegra_plane_reset':
>> drivers/gpu/drm/tegra/plane.c:46:42: error: 'DMA_MAPPING_ERROR' undeclared (first use in this function)
      46 |                         state->iova[i] = DMA_MAPPING_ERROR;
         |                                          ^~~~~~~~~~~~~~~~~
   drivers/gpu/drm/tegra/plane.c:46:42: note: each undeclared identifier is reported only once for each function it appears in
   drivers/gpu/drm/tegra/plane.c: In function 'tegra_plane_atomic_duplicate_state':
   drivers/gpu/drm/tegra/plane.c:76:33: error: 'DMA_MAPPING_ERROR' undeclared (first use in this function)
      76 |                 copy->iova[i] = DMA_MAPPING_ERROR;
         |                                 ^~~~~~~~~~~~~~~~~
   drivers/gpu/drm/tegra/plane.c: In function 'tegra_dc_pin':
>> drivers/gpu/drm/tegra/plane.c:170:31: error: implicit declaration of function 'dma_map_sgtable'; did you mean 'iommu_map_sgtable'? [-Werror=implicit-function-declaration]
     170 |                         err = dma_map_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
         |                               ^~~~~~~~~~~~~~~
         |                               iommu_map_sgtable
>> drivers/gpu/drm/tegra/plane.c:170:61: error: 'DMA_TO_DEVICE' undeclared (first use in this function); did you mean 'MT_DEVICE'?
     170 |                         err = dma_map_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
         |                                                             ^~~~~~~~~~~~~
         |                                                             MT_DEVICE
>> drivers/gpu/drm/tegra/plane.c:202:25: error: implicit declaration of function 'dma_unmap_sgtable'; did you mean 'iommu_map_sgtable'? [-Werror=implicit-function-declaration]
     202 |                         dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
         |                         ^~~~~~~~~~~~~~~~~
         |                         iommu_map_sgtable
   drivers/gpu/drm/tegra/plane.c:205:34: error: 'DMA_MAPPING_ERROR' undeclared (first use in this function)
     205 |                 state->iova[i] = DMA_MAPPING_ERROR;
         |                                  ^~~~~~~~~~~~~~~~~
   drivers/gpu/drm/tegra/plane.c: In function 'tegra_dc_unpin':
   drivers/gpu/drm/tegra/plane.c:221:57: error: 'DMA_TO_DEVICE' undeclared (first use in this function); did you mean 'MT_DEVICE'?
     221 |                         dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
         |                                                         ^~~~~~~~~~~~~
         |                                                         MT_DEVICE
   drivers/gpu/drm/tegra/plane.c:224:34: error: 'DMA_MAPPING_ERROR' undeclared (first use in this function)
     224 |                 state->iova[i] = DMA_MAPPING_ERROR;
         |                                  ^~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
   drivers/gpu/drm/tegra/dc.c: In function 'tegra_crtc_calculate_memory_bandwidth':
   drivers/gpu/drm/tegra/dc.c:2225:38: warning: variable 'old_state' set but not used [-Wunused-but-set-variable]
    2225 |         const struct drm_crtc_state *old_state;
         |                                      ^~~~~~~~~
   drivers/gpu/drm/tegra/dc.c: In function 'tegra_dc_probe':
>> drivers/gpu/drm/tegra/dc.c:2978:24: error: implicit declaration of function 'dma_get_mask'; did you mean 'xa_get_mark'? [-Werror=implicit-function-declaration]
    2978 |         u64 dma_mask = dma_get_mask(pdev->dev.parent);
         |                        ^~~~~~~~~~~~
         |                        xa_get_mark
>> drivers/gpu/drm/tegra/dc.c:2982:15: error: implicit declaration of function 'dma_coerce_mask_and_coherent' [-Werror=implicit-function-declaration]
    2982 |         err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
         |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors


vim +1043 drivers/gpu/drm/tegra/hub.c

c4755fb9064f64 Thierry Reding 2017-11-13  1040  
c4755fb9064f64 Thierry Reding 2017-11-13  1041  static int tegra_display_hub_probe(struct platform_device *pdev)
c4755fb9064f64 Thierry Reding 2017-11-13  1042  {
86044e749be77a Thierry Reding 2021-03-26 @1043  	u64 dma_mask = dma_get_mask(pdev->dev.parent);
0cffbde2e318cc Thierry Reding 2018-11-29  1044  	struct device_node *child = NULL;
c4755fb9064f64 Thierry Reding 2017-11-13  1045  	struct tegra_display_hub *hub;
0cffbde2e318cc Thierry Reding 2018-11-29  1046  	struct clk *clk;
c4755fb9064f64 Thierry Reding 2017-11-13  1047  	unsigned int i;
c4755fb9064f64 Thierry Reding 2017-11-13  1048  	int err;
c4755fb9064f64 Thierry Reding 2017-11-13  1049  
86044e749be77a Thierry Reding 2021-03-26 @1050  	err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
86044e749be77a Thierry Reding 2021-03-26  1051  	if (err < 0) {
86044e749be77a Thierry Reding 2021-03-26  1052  		dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err);
86044e749be77a Thierry Reding 2021-03-26  1053  		return err;
86044e749be77a Thierry Reding 2021-03-26  1054  	}
86044e749be77a Thierry Reding 2021-03-26  1055  
c4755fb9064f64 Thierry Reding 2017-11-13  1056  	hub = devm_kzalloc(&pdev->dev, sizeof(*hub), GFP_KERNEL);
c4755fb9064f64 Thierry Reding 2017-11-13  1057  	if (!hub)
c4755fb9064f64 Thierry Reding 2017-11-13  1058  		return -ENOMEM;
c4755fb9064f64 Thierry Reding 2017-11-13  1059  
c4755fb9064f64 Thierry Reding 2017-11-13  1060  	hub->soc = of_device_get_match_data(&pdev->dev);
c4755fb9064f64 Thierry Reding 2017-11-13  1061  
c4755fb9064f64 Thierry Reding 2017-11-13  1062  	hub->clk_disp = devm_clk_get(&pdev->dev, "disp");
c4755fb9064f64 Thierry Reding 2017-11-13  1063  	if (IS_ERR(hub->clk_disp)) {
c4755fb9064f64 Thierry Reding 2017-11-13  1064  		err = PTR_ERR(hub->clk_disp);
c4755fb9064f64 Thierry Reding 2017-11-13  1065  		return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1066  	}
c4755fb9064f64 Thierry Reding 2017-11-13  1067  
5725daaab55ca0 Thierry Reding 2018-09-21  1068  	if (hub->soc->supports_dsc) {
c4755fb9064f64 Thierry Reding 2017-11-13  1069  		hub->clk_dsc = devm_clk_get(&pdev->dev, "dsc");
c4755fb9064f64 Thierry Reding 2017-11-13  1070  		if (IS_ERR(hub->clk_dsc)) {
c4755fb9064f64 Thierry Reding 2017-11-13  1071  			err = PTR_ERR(hub->clk_dsc);
c4755fb9064f64 Thierry Reding 2017-11-13  1072  			return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1073  		}
5725daaab55ca0 Thierry Reding 2018-09-21  1074  	}
c4755fb9064f64 Thierry Reding 2017-11-13  1075  
c4755fb9064f64 Thierry Reding 2017-11-13  1076  	hub->clk_hub = devm_clk_get(&pdev->dev, "hub");
c4755fb9064f64 Thierry Reding 2017-11-13  1077  	if (IS_ERR(hub->clk_hub)) {
c4755fb9064f64 Thierry Reding 2017-11-13  1078  		err = PTR_ERR(hub->clk_hub);
c4755fb9064f64 Thierry Reding 2017-11-13  1079  		return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1080  	}
c4755fb9064f64 Thierry Reding 2017-11-13  1081  
c4755fb9064f64 Thierry Reding 2017-11-13  1082  	hub->rst = devm_reset_control_get(&pdev->dev, "misc");
c4755fb9064f64 Thierry Reding 2017-11-13  1083  	if (IS_ERR(hub->rst)) {
c4755fb9064f64 Thierry Reding 2017-11-13  1084  		err = PTR_ERR(hub->rst);
c4755fb9064f64 Thierry Reding 2017-11-13  1085  		return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1086  	}
c4755fb9064f64 Thierry Reding 2017-11-13  1087  
c4755fb9064f64 Thierry Reding 2017-11-13  1088  	hub->wgrps = devm_kcalloc(&pdev->dev, hub->soc->num_wgrps,
c4755fb9064f64 Thierry Reding 2017-11-13  1089  				  sizeof(*hub->wgrps), GFP_KERNEL);
c4755fb9064f64 Thierry Reding 2017-11-13  1090  	if (!hub->wgrps)
c4755fb9064f64 Thierry Reding 2017-11-13  1091  		return -ENOMEM;
c4755fb9064f64 Thierry Reding 2017-11-13  1092  
c4755fb9064f64 Thierry Reding 2017-11-13  1093  	for (i = 0; i < hub->soc->num_wgrps; i++) {
c4755fb9064f64 Thierry Reding 2017-11-13  1094  		struct tegra_windowgroup *wgrp = &hub->wgrps[i];
c4755fb9064f64 Thierry Reding 2017-11-13  1095  		char id[8];
c4755fb9064f64 Thierry Reding 2017-11-13  1096  
c4755fb9064f64 Thierry Reding 2017-11-13  1097  		snprintf(id, sizeof(id), "wgrp%u", i);
c4755fb9064f64 Thierry Reding 2017-11-13  1098  		mutex_init(&wgrp->lock);
c4755fb9064f64 Thierry Reding 2017-11-13  1099  		wgrp->usecount = 0;
c4755fb9064f64 Thierry Reding 2017-11-13  1100  		wgrp->index = i;
c4755fb9064f64 Thierry Reding 2017-11-13  1101  
c4755fb9064f64 Thierry Reding 2017-11-13  1102  		wgrp->rst = devm_reset_control_get(&pdev->dev, id);
c4755fb9064f64 Thierry Reding 2017-11-13  1103  		if (IS_ERR(wgrp->rst))
c4755fb9064f64 Thierry Reding 2017-11-13  1104  			return PTR_ERR(wgrp->rst);
c4755fb9064f64 Thierry Reding 2017-11-13  1105  
c4755fb9064f64 Thierry Reding 2017-11-13  1106  		err = reset_control_assert(wgrp->rst);
c4755fb9064f64 Thierry Reding 2017-11-13  1107  		if (err < 0)
c4755fb9064f64 Thierry Reding 2017-11-13  1108  			return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1109  	}
c4755fb9064f64 Thierry Reding 2017-11-13  1110  
0cffbde2e318cc Thierry Reding 2018-11-29  1111  	hub->num_heads = of_get_child_count(pdev->dev.of_node);
0cffbde2e318cc Thierry Reding 2018-11-29  1112  
0cffbde2e318cc Thierry Reding 2018-11-29  1113  	hub->clk_heads = devm_kcalloc(&pdev->dev, hub->num_heads, sizeof(clk),
0cffbde2e318cc Thierry Reding 2018-11-29  1114  				      GFP_KERNEL);
0cffbde2e318cc Thierry Reding 2018-11-29  1115  	if (!hub->clk_heads)
0cffbde2e318cc Thierry Reding 2018-11-29  1116  		return -ENOMEM;
0cffbde2e318cc Thierry Reding 2018-11-29  1117  
0cffbde2e318cc Thierry Reding 2018-11-29  1118  	for (i = 0; i < hub->num_heads; i++) {
0cffbde2e318cc Thierry Reding 2018-11-29  1119  		child = of_get_next_child(pdev->dev.of_node, child);
0cffbde2e318cc Thierry Reding 2018-11-29  1120  		if (!child) {
0cffbde2e318cc Thierry Reding 2018-11-29  1121  			dev_err(&pdev->dev, "failed to find node for head %u\n",
0cffbde2e318cc Thierry Reding 2018-11-29  1122  				i);
0cffbde2e318cc Thierry Reding 2018-11-29  1123  			return -ENODEV;
0cffbde2e318cc Thierry Reding 2018-11-29  1124  		}
0cffbde2e318cc Thierry Reding 2018-11-29  1125  
0cffbde2e318cc Thierry Reding 2018-11-29  1126  		clk = devm_get_clk_from_child(&pdev->dev, child, "dc");
0cffbde2e318cc Thierry Reding 2018-11-29  1127  		if (IS_ERR(clk)) {
0cffbde2e318cc Thierry Reding 2018-11-29  1128  			dev_err(&pdev->dev, "failed to get clock for head %u\n",
0cffbde2e318cc Thierry Reding 2018-11-29  1129  				i);
0cffbde2e318cc Thierry Reding 2018-11-29  1130  			of_node_put(child);
0cffbde2e318cc Thierry Reding 2018-11-29  1131  			return PTR_ERR(clk);
0cffbde2e318cc Thierry Reding 2018-11-29  1132  		}
0cffbde2e318cc Thierry Reding 2018-11-29  1133  
0cffbde2e318cc Thierry Reding 2018-11-29  1134  		hub->clk_heads[i] = clk;
0cffbde2e318cc Thierry Reding 2018-11-29  1135  	}
0cffbde2e318cc Thierry Reding 2018-11-29  1136  
0cffbde2e318cc Thierry Reding 2018-11-29  1137  	of_node_put(child);
0cffbde2e318cc Thierry Reding 2018-11-29  1138  
c4755fb9064f64 Thierry Reding 2017-11-13  1139  	/* XXX: enable clock across reset? */
c4755fb9064f64 Thierry Reding 2017-11-13  1140  	err = reset_control_assert(hub->rst);
c4755fb9064f64 Thierry Reding 2017-11-13  1141  	if (err < 0)
c4755fb9064f64 Thierry Reding 2017-11-13  1142  		return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1143  
c4755fb9064f64 Thierry Reding 2017-11-13  1144  	platform_set_drvdata(pdev, hub);
c4755fb9064f64 Thierry Reding 2017-11-13  1145  	pm_runtime_enable(&pdev->dev);
c4755fb9064f64 Thierry Reding 2017-11-13  1146  
c4755fb9064f64 Thierry Reding 2017-11-13  1147  	INIT_LIST_HEAD(&hub->client.list);
c4755fb9064f64 Thierry Reding 2017-11-13  1148  	hub->client.ops = &tegra_display_hub_ops;
c4755fb9064f64 Thierry Reding 2017-11-13  1149  	hub->client.dev = &pdev->dev;
c4755fb9064f64 Thierry Reding 2017-11-13  1150  
c4755fb9064f64 Thierry Reding 2017-11-13  1151  	err = host1x_client_register(&hub->client);
c4755fb9064f64 Thierry Reding 2017-11-13  1152  	if (err < 0)
c4755fb9064f64 Thierry Reding 2017-11-13  1153  		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
c4755fb9064f64 Thierry Reding 2017-11-13  1154  			err);
c4755fb9064f64 Thierry Reding 2017-11-13  1155  
a101e3dad8a90a Thierry Reding 2020-06-12  1156  	err = devm_of_platform_populate(&pdev->dev);
a101e3dad8a90a Thierry Reding 2020-06-12  1157  	if (err < 0)
a101e3dad8a90a Thierry Reding 2020-06-12  1158  		goto unregister;
a101e3dad8a90a Thierry Reding 2020-06-12  1159  
a101e3dad8a90a Thierry Reding 2020-06-12  1160  	return err;
a101e3dad8a90a Thierry Reding 2020-06-12  1161  
a101e3dad8a90a Thierry Reding 2020-06-12  1162  unregister:
a101e3dad8a90a Thierry Reding 2020-06-12  1163  	host1x_client_unregister(&hub->client);
a101e3dad8a90a Thierry Reding 2020-06-12  1164  	pm_runtime_disable(&pdev->dev);
c4755fb9064f64 Thierry Reding 2017-11-13  1165  	return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1166  }
c4755fb9064f64 Thierry Reding 2017-11-13  1167  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

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

* Re: [PATCH v2 11/11] iommu: Move flush queue data into iommu_dma_cookie
@ 2021-12-10 23:30     ` kernel test robot
  0 siblings, 0 replies; 66+ messages in thread
From: kernel test robot @ 2021-12-10 23:30 UTC (permalink / raw)
  To: kbuild-all

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

Hi Robin,

I love your patch! Yet something to improve:

[auto build test ERROR on joro-iommu/next]
[also build test ERROR on tegra/for-next v5.16-rc4]
[cannot apply to tegra-drm/drm/tegra/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/Robin-Murphy/iommu-refactor-flush-queues-into-iommu-dma/20211211-015635
base:   https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next
config: arm-randconfig-r013-20211210 (https://download.01.org/0day-ci/archive/20211211/202112110753.vYbSlMnq-lkp(a)intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/3b6adb4a8ec42d7b5c1b3b1af2c857a2375fd7e1
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Robin-Murphy/iommu-refactor-flush-queues-into-iommu-dma/20211211-015635
        git checkout 3b6adb4a8ec42d7b5c1b3b1af2c857a2375fd7e1
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=arm SHELL=/bin/bash drivers/gpu/drm/tegra/ drivers/iommu/

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

All errors (new ones prefixed by >>):

   drivers/gpu/drm/tegra/hub.c: In function 'tegra_display_hub_probe':
>> drivers/gpu/drm/tegra/hub.c:1043:24: error: implicit declaration of function 'dma_get_mask'; did you mean 'xa_get_mark'? [-Werror=implicit-function-declaration]
    1043 |         u64 dma_mask = dma_get_mask(pdev->dev.parent);
         |                        ^~~~~~~~~~~~
         |                        xa_get_mark
>> drivers/gpu/drm/tegra/hub.c:1050:15: error: implicit declaration of function 'dma_coerce_mask_and_coherent' [-Werror=implicit-function-declaration]
    1050 |         err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
         |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
   drivers/gpu/drm/tegra/plane.c: In function 'tegra_plane_reset':
>> drivers/gpu/drm/tegra/plane.c:46:42: error: 'DMA_MAPPING_ERROR' undeclared (first use in this function)
      46 |                         state->iova[i] = DMA_MAPPING_ERROR;
         |                                          ^~~~~~~~~~~~~~~~~
   drivers/gpu/drm/tegra/plane.c:46:42: note: each undeclared identifier is reported only once for each function it appears in
   drivers/gpu/drm/tegra/plane.c: In function 'tegra_plane_atomic_duplicate_state':
   drivers/gpu/drm/tegra/plane.c:76:33: error: 'DMA_MAPPING_ERROR' undeclared (first use in this function)
      76 |                 copy->iova[i] = DMA_MAPPING_ERROR;
         |                                 ^~~~~~~~~~~~~~~~~
   drivers/gpu/drm/tegra/plane.c: In function 'tegra_dc_pin':
>> drivers/gpu/drm/tegra/plane.c:170:31: error: implicit declaration of function 'dma_map_sgtable'; did you mean 'iommu_map_sgtable'? [-Werror=implicit-function-declaration]
     170 |                         err = dma_map_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
         |                               ^~~~~~~~~~~~~~~
         |                               iommu_map_sgtable
>> drivers/gpu/drm/tegra/plane.c:170:61: error: 'DMA_TO_DEVICE' undeclared (first use in this function); did you mean 'MT_DEVICE'?
     170 |                         err = dma_map_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
         |                                                             ^~~~~~~~~~~~~
         |                                                             MT_DEVICE
>> drivers/gpu/drm/tegra/plane.c:202:25: error: implicit declaration of function 'dma_unmap_sgtable'; did you mean 'iommu_map_sgtable'? [-Werror=implicit-function-declaration]
     202 |                         dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
         |                         ^~~~~~~~~~~~~~~~~
         |                         iommu_map_sgtable
   drivers/gpu/drm/tegra/plane.c:205:34: error: 'DMA_MAPPING_ERROR' undeclared (first use in this function)
     205 |                 state->iova[i] = DMA_MAPPING_ERROR;
         |                                  ^~~~~~~~~~~~~~~~~
   drivers/gpu/drm/tegra/plane.c: In function 'tegra_dc_unpin':
   drivers/gpu/drm/tegra/plane.c:221:57: error: 'DMA_TO_DEVICE' undeclared (first use in this function); did you mean 'MT_DEVICE'?
     221 |                         dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
         |                                                         ^~~~~~~~~~~~~
         |                                                         MT_DEVICE
   drivers/gpu/drm/tegra/plane.c:224:34: error: 'DMA_MAPPING_ERROR' undeclared (first use in this function)
     224 |                 state->iova[i] = DMA_MAPPING_ERROR;
         |                                  ^~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
   drivers/gpu/drm/tegra/dc.c: In function 'tegra_crtc_calculate_memory_bandwidth':
   drivers/gpu/drm/tegra/dc.c:2225:38: warning: variable 'old_state' set but not used [-Wunused-but-set-variable]
    2225 |         const struct drm_crtc_state *old_state;
         |                                      ^~~~~~~~~
   drivers/gpu/drm/tegra/dc.c: In function 'tegra_dc_probe':
>> drivers/gpu/drm/tegra/dc.c:2978:24: error: implicit declaration of function 'dma_get_mask'; did you mean 'xa_get_mark'? [-Werror=implicit-function-declaration]
    2978 |         u64 dma_mask = dma_get_mask(pdev->dev.parent);
         |                        ^~~~~~~~~~~~
         |                        xa_get_mark
>> drivers/gpu/drm/tegra/dc.c:2982:15: error: implicit declaration of function 'dma_coerce_mask_and_coherent' [-Werror=implicit-function-declaration]
    2982 |         err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
         |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors


vim +1043 drivers/gpu/drm/tegra/hub.c

c4755fb9064f64 Thierry Reding 2017-11-13  1040  
c4755fb9064f64 Thierry Reding 2017-11-13  1041  static int tegra_display_hub_probe(struct platform_device *pdev)
c4755fb9064f64 Thierry Reding 2017-11-13  1042  {
86044e749be77a Thierry Reding 2021-03-26 @1043  	u64 dma_mask = dma_get_mask(pdev->dev.parent);
0cffbde2e318cc Thierry Reding 2018-11-29  1044  	struct device_node *child = NULL;
c4755fb9064f64 Thierry Reding 2017-11-13  1045  	struct tegra_display_hub *hub;
0cffbde2e318cc Thierry Reding 2018-11-29  1046  	struct clk *clk;
c4755fb9064f64 Thierry Reding 2017-11-13  1047  	unsigned int i;
c4755fb9064f64 Thierry Reding 2017-11-13  1048  	int err;
c4755fb9064f64 Thierry Reding 2017-11-13  1049  
86044e749be77a Thierry Reding 2021-03-26 @1050  	err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
86044e749be77a Thierry Reding 2021-03-26  1051  	if (err < 0) {
86044e749be77a Thierry Reding 2021-03-26  1052  		dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err);
86044e749be77a Thierry Reding 2021-03-26  1053  		return err;
86044e749be77a Thierry Reding 2021-03-26  1054  	}
86044e749be77a Thierry Reding 2021-03-26  1055  
c4755fb9064f64 Thierry Reding 2017-11-13  1056  	hub = devm_kzalloc(&pdev->dev, sizeof(*hub), GFP_KERNEL);
c4755fb9064f64 Thierry Reding 2017-11-13  1057  	if (!hub)
c4755fb9064f64 Thierry Reding 2017-11-13  1058  		return -ENOMEM;
c4755fb9064f64 Thierry Reding 2017-11-13  1059  
c4755fb9064f64 Thierry Reding 2017-11-13  1060  	hub->soc = of_device_get_match_data(&pdev->dev);
c4755fb9064f64 Thierry Reding 2017-11-13  1061  
c4755fb9064f64 Thierry Reding 2017-11-13  1062  	hub->clk_disp = devm_clk_get(&pdev->dev, "disp");
c4755fb9064f64 Thierry Reding 2017-11-13  1063  	if (IS_ERR(hub->clk_disp)) {
c4755fb9064f64 Thierry Reding 2017-11-13  1064  		err = PTR_ERR(hub->clk_disp);
c4755fb9064f64 Thierry Reding 2017-11-13  1065  		return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1066  	}
c4755fb9064f64 Thierry Reding 2017-11-13  1067  
5725daaab55ca0 Thierry Reding 2018-09-21  1068  	if (hub->soc->supports_dsc) {
c4755fb9064f64 Thierry Reding 2017-11-13  1069  		hub->clk_dsc = devm_clk_get(&pdev->dev, "dsc");
c4755fb9064f64 Thierry Reding 2017-11-13  1070  		if (IS_ERR(hub->clk_dsc)) {
c4755fb9064f64 Thierry Reding 2017-11-13  1071  			err = PTR_ERR(hub->clk_dsc);
c4755fb9064f64 Thierry Reding 2017-11-13  1072  			return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1073  		}
5725daaab55ca0 Thierry Reding 2018-09-21  1074  	}
c4755fb9064f64 Thierry Reding 2017-11-13  1075  
c4755fb9064f64 Thierry Reding 2017-11-13  1076  	hub->clk_hub = devm_clk_get(&pdev->dev, "hub");
c4755fb9064f64 Thierry Reding 2017-11-13  1077  	if (IS_ERR(hub->clk_hub)) {
c4755fb9064f64 Thierry Reding 2017-11-13  1078  		err = PTR_ERR(hub->clk_hub);
c4755fb9064f64 Thierry Reding 2017-11-13  1079  		return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1080  	}
c4755fb9064f64 Thierry Reding 2017-11-13  1081  
c4755fb9064f64 Thierry Reding 2017-11-13  1082  	hub->rst = devm_reset_control_get(&pdev->dev, "misc");
c4755fb9064f64 Thierry Reding 2017-11-13  1083  	if (IS_ERR(hub->rst)) {
c4755fb9064f64 Thierry Reding 2017-11-13  1084  		err = PTR_ERR(hub->rst);
c4755fb9064f64 Thierry Reding 2017-11-13  1085  		return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1086  	}
c4755fb9064f64 Thierry Reding 2017-11-13  1087  
c4755fb9064f64 Thierry Reding 2017-11-13  1088  	hub->wgrps = devm_kcalloc(&pdev->dev, hub->soc->num_wgrps,
c4755fb9064f64 Thierry Reding 2017-11-13  1089  				  sizeof(*hub->wgrps), GFP_KERNEL);
c4755fb9064f64 Thierry Reding 2017-11-13  1090  	if (!hub->wgrps)
c4755fb9064f64 Thierry Reding 2017-11-13  1091  		return -ENOMEM;
c4755fb9064f64 Thierry Reding 2017-11-13  1092  
c4755fb9064f64 Thierry Reding 2017-11-13  1093  	for (i = 0; i < hub->soc->num_wgrps; i++) {
c4755fb9064f64 Thierry Reding 2017-11-13  1094  		struct tegra_windowgroup *wgrp = &hub->wgrps[i];
c4755fb9064f64 Thierry Reding 2017-11-13  1095  		char id[8];
c4755fb9064f64 Thierry Reding 2017-11-13  1096  
c4755fb9064f64 Thierry Reding 2017-11-13  1097  		snprintf(id, sizeof(id), "wgrp%u", i);
c4755fb9064f64 Thierry Reding 2017-11-13  1098  		mutex_init(&wgrp->lock);
c4755fb9064f64 Thierry Reding 2017-11-13  1099  		wgrp->usecount = 0;
c4755fb9064f64 Thierry Reding 2017-11-13  1100  		wgrp->index = i;
c4755fb9064f64 Thierry Reding 2017-11-13  1101  
c4755fb9064f64 Thierry Reding 2017-11-13  1102  		wgrp->rst = devm_reset_control_get(&pdev->dev, id);
c4755fb9064f64 Thierry Reding 2017-11-13  1103  		if (IS_ERR(wgrp->rst))
c4755fb9064f64 Thierry Reding 2017-11-13  1104  			return PTR_ERR(wgrp->rst);
c4755fb9064f64 Thierry Reding 2017-11-13  1105  
c4755fb9064f64 Thierry Reding 2017-11-13  1106  		err = reset_control_assert(wgrp->rst);
c4755fb9064f64 Thierry Reding 2017-11-13  1107  		if (err < 0)
c4755fb9064f64 Thierry Reding 2017-11-13  1108  			return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1109  	}
c4755fb9064f64 Thierry Reding 2017-11-13  1110  
0cffbde2e318cc Thierry Reding 2018-11-29  1111  	hub->num_heads = of_get_child_count(pdev->dev.of_node);
0cffbde2e318cc Thierry Reding 2018-11-29  1112  
0cffbde2e318cc Thierry Reding 2018-11-29  1113  	hub->clk_heads = devm_kcalloc(&pdev->dev, hub->num_heads, sizeof(clk),
0cffbde2e318cc Thierry Reding 2018-11-29  1114  				      GFP_KERNEL);
0cffbde2e318cc Thierry Reding 2018-11-29  1115  	if (!hub->clk_heads)
0cffbde2e318cc Thierry Reding 2018-11-29  1116  		return -ENOMEM;
0cffbde2e318cc Thierry Reding 2018-11-29  1117  
0cffbde2e318cc Thierry Reding 2018-11-29  1118  	for (i = 0; i < hub->num_heads; i++) {
0cffbde2e318cc Thierry Reding 2018-11-29  1119  		child = of_get_next_child(pdev->dev.of_node, child);
0cffbde2e318cc Thierry Reding 2018-11-29  1120  		if (!child) {
0cffbde2e318cc Thierry Reding 2018-11-29  1121  			dev_err(&pdev->dev, "failed to find node for head %u\n",
0cffbde2e318cc Thierry Reding 2018-11-29  1122  				i);
0cffbde2e318cc Thierry Reding 2018-11-29  1123  			return -ENODEV;
0cffbde2e318cc Thierry Reding 2018-11-29  1124  		}
0cffbde2e318cc Thierry Reding 2018-11-29  1125  
0cffbde2e318cc Thierry Reding 2018-11-29  1126  		clk = devm_get_clk_from_child(&pdev->dev, child, "dc");
0cffbde2e318cc Thierry Reding 2018-11-29  1127  		if (IS_ERR(clk)) {
0cffbde2e318cc Thierry Reding 2018-11-29  1128  			dev_err(&pdev->dev, "failed to get clock for head %u\n",
0cffbde2e318cc Thierry Reding 2018-11-29  1129  				i);
0cffbde2e318cc Thierry Reding 2018-11-29  1130  			of_node_put(child);
0cffbde2e318cc Thierry Reding 2018-11-29  1131  			return PTR_ERR(clk);
0cffbde2e318cc Thierry Reding 2018-11-29  1132  		}
0cffbde2e318cc Thierry Reding 2018-11-29  1133  
0cffbde2e318cc Thierry Reding 2018-11-29  1134  		hub->clk_heads[i] = clk;
0cffbde2e318cc Thierry Reding 2018-11-29  1135  	}
0cffbde2e318cc Thierry Reding 2018-11-29  1136  
0cffbde2e318cc Thierry Reding 2018-11-29  1137  	of_node_put(child);
0cffbde2e318cc Thierry Reding 2018-11-29  1138  
c4755fb9064f64 Thierry Reding 2017-11-13  1139  	/* XXX: enable clock across reset? */
c4755fb9064f64 Thierry Reding 2017-11-13  1140  	err = reset_control_assert(hub->rst);
c4755fb9064f64 Thierry Reding 2017-11-13  1141  	if (err < 0)
c4755fb9064f64 Thierry Reding 2017-11-13  1142  		return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1143  
c4755fb9064f64 Thierry Reding 2017-11-13  1144  	platform_set_drvdata(pdev, hub);
c4755fb9064f64 Thierry Reding 2017-11-13  1145  	pm_runtime_enable(&pdev->dev);
c4755fb9064f64 Thierry Reding 2017-11-13  1146  
c4755fb9064f64 Thierry Reding 2017-11-13  1147  	INIT_LIST_HEAD(&hub->client.list);
c4755fb9064f64 Thierry Reding 2017-11-13  1148  	hub->client.ops = &tegra_display_hub_ops;
c4755fb9064f64 Thierry Reding 2017-11-13  1149  	hub->client.dev = &pdev->dev;
c4755fb9064f64 Thierry Reding 2017-11-13  1150  
c4755fb9064f64 Thierry Reding 2017-11-13  1151  	err = host1x_client_register(&hub->client);
c4755fb9064f64 Thierry Reding 2017-11-13  1152  	if (err < 0)
c4755fb9064f64 Thierry Reding 2017-11-13  1153  		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
c4755fb9064f64 Thierry Reding 2017-11-13  1154  			err);
c4755fb9064f64 Thierry Reding 2017-11-13  1155  
a101e3dad8a90a Thierry Reding 2020-06-12  1156  	err = devm_of_platform_populate(&pdev->dev);
a101e3dad8a90a Thierry Reding 2020-06-12  1157  	if (err < 0)
a101e3dad8a90a Thierry Reding 2020-06-12  1158  		goto unregister;
a101e3dad8a90a Thierry Reding 2020-06-12  1159  
a101e3dad8a90a Thierry Reding 2020-06-12  1160  	return err;
a101e3dad8a90a Thierry Reding 2020-06-12  1161  
a101e3dad8a90a Thierry Reding 2020-06-12  1162  unregister:
a101e3dad8a90a Thierry Reding 2020-06-12  1163  	host1x_client_unregister(&hub->client);
a101e3dad8a90a Thierry Reding 2020-06-12  1164  	pm_runtime_disable(&pdev->dev);
c4755fb9064f64 Thierry Reding 2017-11-13  1165  	return err;
c4755fb9064f64 Thierry Reding 2017-11-13  1166  }
c4755fb9064f64 Thierry Reding 2017-11-13  1167  

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

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

* Re: [PATCH v2 11/11] iommu: Move flush queue data into iommu_dma_cookie
  2021-12-10 17:54   ` Robin Murphy
  (?)
@ 2021-12-10 23:50     ` kernel test robot
  -1 siblings, 0 replies; 66+ messages in thread
From: kernel test robot @ 2021-12-10 23:50 UTC (permalink / raw)
  To: Robin Murphy, joro, will
  Cc: llvm, kbuild-all, iommu, suravee.suthikulpanit, baolu.lu, willy,
	linux-kernel, john.garry, linux-mm

Hi Robin,

I love your patch! Yet something to improve:

[auto build test ERROR on joro-iommu/next]
[also build test ERROR on tegra/for-next v5.16-rc4]
[cannot apply to tegra-drm/drm/tegra/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/Robin-Murphy/iommu-refactor-flush-queues-into-iommu-dma/20211211-015635
base:   https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next
config: arm64-randconfig-r014-20211210 (https://download.01.org/0day-ci/archive/20211211/202112110744.cWU0wC1O-lkp@intel.com/config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 097a1cb1d5ebb3a0ec4bcaed8ba3ff6a8e33c00a)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install arm64 cross compiling tool for clang build
        # apt-get install binutils-aarch64-linux-gnu
        # https://github.com/0day-ci/linux/commit/3b6adb4a8ec42d7b5c1b3b1af2c857a2375fd7e1
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Robin-Murphy/iommu-refactor-flush-queues-into-iommu-dma/20211211-015635
        git checkout 3b6adb4a8ec42d7b5c1b3b1af2c857a2375fd7e1
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm64 SHELL=/bin/bash drivers/gpu/drm/tegra/

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

All errors (new ones prefixed by >>):

>> drivers/gpu/drm/tegra/hub.c:1043:17: error: implicit declaration of function 'dma_get_mask' [-Werror,-Wimplicit-function-declaration]
           u64 dma_mask = dma_get_mask(pdev->dev.parent);
                          ^
   drivers/gpu/drm/tegra/hub.c:1043:17: note: did you mean 'xa_get_mark'?
   include/linux/xarray.h:354:6: note: 'xa_get_mark' declared here
   bool xa_get_mark(struct xarray *, unsigned long index, xa_mark_t);
        ^
>> drivers/gpu/drm/tegra/hub.c:1050:8: error: implicit declaration of function 'dma_coerce_mask_and_coherent' [-Werror,-Wimplicit-function-declaration]
           err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
                 ^
   2 errors generated.
--
>> drivers/gpu/drm/tegra/plane.c:46:21: error: use of undeclared identifier 'DMA_MAPPING_ERROR'
                           state->iova[i] = DMA_MAPPING_ERROR;
                                            ^
   drivers/gpu/drm/tegra/plane.c:76:19: error: use of undeclared identifier 'DMA_MAPPING_ERROR'
                   copy->iova[i] = DMA_MAPPING_ERROR;
                                   ^
>> drivers/gpu/drm/tegra/plane.c:170:10: error: implicit declaration of function 'dma_map_sgtable' [-Werror,-Wimplicit-function-declaration]
                           err = dma_map_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
                                 ^
   drivers/gpu/drm/tegra/plane.c:170:10: note: did you mean 'iommu_map_sgtable'?
   include/linux/iommu.h:1097:22: note: 'iommu_map_sgtable' declared here
   static inline size_t iommu_map_sgtable(struct iommu_domain *domain,
                        ^
>> drivers/gpu/drm/tegra/plane.c:170:40: error: use of undeclared identifier 'DMA_TO_DEVICE'
                           err = dma_map_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
                                                               ^
>> drivers/gpu/drm/tegra/plane.c:202:4: error: implicit declaration of function 'dma_unmap_sgtable' [-Werror,-Wimplicit-function-declaration]
                           dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
                           ^
   drivers/gpu/drm/tegra/plane.c:202:4: note: did you mean 'iommu_map_sgtable'?
   include/linux/iommu.h:1097:22: note: 'iommu_map_sgtable' declared here
   static inline size_t iommu_map_sgtable(struct iommu_domain *domain,
                        ^
   drivers/gpu/drm/tegra/plane.c:202:36: error: use of undeclared identifier 'DMA_TO_DEVICE'
                           dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
                                                           ^
   drivers/gpu/drm/tegra/plane.c:205:20: error: use of undeclared identifier 'DMA_MAPPING_ERROR'
                   state->iova[i] = DMA_MAPPING_ERROR;
                                    ^
   drivers/gpu/drm/tegra/plane.c:221:4: error: implicit declaration of function 'dma_unmap_sgtable' [-Werror,-Wimplicit-function-declaration]
                           dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
                           ^
   drivers/gpu/drm/tegra/plane.c:221:36: error: use of undeclared identifier 'DMA_TO_DEVICE'
                           dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
                                                           ^
   drivers/gpu/drm/tegra/plane.c:224:20: error: use of undeclared identifier 'DMA_MAPPING_ERROR'
                   state->iova[i] = DMA_MAPPING_ERROR;
                                    ^
   10 errors generated.
--
   drivers/gpu/drm/tegra/dc.c:2225:31: warning: variable 'old_state' set but not used [-Wunused-but-set-variable]
           const struct drm_crtc_state *old_state;
                                        ^
>> drivers/gpu/drm/tegra/dc.c:2978:17: error: implicit declaration of function 'dma_get_mask' [-Werror,-Wimplicit-function-declaration]
           u64 dma_mask = dma_get_mask(pdev->dev.parent);
                          ^
   drivers/gpu/drm/tegra/dc.c:2978:17: note: did you mean 'xa_get_mark'?
   include/linux/xarray.h:354:6: note: 'xa_get_mark' declared here
   bool xa_get_mark(struct xarray *, unsigned long index, xa_mark_t);
        ^
>> drivers/gpu/drm/tegra/dc.c:2982:8: error: implicit declaration of function 'dma_coerce_mask_and_coherent' [-Werror,-Wimplicit-function-declaration]
           err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
                 ^
   1 warning and 2 errors generated.


vim +/dma_get_mask +1043 drivers/gpu/drm/tegra/hub.c

c4755fb9064f640 Thierry Reding 2017-11-13  1040  
c4755fb9064f640 Thierry Reding 2017-11-13  1041  static int tegra_display_hub_probe(struct platform_device *pdev)
c4755fb9064f640 Thierry Reding 2017-11-13  1042  {
86044e749be77a3 Thierry Reding 2021-03-26 @1043  	u64 dma_mask = dma_get_mask(pdev->dev.parent);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1044  	struct device_node *child = NULL;
c4755fb9064f640 Thierry Reding 2017-11-13  1045  	struct tegra_display_hub *hub;
0cffbde2e318cc1 Thierry Reding 2018-11-29  1046  	struct clk *clk;
c4755fb9064f640 Thierry Reding 2017-11-13  1047  	unsigned int i;
c4755fb9064f640 Thierry Reding 2017-11-13  1048  	int err;
c4755fb9064f640 Thierry Reding 2017-11-13  1049  
86044e749be77a3 Thierry Reding 2021-03-26 @1050  	err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
86044e749be77a3 Thierry Reding 2021-03-26  1051  	if (err < 0) {
86044e749be77a3 Thierry Reding 2021-03-26  1052  		dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err);
86044e749be77a3 Thierry Reding 2021-03-26  1053  		return err;
86044e749be77a3 Thierry Reding 2021-03-26  1054  	}
86044e749be77a3 Thierry Reding 2021-03-26  1055  
c4755fb9064f640 Thierry Reding 2017-11-13  1056  	hub = devm_kzalloc(&pdev->dev, sizeof(*hub), GFP_KERNEL);
c4755fb9064f640 Thierry Reding 2017-11-13  1057  	if (!hub)
c4755fb9064f640 Thierry Reding 2017-11-13  1058  		return -ENOMEM;
c4755fb9064f640 Thierry Reding 2017-11-13  1059  
c4755fb9064f640 Thierry Reding 2017-11-13  1060  	hub->soc = of_device_get_match_data(&pdev->dev);
c4755fb9064f640 Thierry Reding 2017-11-13  1061  
c4755fb9064f640 Thierry Reding 2017-11-13  1062  	hub->clk_disp = devm_clk_get(&pdev->dev, "disp");
c4755fb9064f640 Thierry Reding 2017-11-13  1063  	if (IS_ERR(hub->clk_disp)) {
c4755fb9064f640 Thierry Reding 2017-11-13  1064  		err = PTR_ERR(hub->clk_disp);
c4755fb9064f640 Thierry Reding 2017-11-13  1065  		return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1066  	}
c4755fb9064f640 Thierry Reding 2017-11-13  1067  
5725daaab55ca02 Thierry Reding 2018-09-21  1068  	if (hub->soc->supports_dsc) {
c4755fb9064f640 Thierry Reding 2017-11-13  1069  		hub->clk_dsc = devm_clk_get(&pdev->dev, "dsc");
c4755fb9064f640 Thierry Reding 2017-11-13  1070  		if (IS_ERR(hub->clk_dsc)) {
c4755fb9064f640 Thierry Reding 2017-11-13  1071  			err = PTR_ERR(hub->clk_dsc);
c4755fb9064f640 Thierry Reding 2017-11-13  1072  			return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1073  		}
5725daaab55ca02 Thierry Reding 2018-09-21  1074  	}
c4755fb9064f640 Thierry Reding 2017-11-13  1075  
c4755fb9064f640 Thierry Reding 2017-11-13  1076  	hub->clk_hub = devm_clk_get(&pdev->dev, "hub");
c4755fb9064f640 Thierry Reding 2017-11-13  1077  	if (IS_ERR(hub->clk_hub)) {
c4755fb9064f640 Thierry Reding 2017-11-13  1078  		err = PTR_ERR(hub->clk_hub);
c4755fb9064f640 Thierry Reding 2017-11-13  1079  		return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1080  	}
c4755fb9064f640 Thierry Reding 2017-11-13  1081  
c4755fb9064f640 Thierry Reding 2017-11-13  1082  	hub->rst = devm_reset_control_get(&pdev->dev, "misc");
c4755fb9064f640 Thierry Reding 2017-11-13  1083  	if (IS_ERR(hub->rst)) {
c4755fb9064f640 Thierry Reding 2017-11-13  1084  		err = PTR_ERR(hub->rst);
c4755fb9064f640 Thierry Reding 2017-11-13  1085  		return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1086  	}
c4755fb9064f640 Thierry Reding 2017-11-13  1087  
c4755fb9064f640 Thierry Reding 2017-11-13  1088  	hub->wgrps = devm_kcalloc(&pdev->dev, hub->soc->num_wgrps,
c4755fb9064f640 Thierry Reding 2017-11-13  1089  				  sizeof(*hub->wgrps), GFP_KERNEL);
c4755fb9064f640 Thierry Reding 2017-11-13  1090  	if (!hub->wgrps)
c4755fb9064f640 Thierry Reding 2017-11-13  1091  		return -ENOMEM;
c4755fb9064f640 Thierry Reding 2017-11-13  1092  
c4755fb9064f640 Thierry Reding 2017-11-13  1093  	for (i = 0; i < hub->soc->num_wgrps; i++) {
c4755fb9064f640 Thierry Reding 2017-11-13  1094  		struct tegra_windowgroup *wgrp = &hub->wgrps[i];
c4755fb9064f640 Thierry Reding 2017-11-13  1095  		char id[8];
c4755fb9064f640 Thierry Reding 2017-11-13  1096  
c4755fb9064f640 Thierry Reding 2017-11-13  1097  		snprintf(id, sizeof(id), "wgrp%u", i);
c4755fb9064f640 Thierry Reding 2017-11-13  1098  		mutex_init(&wgrp->lock);
c4755fb9064f640 Thierry Reding 2017-11-13  1099  		wgrp->usecount = 0;
c4755fb9064f640 Thierry Reding 2017-11-13  1100  		wgrp->index = i;
c4755fb9064f640 Thierry Reding 2017-11-13  1101  
c4755fb9064f640 Thierry Reding 2017-11-13  1102  		wgrp->rst = devm_reset_control_get(&pdev->dev, id);
c4755fb9064f640 Thierry Reding 2017-11-13  1103  		if (IS_ERR(wgrp->rst))
c4755fb9064f640 Thierry Reding 2017-11-13  1104  			return PTR_ERR(wgrp->rst);
c4755fb9064f640 Thierry Reding 2017-11-13  1105  
c4755fb9064f640 Thierry Reding 2017-11-13  1106  		err = reset_control_assert(wgrp->rst);
c4755fb9064f640 Thierry Reding 2017-11-13  1107  		if (err < 0)
c4755fb9064f640 Thierry Reding 2017-11-13  1108  			return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1109  	}
c4755fb9064f640 Thierry Reding 2017-11-13  1110  
0cffbde2e318cc1 Thierry Reding 2018-11-29  1111  	hub->num_heads = of_get_child_count(pdev->dev.of_node);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1112  
0cffbde2e318cc1 Thierry Reding 2018-11-29  1113  	hub->clk_heads = devm_kcalloc(&pdev->dev, hub->num_heads, sizeof(clk),
0cffbde2e318cc1 Thierry Reding 2018-11-29  1114  				      GFP_KERNEL);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1115  	if (!hub->clk_heads)
0cffbde2e318cc1 Thierry Reding 2018-11-29  1116  		return -ENOMEM;
0cffbde2e318cc1 Thierry Reding 2018-11-29  1117  
0cffbde2e318cc1 Thierry Reding 2018-11-29  1118  	for (i = 0; i < hub->num_heads; i++) {
0cffbde2e318cc1 Thierry Reding 2018-11-29  1119  		child = of_get_next_child(pdev->dev.of_node, child);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1120  		if (!child) {
0cffbde2e318cc1 Thierry Reding 2018-11-29  1121  			dev_err(&pdev->dev, "failed to find node for head %u\n",
0cffbde2e318cc1 Thierry Reding 2018-11-29  1122  				i);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1123  			return -ENODEV;
0cffbde2e318cc1 Thierry Reding 2018-11-29  1124  		}
0cffbde2e318cc1 Thierry Reding 2018-11-29  1125  
0cffbde2e318cc1 Thierry Reding 2018-11-29  1126  		clk = devm_get_clk_from_child(&pdev->dev, child, "dc");
0cffbde2e318cc1 Thierry Reding 2018-11-29  1127  		if (IS_ERR(clk)) {
0cffbde2e318cc1 Thierry Reding 2018-11-29  1128  			dev_err(&pdev->dev, "failed to get clock for head %u\n",
0cffbde2e318cc1 Thierry Reding 2018-11-29  1129  				i);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1130  			of_node_put(child);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1131  			return PTR_ERR(clk);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1132  		}
0cffbde2e318cc1 Thierry Reding 2018-11-29  1133  
0cffbde2e318cc1 Thierry Reding 2018-11-29  1134  		hub->clk_heads[i] = clk;
0cffbde2e318cc1 Thierry Reding 2018-11-29  1135  	}
0cffbde2e318cc1 Thierry Reding 2018-11-29  1136  
0cffbde2e318cc1 Thierry Reding 2018-11-29  1137  	of_node_put(child);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1138  
c4755fb9064f640 Thierry Reding 2017-11-13  1139  	/* XXX: enable clock across reset? */
c4755fb9064f640 Thierry Reding 2017-11-13  1140  	err = reset_control_assert(hub->rst);
c4755fb9064f640 Thierry Reding 2017-11-13  1141  	if (err < 0)
c4755fb9064f640 Thierry Reding 2017-11-13  1142  		return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1143  
c4755fb9064f640 Thierry Reding 2017-11-13  1144  	platform_set_drvdata(pdev, hub);
c4755fb9064f640 Thierry Reding 2017-11-13  1145  	pm_runtime_enable(&pdev->dev);
c4755fb9064f640 Thierry Reding 2017-11-13  1146  
c4755fb9064f640 Thierry Reding 2017-11-13  1147  	INIT_LIST_HEAD(&hub->client.list);
c4755fb9064f640 Thierry Reding 2017-11-13  1148  	hub->client.ops = &tegra_display_hub_ops;
c4755fb9064f640 Thierry Reding 2017-11-13  1149  	hub->client.dev = &pdev->dev;
c4755fb9064f640 Thierry Reding 2017-11-13  1150  
c4755fb9064f640 Thierry Reding 2017-11-13  1151  	err = host1x_client_register(&hub->client);
c4755fb9064f640 Thierry Reding 2017-11-13  1152  	if (err < 0)
c4755fb9064f640 Thierry Reding 2017-11-13  1153  		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
c4755fb9064f640 Thierry Reding 2017-11-13  1154  			err);
c4755fb9064f640 Thierry Reding 2017-11-13  1155  
a101e3dad8a90a8 Thierry Reding 2020-06-12  1156  	err = devm_of_platform_populate(&pdev->dev);
a101e3dad8a90a8 Thierry Reding 2020-06-12  1157  	if (err < 0)
a101e3dad8a90a8 Thierry Reding 2020-06-12  1158  		goto unregister;
a101e3dad8a90a8 Thierry Reding 2020-06-12  1159  
a101e3dad8a90a8 Thierry Reding 2020-06-12  1160  	return err;
a101e3dad8a90a8 Thierry Reding 2020-06-12  1161  
a101e3dad8a90a8 Thierry Reding 2020-06-12  1162  unregister:
a101e3dad8a90a8 Thierry Reding 2020-06-12  1163  	host1x_client_unregister(&hub->client);
a101e3dad8a90a8 Thierry Reding 2020-06-12  1164  	pm_runtime_disable(&pdev->dev);
c4755fb9064f640 Thierry Reding 2017-11-13  1165  	return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1166  }
c4755fb9064f640 Thierry Reding 2017-11-13  1167  

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

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

* Re: [PATCH v2 11/11] iommu: Move flush queue data into iommu_dma_cookie
@ 2021-12-10 23:50     ` kernel test robot
  0 siblings, 0 replies; 66+ messages in thread
From: kernel test robot @ 2021-12-10 23:50 UTC (permalink / raw)
  To: Robin Murphy, joro, will
  Cc: kbuild-all, llvm, linux-kernel, willy, linux-mm, iommu

Hi Robin,

I love your patch! Yet something to improve:

[auto build test ERROR on joro-iommu/next]
[also build test ERROR on tegra/for-next v5.16-rc4]
[cannot apply to tegra-drm/drm/tegra/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/Robin-Murphy/iommu-refactor-flush-queues-into-iommu-dma/20211211-015635
base:   https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next
config: arm64-randconfig-r014-20211210 (https://download.01.org/0day-ci/archive/20211211/202112110744.cWU0wC1O-lkp@intel.com/config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 097a1cb1d5ebb3a0ec4bcaed8ba3ff6a8e33c00a)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install arm64 cross compiling tool for clang build
        # apt-get install binutils-aarch64-linux-gnu
        # https://github.com/0day-ci/linux/commit/3b6adb4a8ec42d7b5c1b3b1af2c857a2375fd7e1
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Robin-Murphy/iommu-refactor-flush-queues-into-iommu-dma/20211211-015635
        git checkout 3b6adb4a8ec42d7b5c1b3b1af2c857a2375fd7e1
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm64 SHELL=/bin/bash drivers/gpu/drm/tegra/

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

All errors (new ones prefixed by >>):

>> drivers/gpu/drm/tegra/hub.c:1043:17: error: implicit declaration of function 'dma_get_mask' [-Werror,-Wimplicit-function-declaration]
           u64 dma_mask = dma_get_mask(pdev->dev.parent);
                          ^
   drivers/gpu/drm/tegra/hub.c:1043:17: note: did you mean 'xa_get_mark'?
   include/linux/xarray.h:354:6: note: 'xa_get_mark' declared here
   bool xa_get_mark(struct xarray *, unsigned long index, xa_mark_t);
        ^
>> drivers/gpu/drm/tegra/hub.c:1050:8: error: implicit declaration of function 'dma_coerce_mask_and_coherent' [-Werror,-Wimplicit-function-declaration]
           err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
                 ^
   2 errors generated.
--
>> drivers/gpu/drm/tegra/plane.c:46:21: error: use of undeclared identifier 'DMA_MAPPING_ERROR'
                           state->iova[i] = DMA_MAPPING_ERROR;
                                            ^
   drivers/gpu/drm/tegra/plane.c:76:19: error: use of undeclared identifier 'DMA_MAPPING_ERROR'
                   copy->iova[i] = DMA_MAPPING_ERROR;
                                   ^
>> drivers/gpu/drm/tegra/plane.c:170:10: error: implicit declaration of function 'dma_map_sgtable' [-Werror,-Wimplicit-function-declaration]
                           err = dma_map_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
                                 ^
   drivers/gpu/drm/tegra/plane.c:170:10: note: did you mean 'iommu_map_sgtable'?
   include/linux/iommu.h:1097:22: note: 'iommu_map_sgtable' declared here
   static inline size_t iommu_map_sgtable(struct iommu_domain *domain,
                        ^
>> drivers/gpu/drm/tegra/plane.c:170:40: error: use of undeclared identifier 'DMA_TO_DEVICE'
                           err = dma_map_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
                                                               ^
>> drivers/gpu/drm/tegra/plane.c:202:4: error: implicit declaration of function 'dma_unmap_sgtable' [-Werror,-Wimplicit-function-declaration]
                           dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
                           ^
   drivers/gpu/drm/tegra/plane.c:202:4: note: did you mean 'iommu_map_sgtable'?
   include/linux/iommu.h:1097:22: note: 'iommu_map_sgtable' declared here
   static inline size_t iommu_map_sgtable(struct iommu_domain *domain,
                        ^
   drivers/gpu/drm/tegra/plane.c:202:36: error: use of undeclared identifier 'DMA_TO_DEVICE'
                           dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
                                                           ^
   drivers/gpu/drm/tegra/plane.c:205:20: error: use of undeclared identifier 'DMA_MAPPING_ERROR'
                   state->iova[i] = DMA_MAPPING_ERROR;
                                    ^
   drivers/gpu/drm/tegra/plane.c:221:4: error: implicit declaration of function 'dma_unmap_sgtable' [-Werror,-Wimplicit-function-declaration]
                           dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
                           ^
   drivers/gpu/drm/tegra/plane.c:221:36: error: use of undeclared identifier 'DMA_TO_DEVICE'
                           dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
                                                           ^
   drivers/gpu/drm/tegra/plane.c:224:20: error: use of undeclared identifier 'DMA_MAPPING_ERROR'
                   state->iova[i] = DMA_MAPPING_ERROR;
                                    ^
   10 errors generated.
--
   drivers/gpu/drm/tegra/dc.c:2225:31: warning: variable 'old_state' set but not used [-Wunused-but-set-variable]
           const struct drm_crtc_state *old_state;
                                        ^
>> drivers/gpu/drm/tegra/dc.c:2978:17: error: implicit declaration of function 'dma_get_mask' [-Werror,-Wimplicit-function-declaration]
           u64 dma_mask = dma_get_mask(pdev->dev.parent);
                          ^
   drivers/gpu/drm/tegra/dc.c:2978:17: note: did you mean 'xa_get_mark'?
   include/linux/xarray.h:354:6: note: 'xa_get_mark' declared here
   bool xa_get_mark(struct xarray *, unsigned long index, xa_mark_t);
        ^
>> drivers/gpu/drm/tegra/dc.c:2982:8: error: implicit declaration of function 'dma_coerce_mask_and_coherent' [-Werror,-Wimplicit-function-declaration]
           err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
                 ^
   1 warning and 2 errors generated.


vim +/dma_get_mask +1043 drivers/gpu/drm/tegra/hub.c

c4755fb9064f640 Thierry Reding 2017-11-13  1040  
c4755fb9064f640 Thierry Reding 2017-11-13  1041  static int tegra_display_hub_probe(struct platform_device *pdev)
c4755fb9064f640 Thierry Reding 2017-11-13  1042  {
86044e749be77a3 Thierry Reding 2021-03-26 @1043  	u64 dma_mask = dma_get_mask(pdev->dev.parent);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1044  	struct device_node *child = NULL;
c4755fb9064f640 Thierry Reding 2017-11-13  1045  	struct tegra_display_hub *hub;
0cffbde2e318cc1 Thierry Reding 2018-11-29  1046  	struct clk *clk;
c4755fb9064f640 Thierry Reding 2017-11-13  1047  	unsigned int i;
c4755fb9064f640 Thierry Reding 2017-11-13  1048  	int err;
c4755fb9064f640 Thierry Reding 2017-11-13  1049  
86044e749be77a3 Thierry Reding 2021-03-26 @1050  	err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
86044e749be77a3 Thierry Reding 2021-03-26  1051  	if (err < 0) {
86044e749be77a3 Thierry Reding 2021-03-26  1052  		dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err);
86044e749be77a3 Thierry Reding 2021-03-26  1053  		return err;
86044e749be77a3 Thierry Reding 2021-03-26  1054  	}
86044e749be77a3 Thierry Reding 2021-03-26  1055  
c4755fb9064f640 Thierry Reding 2017-11-13  1056  	hub = devm_kzalloc(&pdev->dev, sizeof(*hub), GFP_KERNEL);
c4755fb9064f640 Thierry Reding 2017-11-13  1057  	if (!hub)
c4755fb9064f640 Thierry Reding 2017-11-13  1058  		return -ENOMEM;
c4755fb9064f640 Thierry Reding 2017-11-13  1059  
c4755fb9064f640 Thierry Reding 2017-11-13  1060  	hub->soc = of_device_get_match_data(&pdev->dev);
c4755fb9064f640 Thierry Reding 2017-11-13  1061  
c4755fb9064f640 Thierry Reding 2017-11-13  1062  	hub->clk_disp = devm_clk_get(&pdev->dev, "disp");
c4755fb9064f640 Thierry Reding 2017-11-13  1063  	if (IS_ERR(hub->clk_disp)) {
c4755fb9064f640 Thierry Reding 2017-11-13  1064  		err = PTR_ERR(hub->clk_disp);
c4755fb9064f640 Thierry Reding 2017-11-13  1065  		return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1066  	}
c4755fb9064f640 Thierry Reding 2017-11-13  1067  
5725daaab55ca02 Thierry Reding 2018-09-21  1068  	if (hub->soc->supports_dsc) {
c4755fb9064f640 Thierry Reding 2017-11-13  1069  		hub->clk_dsc = devm_clk_get(&pdev->dev, "dsc");
c4755fb9064f640 Thierry Reding 2017-11-13  1070  		if (IS_ERR(hub->clk_dsc)) {
c4755fb9064f640 Thierry Reding 2017-11-13  1071  			err = PTR_ERR(hub->clk_dsc);
c4755fb9064f640 Thierry Reding 2017-11-13  1072  			return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1073  		}
5725daaab55ca02 Thierry Reding 2018-09-21  1074  	}
c4755fb9064f640 Thierry Reding 2017-11-13  1075  
c4755fb9064f640 Thierry Reding 2017-11-13  1076  	hub->clk_hub = devm_clk_get(&pdev->dev, "hub");
c4755fb9064f640 Thierry Reding 2017-11-13  1077  	if (IS_ERR(hub->clk_hub)) {
c4755fb9064f640 Thierry Reding 2017-11-13  1078  		err = PTR_ERR(hub->clk_hub);
c4755fb9064f640 Thierry Reding 2017-11-13  1079  		return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1080  	}
c4755fb9064f640 Thierry Reding 2017-11-13  1081  
c4755fb9064f640 Thierry Reding 2017-11-13  1082  	hub->rst = devm_reset_control_get(&pdev->dev, "misc");
c4755fb9064f640 Thierry Reding 2017-11-13  1083  	if (IS_ERR(hub->rst)) {
c4755fb9064f640 Thierry Reding 2017-11-13  1084  		err = PTR_ERR(hub->rst);
c4755fb9064f640 Thierry Reding 2017-11-13  1085  		return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1086  	}
c4755fb9064f640 Thierry Reding 2017-11-13  1087  
c4755fb9064f640 Thierry Reding 2017-11-13  1088  	hub->wgrps = devm_kcalloc(&pdev->dev, hub->soc->num_wgrps,
c4755fb9064f640 Thierry Reding 2017-11-13  1089  				  sizeof(*hub->wgrps), GFP_KERNEL);
c4755fb9064f640 Thierry Reding 2017-11-13  1090  	if (!hub->wgrps)
c4755fb9064f640 Thierry Reding 2017-11-13  1091  		return -ENOMEM;
c4755fb9064f640 Thierry Reding 2017-11-13  1092  
c4755fb9064f640 Thierry Reding 2017-11-13  1093  	for (i = 0; i < hub->soc->num_wgrps; i++) {
c4755fb9064f640 Thierry Reding 2017-11-13  1094  		struct tegra_windowgroup *wgrp = &hub->wgrps[i];
c4755fb9064f640 Thierry Reding 2017-11-13  1095  		char id[8];
c4755fb9064f640 Thierry Reding 2017-11-13  1096  
c4755fb9064f640 Thierry Reding 2017-11-13  1097  		snprintf(id, sizeof(id), "wgrp%u", i);
c4755fb9064f640 Thierry Reding 2017-11-13  1098  		mutex_init(&wgrp->lock);
c4755fb9064f640 Thierry Reding 2017-11-13  1099  		wgrp->usecount = 0;
c4755fb9064f640 Thierry Reding 2017-11-13  1100  		wgrp->index = i;
c4755fb9064f640 Thierry Reding 2017-11-13  1101  
c4755fb9064f640 Thierry Reding 2017-11-13  1102  		wgrp->rst = devm_reset_control_get(&pdev->dev, id);
c4755fb9064f640 Thierry Reding 2017-11-13  1103  		if (IS_ERR(wgrp->rst))
c4755fb9064f640 Thierry Reding 2017-11-13  1104  			return PTR_ERR(wgrp->rst);
c4755fb9064f640 Thierry Reding 2017-11-13  1105  
c4755fb9064f640 Thierry Reding 2017-11-13  1106  		err = reset_control_assert(wgrp->rst);
c4755fb9064f640 Thierry Reding 2017-11-13  1107  		if (err < 0)
c4755fb9064f640 Thierry Reding 2017-11-13  1108  			return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1109  	}
c4755fb9064f640 Thierry Reding 2017-11-13  1110  
0cffbde2e318cc1 Thierry Reding 2018-11-29  1111  	hub->num_heads = of_get_child_count(pdev->dev.of_node);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1112  
0cffbde2e318cc1 Thierry Reding 2018-11-29  1113  	hub->clk_heads = devm_kcalloc(&pdev->dev, hub->num_heads, sizeof(clk),
0cffbde2e318cc1 Thierry Reding 2018-11-29  1114  				      GFP_KERNEL);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1115  	if (!hub->clk_heads)
0cffbde2e318cc1 Thierry Reding 2018-11-29  1116  		return -ENOMEM;
0cffbde2e318cc1 Thierry Reding 2018-11-29  1117  
0cffbde2e318cc1 Thierry Reding 2018-11-29  1118  	for (i = 0; i < hub->num_heads; i++) {
0cffbde2e318cc1 Thierry Reding 2018-11-29  1119  		child = of_get_next_child(pdev->dev.of_node, child);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1120  		if (!child) {
0cffbde2e318cc1 Thierry Reding 2018-11-29  1121  			dev_err(&pdev->dev, "failed to find node for head %u\n",
0cffbde2e318cc1 Thierry Reding 2018-11-29  1122  				i);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1123  			return -ENODEV;
0cffbde2e318cc1 Thierry Reding 2018-11-29  1124  		}
0cffbde2e318cc1 Thierry Reding 2018-11-29  1125  
0cffbde2e318cc1 Thierry Reding 2018-11-29  1126  		clk = devm_get_clk_from_child(&pdev->dev, child, "dc");
0cffbde2e318cc1 Thierry Reding 2018-11-29  1127  		if (IS_ERR(clk)) {
0cffbde2e318cc1 Thierry Reding 2018-11-29  1128  			dev_err(&pdev->dev, "failed to get clock for head %u\n",
0cffbde2e318cc1 Thierry Reding 2018-11-29  1129  				i);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1130  			of_node_put(child);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1131  			return PTR_ERR(clk);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1132  		}
0cffbde2e318cc1 Thierry Reding 2018-11-29  1133  
0cffbde2e318cc1 Thierry Reding 2018-11-29  1134  		hub->clk_heads[i] = clk;
0cffbde2e318cc1 Thierry Reding 2018-11-29  1135  	}
0cffbde2e318cc1 Thierry Reding 2018-11-29  1136  
0cffbde2e318cc1 Thierry Reding 2018-11-29  1137  	of_node_put(child);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1138  
c4755fb9064f640 Thierry Reding 2017-11-13  1139  	/* XXX: enable clock across reset? */
c4755fb9064f640 Thierry Reding 2017-11-13  1140  	err = reset_control_assert(hub->rst);
c4755fb9064f640 Thierry Reding 2017-11-13  1141  	if (err < 0)
c4755fb9064f640 Thierry Reding 2017-11-13  1142  		return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1143  
c4755fb9064f640 Thierry Reding 2017-11-13  1144  	platform_set_drvdata(pdev, hub);
c4755fb9064f640 Thierry Reding 2017-11-13  1145  	pm_runtime_enable(&pdev->dev);
c4755fb9064f640 Thierry Reding 2017-11-13  1146  
c4755fb9064f640 Thierry Reding 2017-11-13  1147  	INIT_LIST_HEAD(&hub->client.list);
c4755fb9064f640 Thierry Reding 2017-11-13  1148  	hub->client.ops = &tegra_display_hub_ops;
c4755fb9064f640 Thierry Reding 2017-11-13  1149  	hub->client.dev = &pdev->dev;
c4755fb9064f640 Thierry Reding 2017-11-13  1150  
c4755fb9064f640 Thierry Reding 2017-11-13  1151  	err = host1x_client_register(&hub->client);
c4755fb9064f640 Thierry Reding 2017-11-13  1152  	if (err < 0)
c4755fb9064f640 Thierry Reding 2017-11-13  1153  		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
c4755fb9064f640 Thierry Reding 2017-11-13  1154  			err);
c4755fb9064f640 Thierry Reding 2017-11-13  1155  
a101e3dad8a90a8 Thierry Reding 2020-06-12  1156  	err = devm_of_platform_populate(&pdev->dev);
a101e3dad8a90a8 Thierry Reding 2020-06-12  1157  	if (err < 0)
a101e3dad8a90a8 Thierry Reding 2020-06-12  1158  		goto unregister;
a101e3dad8a90a8 Thierry Reding 2020-06-12  1159  
a101e3dad8a90a8 Thierry Reding 2020-06-12  1160  	return err;
a101e3dad8a90a8 Thierry Reding 2020-06-12  1161  
a101e3dad8a90a8 Thierry Reding 2020-06-12  1162  unregister:
a101e3dad8a90a8 Thierry Reding 2020-06-12  1163  	host1x_client_unregister(&hub->client);
a101e3dad8a90a8 Thierry Reding 2020-06-12  1164  	pm_runtime_disable(&pdev->dev);
c4755fb9064f640 Thierry Reding 2017-11-13  1165  	return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1166  }
c4755fb9064f640 Thierry Reding 2017-11-13  1167  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

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

* Re: [PATCH v2 11/11] iommu: Move flush queue data into iommu_dma_cookie
@ 2021-12-10 23:50     ` kernel test robot
  0 siblings, 0 replies; 66+ messages in thread
From: kernel test robot @ 2021-12-10 23:50 UTC (permalink / raw)
  To: kbuild-all

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

Hi Robin,

I love your patch! Yet something to improve:

[auto build test ERROR on joro-iommu/next]
[also build test ERROR on tegra/for-next v5.16-rc4]
[cannot apply to tegra-drm/drm/tegra/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/Robin-Murphy/iommu-refactor-flush-queues-into-iommu-dma/20211211-015635
base:   https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next
config: arm64-randconfig-r014-20211210 (https://download.01.org/0day-ci/archive/20211211/202112110744.cWU0wC1O-lkp(a)intel.com/config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 097a1cb1d5ebb3a0ec4bcaed8ba3ff6a8e33c00a)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install arm64 cross compiling tool for clang build
        # apt-get install binutils-aarch64-linux-gnu
        # https://github.com/0day-ci/linux/commit/3b6adb4a8ec42d7b5c1b3b1af2c857a2375fd7e1
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Robin-Murphy/iommu-refactor-flush-queues-into-iommu-dma/20211211-015635
        git checkout 3b6adb4a8ec42d7b5c1b3b1af2c857a2375fd7e1
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm64 SHELL=/bin/bash drivers/gpu/drm/tegra/

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

All errors (new ones prefixed by >>):

>> drivers/gpu/drm/tegra/hub.c:1043:17: error: implicit declaration of function 'dma_get_mask' [-Werror,-Wimplicit-function-declaration]
           u64 dma_mask = dma_get_mask(pdev->dev.parent);
                          ^
   drivers/gpu/drm/tegra/hub.c:1043:17: note: did you mean 'xa_get_mark'?
   include/linux/xarray.h:354:6: note: 'xa_get_mark' declared here
   bool xa_get_mark(struct xarray *, unsigned long index, xa_mark_t);
        ^
>> drivers/gpu/drm/tegra/hub.c:1050:8: error: implicit declaration of function 'dma_coerce_mask_and_coherent' [-Werror,-Wimplicit-function-declaration]
           err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
                 ^
   2 errors generated.
--
>> drivers/gpu/drm/tegra/plane.c:46:21: error: use of undeclared identifier 'DMA_MAPPING_ERROR'
                           state->iova[i] = DMA_MAPPING_ERROR;
                                            ^
   drivers/gpu/drm/tegra/plane.c:76:19: error: use of undeclared identifier 'DMA_MAPPING_ERROR'
                   copy->iova[i] = DMA_MAPPING_ERROR;
                                   ^
>> drivers/gpu/drm/tegra/plane.c:170:10: error: implicit declaration of function 'dma_map_sgtable' [-Werror,-Wimplicit-function-declaration]
                           err = dma_map_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
                                 ^
   drivers/gpu/drm/tegra/plane.c:170:10: note: did you mean 'iommu_map_sgtable'?
   include/linux/iommu.h:1097:22: note: 'iommu_map_sgtable' declared here
   static inline size_t iommu_map_sgtable(struct iommu_domain *domain,
                        ^
>> drivers/gpu/drm/tegra/plane.c:170:40: error: use of undeclared identifier 'DMA_TO_DEVICE'
                           err = dma_map_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
                                                               ^
>> drivers/gpu/drm/tegra/plane.c:202:4: error: implicit declaration of function 'dma_unmap_sgtable' [-Werror,-Wimplicit-function-declaration]
                           dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
                           ^
   drivers/gpu/drm/tegra/plane.c:202:4: note: did you mean 'iommu_map_sgtable'?
   include/linux/iommu.h:1097:22: note: 'iommu_map_sgtable' declared here
   static inline size_t iommu_map_sgtable(struct iommu_domain *domain,
                        ^
   drivers/gpu/drm/tegra/plane.c:202:36: error: use of undeclared identifier 'DMA_TO_DEVICE'
                           dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
                                                           ^
   drivers/gpu/drm/tegra/plane.c:205:20: error: use of undeclared identifier 'DMA_MAPPING_ERROR'
                   state->iova[i] = DMA_MAPPING_ERROR;
                                    ^
   drivers/gpu/drm/tegra/plane.c:221:4: error: implicit declaration of function 'dma_unmap_sgtable' [-Werror,-Wimplicit-function-declaration]
                           dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
                           ^
   drivers/gpu/drm/tegra/plane.c:221:36: error: use of undeclared identifier 'DMA_TO_DEVICE'
                           dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
                                                           ^
   drivers/gpu/drm/tegra/plane.c:224:20: error: use of undeclared identifier 'DMA_MAPPING_ERROR'
                   state->iova[i] = DMA_MAPPING_ERROR;
                                    ^
   10 errors generated.
--
   drivers/gpu/drm/tegra/dc.c:2225:31: warning: variable 'old_state' set but not used [-Wunused-but-set-variable]
           const struct drm_crtc_state *old_state;
                                        ^
>> drivers/gpu/drm/tegra/dc.c:2978:17: error: implicit declaration of function 'dma_get_mask' [-Werror,-Wimplicit-function-declaration]
           u64 dma_mask = dma_get_mask(pdev->dev.parent);
                          ^
   drivers/gpu/drm/tegra/dc.c:2978:17: note: did you mean 'xa_get_mark'?
   include/linux/xarray.h:354:6: note: 'xa_get_mark' declared here
   bool xa_get_mark(struct xarray *, unsigned long index, xa_mark_t);
        ^
>> drivers/gpu/drm/tegra/dc.c:2982:8: error: implicit declaration of function 'dma_coerce_mask_and_coherent' [-Werror,-Wimplicit-function-declaration]
           err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
                 ^
   1 warning and 2 errors generated.


vim +/dma_get_mask +1043 drivers/gpu/drm/tegra/hub.c

c4755fb9064f640 Thierry Reding 2017-11-13  1040  
c4755fb9064f640 Thierry Reding 2017-11-13  1041  static int tegra_display_hub_probe(struct platform_device *pdev)
c4755fb9064f640 Thierry Reding 2017-11-13  1042  {
86044e749be77a3 Thierry Reding 2021-03-26 @1043  	u64 dma_mask = dma_get_mask(pdev->dev.parent);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1044  	struct device_node *child = NULL;
c4755fb9064f640 Thierry Reding 2017-11-13  1045  	struct tegra_display_hub *hub;
0cffbde2e318cc1 Thierry Reding 2018-11-29  1046  	struct clk *clk;
c4755fb9064f640 Thierry Reding 2017-11-13  1047  	unsigned int i;
c4755fb9064f640 Thierry Reding 2017-11-13  1048  	int err;
c4755fb9064f640 Thierry Reding 2017-11-13  1049  
86044e749be77a3 Thierry Reding 2021-03-26 @1050  	err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
86044e749be77a3 Thierry Reding 2021-03-26  1051  	if (err < 0) {
86044e749be77a3 Thierry Reding 2021-03-26  1052  		dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err);
86044e749be77a3 Thierry Reding 2021-03-26  1053  		return err;
86044e749be77a3 Thierry Reding 2021-03-26  1054  	}
86044e749be77a3 Thierry Reding 2021-03-26  1055  
c4755fb9064f640 Thierry Reding 2017-11-13  1056  	hub = devm_kzalloc(&pdev->dev, sizeof(*hub), GFP_KERNEL);
c4755fb9064f640 Thierry Reding 2017-11-13  1057  	if (!hub)
c4755fb9064f640 Thierry Reding 2017-11-13  1058  		return -ENOMEM;
c4755fb9064f640 Thierry Reding 2017-11-13  1059  
c4755fb9064f640 Thierry Reding 2017-11-13  1060  	hub->soc = of_device_get_match_data(&pdev->dev);
c4755fb9064f640 Thierry Reding 2017-11-13  1061  
c4755fb9064f640 Thierry Reding 2017-11-13  1062  	hub->clk_disp = devm_clk_get(&pdev->dev, "disp");
c4755fb9064f640 Thierry Reding 2017-11-13  1063  	if (IS_ERR(hub->clk_disp)) {
c4755fb9064f640 Thierry Reding 2017-11-13  1064  		err = PTR_ERR(hub->clk_disp);
c4755fb9064f640 Thierry Reding 2017-11-13  1065  		return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1066  	}
c4755fb9064f640 Thierry Reding 2017-11-13  1067  
5725daaab55ca02 Thierry Reding 2018-09-21  1068  	if (hub->soc->supports_dsc) {
c4755fb9064f640 Thierry Reding 2017-11-13  1069  		hub->clk_dsc = devm_clk_get(&pdev->dev, "dsc");
c4755fb9064f640 Thierry Reding 2017-11-13  1070  		if (IS_ERR(hub->clk_dsc)) {
c4755fb9064f640 Thierry Reding 2017-11-13  1071  			err = PTR_ERR(hub->clk_dsc);
c4755fb9064f640 Thierry Reding 2017-11-13  1072  			return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1073  		}
5725daaab55ca02 Thierry Reding 2018-09-21  1074  	}
c4755fb9064f640 Thierry Reding 2017-11-13  1075  
c4755fb9064f640 Thierry Reding 2017-11-13  1076  	hub->clk_hub = devm_clk_get(&pdev->dev, "hub");
c4755fb9064f640 Thierry Reding 2017-11-13  1077  	if (IS_ERR(hub->clk_hub)) {
c4755fb9064f640 Thierry Reding 2017-11-13  1078  		err = PTR_ERR(hub->clk_hub);
c4755fb9064f640 Thierry Reding 2017-11-13  1079  		return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1080  	}
c4755fb9064f640 Thierry Reding 2017-11-13  1081  
c4755fb9064f640 Thierry Reding 2017-11-13  1082  	hub->rst = devm_reset_control_get(&pdev->dev, "misc");
c4755fb9064f640 Thierry Reding 2017-11-13  1083  	if (IS_ERR(hub->rst)) {
c4755fb9064f640 Thierry Reding 2017-11-13  1084  		err = PTR_ERR(hub->rst);
c4755fb9064f640 Thierry Reding 2017-11-13  1085  		return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1086  	}
c4755fb9064f640 Thierry Reding 2017-11-13  1087  
c4755fb9064f640 Thierry Reding 2017-11-13  1088  	hub->wgrps = devm_kcalloc(&pdev->dev, hub->soc->num_wgrps,
c4755fb9064f640 Thierry Reding 2017-11-13  1089  				  sizeof(*hub->wgrps), GFP_KERNEL);
c4755fb9064f640 Thierry Reding 2017-11-13  1090  	if (!hub->wgrps)
c4755fb9064f640 Thierry Reding 2017-11-13  1091  		return -ENOMEM;
c4755fb9064f640 Thierry Reding 2017-11-13  1092  
c4755fb9064f640 Thierry Reding 2017-11-13  1093  	for (i = 0; i < hub->soc->num_wgrps; i++) {
c4755fb9064f640 Thierry Reding 2017-11-13  1094  		struct tegra_windowgroup *wgrp = &hub->wgrps[i];
c4755fb9064f640 Thierry Reding 2017-11-13  1095  		char id[8];
c4755fb9064f640 Thierry Reding 2017-11-13  1096  
c4755fb9064f640 Thierry Reding 2017-11-13  1097  		snprintf(id, sizeof(id), "wgrp%u", i);
c4755fb9064f640 Thierry Reding 2017-11-13  1098  		mutex_init(&wgrp->lock);
c4755fb9064f640 Thierry Reding 2017-11-13  1099  		wgrp->usecount = 0;
c4755fb9064f640 Thierry Reding 2017-11-13  1100  		wgrp->index = i;
c4755fb9064f640 Thierry Reding 2017-11-13  1101  
c4755fb9064f640 Thierry Reding 2017-11-13  1102  		wgrp->rst = devm_reset_control_get(&pdev->dev, id);
c4755fb9064f640 Thierry Reding 2017-11-13  1103  		if (IS_ERR(wgrp->rst))
c4755fb9064f640 Thierry Reding 2017-11-13  1104  			return PTR_ERR(wgrp->rst);
c4755fb9064f640 Thierry Reding 2017-11-13  1105  
c4755fb9064f640 Thierry Reding 2017-11-13  1106  		err = reset_control_assert(wgrp->rst);
c4755fb9064f640 Thierry Reding 2017-11-13  1107  		if (err < 0)
c4755fb9064f640 Thierry Reding 2017-11-13  1108  			return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1109  	}
c4755fb9064f640 Thierry Reding 2017-11-13  1110  
0cffbde2e318cc1 Thierry Reding 2018-11-29  1111  	hub->num_heads = of_get_child_count(pdev->dev.of_node);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1112  
0cffbde2e318cc1 Thierry Reding 2018-11-29  1113  	hub->clk_heads = devm_kcalloc(&pdev->dev, hub->num_heads, sizeof(clk),
0cffbde2e318cc1 Thierry Reding 2018-11-29  1114  				      GFP_KERNEL);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1115  	if (!hub->clk_heads)
0cffbde2e318cc1 Thierry Reding 2018-11-29  1116  		return -ENOMEM;
0cffbde2e318cc1 Thierry Reding 2018-11-29  1117  
0cffbde2e318cc1 Thierry Reding 2018-11-29  1118  	for (i = 0; i < hub->num_heads; i++) {
0cffbde2e318cc1 Thierry Reding 2018-11-29  1119  		child = of_get_next_child(pdev->dev.of_node, child);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1120  		if (!child) {
0cffbde2e318cc1 Thierry Reding 2018-11-29  1121  			dev_err(&pdev->dev, "failed to find node for head %u\n",
0cffbde2e318cc1 Thierry Reding 2018-11-29  1122  				i);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1123  			return -ENODEV;
0cffbde2e318cc1 Thierry Reding 2018-11-29  1124  		}
0cffbde2e318cc1 Thierry Reding 2018-11-29  1125  
0cffbde2e318cc1 Thierry Reding 2018-11-29  1126  		clk = devm_get_clk_from_child(&pdev->dev, child, "dc");
0cffbde2e318cc1 Thierry Reding 2018-11-29  1127  		if (IS_ERR(clk)) {
0cffbde2e318cc1 Thierry Reding 2018-11-29  1128  			dev_err(&pdev->dev, "failed to get clock for head %u\n",
0cffbde2e318cc1 Thierry Reding 2018-11-29  1129  				i);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1130  			of_node_put(child);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1131  			return PTR_ERR(clk);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1132  		}
0cffbde2e318cc1 Thierry Reding 2018-11-29  1133  
0cffbde2e318cc1 Thierry Reding 2018-11-29  1134  		hub->clk_heads[i] = clk;
0cffbde2e318cc1 Thierry Reding 2018-11-29  1135  	}
0cffbde2e318cc1 Thierry Reding 2018-11-29  1136  
0cffbde2e318cc1 Thierry Reding 2018-11-29  1137  	of_node_put(child);
0cffbde2e318cc1 Thierry Reding 2018-11-29  1138  
c4755fb9064f640 Thierry Reding 2017-11-13  1139  	/* XXX: enable clock across reset? */
c4755fb9064f640 Thierry Reding 2017-11-13  1140  	err = reset_control_assert(hub->rst);
c4755fb9064f640 Thierry Reding 2017-11-13  1141  	if (err < 0)
c4755fb9064f640 Thierry Reding 2017-11-13  1142  		return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1143  
c4755fb9064f640 Thierry Reding 2017-11-13  1144  	platform_set_drvdata(pdev, hub);
c4755fb9064f640 Thierry Reding 2017-11-13  1145  	pm_runtime_enable(&pdev->dev);
c4755fb9064f640 Thierry Reding 2017-11-13  1146  
c4755fb9064f640 Thierry Reding 2017-11-13  1147  	INIT_LIST_HEAD(&hub->client.list);
c4755fb9064f640 Thierry Reding 2017-11-13  1148  	hub->client.ops = &tegra_display_hub_ops;
c4755fb9064f640 Thierry Reding 2017-11-13  1149  	hub->client.dev = &pdev->dev;
c4755fb9064f640 Thierry Reding 2017-11-13  1150  
c4755fb9064f640 Thierry Reding 2017-11-13  1151  	err = host1x_client_register(&hub->client);
c4755fb9064f640 Thierry Reding 2017-11-13  1152  	if (err < 0)
c4755fb9064f640 Thierry Reding 2017-11-13  1153  		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
c4755fb9064f640 Thierry Reding 2017-11-13  1154  			err);
c4755fb9064f640 Thierry Reding 2017-11-13  1155  
a101e3dad8a90a8 Thierry Reding 2020-06-12  1156  	err = devm_of_platform_populate(&pdev->dev);
a101e3dad8a90a8 Thierry Reding 2020-06-12  1157  	if (err < 0)
a101e3dad8a90a8 Thierry Reding 2020-06-12  1158  		goto unregister;
a101e3dad8a90a8 Thierry Reding 2020-06-12  1159  
a101e3dad8a90a8 Thierry Reding 2020-06-12  1160  	return err;
a101e3dad8a90a8 Thierry Reding 2020-06-12  1161  
a101e3dad8a90a8 Thierry Reding 2020-06-12  1162  unregister:
a101e3dad8a90a8 Thierry Reding 2020-06-12  1163  	host1x_client_unregister(&hub->client);
a101e3dad8a90a8 Thierry Reding 2020-06-12  1164  	pm_runtime_disable(&pdev->dev);
c4755fb9064f640 Thierry Reding 2017-11-13  1165  	return err;
c4755fb9064f640 Thierry Reding 2017-11-13  1166  }
c4755fb9064f640 Thierry Reding 2017-11-13  1167  

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

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

* Re: [PATCH v2 04/11] iommu/iova: Squash entry_dtor abstraction
  2021-12-10 17:54   ` Robin Murphy
@ 2021-12-14 16:39     ` John Garry via iommu
  -1 siblings, 0 replies; 66+ messages in thread
From: John Garry @ 2021-12-14 16:39 UTC (permalink / raw)
  To: Robin Murphy, joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel, linux-mm

On 10/12/2021 17:54, Robin Murphy wrote:
> All flush queues are driven by iommu-dma now, so there is no need to
> abstract entry_dtor or its data any more. Squash the now-canonical
> implementation directly into the IOVA code to get it out of the way.
> 
> Signed-off-by: Robin Murphy<robin.murphy@arm.com>

Seems pretty straightforward, so FWIW:

Reviewed-by: John Garry <john.garry@huawei.com>

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

* Re: [PATCH v2 04/11] iommu/iova: Squash entry_dtor abstraction
@ 2021-12-14 16:39     ` John Garry via iommu
  0 siblings, 0 replies; 66+ messages in thread
From: John Garry via iommu @ 2021-12-14 16:39 UTC (permalink / raw)
  To: Robin Murphy, joro, will; +Cc: linux-kernel, willy, linux-mm, iommu

On 10/12/2021 17:54, Robin Murphy wrote:
> All flush queues are driven by iommu-dma now, so there is no need to
> abstract entry_dtor or its data any more. Squash the now-canonical
> implementation directly into the IOVA code to get it out of the way.
> 
> Signed-off-by: Robin Murphy<robin.murphy@arm.com>

Seems pretty straightforward, so FWIW:

Reviewed-by: John Garry <john.garry@huawei.com>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

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

* Re: [PATCH v2 05/11] iommu/iova: Squash flush_cb abstraction
  2021-12-10 17:54   ` Robin Murphy
@ 2021-12-14 16:39     ` John Garry via iommu
  -1 siblings, 0 replies; 66+ messages in thread
From: John Garry @ 2021-12-14 16:39 UTC (permalink / raw)
  To: Robin Murphy, joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel, linux-mm

On 10/12/2021 17:54, Robin Murphy wrote:
> Once again, with iommu-dma now being the only flush queue user, we no
> longer need the extra level of indirection through flush_cb. Squash that
> and let the flush queue code call the domain method directly.
> 
> Signed-off-by: Robin Murphy<robin.murphy@arm.com>

Again seems pretty straightforward, so FWIW:

Reviewed-by: John Garry <john.garry@huawei.com>


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

* Re: [PATCH v2 05/11] iommu/iova: Squash flush_cb abstraction
@ 2021-12-14 16:39     ` John Garry via iommu
  0 siblings, 0 replies; 66+ messages in thread
From: John Garry via iommu @ 2021-12-14 16:39 UTC (permalink / raw)
  To: Robin Murphy, joro, will; +Cc: linux-kernel, willy, linux-mm, iommu

On 10/12/2021 17:54, Robin Murphy wrote:
> Once again, with iommu-dma now being the only flush queue user, we no
> longer need the extra level of indirection through flush_cb. Squash that
> and let the flush queue code call the domain method directly.
> 
> Signed-off-by: Robin Murphy<robin.murphy@arm.com>

Again seems pretty straightforward, so FWIW:

Reviewed-by: John Garry <john.garry@huawei.com>

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

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

* Re: [PATCH v2 09/11] iommu/iova: Consolidate flush queue code
  2021-12-10 17:54   ` Robin Murphy
@ 2021-12-14 16:39     ` John Garry via iommu
  -1 siblings, 0 replies; 66+ messages in thread
From: John Garry @ 2021-12-14 16:39 UTC (permalink / raw)
  To: Robin Murphy, joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel, linux-mm

On 10/12/2021 17:54, Robin Murphy wrote:
> Squash and simplify some of the freeing code, and move the init
> and free routines down into the rest of the flush queue code to

> obviate the forward declarations.
> 

It would be good to get rid of all of these eventually...

> Signed-off-by: Robin Murphy<robin.murphy@arm.com>
> ---

FWIW:

Reviewed-by: John Garry <john.garry@huawei.com>

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

* Re: [PATCH v2 09/11] iommu/iova: Consolidate flush queue code
@ 2021-12-14 16:39     ` John Garry via iommu
  0 siblings, 0 replies; 66+ messages in thread
From: John Garry via iommu @ 2021-12-14 16:39 UTC (permalink / raw)
  To: Robin Murphy, joro, will; +Cc: linux-kernel, willy, linux-mm, iommu

On 10/12/2021 17:54, Robin Murphy wrote:
> Squash and simplify some of the freeing code, and move the init
> and free routines down into the rest of the flush queue code to

> obviate the forward declarations.
> 

It would be good to get rid of all of these eventually...

> Signed-off-by: Robin Murphy<robin.murphy@arm.com>
> ---

FWIW:

Reviewed-by: John Garry <john.garry@huawei.com>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

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

* Re: [PATCH v2 10/11] iommu/iova: Move flush queue code to iommu-dma
  2021-12-10 17:54   ` Robin Murphy
@ 2021-12-14 16:40     ` John Garry via iommu
  -1 siblings, 0 replies; 66+ messages in thread
From: John Garry @ 2021-12-14 16:40 UTC (permalink / raw)
  To: Robin Murphy, joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel, linux-mm

On 10/12/2021 17:54, Robin Murphy wrote:
> Flush queues are specific to DMA ops, which are now handled exclusively
> by iommu-dma. As such, now that the historical artefacts from being
> shared directly with drivers have been cleaned up, move the flush queue
> code into iommu-dma itself to get it out of the way of other IOVA users.
> 
> This is pure code movement with no functional change; refactoring to
> clean up the headers and definitions will follow.
> 
> Signed-off-by: Robin Murphy<robin.murphy@arm.com>

Again FWIW:

Reviewed-by: John Garry <john.garry@huawei.com>

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

* Re: [PATCH v2 10/11] iommu/iova: Move flush queue code to iommu-dma
@ 2021-12-14 16:40     ` John Garry via iommu
  0 siblings, 0 replies; 66+ messages in thread
From: John Garry via iommu @ 2021-12-14 16:40 UTC (permalink / raw)
  To: Robin Murphy, joro, will; +Cc: linux-kernel, willy, linux-mm, iommu

On 10/12/2021 17:54, Robin Murphy wrote:
> Flush queues are specific to DMA ops, which are now handled exclusively
> by iommu-dma. As such, now that the historical artefacts from being
> shared directly with drivers have been cleaned up, move the flush queue
> code into iommu-dma itself to get it out of the way of other IOVA users.
> 
> This is pure code movement with no functional change; refactoring to
> clean up the headers and definitions will follow.
> 
> Signed-off-by: Robin Murphy<robin.murphy@arm.com>

Again FWIW:

Reviewed-by: John Garry <john.garry@huawei.com>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

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

* Re: [PATCH v2 11/11] iommu: Move flush queue data into iommu_dma_cookie
  2021-12-10 17:54   ` Robin Murphy
@ 2021-12-14 17:16     ` John Garry via iommu
  -1 siblings, 0 replies; 66+ messages in thread
From: John Garry @ 2021-12-14 17:16 UTC (permalink / raw)
  To: Robin Murphy, joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel, linux-mm

On 10/12/2021 17:54, Robin Murphy wrote:
> Complete the move into iommu-dma by refactoring the flush queues
> themselves to belong to the DMA cookie rather than the IOVA domain.
> 
> The refactoring may as well extend to some minor cosmetic aspects
> too, to help us stay one step ahead of the style police.
> 
> Signed-off-by: Robin Murphy<robin.murphy@arm.com>
> ---

Again, FWIW:

Reviewed-by: John Garry <john.garry@huawei.com>

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

* Re: [PATCH v2 11/11] iommu: Move flush queue data into iommu_dma_cookie
@ 2021-12-14 17:16     ` John Garry via iommu
  0 siblings, 0 replies; 66+ messages in thread
From: John Garry via iommu @ 2021-12-14 17:16 UTC (permalink / raw)
  To: Robin Murphy, joro, will; +Cc: linux-kernel, willy, linux-mm, iommu

On 10/12/2021 17:54, Robin Murphy wrote:
> Complete the move into iommu-dma by refactoring the flush queues
> themselves to belong to the DMA cookie rather than the IOVA domain.
> 
> The refactoring may as well extend to some minor cosmetic aspects
> too, to help us stay one step ahead of the style police.
> 
> Signed-off-by: Robin Murphy<robin.murphy@arm.com>
> ---

Again, FWIW:

Reviewed-by: John Garry <john.garry@huawei.com>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

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

* Re: [PATCH v2 10/11] iommu/iova: Move flush queue code to iommu-dma
  2021-12-10 17:54   ` Robin Murphy
@ 2021-12-14 17:18     ` John Garry via iommu
  -1 siblings, 0 replies; 66+ messages in thread
From: John Garry @ 2021-12-14 17:18 UTC (permalink / raw)
  To: Robin Murphy, joro, will
  Cc: iommu, suravee.suthikulpanit, baolu.lu, willy, linux-kernel, linux-mm

On 10/12/2021 17:54, Robin Murphy wrote:
> +	iovad->fq_domain = fq_domain;
> +	iovad->fq = queue;
> +
> +	timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
> +	atomic_set(&iovad->fq_timer_on, 0);
> +
> +	return 0;
> +}
> +
> +

nit: a single blank line is standard, I think

Cheers

>   static inline size_t cookie_msi_granule(struct iommu_dma_cookie *cookie)
>   {



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

* Re: [PATCH v2 10/11] iommu/iova: Move flush queue code to iommu-dma
@ 2021-12-14 17:18     ` John Garry via iommu
  0 siblings, 0 replies; 66+ messages in thread
From: John Garry via iommu @ 2021-12-14 17:18 UTC (permalink / raw)
  To: Robin Murphy, joro, will; +Cc: linux-kernel, willy, linux-mm, iommu

On 10/12/2021 17:54, Robin Murphy wrote:
> +	iovad->fq_domain = fq_domain;
> +	iovad->fq = queue;
> +
> +	timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
> +	atomic_set(&iovad->fq_timer_on, 0);
> +
> +	return 0;
> +}
> +
> +

nit: a single blank line is standard, I think

Cheers

>   static inline size_t cookie_msi_granule(struct iommu_dma_cookie *cookie)
>   {


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

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

* Re: [PATCH v2 10/11] iommu/iova: Move flush queue code to iommu-dma
  2021-12-14 17:18     ` John Garry via iommu
@ 2021-12-14 17:50       ` Robin Murphy
  -1 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-14 17:50 UTC (permalink / raw)
  To: John Garry, joro, will; +Cc: linux-kernel, willy, linux-mm, iommu

On 2021-12-14 17:18, John Garry via iommu wrote:
> On 10/12/2021 17:54, Robin Murphy wrote:
>> +    iovad->fq_domain = fq_domain;
>> +    iovad->fq = queue;
>> +
>> +    timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
>> +    atomic_set(&iovad->fq_timer_on, 0);
>> +
>> +    return 0;
>> +}
>> +
>> +
> 
> nit: a single blank line is standard, I think

Hmm, you're right - I've grown fond of leaving an extra little bit of 
breathing space between logically-independent sections of code, and for 
some reason I thought this file was already in that style, but indeed it 
isn't.

Joerg - let me know if you feel strongly enough that you'd like me to 
change that. I'm going to have one last go at fixing tegra-drm, so I'm 
happy to send a v3 of the whole series later this week if there are any 
other minor tweaks too.

Thanks for all the reviews!

Robin.

> 
> Cheers
> 
>>   static inline size_t cookie_msi_granule(struct iommu_dma_cookie 
>> *cookie)
>>   {
> 
> 
> _______________________________________________
> iommu mailing list
> iommu@lists.linux-foundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/iommu

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

* Re: [PATCH v2 10/11] iommu/iova: Move flush queue code to iommu-dma
@ 2021-12-14 17:50       ` Robin Murphy
  0 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-14 17:50 UTC (permalink / raw)
  To: John Garry, joro, will; +Cc: linux-mm, iommu, linux-kernel, willy

On 2021-12-14 17:18, John Garry via iommu wrote:
> On 10/12/2021 17:54, Robin Murphy wrote:
>> +    iovad->fq_domain = fq_domain;
>> +    iovad->fq = queue;
>> +
>> +    timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
>> +    atomic_set(&iovad->fq_timer_on, 0);
>> +
>> +    return 0;
>> +}
>> +
>> +
> 
> nit: a single blank line is standard, I think

Hmm, you're right - I've grown fond of leaving an extra little bit of 
breathing space between logically-independent sections of code, and for 
some reason I thought this file was already in that style, but indeed it 
isn't.

Joerg - let me know if you feel strongly enough that you'd like me to 
change that. I'm going to have one last go at fixing tegra-drm, so I'm 
happy to send a v3 of the whole series later this week if there are any 
other minor tweaks too.

Thanks for all the reviews!

Robin.

> 
> Cheers
> 
>>   static inline size_t cookie_msi_granule(struct iommu_dma_cookie 
>> *cookie)
>>   {
> 
> 
> _______________________________________________
> iommu mailing list
> iommu@lists.linux-foundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/iommu
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

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

* Re: [PATCH v2 03/11] drm/tegra: vic: Fix DMA API misuse
  2021-12-10 17:54   ` Robin Murphy
@ 2021-12-16  8:01     ` Christoph Hellwig
  -1 siblings, 0 replies; 66+ messages in thread
From: Christoph Hellwig @ 2021-12-16  8:01 UTC (permalink / raw)
  To: Robin Murphy
  Cc: joro, will, linux-kernel, willy, Mikko Perttunen, linux-mm,
	iommu, Thierry Reding, dri-devel

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

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

* Re: [PATCH v2 03/11] drm/tegra: vic: Fix DMA API misuse
@ 2021-12-16  8:01     ` Christoph Hellwig
  0 siblings, 0 replies; 66+ messages in thread
From: Christoph Hellwig @ 2021-12-16  8:01 UTC (permalink / raw)
  To: Robin Murphy
  Cc: linux-kernel, willy, Mikko Perttunen, linux-mm, iommu,
	Thierry Reding, dri-devel, will

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

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

* Re: [PATCH v2 04/11] iommu/iova: Squash entry_dtor abstraction
  2021-12-10 17:54   ` Robin Murphy
@ 2021-12-16  8:02     ` Christoph Hellwig
  -1 siblings, 0 replies; 66+ messages in thread
From: Christoph Hellwig @ 2021-12-16  8:02 UTC (permalink / raw)
  To: Robin Murphy; +Cc: joro, will, linux-kernel, willy, linux-mm, iommu

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

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

* Re: [PATCH v2 04/11] iommu/iova: Squash entry_dtor abstraction
@ 2021-12-16  8:02     ` Christoph Hellwig
  0 siblings, 0 replies; 66+ messages in thread
From: Christoph Hellwig @ 2021-12-16  8:02 UTC (permalink / raw)
  To: Robin Murphy; +Cc: linux-kernel, willy, linux-mm, iommu, will

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

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

* Re: [PATCH v2 05/11] iommu/iova: Squash flush_cb abstraction
  2021-12-10 17:54   ` Robin Murphy
@ 2021-12-16  8:02     ` Christoph Hellwig
  -1 siblings, 0 replies; 66+ messages in thread
From: Christoph Hellwig @ 2021-12-16  8:02 UTC (permalink / raw)
  To: Robin Murphy; +Cc: joro, will, linux-kernel, willy, linux-mm, iommu

> @@ -147,7 +142,7 @@ 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);
> -int init_iova_flush_queue(struct iova_domain *iovad, iova_flush_cb flush_cb);
> +int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain);

Overly long line here.

Otherwise looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>

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

* Re: [PATCH v2 05/11] iommu/iova: Squash flush_cb abstraction
@ 2021-12-16  8:02     ` Christoph Hellwig
  0 siblings, 0 replies; 66+ messages in thread
From: Christoph Hellwig @ 2021-12-16  8:02 UTC (permalink / raw)
  To: Robin Murphy; +Cc: linux-kernel, willy, linux-mm, iommu, will

> @@ -147,7 +142,7 @@ 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);
> -int init_iova_flush_queue(struct iova_domain *iovad, iova_flush_cb flush_cb);
> +int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain);

Overly long line here.

Otherwise looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

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

* Re: [PATCH v2 02/11] gpu: host1x: Add missing DMA API include
  2021-12-10 17:54   ` Robin Murphy
  (?)
@ 2021-12-16  8:53     ` Thierry Reding
  -1 siblings, 0 replies; 66+ messages in thread
From: Thierry Reding @ 2021-12-16  8:53 UTC (permalink / raw)
  To: Robin Murphy
  Cc: joro, will, iommu, suravee.suthikulpanit, baolu.lu, willy,
	linux-kernel, john.garry, linux-mm, Mikko Perttunen, dri-devel

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

On Fri, Dec 10, 2021 at 05:54:43PM +0000, Robin Murphy wrote:
> Host1x seems to be relying on picking up dma-mapping.h transitively from
> iova.h, which has no reason to include it in the first place. Fix the
> former issue before we totally break things by fixing the latter one.
> 
> CC: Thierry Reding <thierry.reding@gmail.com>
> CC: Mikko Perttunen <mperttunen@nvidia.com>
> CC: dri-devel@lists.freedesktop.org
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> ---
> 
> v2: No change
> 
>  drivers/gpu/host1x/bus.c | 1 +
>  1 file changed, 1 insertion(+)

Applied, thanks.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 02/11] gpu: host1x: Add missing DMA API include
@ 2021-12-16  8:53     ` Thierry Reding
  0 siblings, 0 replies; 66+ messages in thread
From: Thierry Reding @ 2021-12-16  8:53 UTC (permalink / raw)
  To: Robin Murphy
  Cc: linux-kernel, willy, Mikko Perttunen, linux-mm, iommu, dri-devel, will


[-- Attachment #1.1: Type: text/plain, Size: 611 bytes --]

On Fri, Dec 10, 2021 at 05:54:43PM +0000, Robin Murphy wrote:
> Host1x seems to be relying on picking up dma-mapping.h transitively from
> iova.h, which has no reason to include it in the first place. Fix the
> former issue before we totally break things by fixing the latter one.
> 
> CC: Thierry Reding <thierry.reding@gmail.com>
> CC: Mikko Perttunen <mperttunen@nvidia.com>
> CC: dri-devel@lists.freedesktop.org
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> ---
> 
> v2: No change
> 
>  drivers/gpu/host1x/bus.c | 1 +
>  1 file changed, 1 insertion(+)

Applied, thanks.

Thierry

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: 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] 66+ messages in thread

* Re: [PATCH v2 02/11] gpu: host1x: Add missing DMA API include
@ 2021-12-16  8:53     ` Thierry Reding
  0 siblings, 0 replies; 66+ messages in thread
From: Thierry Reding @ 2021-12-16  8:53 UTC (permalink / raw)
  To: Robin Murphy
  Cc: joro, john.garry, linux-kernel, willy, Mikko Perttunen, linux-mm,
	iommu, dri-devel, suravee.suthikulpanit, will, baolu.lu

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

On Fri, Dec 10, 2021 at 05:54:43PM +0000, Robin Murphy wrote:
> Host1x seems to be relying on picking up dma-mapping.h transitively from
> iova.h, which has no reason to include it in the first place. Fix the
> former issue before we totally break things by fixing the latter one.
> 
> CC: Thierry Reding <thierry.reding@gmail.com>
> CC: Mikko Perttunen <mperttunen@nvidia.com>
> CC: dri-devel@lists.freedesktop.org
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> ---
> 
> v2: No change
> 
>  drivers/gpu/host1x/bus.c | 1 +
>  1 file changed, 1 insertion(+)

Applied, thanks.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 03/11] drm/tegra: vic: Fix DMA API misuse
  2021-12-10 17:54   ` Robin Murphy
  (?)
@ 2021-12-16  8:55     ` Thierry Reding
  -1 siblings, 0 replies; 66+ messages in thread
From: Thierry Reding @ 2021-12-16  8:55 UTC (permalink / raw)
  To: Robin Murphy
  Cc: joro, will, iommu, suravee.suthikulpanit, baolu.lu, willy,
	linux-kernel, john.garry, linux-mm, Mikko Perttunen, dri-devel

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

On Fri, Dec 10, 2021 at 05:54:44PM +0000, Robin Murphy wrote:
> Upon failure, dma_alloc_coherent() returns NULL. If that does happen,
> passing some uninitialised stack contents to dma_mapping_error() - which
> belongs to a different API in the first place - has precious little
> chance of detecting it.
> 
> Also include the correct header, because the fragile transitive
> inclusion currently providing it is going to break soon.
> 
> Fixes: 20e7dce255e9 ("drm/tegra: Remove memory allocation from Falcon library")
> CC: Thierry Reding <thierry.reding@gmail.com>
> CC: Mikko Perttunen <mperttunen@nvidia.com>
> CC: dri-devel@lists.freedesktop.org
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> 
> ---
> 
> It also doesn't appear to handle failure of the tegra_drm_alloc() path
> either, but that's a loose thread I have no desire to pull on... ;)
> 
> v2: Resend as part of the series, originally posted separately here:
> 
> https://lore.kernel.org/dri-devel/2703882439344010e33bf21ecd63cf9e5e6dc00d.1637781007.git.robin.murphy@arm.com/
> 
>  drivers/gpu/drm/tegra/vic.c | 7 +++----
>  1 file changed, 3 insertions(+), 4 deletions(-)

Applied, thanks. I've also fixed up the missing failure handling for
tegra_drm_alloc(), which was actually quite trivial to do.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 03/11] drm/tegra: vic: Fix DMA API misuse
@ 2021-12-16  8:55     ` Thierry Reding
  0 siblings, 0 replies; 66+ messages in thread
From: Thierry Reding @ 2021-12-16  8:55 UTC (permalink / raw)
  To: Robin Murphy
  Cc: linux-kernel, willy, Mikko Perttunen, linux-mm, iommu, dri-devel, will


[-- Attachment #1.1: Type: text/plain, Size: 1315 bytes --]

On Fri, Dec 10, 2021 at 05:54:44PM +0000, Robin Murphy wrote:
> Upon failure, dma_alloc_coherent() returns NULL. If that does happen,
> passing some uninitialised stack contents to dma_mapping_error() - which
> belongs to a different API in the first place - has precious little
> chance of detecting it.
> 
> Also include the correct header, because the fragile transitive
> inclusion currently providing it is going to break soon.
> 
> Fixes: 20e7dce255e9 ("drm/tegra: Remove memory allocation from Falcon library")
> CC: Thierry Reding <thierry.reding@gmail.com>
> CC: Mikko Perttunen <mperttunen@nvidia.com>
> CC: dri-devel@lists.freedesktop.org
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> 
> ---
> 
> It also doesn't appear to handle failure of the tegra_drm_alloc() path
> either, but that's a loose thread I have no desire to pull on... ;)
> 
> v2: Resend as part of the series, originally posted separately here:
> 
> https://lore.kernel.org/dri-devel/2703882439344010e33bf21ecd63cf9e5e6dc00d.1637781007.git.robin.murphy@arm.com/
> 
>  drivers/gpu/drm/tegra/vic.c | 7 +++----
>  1 file changed, 3 insertions(+), 4 deletions(-)

Applied, thanks. I've also fixed up the missing failure handling for
tegra_drm_alloc(), which was actually quite trivial to do.

Thierry

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: 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] 66+ messages in thread

* Re: [PATCH v2 03/11] drm/tegra: vic: Fix DMA API misuse
@ 2021-12-16  8:55     ` Thierry Reding
  0 siblings, 0 replies; 66+ messages in thread
From: Thierry Reding @ 2021-12-16  8:55 UTC (permalink / raw)
  To: Robin Murphy
  Cc: joro, john.garry, linux-kernel, willy, Mikko Perttunen, linux-mm,
	iommu, dri-devel, suravee.suthikulpanit, will, baolu.lu

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

On Fri, Dec 10, 2021 at 05:54:44PM +0000, Robin Murphy wrote:
> Upon failure, dma_alloc_coherent() returns NULL. If that does happen,
> passing some uninitialised stack contents to dma_mapping_error() - which
> belongs to a different API in the first place - has precious little
> chance of detecting it.
> 
> Also include the correct header, because the fragile transitive
> inclusion currently providing it is going to break soon.
> 
> Fixes: 20e7dce255e9 ("drm/tegra: Remove memory allocation from Falcon library")
> CC: Thierry Reding <thierry.reding@gmail.com>
> CC: Mikko Perttunen <mperttunen@nvidia.com>
> CC: dri-devel@lists.freedesktop.org
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> 
> ---
> 
> It also doesn't appear to handle failure of the tegra_drm_alloc() path
> either, but that's a loose thread I have no desire to pull on... ;)
> 
> v2: Resend as part of the series, originally posted separately here:
> 
> https://lore.kernel.org/dri-devel/2703882439344010e33bf21ecd63cf9e5e6dc00d.1637781007.git.robin.murphy@arm.com/
> 
>  drivers/gpu/drm/tegra/vic.c | 7 +++----
>  1 file changed, 3 insertions(+), 4 deletions(-)

Applied, thanks. I've also fixed up the missing failure handling for
tegra_drm_alloc(), which was actually quite trivial to do.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 05/11] iommu/iova: Squash flush_cb abstraction
  2021-12-16  8:02     ` Christoph Hellwig
@ 2021-12-17 12:08       ` Robin Murphy
  -1 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-17 12:08 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: joro, will, linux-kernel, willy, linux-mm, iommu

On 2021-12-16 08:02, Christoph Hellwig wrote:
>> @@ -147,7 +142,7 @@ 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);
>> -int init_iova_flush_queue(struct iova_domain *iovad, iova_flush_cb flush_cb);
>> +int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain);
> 
> Overly long line here.

Fear not, it disappears again in the final patch. In cases like this I 
much prefer to minimise the amount of churn within the series, to keep 
the patches focused on the meaningful changes.

> Otherwise looks good:
> 
> Reviewed-by: Christoph Hellwig <hch@lst.de>

Thanks for the reviews!

Robin.

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

* Re: [PATCH v2 05/11] iommu/iova: Squash flush_cb abstraction
@ 2021-12-17 12:08       ` Robin Murphy
  0 siblings, 0 replies; 66+ messages in thread
From: Robin Murphy @ 2021-12-17 12:08 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-kernel, willy, linux-mm, iommu, will

On 2021-12-16 08:02, Christoph Hellwig wrote:
>> @@ -147,7 +142,7 @@ 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);
>> -int init_iova_flush_queue(struct iova_domain *iovad, iova_flush_cb flush_cb);
>> +int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain);
> 
> Overly long line here.

Fear not, it disappears again in the final patch. In cases like this I 
much prefer to minimise the amount of churn within the series, to keep 
the patches focused on the meaningful changes.

> Otherwise looks good:
> 
> Reviewed-by: Christoph Hellwig <hch@lst.de>

Thanks for the reviews!

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

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

end of thread, other threads:[~2021-12-17 12:08 UTC | newest]

Thread overview: 66+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-10 17:54 [PATCH v2 00/11] iommu: refactor flush queues into iommu-dma Robin Murphy
2021-12-10 17:54 ` Robin Murphy
2021-12-10 17:54 ` [PATCH v2 01/11] iommu/iova: Fix race between FQ timeout and teardown Robin Murphy
2021-12-10 17:54   ` Robin Murphy
2021-12-10 18:04   ` John Garry
2021-12-10 18:04     ` John Garry via iommu
2021-12-10 18:13     ` Robin Murphy
2021-12-10 18:13       ` Robin Murphy
2021-12-10 19:19       ` John Garry
2021-12-10 19:19         ` John Garry via iommu
2021-12-10 17:54 ` [PATCH v2 02/11] gpu: host1x: Add missing DMA API include Robin Murphy
2021-12-10 17:54   ` Robin Murphy
2021-12-10 17:54   ` Robin Murphy
2021-12-16  8:53   ` Thierry Reding
2021-12-16  8:53     ` Thierry Reding
2021-12-16  8:53     ` Thierry Reding
2021-12-10 17:54 ` [PATCH v2 03/11] drm/tegra: vic: Fix DMA API misuse Robin Murphy
2021-12-10 17:54   ` Robin Murphy
2021-12-10 17:54   ` Robin Murphy
2021-12-16  8:01   ` Christoph Hellwig
2021-12-16  8:01     ` Christoph Hellwig
2021-12-16  8:55   ` Thierry Reding
2021-12-16  8:55     ` Thierry Reding
2021-12-16  8:55     ` Thierry Reding
2021-12-10 17:54 ` [PATCH v2 04/11] iommu/iova: Squash entry_dtor abstraction Robin Murphy
2021-12-10 17:54   ` Robin Murphy
2021-12-14 16:39   ` John Garry
2021-12-14 16:39     ` John Garry via iommu
2021-12-16  8:02   ` Christoph Hellwig
2021-12-16  8:02     ` Christoph Hellwig
2021-12-10 17:54 ` [PATCH v2 05/11] iommu/iova: Squash flush_cb abstraction Robin Murphy
2021-12-10 17:54   ` Robin Murphy
2021-12-14 16:39   ` John Garry
2021-12-14 16:39     ` John Garry via iommu
2021-12-16  8:02   ` Christoph Hellwig
2021-12-16  8:02     ` Christoph Hellwig
2021-12-17 12:08     ` Robin Murphy
2021-12-17 12:08       ` Robin Murphy
2021-12-10 17:54 ` [PATCH v2 06/11] iommu/amd: Simplify pagetable freeing Robin Murphy
2021-12-10 17:54   ` Robin Murphy
2021-12-10 17:54 ` [PATCH v2 07/11] iommu/amd: Use put_pages_list Robin Murphy
2021-12-10 17:54   ` Robin Murphy
2021-12-10 17:54 ` [PATCH v2 08/11] iommu/vt-d: " Robin Murphy
2021-12-10 17:54   ` Robin Murphy
2021-12-10 17:54 ` [PATCH v2 09/11] iommu/iova: Consolidate flush queue code Robin Murphy
2021-12-10 17:54   ` Robin Murphy
2021-12-14 16:39   ` John Garry
2021-12-14 16:39     ` John Garry via iommu
2021-12-10 17:54 ` [PATCH v2 10/11] iommu/iova: Move flush queue code to iommu-dma Robin Murphy
2021-12-10 17:54   ` Robin Murphy
2021-12-14 16:40   ` John Garry
2021-12-14 16:40     ` John Garry via iommu
2021-12-14 17:18   ` John Garry
2021-12-14 17:18     ` John Garry via iommu
2021-12-14 17:50     ` Robin Murphy
2021-12-14 17:50       ` Robin Murphy
2021-12-10 17:54 ` [PATCH v2 11/11] iommu: Move flush queue data into iommu_dma_cookie Robin Murphy
2021-12-10 17:54   ` Robin Murphy
2021-12-10 23:30   ` kernel test robot
2021-12-10 23:30     ` kernel test robot
2021-12-10 23:30     ` kernel test robot
2021-12-10 23:50   ` kernel test robot
2021-12-10 23:50     ` kernel test robot
2021-12-10 23:50     ` kernel test robot
2021-12-14 17:16   ` John Garry
2021-12-14 17:16     ` John Garry via iommu

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.