[PATCH v3 0/1] iommu/arm-smmu-v3: Simplify useless instructions in arm_smmu_cmdq_build_cmd()

2021-12-07 Thread Zhen Lei via iommu
v2 --> v3:
Discard 'register' modifier for local variable 'cmd'.

v1 --> v2:
1. Add patch 1, Properly handle the return value of arm_smmu_cmdq_build_cmd()
2. Remove arm_smmu_cmdq_copy_cmd(). In addition, when build command fails, 
out_cmd is not filled.

[v2] https://lists.linuxfoundation.org/pipermail/iommu/2021-October/059831.html


Zhen Lei (1):
  iommu/arm-smmu-v3: Simplify useless instructions in
arm_smmu_cmdq_build_cmd()

 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

-- 
2.25.1

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


[PATCH v3 1/1] iommu/arm-smmu-v3: Simplify useless instructions in arm_smmu_cmdq_build_cmd()

2021-12-07 Thread Zhen Lei via iommu
Although the parameter 'cmd' is always passed by a local array variable,
and only this function modifies it, the compiler does not know this. Every
time the 'cmd' variable is updated, a memory write operation is generated.
This generates many useless instruction operations.

To guide the compiler for proper optimization, 'cmd' is defined as a local
array variable, and copied to the output parameter at a time when the
function is returned.

The optimization effect can be viewed by running the "size arm-smmu-v3.o"
command.

Before:
   textdata bss dec hex
  282461332  56   2963473c2

After:
   textdata bss dec hex
  281341332  56   295227352

For example:
cmd[0] = FIELD_PREP(CMDQ_0_OP, ent->opcode);
case CMDQ_OP_TLBI_EL2_VA:
cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_NUM, ent->tlbi.num);
cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_SCALE, ent->tlbi.scale);
cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_ASID, ent->tlbi.asid);
cmd[1] |= FIELD_PREP(CMDQ_TLBI_1_LEAF, ent->tlbi.leaf);
cmd[1] |= FIELD_PREP(CMDQ_TLBI_1_TTL, ent->tlbi.ttl);
cmd[1] |= FIELD_PREP(CMDQ_TLBI_1_TG, ent->tlbi.tg);
cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_VA_MASK;

Before:
  Each "cmd[0] |=" or "cmd[1] |=" operation generates a "str" instruction,
sum = 8.

 ldrb   w4, [x1, #8]//w4 = ent->tlbi.num
 ubfiz  x4, x4, #12, #5
 movw0, #0x0
 orrx4, x4, x3
 strx4, [x2]
 autiasp
 ldrb   w3, [x1, #9]//w3 = ent->tlbi.scale
 ubfiz  x3, x3, #20, #5
 orrx3, x3, x4
 strx3, [x2]
 ldrh   w4, [x1, #10]   //w4 = ent->tlbi.asid
 orrx3, x3, x4, lsl #48
 strx3, [x2]
 ldrb   w3, [x1, #14]   //w3 = ent->tlbi.leaf
 strx3, [x2, #8]
 ldrb   w4, [x1, #15]   //w4 = ent->tlbi.ttl
 ubfiz  x4, x4, #8, #2
 orrx4, x4, x3
 strx4, [x2, #8]
 ldrb   w3, [x1, #16]   //ent->tlbi.tg
 ubfiz  x3, x3, #10, #2
 orrx3, x3, x4
 strx3, [x2, #8]
 ldrx1, [x1, #24]   //ent->tlbi.addr
 andx1, x1, #0xf000
 orrx1, x1, x3
 strx1, [x2, #8]
 ret

After:
  All "cmd[0] |=" and "cmd[1] |=" operations generate a "stp" instruction,
sum = 1.

3e8:
 movw0, #0x0
 autiasp
 stpx2, x1, [x3]
 ret
 btij
3fc:
 ldrb   w5, [x1, #8]//w5 = ent->tlbi.num
 movx2, #0x22   //x2 = ent->opcode = CMDQ_0_OP
 ldrb   w6, [x1, #9]//w6 = ent->tlbi.scale
 ubfiz  x5, x5, #12, #5
 ldrb   w0, [x1, #16]   //w0 = ent->tlbi.tg
 orrx5, x5, x2
 ldrb   w7, [x1, #15]   //w7 = ent->tlbi.ttl
 ldrx4, [x1, #24]   //x4 = ent->tlbi.addr
 ubfiz  x0, x0, #10, #2
 ldrh   w2, [x1, #10]   //w2 = ent->tlbi.asid
 ubfiz  x6, x6, #20, #5
 ldrb   w8, [x1, #14]   //w8 = ent->tlbi.leaf
 andx4, x4, #0xf000
 ubfiz  x1, x7, #8, #2
 orrx1, x0, x1
 orr    x2, x6, x2, lsl #48
 orrx0, x4, x8
 orrx2, x2, x5
 orrx1, x1, x0
 b  3e8

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index f5848b351b19359..e55dfc14cac6005 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -234,10 +234,12 @@ static int queue_remove_raw(struct arm_smmu_queue *q, u64 
*ent)
 }
 
 /* High-level queue accessors */
-static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent)
+static int arm_smmu_cmdq_build_cmd(u64 *out_cmd, struct arm_smmu_cmdq_ent *ent)
 {
-   memset(cmd, 0, 1 << CMDQ_ENT_SZ_SHIFT);
-   cmd[0] |= FIELD_PREP(CMDQ_0_OP, ent->opcode);
+   int i;
+   u64 cmd[CMDQ_ENT_DWORDS] = {0};
+
+   cmd[0] = FIELD_PREP(CMDQ_0_OP, ent->opcode);
 
switch (ent->opcode) {
case CMDQ_OP_TLBI_EL2_ALL:
@@ -332,6 +334,9 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct 
arm_smmu_cmdq_ent *ent)
return -ENOENT;
}
 
+   for (i = 0; i < CMDQ_ENT_DWORDS; i++)
+   out_cmd[i] = cmd[i];
+
return 0;
 }
 
-- 
2.25.1

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


[PATCH v2 2/2] iommu/arm-smmu-v3: Simplify useless instructions in arm_smmu_cmdq_build_cmd()

2021-08-18 Thread Zhen Lei
Although the parameter 'cmd' is always passed by a local array variable,
and only this function modifies it, the compiler does not know this. The
compiler almost always reads the value of cmd[i] from memory rather than
directly using the value cached in the register. This generates many
useless instruction operations and affects the performance to some extent.

To guide the compiler for proper optimization, 'cmd' is defined as a local
array variable, marked as register, and copied to the output parameter at
a time when the function is returned.

The optimization effect can be viewed by running the "size arm-smmu-v3.o"
command.

Before:
   textdata bss dec hex
  269541348  56   283586ec6

After:
   textdata bss dec hex
  267621348  56   281666e06

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 01e95b56ffa07d1..7cec0c967f71d86 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -234,10 +234,12 @@ static int queue_remove_raw(struct arm_smmu_queue *q, u64 
*ent)
 }
 
 /* High-level queue accessors */
-static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent)
+static int arm_smmu_cmdq_build_cmd(u64 *out_cmd, struct arm_smmu_cmdq_ent *ent)
 {
-   memset(cmd, 0, 1 << CMDQ_ENT_SZ_SHIFT);
-   cmd[0] |= FIELD_PREP(CMDQ_0_OP, ent->opcode);
+   register u64 cmd[CMDQ_ENT_DWORDS];
+
+   cmd[0] = FIELD_PREP(CMDQ_0_OP, ent->opcode);
+   cmd[1] = 0;
 
switch (ent->opcode) {
case CMDQ_OP_TLBI_EL2_ALL:
@@ -332,6 +334,9 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct 
arm_smmu_cmdq_ent *ent)
return -ENOENT;
}
 
+   out_cmd[0] = cmd[0];
+   out_cmd[1] = cmd[1];
+
return 0;
 }
 
-- 
2.26.0.106.g9fadedd

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


[PATCH v2 1/2] iommu/arm-smmu-v3: Properly handle the return value of arm_smmu_cmdq_build_cmd()

2021-08-18 Thread Zhen Lei
1. Build command CMD_SYNC cannot fail. So the return value can be ignored.
2. The arm_smmu_cmdq_build_cmd() almost never fails, the addition of
   "unlikely()" can optimize the instruction pipeline.
3. Check the return value in arm_smmu_cmdq_batch_add().

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 18 --
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 3646bf8f021cd4c..01e95b56ffa07d1 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -409,10 +409,7 @@ static void __arm_smmu_cmdq_skip_err(struct 
arm_smmu_device *smmu,
dev_err(smmu->dev, "\t0x%016llx\n", (unsigned long long)cmd[i]);
 
/* Convert the erroneous command into a CMD_SYNC */
-   if (arm_smmu_cmdq_build_cmd(cmd, _sync)) {
-   dev_err(smmu->dev, "failed to convert to CMD_SYNC\n");
-   return;
-   }
+   arm_smmu_cmdq_build_cmd(cmd, _sync);
 
queue_write(Q_ENT(q, cons), cmd, q->ent_dwords);
 }
@@ -860,7 +857,7 @@ static int __arm_smmu_cmdq_issue_cmd(struct arm_smmu_device 
*smmu,
 {
u64 cmd[CMDQ_ENT_DWORDS];
 
-   if (arm_smmu_cmdq_build_cmd(cmd, ent)) {
+   if (unlikely(arm_smmu_cmdq_build_cmd(cmd, ent))) {
dev_warn(smmu->dev, "ignoring unknown CMDQ opcode 0x%x\n",
 ent->opcode);
return -EINVAL;
@@ -885,11 +882,20 @@ static void arm_smmu_cmdq_batch_add(struct 
arm_smmu_device *smmu,
struct arm_smmu_cmdq_batch *cmds,
struct arm_smmu_cmdq_ent *cmd)
 {
+   int index;
+
if (cmds->num == CMDQ_BATCH_ENTRIES) {
arm_smmu_cmdq_issue_cmdlist(smmu, cmds->cmds, cmds->num, false);
cmds->num = 0;
}
-   arm_smmu_cmdq_build_cmd(>cmds[cmds->num * CMDQ_ENT_DWORDS], cmd);
+
+   index = cmds->num * CMDQ_ENT_DWORDS;
+   if (unlikely(arm_smmu_cmdq_build_cmd(>cmds[index], cmd))) {
+   dev_warn(smmu->dev, "ignoring unknown CMDQ opcode 0x%x\n",
+cmd->opcode);
+   return;
+   }
+
cmds->num++;
 }
 
-- 
2.26.0.106.g9fadedd

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


[PATCH v2 0/2] iommu/arm-smmu-v3: Perform some simple optimizations for arm_smmu_cmdq_build_cmd()

2021-08-18 Thread Zhen Lei
v1 --> v2:
1. Add patch 1, Properly handle the return value of arm_smmu_cmdq_build_cmd()
2. Remove arm_smmu_cmdq_copy_cmd(). In addition, when build command fails, 
out_cmd is not filled.


Zhen Lei (2):
  iommu/arm-smmu-v3: Properly handle the return value of
arm_smmu_cmdq_build_cmd()
  iommu/arm-smmu-v3: Simplify useless instructions in
arm_smmu_cmdq_build_cmd()

 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 29 ++---
 1 file changed, 20 insertions(+), 9 deletions(-)

-- 
2.26.0.106.g9fadedd

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


[PATCH] iommu/arm-smmu-v3: Simplify useless instructions in arm_smmu_cmdq_build_cmd()

2021-08-17 Thread Zhen Lei
Although the parameter 'cmd' is always passed by a local array variable,
and only this function modifies it, the compiler does not know this. The
compiler almost always reads the value of cmd[i] from memory rather than
directly using the value cached in the register. This generates many
useless instruction operations and affects the performance to some extent.

To guide the compiler for proper optimization, 'cmd' is defined as a local
array variable, marked as register, and copied to the output parameter at
a time when the function is returned.

The optimization effect can be viewed by running the "size arm-smmu-v3.o"
command.

Before:
   textdata bss dec hex
  276021348  56   29006714e

After:
   textdata bss dec hex
  274021348  56   288067086

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 18 +++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index d76bbbde558b776..50a9db5bac466c7 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -233,11 +233,19 @@ static int queue_remove_raw(struct arm_smmu_queue *q, u64 
*ent)
return 0;
 }
 
+#define arm_smmu_cmdq_copy_cmd(dst, src)   \
+   do {\
+   dst[0] = src[0];\
+   dst[1] = src[1];\
+   } while (0)
+
 /* High-level queue accessors */
-static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent)
+static int arm_smmu_cmdq_build_cmd(u64 *out_cmd, struct arm_smmu_cmdq_ent *ent)
 {
-   memset(cmd, 0, 1 << CMDQ_ENT_SZ_SHIFT);
-   cmd[0] |= FIELD_PREP(CMDQ_0_OP, ent->opcode);
+   register u64 cmd[CMDQ_ENT_DWORDS];
+
+   cmd[0] = FIELD_PREP(CMDQ_0_OP, ent->opcode);
+   cmd[1] = 0;
 
switch (ent->opcode) {
case CMDQ_OP_TLBI_EL2_ALL:
@@ -309,6 +317,7 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct 
arm_smmu_cmdq_ent *ent)
case PRI_RESP_SUCC:
break;
default:
+   arm_smmu_cmdq_copy_cmd(out_cmd, cmd);
return -EINVAL;
}
cmd[1] |= FIELD_PREP(CMDQ_PRI_1_RESP, ent->pri.resp);
@@ -329,9 +338,12 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct 
arm_smmu_cmdq_ent *ent)
cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_MSIATTR, 
ARM_SMMU_MEMATTR_OIWB);
break;
default:
+   arm_smmu_cmdq_copy_cmd(out_cmd, cmd);
return -ENOENT;
}
 
+   arm_smmu_cmdq_copy_cmd(out_cmd, cmd);
+
return 0;
 }
 
-- 
2.26.0.106.g9fadedd

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


[PATCH] iommu/arm-smmu-v3: Stop pre-zeroing batch commands in arm_smmu_atc_inv_master()

2021-08-17 Thread Zhen Lei
Pre-zeroing the batched commands structure is inefficient, as individual
commands are zeroed later in arm_smmu_cmdq_build_cmd(). Therefore, only
the member 'num' needs to be initialized to 0.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 50a9db5bac466c7..e6882ae81fd08f6 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1776,10 +1776,11 @@ static int arm_smmu_atc_inv_master(struct 
arm_smmu_master *master)
 {
int i;
struct arm_smmu_cmdq_ent cmd;
-   struct arm_smmu_cmdq_batch cmds = {};
+   struct arm_smmu_cmdq_batch cmds;
 
arm_smmu_atc_inv_to_cmd(0, 0, 0, );
 
+   cmds.num = 0;
for (i = 0; i < master->num_streams; i++) {
cmd.atc.sid = master->streams[i].id;
arm_smmu_cmdq_batch_add(master->smmu, , );
-- 
2.26.0.106.g9fadedd

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


[PATCH v2 3/4] iommu/arm-smmu-v3: Add and use static helper function arm_smmu_get_cmdq()

2021-08-16 Thread Zhen Lei
One SMMU has only one normal CMDQ. Therefore, this CMDQ is used regardless
of the core on which the command is inserted. It can be referenced
directly through "smmu->cmdq". However, one SMMU has multiple ECMDQs, and
the ECMDQ used by the core on which the command insertion is executed may
be different. So the helper function arm_smmu_get_cmdq() is added, which
returns the CMDQ/ECMDQ that the current core should use. Currently, the
code that supports ECMDQ is not added. just simply returns ">cmdq".

Many subfunctions of arm_smmu_cmdq_issue_cmdlist() use ">cmdq" or
">cmdq.q" directly. To support ECMDQ, they need to call the newly
added function arm_smmu_get_cmdq() instead.

Note that normal CMDQ is still required until ECMDQ is available.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 22 -
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 9be07f6915cc3c8..7814366778fda35 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -335,10 +335,14 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct 
arm_smmu_cmdq_ent *ent)
return 0;
 }
 
+static struct arm_smmu_cmdq *arm_smmu_get_cmdq(struct arm_smmu_device *smmu)
+{
+   return >cmdq;
+}
+
 static void arm_smmu_cmdq_build_sync_cmd(u64 *cmd, struct arm_smmu_device 
*smmu,
-u32 prod)
+struct arm_smmu_queue *q, u32 prod)
 {
-   struct arm_smmu_queue *q = >cmdq.q;
struct arm_smmu_cmdq_ent ent = {
.opcode = CMDQ_OP_CMD_SYNC,
};
@@ -579,7 +583,7 @@ static int arm_smmu_cmdq_poll_until_not_full(struct 
arm_smmu_device *smmu,
 {
unsigned long flags;
struct arm_smmu_queue_poll qp;
-   struct arm_smmu_cmdq *cmdq = >cmdq;
+   struct arm_smmu_cmdq *cmdq = arm_smmu_get_cmdq(smmu);
int ret = 0;
 
/*
@@ -595,7 +599,7 @@ static int arm_smmu_cmdq_poll_until_not_full(struct 
arm_smmu_device *smmu,
 
queue_poll_init(smmu, );
do {
-   llq->val = READ_ONCE(smmu->cmdq.q.llq.val);
+   llq->val = READ_ONCE(cmdq->q.llq.val);
if (!queue_full(llq))
break;
 
@@ -614,7 +618,7 @@ static int __arm_smmu_cmdq_poll_until_msi(struct 
arm_smmu_device *smmu,
 {
int ret = 0;
struct arm_smmu_queue_poll qp;
-   struct arm_smmu_cmdq *cmdq = >cmdq;
+   struct arm_smmu_cmdq *cmdq = arm_smmu_get_cmdq(smmu);
u32 *cmd = (u32 *)(Q_ENT(>q, llq->prod));
 
queue_poll_init(smmu, );
@@ -637,12 +641,12 @@ static int __arm_smmu_cmdq_poll_until_consumed(struct 
arm_smmu_device *smmu,
   struct arm_smmu_ll_queue *llq)
 {
struct arm_smmu_queue_poll qp;
-   struct arm_smmu_cmdq *cmdq = >cmdq;
+   struct arm_smmu_cmdq *cmdq = arm_smmu_get_cmdq(smmu);
u32 prod = llq->prod;
int ret = 0;
 
queue_poll_init(smmu, );
-   llq->val = READ_ONCE(smmu->cmdq.q.llq.val);
+   llq->val = READ_ONCE(cmdq->q.llq.val);
do {
if (queue_consumed(llq, prod))
break;
@@ -732,7 +736,7 @@ static int arm_smmu_cmdq_issue_cmdlist(struct 
arm_smmu_device *smmu,
u32 prod;
unsigned long flags;
bool owner;
-   struct arm_smmu_cmdq *cmdq = >cmdq;
+   struct arm_smmu_cmdq *cmdq = arm_smmu_get_cmdq(smmu);
struct arm_smmu_ll_queue llq = {
.max_n_shift = cmdq->q.llq.max_n_shift,
}, head = llq;
@@ -772,7 +776,7 @@ static int arm_smmu_cmdq_issue_cmdlist(struct 
arm_smmu_device *smmu,
arm_smmu_cmdq_write_entries(cmdq, cmds, llq.prod, n);
if (sync) {
prod = queue_inc_prod_n(, n);
-   arm_smmu_cmdq_build_sync_cmd(cmd_sync, smmu, prod);
+   arm_smmu_cmdq_build_sync_cmd(cmd_sync, smmu, >q, prod);
queue_write(Q_ENT(>q, prod), cmd_sync, CMDQ_ENT_DWORDS);
 
/*
-- 
2.26.0.106.g9fadedd

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


[PATCH v2 1/4] iommu/arm-smmu-v3: Use command queue batching helpers to improve performance

2021-08-16 Thread Zhen Lei
The obvious key to the performance optimization of commit 587e6c10a7ce
("iommu/arm-smmu-v3: Reduce contention during command-queue insertion") is
to allow multiple cores to insert commands in parallel after a brief mutex
contention.

Obviously, inserting as many commands at a time as possible can reduce the
number of times the mutex contention participates, thereby improving the
overall performance. At least it reduces the number of calls to function
arm_smmu_cmdq_issue_cmdlist().

Therefore, use command queue batching helpers to insert multiple commands
at a time.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 235f9bdaeaf223b..5eedb46aaceece8 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1747,15 +1747,17 @@ static int arm_smmu_atc_inv_master(struct 
arm_smmu_master *master)
 {
int i;
struct arm_smmu_cmdq_ent cmd;
+   struct arm_smmu_cmdq_batch cmds;
 
arm_smmu_atc_inv_to_cmd(0, 0, 0, );
 
+   cmds.num = 0;
for (i = 0; i < master->num_streams; i++) {
cmd.atc.sid = master->streams[i].id;
-   arm_smmu_cmdq_issue_cmd(master->smmu, );
+   arm_smmu_cmdq_batch_add(master->smmu, , );
}
 
-   return arm_smmu_cmdq_issue_sync(master->smmu);
+   return arm_smmu_cmdq_batch_submit(master->smmu, );
 }
 
 int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid,
-- 
2.26.0.106.g9fadedd

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


[PATCH v2 0/4] Prepare for ECMDQ support

2021-08-16 Thread Zhen Lei
v1 --> v2:
1. Stop pre-zeroing batch commands. Patch 1 is modified. Other patches remain 
unchanged.
   Before:
   struct arm_smmu_cmdq_batch cmds = {};

   After:
   struct arm_smmu_cmdq_batch cmds;
   cmds.num = 0;

RFC --> v1
1. Resend the patches for ECMDQ preparation and remove the patches for ECMDQ 
implementation.
2. Patch 2 is modified. Other patches remain unchanged.
   1) Add static helper __arm_smmu_cmdq_issue_cmd(), and make 
arm_smmu_cmdq_issue_cmd()
  and arm_smmu_cmdq_issue_cmd_with_sync() implement based on it.
   2) Remove unused arm_smmu_cmdq_issue_sync().

RFC:
https://www.spinics.net/lists/arm-kernel/msg904879.html


Zhen Lei (4):
  iommu/arm-smmu-v3: Use command queue batching helpers to improve
performance
  iommu/arm-smmu-v3: Add and use static helper function
arm_smmu_cmdq_issue_cmd_with_sync()
  iommu/arm-smmu-v3: Add and use static helper function
arm_smmu_get_cmdq()
  iommu/arm-smmu-v3: Extract reusable function
__arm_smmu_cmdq_skip_err()

 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 72 -
 1 file changed, 43 insertions(+), 29 deletions(-)

-- 
2.26.0.106.g9fadedd

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


[PATCH v2 4/4] iommu/arm-smmu-v3: Extract reusable function __arm_smmu_cmdq_skip_err()

2021-08-16 Thread Zhen Lei
When SMMU_GERROR.CMDQP_ERR is different to SMMU_GERRORN.CMDQP_ERR, it
indicates that one or more errors have been encountered on a command queue
control page interface. We need to traverse all ECMDQs in that control
page to find all errors. For each ECMDQ error handling, it is much the
same as the CMDQ error handling. This common processing part is extracted
as a new function __arm_smmu_cmdq_skip_err().

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 7814366778fda35..f3824c37f1832a2 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -359,7 +359,8 @@ static void arm_smmu_cmdq_build_sync_cmd(u64 *cmd, struct 
arm_smmu_device *smmu,
arm_smmu_cmdq_build_cmd(cmd, );
 }
 
-static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu)
+static void __arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu,
+struct arm_smmu_queue *q)
 {
static const char * const cerror_str[] = {
[CMDQ_ERR_CERROR_NONE_IDX]  = "No error",
@@ -370,7 +371,6 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_device 
*smmu)
 
int i;
u64 cmd[CMDQ_ENT_DWORDS];
-   struct arm_smmu_queue *q = >cmdq.q;
u32 cons = readl_relaxed(q->cons_reg);
u32 idx = FIELD_GET(CMDQ_CONS_ERR, cons);
struct arm_smmu_cmdq_ent cmd_sync = {
@@ -417,6 +417,11 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_device 
*smmu)
queue_write(Q_ENT(q, cons), cmd, q->ent_dwords);
 }
 
+static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu)
+{
+   __arm_smmu_cmdq_skip_err(smmu, >cmdq.q);
+}
+
 /*
  * Command queue locking.
  * This is a form of bastardised rwlock with the following major changes:
-- 
2.26.0.106.g9fadedd

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


[PATCH v2 2/4] iommu/arm-smmu-v3: Add and use static helper function arm_smmu_cmdq_issue_cmd_with_sync()

2021-08-16 Thread Zhen Lei
The obvious key to the performance optimization of commit 587e6c10a7ce
("iommu/arm-smmu-v3: Reduce contention during command-queue insertion") is
to allow multiple cores to insert commands in parallel after a brief mutex
contention.

Obviously, inserting as many commands at a time as possible can reduce the
number of times the mutex contention participates, thereby improving the
overall performance. At least it reduces the number of calls to function
arm_smmu_cmdq_issue_cmdlist().

Therefore, function arm_smmu_cmdq_issue_cmd_with_sync() is added to insert
the 'cmd+sync' commands at a time.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 35 +++--
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 5eedb46aaceece8..9be07f6915cc3c8 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -845,8 +845,9 @@ static int arm_smmu_cmdq_issue_cmdlist(struct 
arm_smmu_device *smmu,
return ret;
 }
 
-static int arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu,
-  struct arm_smmu_cmdq_ent *ent)
+static int __arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu,
+struct arm_smmu_cmdq_ent *ent,
+bool sync)
 {
u64 cmd[CMDQ_ENT_DWORDS];
 
@@ -856,12 +857,19 @@ static int arm_smmu_cmdq_issue_cmd(struct arm_smmu_device 
*smmu,
return -EINVAL;
}
 
-   return arm_smmu_cmdq_issue_cmdlist(smmu, cmd, 1, false);
+   return arm_smmu_cmdq_issue_cmdlist(smmu, cmd, 1, sync);
 }
 
-static int arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu)
+static int arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu,
+  struct arm_smmu_cmdq_ent *ent)
 {
-   return arm_smmu_cmdq_issue_cmdlist(smmu, NULL, 0, true);
+   return __arm_smmu_cmdq_issue_cmd(smmu, ent, false);
+}
+
+static int arm_smmu_cmdq_issue_cmd_with_sync(struct arm_smmu_device *smmu,
+struct arm_smmu_cmdq_ent *ent)
+{
+   return __arm_smmu_cmdq_issue_cmd(smmu, ent, true);
 }
 
 static void arm_smmu_cmdq_batch_add(struct arm_smmu_device *smmu,
@@ -929,8 +937,7 @@ void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, 
u16 asid)
.tlbi.asid = asid,
};
 
-   arm_smmu_cmdq_issue_cmd(smmu, );
-   arm_smmu_cmdq_issue_sync(smmu);
+   arm_smmu_cmdq_issue_cmd_with_sync(smmu, );
 }
 
 static void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain,
@@ -1211,8 +1218,7 @@ static void arm_smmu_sync_ste_for_sid(struct 
arm_smmu_device *smmu, u32 sid)
},
};
 
-   arm_smmu_cmdq_issue_cmd(smmu, );
-   arm_smmu_cmdq_issue_sync(smmu);
+   arm_smmu_cmdq_issue_cmd_with_sync(smmu, );
 }
 
 static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
@@ -1825,8 +1831,7 @@ static void arm_smmu_tlb_inv_context(void *cookie)
} else {
cmd.opcode  = CMDQ_OP_TLBI_S12_VMALL;
cmd.tlbi.vmid   = smmu_domain->s2_cfg.vmid;
-   arm_smmu_cmdq_issue_cmd(smmu, );
-   arm_smmu_cmdq_issue_sync(smmu);
+   arm_smmu_cmdq_issue_cmd_with_sync(smmu, );
}
arm_smmu_atc_inv_domain(smmu_domain, 0, 0, 0);
 }
@@ -3340,18 +3345,16 @@ static int arm_smmu_device_reset(struct arm_smmu_device 
*smmu, bool bypass)
 
/* Invalidate any cached configuration */
cmd.opcode = CMDQ_OP_CFGI_ALL;
-   arm_smmu_cmdq_issue_cmd(smmu, );
-   arm_smmu_cmdq_issue_sync(smmu);
+   arm_smmu_cmdq_issue_cmd_with_sync(smmu, );
 
/* Invalidate any stale TLB entries */
if (smmu->features & ARM_SMMU_FEAT_HYP) {
cmd.opcode = CMDQ_OP_TLBI_EL2_ALL;
-   arm_smmu_cmdq_issue_cmd(smmu, );
+   arm_smmu_cmdq_issue_cmd_with_sync(smmu, );
}
 
cmd.opcode = CMDQ_OP_TLBI_NSNH_ALL;
-   arm_smmu_cmdq_issue_cmd(smmu, );
-   arm_smmu_cmdq_issue_sync(smmu);
+   arm_smmu_cmdq_issue_cmd_with_sync(smmu, );
 
/* Event queue */
writeq_relaxed(smmu->evtq.q.q_base, smmu->base + ARM_SMMU_EVTQ_BASE);
-- 
2.26.0.106.g9fadedd

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


[PATCH 0/4] Prepare for ECMDQ support

2021-08-11 Thread Zhen Lei
RFC --> v1
1. Resend the patches for ECMDQ preparation and remove the patches for ECMDQ 
implementation.
2. Patch 2 is modified. Other patches remain unchanged.
   1) Add static helper __arm_smmu_cmdq_issue_cmd(), and make 
arm_smmu_cmdq_issue_cmd()
  and arm_smmu_cmdq_issue_cmd_with_sync() implement based on it.
   2) Remove unused arm_smmu_cmdq_issue_sync().

RFC:
https://www.spinics.net/lists/arm-kernel/msg904879.html


Zhen Lei (4):
  iommu/arm-smmu-v3: Use command queue batching helpers to improve
performance
  iommu/arm-smmu-v3: Add and use static helper function
arm_smmu_cmdq_issue_cmd_with_sync()
  iommu/arm-smmu-v3: Add and use static helper function
arm_smmu_get_cmdq()
  iommu/arm-smmu-v3: Extract reusable function
__arm_smmu_cmdq_skip_err()

 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 71 -
 1 file changed, 42 insertions(+), 29 deletions(-)

-- 
2.26.0.106.g9fadedd

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


[PATCH 3/4] iommu/arm-smmu-v3: Add and use static helper function arm_smmu_get_cmdq()

2021-08-11 Thread Zhen Lei
One SMMU has only one normal CMDQ. Therefore, this CMDQ is used regardless
of the core on which the command is inserted. It can be referenced
directly through "smmu->cmdq". However, one SMMU has multiple ECMDQs, and
the ECMDQ used by the core on which the command insertion is executed may
be different. So the helper function arm_smmu_get_cmdq() is added, which
returns the CMDQ/ECMDQ that the current core should use. Currently, the
code that supports ECMDQ is not added. just simply returns ">cmdq".

Many subfunctions of arm_smmu_cmdq_issue_cmdlist() use ">cmdq" or
">cmdq.q" directly. To support ECMDQ, they need to call the newly
added function arm_smmu_get_cmdq() instead.

Note that normal CMDQ is still required until ECMDQ is available.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 22 -
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 282f95659580267..be2df5ad2eb51b8 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -335,10 +335,14 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct 
arm_smmu_cmdq_ent *ent)
return 0;
 }
 
+static struct arm_smmu_cmdq *arm_smmu_get_cmdq(struct arm_smmu_device *smmu)
+{
+   return >cmdq;
+}
+
 static void arm_smmu_cmdq_build_sync_cmd(u64 *cmd, struct arm_smmu_device 
*smmu,
-u32 prod)
+struct arm_smmu_queue *q, u32 prod)
 {
-   struct arm_smmu_queue *q = >cmdq.q;
struct arm_smmu_cmdq_ent ent = {
.opcode = CMDQ_OP_CMD_SYNC,
};
@@ -579,7 +583,7 @@ static int arm_smmu_cmdq_poll_until_not_full(struct 
arm_smmu_device *smmu,
 {
unsigned long flags;
struct arm_smmu_queue_poll qp;
-   struct arm_smmu_cmdq *cmdq = >cmdq;
+   struct arm_smmu_cmdq *cmdq = arm_smmu_get_cmdq(smmu);
int ret = 0;
 
/*
@@ -595,7 +599,7 @@ static int arm_smmu_cmdq_poll_until_not_full(struct 
arm_smmu_device *smmu,
 
queue_poll_init(smmu, );
do {
-   llq->val = READ_ONCE(smmu->cmdq.q.llq.val);
+   llq->val = READ_ONCE(cmdq->q.llq.val);
if (!queue_full(llq))
break;
 
@@ -614,7 +618,7 @@ static int __arm_smmu_cmdq_poll_until_msi(struct 
arm_smmu_device *smmu,
 {
int ret = 0;
struct arm_smmu_queue_poll qp;
-   struct arm_smmu_cmdq *cmdq = >cmdq;
+   struct arm_smmu_cmdq *cmdq = arm_smmu_get_cmdq(smmu);
u32 *cmd = (u32 *)(Q_ENT(>q, llq->prod));
 
queue_poll_init(smmu, );
@@ -637,12 +641,12 @@ static int __arm_smmu_cmdq_poll_until_consumed(struct 
arm_smmu_device *smmu,
   struct arm_smmu_ll_queue *llq)
 {
struct arm_smmu_queue_poll qp;
-   struct arm_smmu_cmdq *cmdq = >cmdq;
+   struct arm_smmu_cmdq *cmdq = arm_smmu_get_cmdq(smmu);
u32 prod = llq->prod;
int ret = 0;
 
queue_poll_init(smmu, );
-   llq->val = READ_ONCE(smmu->cmdq.q.llq.val);
+   llq->val = READ_ONCE(cmdq->q.llq.val);
do {
if (queue_consumed(llq, prod))
break;
@@ -732,7 +736,7 @@ static int arm_smmu_cmdq_issue_cmdlist(struct 
arm_smmu_device *smmu,
u32 prod;
unsigned long flags;
bool owner;
-   struct arm_smmu_cmdq *cmdq = >cmdq;
+   struct arm_smmu_cmdq *cmdq = arm_smmu_get_cmdq(smmu);
struct arm_smmu_ll_queue llq = {
.max_n_shift = cmdq->q.llq.max_n_shift,
}, head = llq;
@@ -772,7 +776,7 @@ static int arm_smmu_cmdq_issue_cmdlist(struct 
arm_smmu_device *smmu,
arm_smmu_cmdq_write_entries(cmdq, cmds, llq.prod, n);
if (sync) {
prod = queue_inc_prod_n(, n);
-   arm_smmu_cmdq_build_sync_cmd(cmd_sync, smmu, prod);
+   arm_smmu_cmdq_build_sync_cmd(cmd_sync, smmu, >q, prod);
queue_write(Q_ENT(>q, prod), cmd_sync, CMDQ_ENT_DWORDS);
 
/*
-- 
2.26.0.106.g9fadedd

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


[PATCH 2/4] iommu/arm-smmu-v3: Add and use static helper function arm_smmu_cmdq_issue_cmd_with_sync()

2021-08-11 Thread Zhen Lei
The obvious key to the performance optimization of commit 587e6c10a7ce
("iommu/arm-smmu-v3: Reduce contention during command-queue insertion") is
to allow multiple cores to insert commands in parallel after a brief mutex
contention.

Obviously, inserting as many commands at a time as possible can reduce the
number of times the mutex contention participates, thereby improving the
overall performance. At least it reduces the number of calls to function
arm_smmu_cmdq_issue_cmdlist().

Therefore, function arm_smmu_cmdq_issue_cmd_with_sync() is added to insert
the 'cmd+sync' commands at a time.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 35 +++--
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index c81cd929047f573..282f95659580267 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -845,8 +845,9 @@ static int arm_smmu_cmdq_issue_cmdlist(struct 
arm_smmu_device *smmu,
return ret;
 }
 
-static int arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu,
-  struct arm_smmu_cmdq_ent *ent)
+static int __arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu,
+struct arm_smmu_cmdq_ent *ent,
+bool sync)
 {
u64 cmd[CMDQ_ENT_DWORDS];
 
@@ -856,12 +857,19 @@ static int arm_smmu_cmdq_issue_cmd(struct arm_smmu_device 
*smmu,
return -EINVAL;
}
 
-   return arm_smmu_cmdq_issue_cmdlist(smmu, cmd, 1, false);
+   return arm_smmu_cmdq_issue_cmdlist(smmu, cmd, 1, sync);
 }
 
-static int arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu)
+static int arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu,
+  struct arm_smmu_cmdq_ent *ent)
 {
-   return arm_smmu_cmdq_issue_cmdlist(smmu, NULL, 0, true);
+   return __arm_smmu_cmdq_issue_cmd(smmu, ent, false);
+}
+
+static int arm_smmu_cmdq_issue_cmd_with_sync(struct arm_smmu_device *smmu,
+struct arm_smmu_cmdq_ent *ent)
+{
+   return __arm_smmu_cmdq_issue_cmd(smmu, ent, true);
 }
 
 static void arm_smmu_cmdq_batch_add(struct arm_smmu_device *smmu,
@@ -929,8 +937,7 @@ void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, 
u16 asid)
.tlbi.asid = asid,
};
 
-   arm_smmu_cmdq_issue_cmd(smmu, );
-   arm_smmu_cmdq_issue_sync(smmu);
+   arm_smmu_cmdq_issue_cmd_with_sync(smmu, );
 }
 
 static void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain,
@@ -1211,8 +1218,7 @@ static void arm_smmu_sync_ste_for_sid(struct 
arm_smmu_device *smmu, u32 sid)
},
};
 
-   arm_smmu_cmdq_issue_cmd(smmu, );
-   arm_smmu_cmdq_issue_sync(smmu);
+   arm_smmu_cmdq_issue_cmd_with_sync(smmu, );
 }
 
 static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
@@ -1824,8 +1830,7 @@ static void arm_smmu_tlb_inv_context(void *cookie)
} else {
cmd.opcode  = CMDQ_OP_TLBI_S12_VMALL;
cmd.tlbi.vmid   = smmu_domain->s2_cfg.vmid;
-   arm_smmu_cmdq_issue_cmd(smmu, );
-   arm_smmu_cmdq_issue_sync(smmu);
+   arm_smmu_cmdq_issue_cmd_with_sync(smmu, );
}
arm_smmu_atc_inv_domain(smmu_domain, 0, 0, 0);
 }
@@ -3339,18 +3344,16 @@ static int arm_smmu_device_reset(struct arm_smmu_device 
*smmu, bool bypass)
 
/* Invalidate any cached configuration */
cmd.opcode = CMDQ_OP_CFGI_ALL;
-   arm_smmu_cmdq_issue_cmd(smmu, );
-   arm_smmu_cmdq_issue_sync(smmu);
+   arm_smmu_cmdq_issue_cmd_with_sync(smmu, );
 
/* Invalidate any stale TLB entries */
if (smmu->features & ARM_SMMU_FEAT_HYP) {
cmd.opcode = CMDQ_OP_TLBI_EL2_ALL;
-   arm_smmu_cmdq_issue_cmd(smmu, );
+   arm_smmu_cmdq_issue_cmd_with_sync(smmu, );
}
 
cmd.opcode = CMDQ_OP_TLBI_NSNH_ALL;
-   arm_smmu_cmdq_issue_cmd(smmu, );
-   arm_smmu_cmdq_issue_sync(smmu);
+   arm_smmu_cmdq_issue_cmd_with_sync(smmu, );
 
/* Event queue */
writeq_relaxed(smmu->evtq.q.q_base, smmu->base + ARM_SMMU_EVTQ_BASE);
-- 
2.26.0.106.g9fadedd

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


[PATCH 1/4] iommu/arm-smmu-v3: Use command queue batching helpers to improve performance

2021-08-11 Thread Zhen Lei
The obvious key to the performance optimization of commit 587e6c10a7ce
("iommu/arm-smmu-v3: Reduce contention during command-queue insertion") is
to allow multiple cores to insert commands in parallel after a brief mutex
contention.

Obviously, inserting as many commands at a time as possible can reduce the
number of times the mutex contention participates, thereby improving the
overall performance. At least it reduces the number of calls to function
arm_smmu_cmdq_issue_cmdlist().

Therefore, use command queue batching helpers to insert multiple commands
at a time.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 235f9bdaeaf223b..c81cd929047f573 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1747,15 +1747,16 @@ static int arm_smmu_atc_inv_master(struct 
arm_smmu_master *master)
 {
int i;
struct arm_smmu_cmdq_ent cmd;
+   struct arm_smmu_cmdq_batch cmds = {};
 
arm_smmu_atc_inv_to_cmd(0, 0, 0, );
 
for (i = 0; i < master->num_streams; i++) {
cmd.atc.sid = master->streams[i].id;
-   arm_smmu_cmdq_issue_cmd(master->smmu, );
+   arm_smmu_cmdq_batch_add(master->smmu, , );
}
 
-   return arm_smmu_cmdq_issue_sync(master->smmu);
+   return arm_smmu_cmdq_batch_submit(master->smmu, );
 }
 
 int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid,
-- 
2.26.0.106.g9fadedd

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


[PATCH 4/4] iommu/arm-smmu-v3: Extract reusable function __arm_smmu_cmdq_skip_err()

2021-08-11 Thread Zhen Lei
When SMMU_GERROR.CMDQP_ERR is different to SMMU_GERRORN.CMDQP_ERR, it
indicates that one or more errors have been encountered on a command queue
control page interface. We need to traverse all ECMDQs in that control
page to find all errors. For each ECMDQ error handling, it is much the
same as the CMDQ error handling. This common processing part is extracted
as a new function __arm_smmu_cmdq_skip_err().

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index be2df5ad2eb51b8..597cc0ff5ef40f0 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -359,7 +359,8 @@ static void arm_smmu_cmdq_build_sync_cmd(u64 *cmd, struct 
arm_smmu_device *smmu,
arm_smmu_cmdq_build_cmd(cmd, );
 }
 
-static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu)
+static void __arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu,
+struct arm_smmu_queue *q)
 {
static const char * const cerror_str[] = {
[CMDQ_ERR_CERROR_NONE_IDX]  = "No error",
@@ -370,7 +371,6 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_device 
*smmu)
 
int i;
u64 cmd[CMDQ_ENT_DWORDS];
-   struct arm_smmu_queue *q = >cmdq.q;
u32 cons = readl_relaxed(q->cons_reg);
u32 idx = FIELD_GET(CMDQ_CONS_ERR, cons);
struct arm_smmu_cmdq_ent cmd_sync = {
@@ -417,6 +417,11 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_device 
*smmu)
queue_write(Q_ENT(q, cons), cmd, q->ent_dwords);
 }
 
+static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu)
+{
+   __arm_smmu_cmdq_skip_err(smmu, >cmdq.q);
+}
+
 /*
  * Command queue locking.
  * This is a form of bastardised rwlock with the following major changes:
-- 
2.26.0.106.g9fadedd

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


[PATCH RFC 2/8] iommu/arm-smmu-v3: Add and use static helper function arm_smmu_cmdq_issue_cmd_with_sync()

2021-06-26 Thread Zhen Lei
The obvious key to the performance optimization of commit 587e6c10a7ce
("iommu/arm-smmu-v3: Reduce contention during command-queue insertion") is
to allow multiple cores to insert commands in parallel after a brief mutex
contention.

Obviously, inserting as many commands at a time as possible can reduce the
number of times the mutex contention participates, thereby improving the
overall performance. At least it reduces the number of calls to function
arm_smmu_cmdq_issue_cmdlist().

Therefore, function arm_smmu_cmdq_issue_cmd_with_sync() is added to insert
the 'cmd+sync' commands at a time.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 33 +
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 2433d3c29b49ff2..a5361153ca1d6a4 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -858,11 +858,25 @@ static int arm_smmu_cmdq_issue_cmd(struct arm_smmu_device 
*smmu,
return arm_smmu_cmdq_issue_cmdlist(smmu, cmd, 1, false);
 }
 
-static int arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu)
+static int __maybe_unused arm_smmu_cmdq_issue_sync(struct arm_smmu_device 
*smmu)
 {
return arm_smmu_cmdq_issue_cmdlist(smmu, NULL, 0, true);
 }
 
+static int arm_smmu_cmdq_issue_cmd_with_sync(struct arm_smmu_device *smmu,
+struct arm_smmu_cmdq_ent *ent)
+{
+   u64 cmd[CMDQ_ENT_DWORDS];
+
+   if (arm_smmu_cmdq_build_cmd(cmd, ent)) {
+   dev_warn(smmu->dev, "ignoring unknown CMDQ opcode 0x%x\n",
+ent->opcode);
+   return -EINVAL;
+   }
+
+   return arm_smmu_cmdq_issue_cmdlist(smmu, cmd, 1, true);
+}
+
 static void arm_smmu_cmdq_batch_add(struct arm_smmu_device *smmu,
struct arm_smmu_cmdq_batch *cmds,
struct arm_smmu_cmdq_ent *cmd)
@@ -928,8 +942,7 @@ void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, 
u16 asid)
.tlbi.asid = asid,
};
 
-   arm_smmu_cmdq_issue_cmd(smmu, );
-   arm_smmu_cmdq_issue_sync(smmu);
+   arm_smmu_cmdq_issue_cmd_with_sync(smmu, );
 }
 
 static void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain,
@@ -1210,8 +1223,7 @@ static void arm_smmu_sync_ste_for_sid(struct 
arm_smmu_device *smmu, u32 sid)
},
};
 
-   arm_smmu_cmdq_issue_cmd(smmu, );
-   arm_smmu_cmdq_issue_sync(smmu);
+   arm_smmu_cmdq_issue_cmd_with_sync(smmu, );
 }
 
 static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
@@ -1823,8 +1835,7 @@ static void arm_smmu_tlb_inv_context(void *cookie)
} else {
cmd.opcode  = CMDQ_OP_TLBI_S12_VMALL;
cmd.tlbi.vmid   = smmu_domain->s2_cfg.vmid;
-   arm_smmu_cmdq_issue_cmd(smmu, );
-   arm_smmu_cmdq_issue_sync(smmu);
+   arm_smmu_cmdq_issue_cmd_with_sync(smmu, );
}
arm_smmu_atc_inv_domain(smmu_domain, 0, 0, 0);
 }
@@ -3338,18 +3349,16 @@ static int arm_smmu_device_reset(struct arm_smmu_device 
*smmu, bool bypass)
 
/* Invalidate any cached configuration */
cmd.opcode = CMDQ_OP_CFGI_ALL;
-   arm_smmu_cmdq_issue_cmd(smmu, );
-   arm_smmu_cmdq_issue_sync(smmu);
+   arm_smmu_cmdq_issue_cmd_with_sync(smmu, );
 
/* Invalidate any stale TLB entries */
if (smmu->features & ARM_SMMU_FEAT_HYP) {
cmd.opcode = CMDQ_OP_TLBI_EL2_ALL;
-   arm_smmu_cmdq_issue_cmd(smmu, );
+   arm_smmu_cmdq_issue_cmd_with_sync(smmu, );
}
 
cmd.opcode = CMDQ_OP_TLBI_NSNH_ALL;
-   arm_smmu_cmdq_issue_cmd(smmu, );
-   arm_smmu_cmdq_issue_sync(smmu);
+   arm_smmu_cmdq_issue_cmd_with_sync(smmu, );
 
/* Event queue */
writeq_relaxed(smmu->evtq.q.q_base, smmu->base + ARM_SMMU_EVTQ_BASE);
-- 
2.26.0.106.g9fadedd


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


[PATCH RFC 7/8] iommu/arm-smmu-v3: Add arm_smmu_ecmdq_issue_cmdlist() for non-shared ECMDQ

2021-06-26 Thread Zhen Lei
When a core can exclusively own an ECMDQ, competition with other cores
does not need to be considered during command insertion. Therefore, we can
delete the part of arm_smmu_cmdq_issue_cmdlist() that deals with
multi-core contention and generate a more efficient ECMDQ-specific
function arm_smmu_ecmdq_issue_cmdlist().

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 85 +
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  1 +
 2 files changed, 86 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index d5205030710bd1a..a088f2479fc6223 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -769,6 +769,87 @@ static void arm_smmu_cmdq_write_entries(struct 
arm_smmu_cmdq *cmdq, u64 *cmds,
}
 }
 
+/*
+ * The function is used when the current core exclusively occupies an ECMDQ.
+ * This is a reduced version of arm_smmu_cmdq_issue_cmdlist(), which eliminates
+ * a lot of unnecessary inter-core competition considerations.
+ */
+static int arm_smmu_ecmdq_issue_cmdlist(struct arm_smmu_device *smmu,
+   struct arm_smmu_cmdq *cmdq,
+   u64 *cmds, int n, bool sync)
+{
+   u32 prod;
+   unsigned long flags;
+   struct arm_smmu_ll_queue llq = {
+   .max_n_shift = cmdq->q.llq.max_n_shift,
+   }, head;
+   int ret = 0;
+
+   /* 1. Allocate some space in the queue */
+   local_irq_save(flags);
+   llq.val = READ_ONCE(cmdq->q.llq.val);
+   do {
+   u64 old;
+
+   while (!queue_has_space(, n + sync)) {
+   local_irq_restore(flags);
+   if (arm_smmu_cmdq_poll_until_not_full(smmu, ))
+   dev_err_ratelimited(smmu->dev, "ECMDQ 
timeout\n");
+   local_irq_save(flags);
+   }
+
+   head.cons = llq.cons;
+   head.prod = queue_inc_prod_n(, n + sync);
+
+   old = cmpxchg_relaxed(>q.llq.val, llq.val, head.val);
+   if (old == llq.val)
+   break;
+
+   llq.val = old;
+   } while (1);
+
+   /* 2. Write our commands into the queue */
+   arm_smmu_cmdq_write_entries(cmdq, cmds, llq.prod, n);
+   if (sync) {
+   u64 cmd_sync[CMDQ_ENT_DWORDS];
+
+   prod = queue_inc_prod_n(, n);
+   arm_smmu_cmdq_build_sync_cmd(cmd_sync, smmu, >q, prod);
+   queue_write(Q_ENT(>q, prod), cmd_sync, CMDQ_ENT_DWORDS);
+   }
+
+   /* 3. Ensuring commands are visible first */
+   dma_wmb();
+
+   /* 4. Advance the hardware prod pointer */
+   read_lock(>q.ecmdq_lock);
+   writel_relaxed(head.prod | cmdq->q.ecmdq_prod, cmdq->q.prod_reg);
+   read_unlock(>q.ecmdq_lock);
+
+   /* 5. If we are inserting a CMD_SYNC, we must wait for it to complete */
+   if (sync) {
+   llq.prod = queue_inc_prod_n(, n);
+   ret = arm_smmu_cmdq_poll_until_sync(smmu, );
+   if (ret) {
+   dev_err_ratelimited(smmu->dev,
+   "CMD_SYNC timeout at 0x%08x [hwprod 
0x%08x, hwcons 0x%08x]\n",
+   llq.prod,
+   readl_relaxed(cmdq->q.prod_reg),
+   readl_relaxed(cmdq->q.cons_reg));
+   }
+
+   /*
+* Update cmdq->q.llq.cons, to improve the success rate of
+* queue_has_space() when some new commands are inserted next
+* time.
+*/
+   WRITE_ONCE(cmdq->q.llq.cons, llq.cons);
+   }
+
+   local_irq_restore(flags);
+   return ret;
+}
+
 /*
  * This is the actual insertion function, and provides the following
  * ordering guarantees to callers:
@@ -798,6 +879,9 @@ static int arm_smmu_cmdq_issue_cmdlist(struct 
arm_smmu_device *smmu,
}, head = llq;
int ret = 0;
 
+   if (!cmdq->shared)
+   return arm_smmu_ecmdq_issue_cmdlist(smmu, cmdq, cmds, n, sync);
+
/* 1. Allocate some space in the queue */
local_irq_save(flags);
llq.val = READ_ONCE(cmdq->q.llq.val);
@@ -3001,6 +3085,7 @@ static int arm_smmu_cmdq_init(struct arm_smmu_device 
*smmu)
unsigned int nents = 1 << cmdq->q.llq.max_n_shift;
atomic_long_t *bitmap;
 
+   cmdq->shared = 1;
atomic_set(>owner_prod, 0);
atomic_set(>lock, 0);
 
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 3f3a867a4626fcd..c6efbea3c0a1cda 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/a

[PATCH RFC 4/8] iommu/arm-smmu-v3: Extract reusable function __arm_smmu_cmdq_skip_err()

2021-06-26 Thread Zhen Lei
When SMMU_GERROR.CMDQP_ERR is different to SMMU_GERRORN.CMDQP_ERR, it
indicates that one or more errors have been encountered on a command queue
control page interface. We need to traverse all ECMDQs in that control
page to find all errors. For each ECMDQ error handling, it is much the
same as the CMDQ error handling. This common processing part is extracted
as a new function __arm_smmu_cmdq_skip_err().

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index e4af13b1e7fc015..62b2742daab3257 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -359,7 +359,8 @@ static void arm_smmu_cmdq_build_sync_cmd(u64 *cmd, struct 
arm_smmu_device *smmu,
arm_smmu_cmdq_build_cmd(cmd, );
 }
 
-static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu)
+static void __arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu,
+struct arm_smmu_queue *q)
 {
static const char * const cerror_str[] = {
[CMDQ_ERR_CERROR_NONE_IDX]  = "No error",
@@ -370,7 +371,6 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_device 
*smmu)
 
int i;
u64 cmd[CMDQ_ENT_DWORDS];
-   struct arm_smmu_queue *q = >cmdq.q;
u32 cons = readl_relaxed(q->cons_reg);
u32 idx = FIELD_GET(CMDQ_CONS_ERR, cons);
struct arm_smmu_cmdq_ent cmd_sync = {
@@ -416,6 +416,11 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_device 
*smmu)
queue_write(Q_ENT(q, cons), cmd, q->ent_dwords);
 }
 
+static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu)
+{
+   __arm_smmu_cmdq_skip_err(smmu, >cmdq.q);
+}
+
 /*
  * Command queue locking.
  * This is a form of bastardised rwlock with the following major changes:
-- 
2.26.0.106.g9fadedd


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


[PATCH RFC 5/8] iommu/arm-smmu-v3: Add support for ECMDQ register mode

2021-06-26 Thread Zhen Lei
Ensure that each core exclusively occupies an ECMDQ and all of them are
enabled during initialization. During this initialization process, any
errors will result in a fallback to using normal CMDQ.

When GERROR is triggered by ECMDQ, all ECMDQs need to be traversed: the
ECMDQs with errors will be processed and the ECMDQs without errors will
be skipped directly.

Compared with register SMMU_CMDQ_PROD, register SMMU_ECMDQ_PROD has one
more 'EN' bit and one more 'ERRACK' bit. Therefore, an extra member
'ecmdq_prod' is added to record the values of these two bits. Each time
register SMMU_ECMDQ_PROD is updated, the value of 'ecmdq_prod' is ORed.
After the error indicated by SMMU_GERROR.CMDQP_ERR is fixed, the 'ERRACK'
bit needs to be toggled to resume the corresponding ECMDQ. Therefore, a
rwlock is used to protect the write operation to bit 'ERRACK' during error
handling and the read operation to bit 'ERRACK' during command insertion.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 210 +++-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  36 
 2 files changed, 245 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 62b2742daab3257..d7b590e911a879d 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -337,6 +337,14 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct 
arm_smmu_cmdq_ent *ent)
 
 static struct arm_smmu_cmdq *arm_smmu_get_cmdq(struct arm_smmu_device *smmu)
 {
+   if (smmu->ecmdq_enabled) {
+   struct arm_smmu_ecmdq *ecmdq;
+
+   ecmdq = *this_cpu_ptr(smmu->ecmdq);
+
+   return >cmdq;
+   }
+
return >cmdq;
 }
 
@@ -421,6 +429,38 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_device 
*smmu)
__arm_smmu_cmdq_skip_err(smmu, >cmdq.q);
 }
 
+static void arm_smmu_ecmdq_skip_err(struct arm_smmu_device *smmu)
+{
+   int i;
+   u32 prod, cons;
+   struct arm_smmu_queue *q;
+   struct arm_smmu_ecmdq *ecmdq;
+
+   for (i = 0; i < smmu->nr_ecmdq; i++) {
+   unsigned long flags;
+
+   ecmdq = *per_cpu_ptr(smmu->ecmdq, i);
+   q = >cmdq.q;
+
+   prod = readl_relaxed(q->prod_reg);
+   cons = readl_relaxed(q->cons_reg);
+   if (((prod ^ cons) & ECMDQ_CONS_ERR) == 0)
+   continue;
+
+   __arm_smmu_cmdq_skip_err(smmu, q);
+
+   write_lock_irqsave(>ecmdq_lock, flags);
+   q->ecmdq_prod &= ~ECMDQ_PROD_ERRACK;
+   q->ecmdq_prod |= cons & ECMDQ_CONS_ERR;
+
+   prod = readl_relaxed(q->prod_reg);
+   prod &= ~ECMDQ_PROD_ERRACK;
+   prod |= cons & ECMDQ_CONS_ERR;
+   writel(prod, q->prod_reg);
+   write_unlock_irqrestore(>ecmdq_lock, flags);
+   }
+}
+
 /*
  * Command queue locking.
  * This is a form of bastardised rwlock with the following major changes:
@@ -817,7 +857,13 @@ static int arm_smmu_cmdq_issue_cmdlist(struct 
arm_smmu_device *smmu,
 * d. Advance the hardware prod pointer
 * Control dependency ordering from the entries becoming valid.
 */
-   writel_relaxed(prod, cmdq->q.prod_reg);
+   if (smmu->ecmdq_enabled) {
+   read_lock(>q.ecmdq_lock);
+   writel_relaxed(prod | cmdq->q.ecmdq_prod, 
cmdq->q.prod_reg);
+   read_unlock(>q.ecmdq_lock);
+   } else {
+   writel_relaxed(prod, cmdq->q.prod_reg);
+   }
 
/*
 * e. Tell the next owner we're done
@@ -1675,6 +1721,9 @@ static irqreturn_t arm_smmu_gerror_handler(int irq, void 
*dev)
if (active & GERROR_CMDQ_ERR)
arm_smmu_cmdq_skip_err(smmu);
 
+   if (active & GERROR_CMDQP_ERR)
+   arm_smmu_ecmdq_skip_err(smmu);
+
writel(gerror, smmu->base + ARM_SMMU_GERRORN);
return IRQ_HANDLED;
 }
@@ -2941,6 +2990,20 @@ static int arm_smmu_cmdq_init(struct arm_smmu_device 
*smmu)
return ret;
 }
 
+static int arm_smmu_ecmdq_init(struct arm_smmu_cmdq *cmdq)
+{
+   unsigned int nents = 1 << cmdq->q.llq.max_n_shift;
+
+   atomic_set(>owner_prod, 0);
+   atomic_set(>lock, 0);
+
+   cmdq->valid_map = (atomic_long_t *)bitmap_zalloc(nents, GFP_KERNEL);
+   if (!cmdq->valid_map)
+   return -ENOMEM;
+
+   return 0;
+}
+
 static int arm_smmu_init_queues(struct arm_smmu_device *smmu)
 {
int ret;
@@ -3304,6 +3367,7 @@ static int arm_smmu_device_disable(struct arm_smmu_device 
*smmu)
 
 static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
 {
+

[PATCH RFC 8/8] iommu/arm-smmu-v3: Add support for less than one ECMDQ per core

2021-06-26 Thread Zhen Lei
Due to limited hardware resources, the number of ECMDQs may be less than
the number of cores. If the number of ECMDQs is greater than the number of
numa nodes, ensure that each node has at least one ECMDQ. This is because
ECMDQ queue memory is requested from the NUMA node where it resides, which
may result in better command filling and insertion performance.

The current ECMDQ implementation reuses the command insertion function
arm_smmu_cmdq_issue_cmdlist() of the normal CMDQ. This function already
supports multiple cores concurrent insertion commands.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 101 ++--
 1 file changed, 92 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index a088f2479fc6223..55f651ce42e7a51 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -3636,14 +3636,15 @@ static int arm_smmu_device_reset(struct arm_smmu_device 
*smmu, bool bypass)
 
 static int arm_smmu_ecmdq_layout(struct arm_smmu_device *smmu)
 {
-   int cpu;
-   struct arm_smmu_ecmdq *ecmdq;
+   int cpu, node, nr_remain, nr_nodes = 0;
+   int *nr_ecmdqs;
+   struct arm_smmu_ecmdq *ecmdq, **ecmdqs;
 
-   if (num_possible_cpus() <= smmu->nr_ecmdq) {
-   ecmdq = devm_alloc_percpu(smmu->dev, *ecmdq);
-   if (!ecmdq)
-   return -ENOMEM;
+   ecmdq = devm_alloc_percpu(smmu->dev, *ecmdq);
+   if (!ecmdq)
+   return -ENOMEM;
 
+   if (num_possible_cpus() <= smmu->nr_ecmdq) {
for_each_possible_cpu(cpu)
*per_cpu_ptr(smmu->ecmdq, cpu) = per_cpu_ptr(ecmdq, 
cpu);
 
@@ -3653,7 +3654,79 @@ static int arm_smmu_ecmdq_layout(struct arm_smmu_device 
*smmu)
return 0;
}
 
-   return -ENOSPC;
+   for_each_node(node)
+   if (nr_cpus_node(node))
+   nr_nodes++;
+
+   if (nr_nodes >= smmu->nr_ecmdq) {
+   dev_err(smmu->dev, "%d ECMDQs is less than %d nodes\n", 
smmu->nr_ecmdq, nr_nodes);
+   return -ENOSPC;
+   }
+
+   nr_ecmdqs = kcalloc(MAX_NUMNODES, sizeof(int), GFP_KERNEL);
+   if (!nr_ecmdqs)
+   return -ENOMEM;
+
+   ecmdqs = kcalloc(smmu->nr_ecmdq, sizeof(*ecmdqs), GFP_KERNEL);
+   if (!ecmdqs) {
+   kfree(nr_ecmdqs);
+   return -ENOMEM;
+   }
+
+   /* [1] Ensure that each node has at least one ECMDQ */
+   nr_remain = smmu->nr_ecmdq - nr_nodes;
+   for_each_node(node) {
+   /*
+* Calculate the number of ECMDQs to be allocated to this node.
+* NR_ECMDQS_PER_CPU = nr_remain / num_possible_cpus();
+* When nr_cpus_node(node) is not zero, less than one ECMDQ
+* may be left due to truncation rounding.
+*/
+   nr_ecmdqs[node] = nr_cpus_node(node) * nr_remain / 
num_possible_cpus();
+   nr_remain -= nr_ecmdqs[node];
+   }
+
+   /* Divide the remaining ECMDQs */
+   while (nr_remain) {
+   for_each_node(node) {
+   if (!nr_remain)
+   break;
+
+   if (nr_ecmdqs[node] >= nr_cpus_node(node))
+   continue;
+
+   nr_ecmdqs[node]++;
+   nr_remain--;
+   }
+   }
+
+   for_each_node(node) {
+   int i, round, shared = 0;
+
+   if (!nr_cpus_node(node))
+   continue;
+
+   /* An ECMDQ has been reserved for each node at above [1] */
+   nr_ecmdqs[node]++;
+
+   if (nr_ecmdqs[node] < nr_cpus_node(node))
+   shared = 1;
+
+   i = 0;
+   for_each_cpu(cpu, cpumask_of_node(node)) {
+   round = i % nr_ecmdqs[node];
+   if (i++ < nr_ecmdqs[node]) {
+   ecmdqs[round] = per_cpu_ptr(ecmdq, cpu);
+   ecmdqs[round]->cmdq.shared = shared;
+   }
+   *per_cpu_ptr(smmu->ecmdq, cpu) = ecmdqs[round];
+   }
+   }
+
+   kfree(nr_ecmdqs);
+   kfree(ecmdqs);
+
+   return 0;
 }
 
 static int arm_smmu_ecmdq_probe(struct arm_smmu_device *smmu)
@@ -3718,10 +3791,20 @@ static int arm_smmu_ecmdq_probe(struct arm_smmu_device 
*smmu)
struct arm_smmu_queue *q;
 
ecmdq = *per_cpu_ptr(smmu->ecmdq, cpu);
-   ecmdq->base = cp_base + addr;
-
q = >cmdq.q;
 
+   /*
+* The boot option "maxcpus=" can limit the number of online
+* CPUs. The CPUs that are not sel

[PATCH RFC 3/8] iommu/arm-smmu-v3: Add and use static helper function arm_smmu_get_cmdq()

2021-06-26 Thread Zhen Lei
One SMMU has only one normal CMDQ. Therefore, this CMDQ is used regardless
of the core on which the command is inserted. It can be referenced
directly through "smmu->cmdq". However, one SMMU has multiple ECMDQs, and
the ECMDQ used by the core on which the command insertion is executed may
be different. So the helper function arm_smmu_get_cmdq() is added, which
returns the CMDQ/ECMDQ that the current core should use. Currently, the
code that supports ECMDQ is not added. just simply returns ">cmdq".

Many subfunctions of arm_smmu_cmdq_issue_cmdlist() use ">cmdq" or
">cmdq.q" directly. To support ECMDQ, they need to call the newly
added function arm_smmu_get_cmdq() instead.

Note that normal CMDQ is still required until ECMDQ is available.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 22 -
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index a5361153ca1d6a4..e4af13b1e7fc015 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -335,10 +335,14 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct 
arm_smmu_cmdq_ent *ent)
return 0;
 }
 
+static struct arm_smmu_cmdq *arm_smmu_get_cmdq(struct arm_smmu_device *smmu)
+{
+   return >cmdq;
+}
+
 static void arm_smmu_cmdq_build_sync_cmd(u64 *cmd, struct arm_smmu_device 
*smmu,
-u32 prod)
+struct arm_smmu_queue *q, u32 prod)
 {
-   struct arm_smmu_queue *q = >cmdq.q;
struct arm_smmu_cmdq_ent ent = {
.opcode = CMDQ_OP_CMD_SYNC,
};
@@ -578,7 +582,7 @@ static int arm_smmu_cmdq_poll_until_not_full(struct 
arm_smmu_device *smmu,
 {
unsigned long flags;
struct arm_smmu_queue_poll qp;
-   struct arm_smmu_cmdq *cmdq = >cmdq;
+   struct arm_smmu_cmdq *cmdq = arm_smmu_get_cmdq(smmu);
int ret = 0;
 
/*
@@ -594,7 +598,7 @@ static int arm_smmu_cmdq_poll_until_not_full(struct 
arm_smmu_device *smmu,
 
queue_poll_init(smmu, );
do {
-   llq->val = READ_ONCE(smmu->cmdq.q.llq.val);
+   llq->val = READ_ONCE(cmdq->q.llq.val);
if (!queue_full(llq))
break;
 
@@ -613,7 +617,7 @@ static int __arm_smmu_cmdq_poll_until_msi(struct 
arm_smmu_device *smmu,
 {
int ret = 0;
struct arm_smmu_queue_poll qp;
-   struct arm_smmu_cmdq *cmdq = >cmdq;
+   struct arm_smmu_cmdq *cmdq = arm_smmu_get_cmdq(smmu);
u32 *cmd = (u32 *)(Q_ENT(>q, llq->prod));
 
queue_poll_init(smmu, );
@@ -636,12 +640,12 @@ static int __arm_smmu_cmdq_poll_until_consumed(struct 
arm_smmu_device *smmu,
   struct arm_smmu_ll_queue *llq)
 {
struct arm_smmu_queue_poll qp;
-   struct arm_smmu_cmdq *cmdq = >cmdq;
+   struct arm_smmu_cmdq *cmdq = arm_smmu_get_cmdq(smmu);
u32 prod = llq->prod;
int ret = 0;
 
queue_poll_init(smmu, );
-   llq->val = READ_ONCE(smmu->cmdq.q.llq.val);
+   llq->val = READ_ONCE(cmdq->q.llq.val);
do {
if (queue_consumed(llq, prod))
break;
@@ -731,7 +735,7 @@ static int arm_smmu_cmdq_issue_cmdlist(struct 
arm_smmu_device *smmu,
u32 prod;
unsigned long flags;
bool owner;
-   struct arm_smmu_cmdq *cmdq = >cmdq;
+   struct arm_smmu_cmdq *cmdq = arm_smmu_get_cmdq(smmu);
struct arm_smmu_ll_queue llq = {
.max_n_shift = cmdq->q.llq.max_n_shift,
}, head = llq;
@@ -771,7 +775,7 @@ static int arm_smmu_cmdq_issue_cmdlist(struct 
arm_smmu_device *smmu,
arm_smmu_cmdq_write_entries(cmdq, cmds, llq.prod, n);
if (sync) {
prod = queue_inc_prod_n(, n);
-   arm_smmu_cmdq_build_sync_cmd(cmd_sync, smmu, prod);
+   arm_smmu_cmdq_build_sync_cmd(cmd_sync, smmu, >q, prod);
queue_write(Q_ENT(>q, prod), cmd_sync, CMDQ_ENT_DWORDS);
 
/*
-- 
2.26.0.106.g9fadedd


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


[PATCH RFC 6/8] iommu/arm-smmu-v3: Ensure that a set of associated commands are inserted in the same ECMDQ

2021-06-26 Thread Zhen Lei
The SYNC command only ensures that the command that precedes it in the
same ECMDQ must be executed, but cannot synchronize the commands in other
ECMDQs. If an unmap involves multiple commands, some commands are executed
on one core, and the other commands are executed on another core. In this
case, after the SYNC execution is complete, the execution of all preceded
commands can not be ensured.

Prevent the process that performs a set of associated commands insertion
from being migrated to other cores ensures that all commands are inserted
into the same ECMDQ.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 40 +
 1 file changed, 33 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index d7b590e911a879d..d5205030710bd1a 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -233,6 +233,18 @@ static int queue_remove_raw(struct arm_smmu_queue *q, u64 
*ent)
return 0;
 }
 
+static void arm_smmu_preempt_disable(struct arm_smmu_device *smmu)
+{
+   if (smmu->ecmdq_enabled)
+   preempt_disable();
+}
+
+static void arm_smmu_preempt_enable(struct arm_smmu_device *smmu)
+{
+   if (smmu->ecmdq_enabled)
+   preempt_enable();
+}
+
 /* High-level queue accessors */
 static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent)
 {
@@ -1016,6 +1028,7 @@ static void arm_smmu_sync_cd(struct arm_smmu_domain 
*smmu_domain,
},
};
 
+   arm_smmu_preempt_disable(smmu);
spin_lock_irqsave(_domain->devices_lock, flags);
list_for_each_entry(master, _domain->devices, domain_head) {
for (i = 0; i < master->num_streams; i++) {
@@ -1026,6 +1039,7 @@ static void arm_smmu_sync_cd(struct arm_smmu_domain 
*smmu_domain,
spin_unlock_irqrestore(_domain->devices_lock, flags);
 
arm_smmu_cmdq_batch_submit(smmu, );
+   arm_smmu_preempt_enable(smmu);
 }
 
 static int arm_smmu_alloc_cd_leaf_table(struct arm_smmu_device *smmu,
@@ -1814,30 +1828,36 @@ arm_smmu_atc_inv_to_cmd(int ssid, unsigned long iova, 
size_t size,
 
 static int arm_smmu_atc_inv_master(struct arm_smmu_master *master)
 {
-   int i;
+   int i, ret;
struct arm_smmu_cmdq_ent cmd;
struct arm_smmu_cmdq_batch cmds = {};
+   struct arm_smmu_device *smmu = master->smmu;
 
arm_smmu_atc_inv_to_cmd(0, 0, 0, );
 
+   arm_smmu_preempt_disable(smmu);
for (i = 0; i < master->num_streams; i++) {
cmd.atc.sid = master->streams[i].id;
-   arm_smmu_cmdq_batch_add(master->smmu, , );
+   arm_smmu_cmdq_batch_add(smmu, , );
}
 
-   return arm_smmu_cmdq_batch_submit(master->smmu, );
+   ret = arm_smmu_cmdq_batch_submit(smmu, );
+   arm_smmu_preempt_enable(smmu);
+
+   return ret;
 }
 
 int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid,
unsigned long iova, size_t size)
 {
-   int i;
+   int i, ret;
unsigned long flags;
struct arm_smmu_cmdq_ent cmd;
struct arm_smmu_master *master;
struct arm_smmu_cmdq_batch cmds = {};
+   struct arm_smmu_device *smmu = smmu_domain->smmu;
 
-   if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_ATS))
+   if (!(smmu->features & ARM_SMMU_FEAT_ATS))
return 0;
 
/*
@@ -1859,6 +1879,7 @@ int arm_smmu_atc_inv_domain(struct arm_smmu_domain 
*smmu_domain, int ssid,
 
arm_smmu_atc_inv_to_cmd(ssid, iova, size, );
 
+   arm_smmu_preempt_disable(smmu);
spin_lock_irqsave(_domain->devices_lock, flags);
list_for_each_entry(master, _domain->devices, domain_head) {
if (!master->ats_enabled)
@@ -1866,12 +1887,15 @@ int arm_smmu_atc_inv_domain(struct arm_smmu_domain 
*smmu_domain, int ssid,
 
for (i = 0; i < master->num_streams; i++) {
cmd.atc.sid = master->streams[i].id;
-   arm_smmu_cmdq_batch_add(smmu_domain->smmu, , );
+   arm_smmu_cmdq_batch_add(smmu, , );
}
}
spin_unlock_irqrestore(_domain->devices_lock, flags);
 
-   return arm_smmu_cmdq_batch_submit(smmu_domain->smmu, );
+   ret = arm_smmu_cmdq_batch_submit(smmu, );
+   arm_smmu_preempt_enable(smmu);
+
+   return ret;
 }
 
 /* IO_PGTABLE API */
@@ -1924,6 +1948,7 @@ static void __arm_smmu_tlb_inv_range(struct 
arm_smmu_cmdq_ent *cmd,
num_pages = size >> tg;
}
 
+   arm_smmu_preempt_disable(smmu);
while (iova < end) {
if (smmu->features & ARM_SMMU_FEAT_RANGE_INV) {
/*
@@ -1955,6 +1980,7 @@ static void __arm_smmu_tlb_inv_range(struct 
arm_sm

[PATCH RFC 1/8] iommu/arm-smmu-v3: Use command queue batching helpers to improve performance

2021-06-26 Thread Zhen Lei
The obvious key to the performance optimization of commit 587e6c10a7ce
("iommu/arm-smmu-v3: Reduce contention during command-queue insertion") is
to allow multiple cores to insert commands in parallel after a brief mutex
contention.

Obviously, inserting as many commands at a time as possible can reduce the
number of times the mutex contention participates, thereby improving the
overall performance. At least it reduces the number of calls to function
arm_smmu_cmdq_issue_cmdlist().

Therefore, use command queue batching helpers to insert multiple commands
at a time.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index dd20b01771c4bd2..2433d3c29b49ff2 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1746,15 +1746,16 @@ static int arm_smmu_atc_inv_master(struct 
arm_smmu_master *master)
 {
int i;
struct arm_smmu_cmdq_ent cmd;
+   struct arm_smmu_cmdq_batch cmds = {};
 
arm_smmu_atc_inv_to_cmd(0, 0, 0, );
 
for (i = 0; i < master->num_streams; i++) {
cmd.atc.sid = master->streams[i].id;
-   arm_smmu_cmdq_issue_cmd(master->smmu, );
+   arm_smmu_cmdq_batch_add(master->smmu, , );
}
 
-   return arm_smmu_cmdq_issue_sync(master->smmu);
+   return arm_smmu_cmdq_batch_submit(master->smmu, );
 }
 
 int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid,
-- 
2.26.0.106.g9fadedd


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


[PATCH RFC 0/8] iommu/arm-smmu-v3: add support for ECMDQ register mode

2021-06-26 Thread Zhen Lei
SMMU v3.3 added a new feature, which is Enhanced Command queue interface
for reducing contention when submitting Commands to the SMMU, in this
patch set, ECMDQ is the abbreviation of Enhanced Command Queue.

When the hardware supports ECMDQ and each core can exclusively use one ECMDQ,
each core does not need to compete with other cores when using its own ECMDQ.
This means that each core can insert commands in parallel. If each ECMDQ can
execute commands in parallel, the overall performance may be better. However,
our hardware currently does not support multiple ECMDQ execute commands in
parallel.

In order to reuse existing code, I originally still call 
arm_smmu_cmdq_issue_cmdlist()
to insert commands. Even so, however, there was a performance improvement of 
nearly 12%
in strict mode.

The test environment is the EMU, which simulates the connection of the 200 
Gbit/s NIC.
Number of queues:passthrough   lazy   strict(ECMDQ)  strict(CMDQ)
  6  188180   162   145--> 
11.7% improvement
  8  188188   184   183--> 
0.55% improvement

In recent days, I implemented a new function without competition with other
cores to replace arm_smmu_cmdq_issue_cmdlist() when a core can have an ECMDQ.
I'm guessing it might get better performance results. Because the EMU is too
slow, it will take a while before the relevant data is available.


Zhen Lei (8):
  iommu/arm-smmu-v3: Use command queue batching helpers to improve
performance
  iommu/arm-smmu-v3: Add and use static helper function
arm_smmu_cmdq_issue_cmd_with_sync()
  iommu/arm-smmu-v3: Add and use static helper function
arm_smmu_get_cmdq()
  iommu/arm-smmu-v3: Extract reusable function
__arm_smmu_cmdq_skip_err()
  iommu/arm-smmu-v3: Add support for ECMDQ register mode
  iommu/arm-smmu-v3: Ensure that a set of associated commands are
inserted in the same ECMDQ
  iommu/arm-smmu-v3: Add arm_smmu_ecmdq_issue_cmdlist() for non-shared
ECMDQ
  iommu/arm-smmu-v3: Add support for less than one ECMDQ per core

 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 483 ++--
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  37 ++
 2 files changed, 489 insertions(+), 31 deletions(-)

-- 
2.26.0.106.g9fadedd


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


[PATCH 1/1] iommu/arm-smmu-v3: remove unnecessary oom message

2021-06-09 Thread Zhen Lei
Fixes scripts/checkpatch.pl warning:
WARNING: Possible unnecessary 'out of memory' message

Remove it can help us save a bit of memory.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 2ddc3cd5a7d1..fd7c55b44881 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2787,10 +2787,8 @@ static int arm_smmu_init_l1_strtab(struct 
arm_smmu_device *smmu)
void *strtab = smmu->strtab_cfg.strtab;
 
cfg->l1_desc = devm_kzalloc(smmu->dev, size, GFP_KERNEL);
-   if (!cfg->l1_desc) {
-   dev_err(smmu->dev, "failed to allocate l1 stream table desc\n");
+   if (!cfg->l1_desc)
return -ENOMEM;
-   }
 
for (i = 0; i < cfg->num_l1_ents; ++i) {
arm_smmu_write_strtab_l1_desc(strtab, >l1_desc[i]);
@@ -3581,10 +3579,8 @@ static int arm_smmu_device_probe(struct platform_device 
*pdev)
bool bypass;
 
smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
-   if (!smmu) {
-   dev_err(dev, "failed to allocate arm_smmu_device\n");
+   if (!smmu)
return -ENOMEM;
-   }
smmu->dev = dev;
 
if (dev->of_node) {
-- 
2.25.1


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


[PATCH 1/1] iommu/arm-smmu: remove unnecessary oom message

2021-06-09 Thread Zhen Lei
Fixes scripts/checkpatch.pl warning:
WARNING: Possible unnecessary 'out of memory' message

Remove it can help us save a bit of memory.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu/arm-smmu.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c 
b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index dba15f312cbd..db7b1e101bc5 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -2051,10 +2051,8 @@ static int arm_smmu_device_probe(struct platform_device 
*pdev)
irqreturn_t (*global_fault)(int irq, void *dev);
 
smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
-   if (!smmu) {
-   dev_err(dev, "failed to allocate arm_smmu_device\n");
+   if (!smmu)
return -ENOMEM;
-   }
smmu->dev = dev;
 
if (dev->of_node)
@@ -2095,10 +2093,8 @@ static int arm_smmu_device_probe(struct platform_device 
*pdev)
 
smmu->irqs = devm_kcalloc(dev, num_irqs, sizeof(*smmu->irqs),
  GFP_KERNEL);
-   if (!smmu->irqs) {
-   dev_err(dev, "failed to allocate %d irqs\n", num_irqs);
+   if (!smmu->irqs)
return -ENOMEM;
-   }
 
for (i = 0; i < num_irqs; ++i) {
int irq = platform_get_irq(pdev, i);
-- 
2.25.1


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


[PATCH 1/1] iommu/vt-d: remove unnecessary oom message

2021-06-09 Thread Zhen Lei
Fixes scripts/checkpatch.pl warning:
WARNING: Possible unnecessary 'out of memory' message

Remove it can help us save a bit of memory.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/intel/dmar.c  | 2 --
 drivers/iommu/intel/iommu.c | 6 +-
 2 files changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index 84057cb9596c..ede7525b4ec3 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -148,8 +148,6 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned 
long event)
} else {
info = kzalloc(size, GFP_KERNEL);
if (!info) {
-   pr_warn("Out of memory when allocating notify_info "
-   "for %s.\n", pci_name(dev));
if (dmar_dev_scope_status == 0)
dmar_dev_scope_status = -ENOMEM;
return NULL;
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index be35284a2016..432f4019d1af 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -1780,11 +1780,8 @@ static int iommu_init_domains(struct intel_iommu *iommu)
spin_lock_init(>lock);
 
iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
-   if (!iommu->domain_ids) {
-   pr_err("%s: Allocating domain id array failed\n",
-  iommu->name);
+   if (!iommu->domain_ids)
return -ENOMEM;
-   }
 
size = (ALIGN(ndomains, 256) >> 8) * sizeof(struct dmar_domain **);
iommu->domains = kzalloc(size, GFP_KERNEL);
@@ -3220,7 +3217,6 @@ static int __init init_dmars(void)
g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
GFP_KERNEL);
if (!g_iommus) {
-   pr_err("Allocating global iommu array failed\n");
ret = -ENOMEM;
goto error;
}
-- 
2.25.1


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


[PATCH 1/1] iommu/ipmmu-vmsa: remove unnecessary oom message

2021-06-09 Thread Zhen Lei
Fixes scripts/checkpatch.pl warning:
WARNING: Possible unnecessary 'out of memory' message

Remove it can help us save a bit of memory.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/ipmmu-vmsa.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index 51ea6f00db2f..d31e3890f5e2 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -992,10 +992,8 @@ static int ipmmu_probe(struct platform_device *pdev)
int ret;
 
mmu = devm_kzalloc(>dev, sizeof(*mmu), GFP_KERNEL);
-   if (!mmu) {
-   dev_err(>dev, "cannot allocate device data\n");
+   if (!mmu)
return -ENOMEM;
-   }
 
mmu->dev = >dev;
spin_lock_init(>lock);
-- 
2.25.1


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


[PATCH v3 0/2] iommu: Fix spelling mistakes

2021-06-09 Thread Zhen Lei
v2 --> v3:
1) Add some new fixes for the latest linux-next:
   drivers/iommu/fsl_pamu_domain.c:366: Traverese ==> Traverse
   drivers/iommu/mtk_iommu.c:977: Uppon ==> Upon
   drivers/iommu/intel/svm.c:488: shuld ==> should
   drivers/iommu/intel/svm.c:920: requeset ==> request
   drivers/iommu/intel/dmar.c:2131: Specifiction ==> Specification
2) Add a new fix "Additionally, The ==> Additionally, the", discovered by Will 
Deacon
3) Add some new fixes for the header files of iommu/iova
   The header files to be checked are as follows:
   include/linux/iommu*.h
   include/linux/iova.h
   include/uapi/linux/iommu.h
4) Changes to files "iova.h" and "iova.c" are grouped into a new patch.


v1 --> v2:
1. Merge into one patch
2. Add a new fix "appropriatley --> appropriately" in iommu.c, discovered by 
John Garry

Zhen Lei (2):
  iommu/iova: Fix spelling mistakes
  iommu: Fix spelling mistakes

 drivers/iommu/amd/amd_iommu_types.h   |  2 +-
 drivers/iommu/amd/init.c  |  2 +-
 drivers/iommu/amd/iommu.c |  2 +-
 drivers/iommu/arm/arm-smmu/arm-smmu.c |  2 +-
 drivers/iommu/fsl_pamu.c  |  2 +-
 drivers/iommu/fsl_pamu_domain.c   |  2 +-
 drivers/iommu/intel/dmar.c|  8 
 drivers/iommu/intel/iommu.c   |  2 +-
 drivers/iommu/intel/irq_remapping.c   |  2 +-
 drivers/iommu/intel/svm.c |  4 ++--
 drivers/iommu/iommu.c |  6 +++---
 drivers/iommu/iova.c  |  2 +-
 drivers/iommu/mtk_iommu.c |  4 ++--
 drivers/iommu/omap-iommu.c|  2 +-
 drivers/iommu/sun50i-iommu.c  |  2 +-
 include/linux/iova.h  | 10 +-
 16 files changed, 27 insertions(+), 27 deletions(-)

-- 
2.25.1


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


[PATCH v3 1/2] iommu/iova: Fix spelling mistakes

2021-06-09 Thread Zhen Lei
Fix some spelling mistakes in comments found by "codespell":
detroyed ==> destroyed
defered ==> deferred
entrie ==> entry
alloced ==> allocated
regularily ==> regularly

Signed-off-by: Zhen Lei 
---
 drivers/iommu/iova.c |  2 +-
 include/linux/iova.h | 10 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index b6cf5f16123b..cce4571548c4 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -594,7 +594,7 @@ 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
+* This code runs when the iova_domain is being destroyed, so don't
 * bother to free iovas, just call the entry_dtor on all remaining
 * entries.
 */
diff --git a/include/linux/iova.h b/include/linux/iova.h
index 71d8a2de6635..16f671b04a37 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -49,12 +49,12 @@ typedef void (* iova_entry_dtor)(unsigned long data);
 /* Timeout (in ms) after which entries are flushed from the Flush-Queue */
 #define IOVA_FQ_TIMEOUT10
 
-/* Flush Queue entry for defered flushing */
+/* Flush Queue entry for deferred flushing */
 struct iova_fq_entry {
unsigned long iova_pfn;
unsigned long pages;
unsigned long data;
-   u64 counter; /* Flush counter when this entrie was added */
+   u64 counter; /* Flush counter when this entry was added */
 };
 
 /* Per-CPU Flush Queue structure */
@@ -68,8 +68,8 @@ struct iova_fq {
 struct iova_domain {
spinlock_t  iova_rbtree_lock; /* Lock to protect update of rbtree */
struct rb_root  rbroot; /* iova domain rbtree root */
-   struct rb_node  *cached_node;   /* Save last alloced node */
-   struct rb_node  *cached32_node; /* Save last 32-bit alloced node */
+   struct rb_node  *cached_node;   /* Save last allocated node */
+   struct rb_node  *cached32_node; /* Save last 32-bit allocated node */
unsigned long   granule;/* pfn granularity for this domain */
unsigned long   start_pfn;  /* Lower limit for this domain */
unsigned long   dma_32bit_pfn;
@@ -91,7 +91,7 @@ struct iova_domain {
iova_entry_dtor entry_dtor; /* IOMMU driver specific destructor for
   iova entry */
 
-   struct timer_list fq_timer; /* Timer to regularily empty the
+   struct timer_list fq_timer; /* Timer to regularly empty the
   flush-queues */
atomic_t fq_timer_on;   /* 1 when timer is active, 0
   when not */
-- 
2.25.1


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


[PATCH v3 2/2] iommu: Fix spelling mistakes

2021-06-09 Thread Zhen Lei
Fix some spelling mistakes in comments found by "codespell":
alignement ==> alignment
implemtation ==> implementation
assignement ==> assignment
initally ==> initially
Returs ==> Returns
Traverese ==> Traverse
guarentees ==> guarantees
resgister ==> register
insufficent ==> insufficient
Specifiction ==> Specification
creats ==> creates
tabke ==> table
shuld ==> should
requeset ==> request
funcions ==> functions
distiguish ==> distinguish
phyiscal ==> physical
Uppon ==> Upon
consits ==> consists

And two were discovered manually by John Garry and Will Deacon:
appropriatley ==> appropriately
Additionally, The ==> Additionally, the

Signed-off-by: Zhen Lei 
---
 drivers/iommu/amd/amd_iommu_types.h   | 2 +-
 drivers/iommu/amd/init.c  | 2 +-
 drivers/iommu/amd/iommu.c | 2 +-
 drivers/iommu/arm/arm-smmu/arm-smmu.c | 2 +-
 drivers/iommu/fsl_pamu.c  | 2 +-
 drivers/iommu/fsl_pamu_domain.c   | 2 +-
 drivers/iommu/intel/dmar.c| 8 
 drivers/iommu/intel/iommu.c   | 2 +-
 drivers/iommu/intel/irq_remapping.c   | 2 +-
 drivers/iommu/intel/svm.c | 4 ++--
 drivers/iommu/iommu.c | 6 +++---
 drivers/iommu/mtk_iommu.c | 4 ++--
 drivers/iommu/omap-iommu.c| 2 +-
 drivers/iommu/sun50i-iommu.c  | 2 +-
 14 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/iommu/amd/amd_iommu_types.h 
b/drivers/iommu/amd/amd_iommu_types.h
index 94c1a7a9876d..67a6c2fb4de9 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -446,7 +446,7 @@ extern struct irq_remap_table **irq_lookup_table;
 /* Interrupt remapping feature used? */
 extern bool amd_iommu_irq_remap;
 
-/* kmem_cache to get tables with 128 byte alignement */
+/* kmem_cache to get tables with 128 byte alignment */
 extern struct kmem_cache *amd_iommu_irq_cache;
 
 /*
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 4e4fb0f4e412..52d450962288 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -2040,7 +2040,7 @@ static int intcapxt_irqdomain_activate(struct irq_domain 
*domain,
xt.destid_24_31 = cfg->dest_apicid >> 24;
 
/**
-* Current IOMMU implemtation uses the same IRQ for all
+* Current IOMMU implementation uses the same IRQ for all
 * 3 IOMMU interrupts.
 */
writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET);
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index b1fbf2c83df5..1b635d4c2142 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -1809,7 +1809,7 @@ int __init amd_iommu_init_api(void)
  * The following functions belong to the exported interface of AMD IOMMU
  *
  * This interface allows access to lower level functions of the IOMMU
- * like protection domain handling and assignement of devices to domains
+ * like protection domain handling and assignment of devices to domains
  * which is not possible with the dma_ops interface.
  *
  */
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c 
b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index dba15f312cbd..79db6e8c5e31 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -1360,7 +1360,7 @@ static struct iommu_device *arm_smmu_probe_device(struct 
device *dev)
ret = arm_smmu_register_legacy_master(dev, );
 
/*
-* If dev->iommu_fwspec is initally NULL, 
arm_smmu_register_legacy_master()
+* If dev->iommu_fwspec is initially NULL, 
arm_smmu_register_legacy_master()
 * will allocate/initialise a new one. Thus we need to update 
fwspec for
 * later use.
 */
diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index fc38b1fba7cf..53aff2766367 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -246,7 +246,7 @@ void get_ome_index(u32 *omi_index, struct device *dev)
  * @stash_dest_hint: L1, L2 or L3
  * @vcpu: vpcu target for a particular cache type.
  *
- * Returs stash on success or ~(u32)0 on failure.
+ * Returns stash on success or ~(u32)0 on failure.
  *
  */
 u32 get_stash_id(u32 stash_dest_hint, u32 vcpu)
diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c
index a47f47307109..2da312645279 100644
--- a/drivers/iommu/fsl_pamu_domain.c
+++ b/drivers/iommu/fsl_pamu_domain.c
@@ -363,7 +363,7 @@ static struct iommu_group 
*get_shared_pci_device_group(struct pci_dev *pdev)
struct pci_bus *bus = pdev->bus;
 
/*
-* Traverese the pci bus device list to get
+* Traverse the pci bus device list to get
 * the shared iommu group.
 */
while (bus) {
diff --git a/drivers/iommu/intel/d

[PATCH 1/1] dma-mapping: remove trailing spaces and tabs

2021-06-08 Thread Zhen Lei
Run the following command to find and remove the trailing spaces and tabs:

find kernel/dma/ -type f | xargs sed -r -i 's/[ \t]+$//'

Signed-off-by: Zhen Lei 
---
 kernel/dma/coherent.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/dma/coherent.c b/kernel/dma/coherent.c
index 5b5b6c7ec7f2..794e76b03b34 100644
--- a/kernel/dma/coherent.c
+++ b/kernel/dma/coherent.c
@@ -111,7 +111,7 @@ static int dma_assign_coherent_memory(struct device *dev,
  * Declare a region of memory to be handed out by dma_alloc_coherent() when it
  * is asked for coherent memory for this device.  This shall only be used
  * from platform code, usually based on the device tree description.
- * 
+ *
  * phys_addr is the CPU physical address to which the memory is currently
  * assigned (this will be ioremapped so the CPU can access the region).
  *
-- 
2.25.1


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


[PATCH 1/1] iommu/arm-smmu-v3: Decrease the queue size of evtq and priq

2021-05-31 Thread Zhen Lei
Commit d25f6ead162e ("iommu/arm-smmu-v3: Increase maximum size of queues")
expands the cmdq queue size to improve the success rate of concurrent
command queue space allocation by multiple cores. However, this extension
does not apply to evtq and priq, because for both of them, the SMMU driver
is the consumer. Instead, memory resources are wasted. Therefore, the
queue size of evtq and priq is restored to the original setting, one page.

Fixes: d25f6ead162e ("iommu/arm-smmu-v3: Increase maximum size of queues")
Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 46e8c49214a872e..8e5094fa2863df5 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -184,6 +184,7 @@
 #else
 #define Q_MAX_SZ_SHIFT (PAGE_SHIFT + MAX_ORDER - 1)
 #endif
+#define Q_MIN_SZ_SHIFT (PAGE_SHIFT)
 
 /*
  * Stream table.
@@ -366,14 +367,14 @@
 /* Event queue */
 #define EVTQ_ENT_SZ_SHIFT  5
 #define EVTQ_ENT_DWORDS((1 << EVTQ_ENT_SZ_SHIFT) >> 3)
-#define EVTQ_MAX_SZ_SHIFT  (Q_MAX_SZ_SHIFT - EVTQ_ENT_SZ_SHIFT)
+#define EVTQ_MAX_SZ_SHIFT  (Q_MIN_SZ_SHIFT - EVTQ_ENT_SZ_SHIFT)
 
 #define EVTQ_0_ID  GENMASK_ULL(7, 0)
 
 /* PRI queue */
 #define PRIQ_ENT_SZ_SHIFT  4
 #define PRIQ_ENT_DWORDS((1 << PRIQ_ENT_SZ_SHIFT) >> 3)
-#define PRIQ_MAX_SZ_SHIFT  (Q_MAX_SZ_SHIFT - PRIQ_ENT_SZ_SHIFT)
+#define PRIQ_MAX_SZ_SHIFT  (Q_MIN_SZ_SHIFT - PRIQ_ENT_SZ_SHIFT)
 
 #define PRIQ_0_SID GENMASK_ULL(31, 0)
 #define PRIQ_0_SSIDGENMASK_ULL(51, 32)
-- 
2.26.0.106.g9fadedd


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


[PATCH 1/1] iommu: Delete a duplicate check in iommu_change_dev_def_domain()

2021-05-13 Thread Zhen Lei
Function iommu_group_store_type() is the only caller of the static
function iommu_change_dev_def_domain() and has performed
"if (WARN_ON(!group))" detection before calling it. So the one here is
redundant.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/iommu.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 971068da67cb91d..8cdf6a1c4bfd773 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -3059,9 +3059,6 @@ static int iommu_change_dev_def_domain(struct iommu_group 
*group,
int ret, dev_def_dom;
struct device *dev;
 
-   if (!group)
-   return -EINVAL;
-
mutex_lock(>mutex);
 
if (group->default_domain != group->domain) {
-- 
2.26.0.106.g9fadedd


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


[PATCH v2 0/1] iommu: Clear a lot of spelling mistakes

2021-05-09 Thread Zhen Lei
v1 --> v2:
1. Merge into one patch
2. Add a new fix "appropriatley --> appropriately" in iommu.c, discovered by 
John Garry

Zhen Lei (1):
  iommu: Clear a lot of spelling mistakes

 drivers/iommu/amd/amd_iommu_types.h   | 2 +-
 drivers/iommu/amd/init.c  | 2 +-
 drivers/iommu/amd/iommu.c | 2 +-
 drivers/iommu/arm/arm-smmu/arm-smmu.c | 2 +-
 drivers/iommu/fsl_pamu.c  | 2 +-
 drivers/iommu/intel/dmar.c| 6 +++---
 drivers/iommu/intel/iommu.c   | 2 +-
 drivers/iommu/intel/irq_remapping.c   | 2 +-
 drivers/iommu/iommu.c | 6 +++---
 drivers/iommu/iova.c  | 2 +-
 drivers/iommu/mtk_iommu.c | 2 +-
 drivers/iommu/omap-iommu.c| 2 +-
 drivers/iommu/sun50i-iommu.c  | 2 +-
 13 files changed, 17 insertions(+), 17 deletions(-)

-- 
2.26.0.106.g9fadedd


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


[PATCH v2 1/1] iommu: Clear a lot of spelling mistakes

2021-05-09 Thread Zhen Lei
All spelling mistakes are in the comments, no functional change.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/amd/amd_iommu_types.h   | 2 +-
 drivers/iommu/amd/init.c  | 2 +-
 drivers/iommu/amd/iommu.c | 2 +-
 drivers/iommu/arm/arm-smmu/arm-smmu.c | 2 +-
 drivers/iommu/fsl_pamu.c  | 2 +-
 drivers/iommu/intel/dmar.c| 6 +++---
 drivers/iommu/intel/iommu.c   | 2 +-
 drivers/iommu/intel/irq_remapping.c   | 2 +-
 drivers/iommu/iommu.c | 6 +++---
 drivers/iommu/iova.c  | 2 +-
 drivers/iommu/mtk_iommu.c | 2 +-
 drivers/iommu/omap-iommu.c| 2 +-
 drivers/iommu/sun50i-iommu.c  | 2 +-
 13 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/drivers/iommu/amd/amd_iommu_types.h 
b/drivers/iommu/amd/amd_iommu_types.h
index 94c1a7a9876d554..67a6c2fb4de9e2a 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -446,7 +446,7 @@ extern struct irq_remap_table **irq_lookup_table;
 /* Interrupt remapping feature used? */
 extern bool amd_iommu_irq_remap;
 
-/* kmem_cache to get tables with 128 byte alignement */
+/* kmem_cache to get tables with 128 byte alignment */
 extern struct kmem_cache *amd_iommu_irq_cache;
 
 /*
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index d006724f4dc2122..d749837dcecc875 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -2040,7 +2040,7 @@ static int intcapxt_irqdomain_activate(struct irq_domain 
*domain,
xt.destid_24_31 = cfg->dest_apicid >> 24;
 
/**
-* Current IOMMU implemtation uses the same IRQ for all
+* Current IOMMU implementation uses the same IRQ for all
 * 3 IOMMU interrupts.
 */
writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET);
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 80e8e1916dd17c9..fa2c98857f3a7d0 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -1812,7 +1812,7 @@ int __init amd_iommu_init_dma_ops(void)
  * The following functions belong to the exported interface of AMD IOMMU
  *
  * This interface allows access to lower level functions of the IOMMU
- * like protection domain handling and assignement of devices to domains
+ * like protection domain handling and assignment of devices to domains
  * which is not possible with the dma_ops interface.
  *
  */
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c 
b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index 6f72c4d208cad84..a56e0d91b5a70a2 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -1361,7 +1361,7 @@ static struct iommu_device *arm_smmu_probe_device(struct 
device *dev)
ret = arm_smmu_register_legacy_master(dev, );
 
/*
-* If dev->iommu_fwspec is initally NULL, 
arm_smmu_register_legacy_master()
+* If dev->iommu_fwspec is initially NULL, 
arm_smmu_register_legacy_master()
 * will allocate/initialise a new one. Thus we need to update 
fwspec for
 * later use.
 */
diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index fc38b1fba7cff0a..53aff27663673a0 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -246,7 +246,7 @@ void get_ome_index(u32 *omi_index, struct device *dev)
  * @stash_dest_hint: L1, L2 or L3
  * @vcpu: vpcu target for a particular cache type.
  *
- * Returs stash on success or ~(u32)0 on failure.
+ * Returns stash on success or ~(u32)0 on failure.
  *
  */
 u32 get_stash_id(u32 stash_dest_hint, u32 vcpu)
diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index 1757ac1e1623e9a..2a2d176b36ec0f2 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -45,7 +45,7 @@ struct dmar_res_callback {
 
 /*
  * Assumptions:
- * 1) The hotplug framework guarentees that DMAR unit will be hot-added
+ * 1) The hotplug framework guarantees that DMAR unit will be hot-added
  *before IO devices managed by that unit.
  * 2) The hotplug framework guarantees that DMAR unit will be hot-removed
  *after IO devices managed by that unit.
@@ -960,10 +960,10 @@ static void unmap_iommu(struct intel_iommu *iommu)
 /**
  * map_iommu: map the iommu's registers
  * @iommu: the iommu to map
- * @phys_addr: the physical address of the base resgister
+ * @phys_addr: the physical address of the base register
  *
  * Memory map the iommu's registers.  Start w/ a single page, and
- * possibly expand if that turns out to be insufficent.
+ * possibly expand if that turns out to be insufficient.
  */
 static int map_iommu(struct intel_iommu *iommu, u64 phys_addr)
 {
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 708f430af1c4403..ba5b0137b4b1fb4 100644
--- a/drivers/i

[PATCH 7/8] iommu/arm-smmu: Fix spelling mistake "initally" -> "initially"

2021-03-26 Thread Zhen Lei
There is a spelling mistake in a comment, fix it.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu/arm-smmu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c 
b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index d8c6bfde6a61587..8e4e8fea106b612 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -1358,7 +1358,7 @@ static struct iommu_device *arm_smmu_probe_device(struct 
device *dev)
ret = arm_smmu_register_legacy_master(dev, );
 
/*
-* If dev->iommu_fwspec is initally NULL, 
arm_smmu_register_legacy_master()
+* If dev->iommu_fwspec is initially NULL, 
arm_smmu_register_legacy_master()
 * will allocate/initialise a new one. Thus we need to update 
fwspec for
 * later use.
 */
-- 
1.8.3


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


[PATCH 8/8] iommu/vt-d: fix a couple of spelling mistakes

2021-03-26 Thread Zhen Lei
There are several spelling mistakes, as follows:
guarentees ==> guarantees
resgister ==> register
insufficent ==> insufficient
creats ==> creates
tabke ==> take

Signed-off-by: Zhen Lei 
---
 drivers/iommu/intel/dmar.c  | 6 +++---
 drivers/iommu/intel/iommu.c | 2 +-
 drivers/iommu/intel/irq_remapping.c | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index d5c51b5c20aff4b..bb6f0880f6f4db0 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -45,7 +45,7 @@ struct dmar_res_callback {
 
 /*
  * Assumptions:
- * 1) The hotplug framework guarentees that DMAR unit will be hot-added
+ * 1) The hotplug framework guarantees that DMAR unit will be hot-added
  *before IO devices managed by that unit.
  * 2) The hotplug framework guarantees that DMAR unit will be hot-removed
  *after IO devices managed by that unit.
@@ -960,10 +960,10 @@ static void unmap_iommu(struct intel_iommu *iommu)
 /**
  * map_iommu: map the iommu's registers
  * @iommu: the iommu to map
- * @phys_addr: the physical address of the base resgister
+ * @phys_addr: the physical address of the base register
  *
  * Memory map the iommu's registers.  Start w/ a single page, and
- * possibly expand if that turns out to be insufficent.
+ * possibly expand if that turns out to be insufficient.
  */
 static int map_iommu(struct intel_iommu *iommu, u64 phys_addr)
 {
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index ee0932307d646bb..f9a2277fba99f9f 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -288,7 +288,7 @@ static inline void context_clear_entry(struct context_entry 
*context)
 
 /*
  * This domain is a statically identity mapping domain.
- * 1. This domain creats a static 1:1 mapping to all usable memory.
+ * 1. This domain creates a static 1:1 mapping to all usable memory.
  * 2. It maps to each iommu if successful.
  * 3. Each iommu mapps to this domain if successful.
  */
diff --git a/drivers/iommu/intel/irq_remapping.c 
b/drivers/iommu/intel/irq_remapping.c
index 611ef5243cb63b9..12e9f2cf84e5101 100644
--- a/drivers/iommu/intel/irq_remapping.c
+++ b/drivers/iommu/intel/irq_remapping.c
@@ -74,7 +74,7 @@ struct intel_ir_data {
  * ->iommu->register_lock
  * Note:
  * intel_irq_remap_ops.{supported,prepare,enable,disable,reenable} are called
- * in single-threaded environment with interrupt disabled, so no need to tabke
+ * in single-threaded environment with interrupt disabled, so no need to take
  * the dmar_global_lock.
  */
 DEFINE_RAW_SPINLOCK(irq_2_ir_lock);
-- 
1.8.3


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


[PATCH 6/8] iommu/amd: fix a couple of spelling mistakes

2021-03-26 Thread Zhen Lei
There are several spelling mistakes, as follows:
alignement ==> alignment
programing ==> programming
implemtation ==> implementation
assignement ==> assignment

By the way, both "programing" and "programming" are acceptable, but the
latter seems more formal.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/amd/amd_iommu_types.h | 2 +-
 drivers/iommu/amd/init.c| 4 ++--
 drivers/iommu/amd/iommu.c   | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/amd/amd_iommu_types.h 
b/drivers/iommu/amd/amd_iommu_types.h
index 6937e3674a16e26..dc1814c355cff77 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -446,7 +446,7 @@ struct irq_remap_table {
 /* Interrupt remapping feature used? */
 extern bool amd_iommu_irq_remap;
 
-/* kmem_cache to get tables with 128 byte alignement */
+/* kmem_cache to get tables with 128 byte alignment */
 extern struct kmem_cache *amd_iommu_irq_cache;
 
 /*
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 321f5906e6ed3a5..48799002b3571d1 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -1734,7 +1734,7 @@ static void __init init_iommu_perf_ctr(struct amd_iommu 
*iommu)
goto pc_false;
 
/*
-* Disable power gating by programing the performance counter
+* Disable power gating by programming the performance counter
 * source to 20 (i.e. counts the reads and writes from/to IOMMU
 * Reserved Register [MMIO Offset 1FF8h] that are ignored.),
 * which never get incremented during this init phase.
@@ -2088,7 +2088,7 @@ static int intcapxt_irqdomain_activate(struct irq_domain 
*domain,
xt.destid_24_31 = cfg->dest_apicid >> 24;
 
/**
-* Current IOMMU implemtation uses the same IRQ for all
+* Current IOMMU implementation uses the same IRQ for all
 * 3 IOMMU interrupts.
 */
writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET);
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index a69a8b573e40d00..d14e4698f507b89 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -1865,7 +1865,7 @@ int __init amd_iommu_init_dma_ops(void)
  * The following functions belong to the exported interface of AMD IOMMU
  *
  * This interface allows access to lower level functions of the IOMMU
- * like protection domain handling and assignement of devices to domains
+ * like protection domain handling and assignment of devices to domains
  * which is not possible with the dma_ops interface.
  *
  */
-- 
1.8.3


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


[PATCH 2/8] iommu/omap: Fix spelling mistake "alignement" -> "alignment"

2021-03-26 Thread Zhen Lei
There is a spelling mistake in a comment, fix it.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/omap-iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 71f29c0927fc710..b2a6ab700ec43d1 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -1754,7 +1754,7 @@ static int __init omap_iommu_init(void)
 {
struct kmem_cache *p;
const slab_flags_t flags = SLAB_HWCACHE_ALIGN;
-   size_t align = 1 << 10; /* L2 pagetable alignement */
+   size_t align = 1 << 10; /* L2 pagetable alignment */
struct device_node *np;
int ret;
 
-- 
1.8.3


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


[PATCH 3/8] iommu/mediatek: Fix spelling mistake "phyiscal" -> "physical"

2021-03-26 Thread Zhen Lei
There is a spelling mistake in a comment, fix it.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/mtk_iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 6ecc007f07cd52e..c8c9bf1d70b29dc 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -160,7 +160,7 @@ struct mtk_iommu_domain {
  * The Region 'A'(I/O) can NOT be mapped by M4U; For Region 'B'/'C'/'D', the
  * bit32 of the CPU physical address always is needed to set, and for Region
  * 'E', the CPU physical address keep as is.
- * Additionally, The iommu consumers always use the CPU phyiscal address.
+ * Additionally, The iommu consumers always use the CPU physical address.
  */
 #define MTK_IOMMU_4GB_MODE_REMAP_BASE   0x14000UL
 
-- 
1.8.3


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


[PATCH 4/8] iommu/sun50i: Fix spelling mistake "consits" -> "consists"

2021-03-26 Thread Zhen Lei
There is a spelling mistake in a comment, fix it.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/sun50i-iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
index ea6db1341916524..7685b96b2d445a7 100644
--- a/drivers/iommu/sun50i-iommu.c
+++ b/drivers/iommu/sun50i-iommu.c
@@ -149,7 +149,7 @@ static void iommu_write(struct sun50i_iommu *iommu, u32 
offset, u32 value)
  * 4096 4-bytes Directory Table Entries (DTE), each pointing to a Page
  * Table (PT).
  *
- * Each PT consits of 256 4-bytes Page Table Entries (PTE), each
+ * Each PT consists of 256 4-bytes Page Table Entries (PTE), each
  * pointing to a 4kB page of physical memory.
  *
  * The IOMMU supports a single DT, pointed by the IOMMU_TTB_REG
-- 
1.8.3


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


[PATCH 5/8] iommu: fix a couple of spelling mistakes

2021-03-26 Thread Zhen Lei
There are several spelling mistakes, as follows:
funcions ==> functions
distiguish ==> distinguish
detroyed ==> destroyed

Signed-off-by: Zhen Lei 
---
 drivers/iommu/iommu.c | 4 ++--
 drivers/iommu/iova.c  | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index d0b0a15dba8413c..0f4e9a6122ee58f 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1453,7 +1453,7 @@ struct iommu_group *pci_device_group(struct device *dev)
 
/*
 * Look for existing groups on non-isolated functions on the same
-* slot and aliases of those funcions, if any.  No need to clear
+* slot and aliases of those functions, if any.  No need to clear
 * the search bitmap, the tested devfns are still valid.
 */
group = get_pci_function_alias_group(pdev, (unsigned long *)devfns);
@@ -2267,7 +2267,7 @@ struct iommu_domain *iommu_get_dma_domain(struct device 
*dev)
  * iterating over the devices in a group.  Ideally we'd have a single
  * device which represents the requestor ID of the group, but we also
  * allow IOMMU drivers to create policy defined minimum sets, where
- * the physical hardware may be able to distiguish members, but we
+ * the physical hardware may be able to distinguish members, but we
  * wish to group them at a higher level (ex. untrusted multi-function
  * PCI devices).  Thus we attach each device.
  */
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index e6e2fa85271c3f8..bf710b0a3713e21 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -524,7 +524,7 @@ 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
+* This code runs when the iova_domain is being destroyed, so don't
 * bother to free iovas, just call the entry_dtor on all remaining
 * entries.
 */
-- 
1.8.3


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


[PATCH 1/8] iommu/pamu: fix a couple of spelling mistakes

2021-03-26 Thread Zhen Lei
There are several spelling mistakes, as follows:
Returs  ==> Returns
defaul ==> default
assocaited ==> associated

Signed-off-by: Zhen Lei 
---
 drivers/iommu/fsl_pamu.c| 2 +-
 drivers/iommu/fsl_pamu_domain.c | 2 +-
 drivers/iommu/fsl_pamu_domain.h | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index b9a974d9783113d..48ebbf0daa21cf9 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -503,7 +503,7 @@ void get_ome_index(u32 *omi_index, struct device *dev)
  * @stash_dest_hint: L1, L2 or L3
  * @vcpu: vpcu target for a particular cache type.
  *
- * Returs stash on success or ~(u32)0 on failure.
+ * Returns stash on success or ~(u32)0 on failure.
  *
  */
 u32 get_stash_id(u32 stash_dest_hint, u32 vcpu)
diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c
index b2110767caf49c8..be664cd18c51970 100644
--- a/drivers/iommu/fsl_pamu_domain.c
+++ b/drivers/iommu/fsl_pamu_domain.c
@@ -418,7 +418,7 @@ static struct iommu_domain *fsl_pamu_domain_alloc(unsigned 
type)
pr_debug("dma_domain allocation failed\n");
return NULL;
}
-   /* defaul geometry 64 GB i.e. maximum system address */
+   /* default geometry 64 GB i.e. maximum system address */
dma_domain->iommu_domain. geometry.aperture_start = 0;
dma_domain->iommu_domain.geometry.aperture_end = (1ULL << 36) - 1;
dma_domain->iommu_domain.geometry.force_aperture = true;
diff --git a/drivers/iommu/fsl_pamu_domain.h b/drivers/iommu/fsl_pamu_domain.h
index 2865d42782e8021..4f508fa041080e3 100644
--- a/drivers/iommu/fsl_pamu_domain.h
+++ b/drivers/iommu/fsl_pamu_domain.h
@@ -24,7 +24,7 @@ struct fsl_dma_domain {
 */
dma_addr_t  geom_size;
/*
-* Number of windows assocaited with this domain.
+* Number of windows associated with this domain.
 * During domain initialization, it is set to the
 * the maximum number of subwindows allowed for a LIODN.
 * Minimum value for this is 1 indicating a single PAMU
-- 
1.8.3


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


[PATCH 0/8] iommu: fix a couple of spelling mistakes detected by codespell tool

2021-03-26 Thread Zhen Lei
This detection and correction covers the entire driver/iommu directory.

Zhen Lei (8):
  iommu/pamu: fix a couple of spelling mistakes
  iommu/omap: Fix spelling mistake "alignement" -> "alignment"
  iommu/mediatek: Fix spelling mistake "phyiscal" -> "physical"
  iommu/sun50i: Fix spelling mistake "consits" -> "consists"
  iommu: fix a couple of spelling mistakes
  iommu/amd: fix a couple of spelling mistakes
  iommu/arm-smmu: Fix spelling mistake "initally" -> "initially"
  iommu/vt-d: fix a couple of spelling mistakes

 drivers/iommu/amd/amd_iommu_types.h   | 2 +-
 drivers/iommu/amd/init.c  | 4 ++--
 drivers/iommu/amd/iommu.c | 2 +-
 drivers/iommu/arm/arm-smmu/arm-smmu.c | 2 +-
 drivers/iommu/fsl_pamu.c  | 2 +-
 drivers/iommu/fsl_pamu_domain.c   | 2 +-
 drivers/iommu/fsl_pamu_domain.h   | 2 +-
 drivers/iommu/intel/dmar.c| 6 +++---
 drivers/iommu/intel/iommu.c   | 2 +-
 drivers/iommu/intel/irq_remapping.c   | 2 +-
 drivers/iommu/iommu.c | 4 ++--
 drivers/iommu/iova.c  | 2 +-
 drivers/iommu/mtk_iommu.c | 2 +-
 drivers/iommu/omap-iommu.c| 2 +-
 drivers/iommu/sun50i-iommu.c  | 2 +-
 15 files changed, 19 insertions(+), 19 deletions(-)

-- 
1.8.3


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


[PATCH 1/1] iommu/arm-smmu-v3: add bit field SFM into GERROR_ERR_MASK

2021-03-24 Thread Zhen Lei
In arm_smmu_gerror_handler(), the value of the SMMU_GERROR register is
filtered by GERROR_ERR_MASK. However, the GERROR_ERR_MASK does not contain
the SFM bit. As a result, the subsequent error processing is not performed
when only the SFM error occurs.

Fixes: 48ec83bcbcf5 ("iommu/arm-smmu: Add initial driver support for ARM SMMUv3 
devices")
Reported-by: Rui Zhu 
Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index f985817c967a257..230b6f6b39016cd 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -115,7 +115,7 @@
 #define GERROR_PRIQ_ABT_ERR(1 << 3)
 #define GERROR_EVTQ_ABT_ERR(1 << 2)
 #define GERROR_CMDQ_ERR(1 << 0)
-#define GERROR_ERR_MASK0xfd
+#define GERROR_ERR_MASK0x1fd
 
 #define ARM_SMMU_GERRORN   0x64
 
-- 
2.26.0.106.g9fadedd


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


[PATCH v5 0/1] perf/smmuv3: Don't reserve the PMCG register spaces

2021-02-01 Thread Zhen Lei
v4 --> v5:
1. Give up doing the mapping for the entire SMMU register space.
2. Fix some compile warnings. Sorry. So sorry.

v3 --> v4:
1. Delete the unnecessary encapsulation function 
smmu_pmu_get_and_ioremap_resource().
2. Discard adding MODULE_SOFTDEP.

v2 --> v3:
Patch 3 is updated because https://lkml.org/lkml/2021/1/22/532 has been queued 
in advance.

v1 --> v2:
According to Robin Murphy's suggestion: https://lkml.org/lkml/2021/1/20/470
Don't reserve the PMCG register spaces, and reserve the entire SMMU register 
space.

v1:
Since the PMCG may implement its resigters space(4KB Page0 and 4KB Page1)
within the SMMUv3 64KB Page0. In this case, when the SMMUv3 driver reserves the
64KB Page0 resource in advance, the PMCG driver try to reserve its Page0 and
Page1 resources, a resource conflict occurs.

commit 52f3fab0067d6fa ("iommu/arm-smmu-v3: Don't reserve implementation
defined register space") reduce the resource reservation range of the SMMUv3
driver, it only reserves the first 0xe00 bytes in the 64KB Page0, to avoid
the above-mentioned resource conflicts.

But the SMMUv3.3 add support for ECMDQ, its registers space is also implemented
in the SMMUv3 64KB Page0. This means we need to build two separate mappings.
New features may be added in the future, and more independent mappings may be
required. The simple problem is complicated because the user expects to map the
entire SMMUv3 64KB Page0.

Therefore, the proper solution is: If the PMCG register resources are located in
the 64KB Page0 of the SMMU, the PMCG driver does not reserve the conflict 
resources
when the SMMUv3 driver has reserved the conflict resources before. Instead, the 
PMCG
driver only performs devm_ioremap() to ensure that it can work properly.

Zhen Lei (1):
  perf/smmuv3: Don't reserve the PMCG register spaces

 drivers/perf/arm_smmuv3_pmu.c | 25 +++--
 1 file changed, 19 insertions(+), 6 deletions(-)

-- 
2.26.0.106.g9fadedd


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


[PATCH v5 1/1] perf/smmuv3: Don't reserve the PMCG register spaces

2021-02-01 Thread Zhen Lei
According to the SMMUv3 specification:
Each PMCG counter group is represented by one 4KB page (Page 0) with one
optional additional 4KB page (Page 1), both of which are at IMPLEMENTATION
DEFINED base addresses.

This means that the PMCG register spaces may be within the 64KB pages of
the SMMUv3 register space. When both the SMMU and PMCG drivers reserve
their own resources, a resource conflict occurs.

To avoid this conflict, don't reserve the PMCG regions.

Suggested-by: Robin Murphy 
Signed-off-by: Zhen Lei 
Reviewed-by: Robin Murphy 
---
 drivers/perf/arm_smmuv3_pmu.c | 25 +++--
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
index 74474bb322c3f26..8f0b71b5d08a815 100644
--- a/drivers/perf/arm_smmuv3_pmu.c
+++ b/drivers/perf/arm_smmuv3_pmu.c
@@ -793,17 +793,30 @@ static int smmu_pmu_probe(struct platform_device *pdev)
.capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
};
 
-   smmu_pmu->reg_base = devm_platform_get_and_ioremap_resource(pdev, 0, 
_0);
-   if (IS_ERR(smmu_pmu->reg_base))
-   return PTR_ERR(smmu_pmu->reg_base);
+   /*
+* The register spaces of the PMCG may be in the register space of
+* other devices. For example, SMMU. Therefore, the PMCG resources are
+* not reserved to avoid resource conflicts with other drivers.
+*/
+   res_0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   if (!res_0)
+   return -EINVAL;
+   smmu_pmu->reg_base = devm_ioremap(dev, res_0->start, 
resource_size(res_0));
+   if (!smmu_pmu->reg_base)
+   return -ENOMEM;
 
cfgr = readl_relaxed(smmu_pmu->reg_base + SMMU_PMCG_CFGR);
 
/* Determine if page 1 is present */
if (cfgr & SMMU_PMCG_CFGR_RELOC_CTRS) {
-   smmu_pmu->reloc_base = devm_platform_ioremap_resource(pdev, 1);
-   if (IS_ERR(smmu_pmu->reloc_base))
-   return PTR_ERR(smmu_pmu->reloc_base);
+   struct resource *res_1;
+
+   res_1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+   if (!res_1)
+   return -EINVAL;
+   smmu_pmu->reloc_base = devm_ioremap(dev, res_1->start, 
resource_size(res_1));
+   if (!smmu_pmu->reloc_base)
+   return -ENOMEM;
} else {
smmu_pmu->reloc_base = smmu_pmu->reg_base;
}
-- 
2.26.0.106.g9fadedd


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


[PATCH v4 0/2] perf/smmuv3: Don't reserve the PMCG register spaces

2021-01-29 Thread Zhen Lei
v3 --> v4:
1. Delete the unnecessary encapsulation function 
smmu_pmu_get_and_ioremap_resource().
2. Discard adding MODULE_SOFTDEP.

v2 --> v3:
Patch 3 is updated because https://lkml.org/lkml/2021/1/22/532 has been queued 
in advance.

v1 --> v2:
According to Robin Murphy's suggestion: https://lkml.org/lkml/2021/1/20/470
Don't reserve the PMCG register spaces, and reserve the entire SMMU register 
space.

v1:
Since the PMCG may implement its resigters space(4KB Page0 and 4KB Page1)
within the SMMUv3 64KB Page0. In this case, when the SMMUv3 driver reserves the
64KB Page0 resource in advance, the PMCG driver try to reserve its Page0 and
Page1 resources, a resource conflict occurs.

commit 52f3fab0067d6fa ("iommu/arm-smmu-v3: Don't reserve implementation
defined register space") reduce the resource reservation range of the SMMUv3
driver, it only reserves the first 0xe00 bytes in the 64KB Page0, to avoid
the above-mentioned resource conflicts.

But the SMMUv3.3 add support for ECMDQ, its registers space is also implemented
in the SMMUv3 64KB Page0. This means we need to build two separate mappings.
New features may be added in the future, and more independent mappings may be
required. The simple problem is complicated because the user expects to map the
entire SMMUv3 64KB Page0.

Therefore, the proper solution is: If the PMCG register resources are located in
the 64KB Page0 of the SMMU, the PMCG driver does not reserve the conflict 
resources
when the SMMUv3 driver has reserved the conflict resources before. Instead, the 
PMCG
driver only performs devm_ioremap() to ensure that it can work properly.

Zhen Lei (2):
  perf/smmuv3: Don't reserve the PMCG register spaces
  iommu/arm-smmu-v3: Reserving the entire SMMU register space

 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 24 
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  2 --
 drivers/perf/arm_smmuv3_pmu.c   | 25 +++--
 3 files changed, 23 insertions(+), 28 deletions(-)

-- 
1.8.3


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


[PATCH v4 2/2] iommu/arm-smmu-v3: Reserving the entire SMMU register space

2021-01-29 Thread Zhen Lei
commit 52f3fab0067d ("iommu/arm-smmu-v3: Don't reserve implementation
defined register space") only reserves the basic SMMU register space. So
the ECMDQ register space is not covered, it should be mapped again. Due
to the size of this ECMDQ resource is not fixed, depending on
SMMU_IDR6.CMDQ_CONTROL_PAGE_LOG2NUMQ. Processing its resource reservation
to avoid resource conflict with PMCG is a bit more complicated.

Therefore, the resources of the PMCG are not reserved, and the entire SMMU
resources are reserved.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 24 
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  2 --
 2 files changed, 4 insertions(+), 22 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index f04c55a7503c790..fde24403b06a9e3 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -3476,14 +3476,6 @@ static int arm_smmu_set_bus_ops(struct iommu_ops *ops)
return err;
 }
 
-static void __iomem *arm_smmu_ioremap(struct device *dev, resource_size_t 
start,
- resource_size_t size)
-{
-   struct resource res = DEFINE_RES_MEM(start, size);
-
-   return devm_ioremap_resource(dev, );
-}
-
 static int arm_smmu_device_probe(struct platform_device *pdev)
 {
int irq, ret;
@@ -3519,22 +3511,14 @@ static int arm_smmu_device_probe(struct platform_device 
*pdev)
}
ioaddr = res->start;
 
-   /*
-* Don't map the IMPLEMENTATION DEFINED regions, since they may contain
-* the PMCG registers which are reserved by the PMU driver.
-*/
-   smmu->base = arm_smmu_ioremap(dev, ioaddr, ARM_SMMU_REG_SZ);
+   smmu->base = devm_ioremap_resource(dev, res);
if (IS_ERR(smmu->base))
return PTR_ERR(smmu->base);
 
-   if (arm_smmu_resource_size(smmu) > SZ_64K) {
-   smmu->page1 = arm_smmu_ioremap(dev, ioaddr + SZ_64K,
-  ARM_SMMU_REG_SZ);
-   if (IS_ERR(smmu->page1))
-   return PTR_ERR(smmu->page1);
-   } else {
+   if (arm_smmu_resource_size(smmu) > SZ_64K)
+   smmu->page1 = smmu->base + SZ_64K;
+   else
smmu->page1 = smmu->base;
-   }
 
/* Interrupt lines */
 
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index da525f46dab4fc1..63f2b476987d6ae 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -152,8 +152,6 @@
 #define ARM_SMMU_PRIQ_IRQ_CFG1 0xd8
 #define ARM_SMMU_PRIQ_IRQ_CFG2 0xdc
 
-#define ARM_SMMU_REG_SZ0xe00
-
 /* Common MSI config fields */
 #define MSI_CFG0_ADDR_MASK GENMASK_ULL(51, 2)
 #define MSI_CFG2_SHGENMASK(5, 4)
-- 
1.8.3


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


[PATCH v4 1/2] perf/smmuv3: Don't reserve the PMCG register spaces

2021-01-29 Thread Zhen Lei
According to the SMMUv3 specification:
Each PMCG counter group is represented by one 4KB page (Page 0) with one
optional additional 4KB page (Page 1), both of which are at IMPLEMENTATION
DEFINED base addresses.

This means that the PMCG register spaces may be within the 64KB pages of
the SMMUv3 register space. When both the SMMU and PMCG drivers reserve
their own resources, a resource conflict occurs.

To avoid this conflict, don't reserve the PMCG regions.

Suggested-by: Robin Murphy 
Signed-off-by: Zhen Lei 
---
 drivers/perf/arm_smmuv3_pmu.c | 25 +++--
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
index 74474bb322c3f26..5e894f957c7b935 100644
--- a/drivers/perf/arm_smmuv3_pmu.c
+++ b/drivers/perf/arm_smmuv3_pmu.c
@@ -793,17 +793,30 @@ static int smmu_pmu_probe(struct platform_device *pdev)
.capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
};
 
-   smmu_pmu->reg_base = devm_platform_get_and_ioremap_resource(pdev, 0, 
_0);
-   if (IS_ERR(smmu_pmu->reg_base))
-   return PTR_ERR(smmu_pmu->reg_base);
+   /*
+* The register spaces of the PMCG may be in the register space of
+* other devices. For example, SMMU. Therefore, the PMCG resources are
+* not reserved to avoid resource conflicts with other drivers.
+*/
+   res_0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   if (!res_0)
+   return ERR_PTR(-EINVAL);
+   smmu_pmu->reg_base = devm_ioremap(dev, res_0->start, 
resource_size(res_0));
+   if (!smmu_pmu->reg_base)
+   return ERR_PTR(-ENOMEM);
 
cfgr = readl_relaxed(smmu_pmu->reg_base + SMMU_PMCG_CFGR);
 
/* Determine if page 1 is present */
if (cfgr & SMMU_PMCG_CFGR_RELOC_CTRS) {
-   smmu_pmu->reloc_base = devm_platform_ioremap_resource(pdev, 1);
-   if (IS_ERR(smmu_pmu->reloc_base))
-   return PTR_ERR(smmu_pmu->reloc_base);
+   struct resource *res_1;
+
+   res_1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+   if (!res_1)
+   return ERR_PTR(-EINVAL);
+   smmu_pmu->reloc_base = devm_ioremap(dev, res_1->start, 
resource_size(res_1));
+   if (!smmu_pmu->reloc_base)
+   return ERR_PTR(-ENOMEM);
} else {
smmu_pmu->reloc_base = smmu_pmu->reg_base;
}
-- 
1.8.3


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


[PATCH 1/1] Revert "iommu/iova: Retry from last rb tree node if iova search fails"

2021-01-29 Thread Zhen Lei
This reverts commit 4e89dce725213d3d0b0475211b500eda4ef4bf2f.

We find that this patch has a great impact on performance. According to
our test: the iops decreases from 1655.6K to 893.5K, about half.

Hardware: 1 SAS expander with 12 SAS SSD
Command:  Only the main parameters are listed.
  fio bs=4k rw=read iodepth=128 cpus_allowed=0-127

Fixes: 4e89dce72521 ("iommu/iova: Retry from last rb tree node if iova search 
fails")
Tested-by: Xiang Chen 
Signed-off-by: Zhen Lei 
---
 drivers/iommu/iova.c | 23 ++-
 1 file changed, 6 insertions(+), 17 deletions(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index d20b8b333d30d17..f840c7207efbced 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -185,9 +185,8 @@ static int __alloc_and_insert_iova_range(struct iova_domain 
*iovad,
struct rb_node *curr, *prev;
struct iova *curr_iova;
unsigned long flags;
-   unsigned long new_pfn, retry_pfn;
+   unsigned long new_pfn;
unsigned long align_mask = ~0UL;
-   unsigned long high_pfn = limit_pfn, low_pfn = iovad->start_pfn;
 
if (size_aligned)
align_mask <<= fls_long(size - 1);
@@ -200,25 +199,15 @@ static int __alloc_and_insert_iova_range(struct 
iova_domain *iovad,
 
curr = __get_cached_rbnode(iovad, limit_pfn);
curr_iova = rb_entry(curr, struct iova, node);
-   retry_pfn = curr_iova->pfn_hi + 1;
-
-retry:
do {
-   high_pfn = min(high_pfn, curr_iova->pfn_lo);
-   new_pfn = (high_pfn - size) & align_mask;
+   limit_pfn = min(limit_pfn, curr_iova->pfn_lo);
+   new_pfn = (limit_pfn - size) & align_mask;
prev = curr;
curr = rb_prev(curr);
curr_iova = rb_entry(curr, struct iova, node);
-   } while (curr && new_pfn <= curr_iova->pfn_hi && new_pfn >= low_pfn);
-
-   if (high_pfn < size || new_pfn < low_pfn) {
-   if (low_pfn == iovad->start_pfn && retry_pfn < limit_pfn) {
-   high_pfn = limit_pfn;
-   low_pfn = retry_pfn;
-   curr = >anchor.node;
-   curr_iova = rb_entry(curr, struct iova, node);
-   goto retry;
-   }
+   } while (curr && new_pfn <= curr_iova->pfn_hi);
+
+   if (limit_pfn < size || new_pfn < iovad->start_pfn) {
iovad->max32_alloc_size = size;
goto iova32_full;
}
-- 
1.8.3


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


[PATCH v3 3/3] iommu/arm-smmu-v3: Reserving the entire SMMU register space

2021-01-27 Thread Zhen Lei
commit 52f3fab0067d ("iommu/arm-smmu-v3: Don't reserve implementation
defined register space") only reserves the basic SMMU register space. So
the ECMDQ register space is not covered, it should be mapped again. Due
to the size of this ECMDQ resource is not fixed, depending on
SMMU_IDR6.CMDQ_CONTROL_PAGE_LOG2NUMQ. Processing its resource reservation
to avoid resource conflict with PMCG is a bit more complicated.

Therefore, the resources of the PMCG are not reserved, and the entire SMMU
resources are reserved.

Suggested-by: Robin Murphy 
Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 24 
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  2 --
 2 files changed, 4 insertions(+), 22 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index f04c55a7503c790..fde24403b06a9e3 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -3476,14 +3476,6 @@ static int arm_smmu_set_bus_ops(struct iommu_ops *ops)
return err;
 }
 
-static void __iomem *arm_smmu_ioremap(struct device *dev, resource_size_t 
start,
- resource_size_t size)
-{
-   struct resource res = DEFINE_RES_MEM(start, size);
-
-   return devm_ioremap_resource(dev, );
-}
-
 static int arm_smmu_device_probe(struct platform_device *pdev)
 {
int irq, ret;
@@ -3519,22 +3511,14 @@ static int arm_smmu_device_probe(struct platform_device 
*pdev)
}
ioaddr = res->start;
 
-   /*
-* Don't map the IMPLEMENTATION DEFINED regions, since they may contain
-* the PMCG registers which are reserved by the PMU driver.
-*/
-   smmu->base = arm_smmu_ioremap(dev, ioaddr, ARM_SMMU_REG_SZ);
+   smmu->base = devm_ioremap_resource(dev, res);
if (IS_ERR(smmu->base))
return PTR_ERR(smmu->base);
 
-   if (arm_smmu_resource_size(smmu) > SZ_64K) {
-   smmu->page1 = arm_smmu_ioremap(dev, ioaddr + SZ_64K,
-  ARM_SMMU_REG_SZ);
-   if (IS_ERR(smmu->page1))
-   return PTR_ERR(smmu->page1);
-   } else {
+   if (arm_smmu_resource_size(smmu) > SZ_64K)
+   smmu->page1 = smmu->base + SZ_64K;
+   else
smmu->page1 = smmu->base;
-   }
 
/* Interrupt lines */
 
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index da525f46dab4fc1..63f2b476987d6ae 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -152,8 +152,6 @@
 #define ARM_SMMU_PRIQ_IRQ_CFG1 0xd8
 #define ARM_SMMU_PRIQ_IRQ_CFG2 0xdc
 
-#define ARM_SMMU_REG_SZ0xe00
-
 /* Common MSI config fields */
 #define MSI_CFG0_ADDR_MASK GENMASK_ULL(51, 2)
 #define MSI_CFG2_SHGENMASK(5, 4)
-- 
1.8.3


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


[PATCH v3 1/3] perf/smmuv3: Don't reserve the PMCG register spaces

2021-01-27 Thread Zhen Lei
According to the SMMUv3 specification:
Each PMCG counter group is represented by one 4KB page (Page 0) with one
optional additional 4KB page (Page 1), both of which are at IMPLEMENTATION
DEFINED base addresses.

This means that the PMCG register spaces may be within the 64KB pages of
the SMMUv3 register space. When both the SMMU and PMCG drivers reserve
their own resources, a resource conflict occurs.

To avoid this conflict, don't reserve the PMCG regions.

Suggested-by: Robin Murphy 
Signed-off-by: Zhen Lei 
---
 drivers/perf/arm_smmuv3_pmu.c | 27 +--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
index 74474bb322c3f26..e5e505a0804fe53 100644
--- a/drivers/perf/arm_smmuv3_pmu.c
+++ b/drivers/perf/arm_smmuv3_pmu.c
@@ -761,6 +761,29 @@ static void smmu_pmu_get_acpi_options(struct smmu_pmu 
*smmu_pmu)
dev_notice(smmu_pmu->dev, "option mask 0x%x\n", smmu_pmu->options);
 }
 
+static void __iomem *
+smmu_pmu_get_and_ioremap_resource(struct platform_device *pdev,
+ unsigned int index,
+ struct resource **res)
+{
+   void __iomem *base;
+   struct resource *r;
+
+   r = platform_get_resource(pdev, IORESOURCE_MEM, index);
+   if (!r) {
+   dev_err(>dev, "invalid resource\n");
+   return ERR_PTR(-EINVAL);
+   }
+   if (res)
+   *res = r;
+
+   base = devm_ioremap(>dev, r->start, resource_size(r));
+   if (!base)
+   return ERR_PTR(-ENOMEM);
+
+   return base;
+}
+
 static int smmu_pmu_probe(struct platform_device *pdev)
 {
struct smmu_pmu *smmu_pmu;
@@ -793,7 +816,7 @@ static int smmu_pmu_probe(struct platform_device *pdev)
.capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
};
 
-   smmu_pmu->reg_base = devm_platform_get_and_ioremap_resource(pdev, 0, 
_0);
+   smmu_pmu->reg_base = smmu_pmu_get_and_ioremap_resource(pdev, 0, _0);
if (IS_ERR(smmu_pmu->reg_base))
return PTR_ERR(smmu_pmu->reg_base);
 
@@ -801,7 +824,7 @@ static int smmu_pmu_probe(struct platform_device *pdev)
 
/* Determine if page 1 is present */
if (cfgr & SMMU_PMCG_CFGR_RELOC_CTRS) {
-   smmu_pmu->reloc_base = devm_platform_ioremap_resource(pdev, 1);
+   smmu_pmu->reloc_base = smmu_pmu_get_and_ioremap_resource(pdev, 
1, NULL);
if (IS_ERR(smmu_pmu->reloc_base))
return PTR_ERR(smmu_pmu->reloc_base);
} else {
-- 
1.8.3


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


[PATCH v3 0/3] perf/smmuv3: Don't reserve the PMCG register spaces

2021-01-27 Thread Zhen Lei
v2 --> v3:
Patch 3 is updated because https://lkml.org/lkml/2021/1/22/532 has been queued 
in advance.

v1 --> v2:
According to Robin Murphy's suggestion: https://lkml.org/lkml/2021/1/20/470
Don't reserve the PMCG register spaces, and reserve the entire SMMU register 
space.

v1:
Since the PMCG may implement its resigters space(4KB Page0 and 4KB Page1)
within the SMMUv3 64KB Page0. In this case, when the SMMUv3 driver reserves the
64KB Page0 resource in advance, the PMCG driver try to reserve its Page0 and
Page1 resources, a resource conflict occurs.

commit 52f3fab0067d6fa ("iommu/arm-smmu-v3: Don't reserve implementation
defined register space") reduce the resource reservation range of the SMMUv3
driver, it only reserves the first 0xe00 bytes in the 64KB Page0, to avoid
the above-mentioned resource conflicts.

But the SMMUv3.3 add support for ECMDQ, its registers space is also implemented
in the SMMUv3 64KB Page0. This means we need to build two separate mappings.
New features may be added in the future, and more independent mappings may be
required. The simple problem is complicated because the user expects to map the
entire SMMUv3 64KB Page0.

Therefore, the proper solution is: If the PMCG register resources are located in
the 64KB Page0 of the SMMU, the PMCG driver does not reserve the conflict 
resources
when the SMMUv3 driver has reserved the conflict resources before. Instead, the 
PMCG
driver only performs devm_ioremap() to ensure that it can work properly.

Zhen Lei (3):
  perf/smmuv3: Don't reserve the PMCG register spaces
  perf/smmuv3: Add a MODULE_SOFTDEP() to indicate dependency on SMMU
  iommu/arm-smmu-v3: Reserving the entire SMMU register space

 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 24 
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  2 --
 drivers/perf/arm_smmuv3_pmu.c   | 28 ++--
 3 files changed, 30 insertions(+), 24 deletions(-)

-- 
1.8.3


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


[PATCH v3 2/3] perf/smmuv3: Add a MODULE_SOFTDEP() to indicate dependency on SMMU

2021-01-27 Thread Zhen Lei
The MODULE_SOFTDEP() gives user space a hint of the loading sequence. And
when command "modprobe arm_smmuv3_pmu" is executed, the arm_smmu_v3.ko is
automatically loaded in advance.

Signed-off-by: Zhen Lei 
---
 drivers/perf/arm_smmuv3_pmu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
index e5e505a0804fe53..9a305ac51208cd2 100644
--- a/drivers/perf/arm_smmuv3_pmu.c
+++ b/drivers/perf/arm_smmuv3_pmu.c
@@ -950,6 +950,7 @@ static void __exit arm_smmu_pmu_exit(void)
 module_exit(arm_smmu_pmu_exit);
 
 MODULE_DESCRIPTION("PMU driver for ARM SMMUv3 Performance Monitors Extension");
+MODULE_SOFTDEP("pre: arm_smmu_v3");
 MODULE_AUTHOR("Neil Leeder ");
 MODULE_AUTHOR("Shameer Kolothum ");
 MODULE_LICENSE("GPL v2");
-- 
1.8.3


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


[PATCH v2 3/3] iommu/arm-smmu-v3: Reserving the entire SMMU register space

2021-01-26 Thread Zhen Lei
commit 52f3fab0067d ("iommu/arm-smmu-v3: Don't reserve implementation
defined register space") only reserves the basic SMMU register space. So
the ECMDQ register space is not covered, it should be mapped again. Due
to the size of this ECMDQ resource is not fixed, depending on
SMMU_IDR6.CMDQ_CONTROL_PAGE_LOG2NUMQ. Processing its resource reservation
to avoid resource conflict with PMCG is a bit more complicated.

Therefore, the resources of the PMCG are not reserved, and the entire SMMU
resources are reserved.

Suggested-by: Robin Murphy 
Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 28 
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  2 --
 2 files changed, 4 insertions(+), 26 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index bca458c00e48a8b..fde24403b06a9e3 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -3476,18 +3476,6 @@ static int arm_smmu_set_bus_ops(struct iommu_ops *ops)
return err;
 }
 
-static void __iomem *arm_smmu_ioremap(struct device *dev, resource_size_t 
start,
- resource_size_t size)
-{
-   struct resource res = {
-   .flags = IORESOURCE_MEM,
-   .start = start,
-   .end = start + size - 1,
-   };
-
-   return devm_ioremap_resource(dev, );
-}
-
 static int arm_smmu_device_probe(struct platform_device *pdev)
 {
int irq, ret;
@@ -3523,22 +3511,14 @@ static int arm_smmu_device_probe(struct platform_device 
*pdev)
}
ioaddr = res->start;
 
-   /*
-* Don't map the IMPLEMENTATION DEFINED regions, since they may contain
-* the PMCG registers which are reserved by the PMU driver.
-*/
-   smmu->base = arm_smmu_ioremap(dev, ioaddr, ARM_SMMU_REG_SZ);
+   smmu->base = devm_ioremap_resource(dev, res);
if (IS_ERR(smmu->base))
return PTR_ERR(smmu->base);
 
-   if (arm_smmu_resource_size(smmu) > SZ_64K) {
-   smmu->page1 = arm_smmu_ioremap(dev, ioaddr + SZ_64K,
-  ARM_SMMU_REG_SZ);
-   if (IS_ERR(smmu->page1))
-   return PTR_ERR(smmu->page1);
-   } else {
+   if (arm_smmu_resource_size(smmu) > SZ_64K)
+   smmu->page1 = smmu->base + SZ_64K;
+   else
smmu->page1 = smmu->base;
-   }
 
/* Interrupt lines */
 
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index da525f46dab4fc1..63f2b476987d6ae 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -152,8 +152,6 @@
 #define ARM_SMMU_PRIQ_IRQ_CFG1 0xd8
 #define ARM_SMMU_PRIQ_IRQ_CFG2 0xdc
 
-#define ARM_SMMU_REG_SZ0xe00
-
 /* Common MSI config fields */
 #define MSI_CFG0_ADDR_MASK GENMASK_ULL(51, 2)
 #define MSI_CFG2_SHGENMASK(5, 4)
-- 
1.8.3


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


[PATCH v2 1/3] perf/smmuv3: Don't reserve the PMCG register spaces

2021-01-26 Thread Zhen Lei
According to the SMMUv3 specification:
Each PMCG counter group is represented by one 4KB page (Page 0) with one
optional additional 4KB page (Page 1), both of which are at IMPLEMENTATION
DEFINED base addresses.

This means that the PMCG register spaces may be within the 64KB pages of
the SMMUv3 register space. When both the SMMU and PMCG drivers reserve
their own resources, a resource conflict occurs.

To avoid this conflict, don't reserve the PMCG regions.

Suggested-by: Robin Murphy 
Signed-off-by: Zhen Lei 
---
 drivers/perf/arm_smmuv3_pmu.c | 27 +--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
index 74474bb322c3f26..e5e505a0804fe53 100644
--- a/drivers/perf/arm_smmuv3_pmu.c
+++ b/drivers/perf/arm_smmuv3_pmu.c
@@ -761,6 +761,29 @@ static void smmu_pmu_get_acpi_options(struct smmu_pmu 
*smmu_pmu)
dev_notice(smmu_pmu->dev, "option mask 0x%x\n", smmu_pmu->options);
 }
 
+static void __iomem *
+smmu_pmu_get_and_ioremap_resource(struct platform_device *pdev,
+ unsigned int index,
+ struct resource **res)
+{
+   void __iomem *base;
+   struct resource *r;
+
+   r = platform_get_resource(pdev, IORESOURCE_MEM, index);
+   if (!r) {
+   dev_err(>dev, "invalid resource\n");
+   return ERR_PTR(-EINVAL);
+   }
+   if (res)
+   *res = r;
+
+   base = devm_ioremap(>dev, r->start, resource_size(r));
+   if (!base)
+   return ERR_PTR(-ENOMEM);
+
+   return base;
+}
+
 static int smmu_pmu_probe(struct platform_device *pdev)
 {
struct smmu_pmu *smmu_pmu;
@@ -793,7 +816,7 @@ static int smmu_pmu_probe(struct platform_device *pdev)
.capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
};
 
-   smmu_pmu->reg_base = devm_platform_get_and_ioremap_resource(pdev, 0, 
_0);
+   smmu_pmu->reg_base = smmu_pmu_get_and_ioremap_resource(pdev, 0, _0);
if (IS_ERR(smmu_pmu->reg_base))
return PTR_ERR(smmu_pmu->reg_base);
 
@@ -801,7 +824,7 @@ static int smmu_pmu_probe(struct platform_device *pdev)
 
/* Determine if page 1 is present */
if (cfgr & SMMU_PMCG_CFGR_RELOC_CTRS) {
-   smmu_pmu->reloc_base = devm_platform_ioremap_resource(pdev, 1);
+   smmu_pmu->reloc_base = smmu_pmu_get_and_ioremap_resource(pdev, 
1, NULL);
if (IS_ERR(smmu_pmu->reloc_base))
return PTR_ERR(smmu_pmu->reloc_base);
} else {
-- 
1.8.3


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


[PATCH v2 2/3] perf/smmuv3: Add a MODULE_SOFTDEP() to indicate dependency on SMMU

2021-01-26 Thread Zhen Lei
The MODULE_SOFTDEP() gives user space a hint of the loading sequence. And
when command "modprobe arm_smmuv3_pmu" is executed, the arm_smmu_v3.ko is
automatically loaded in advance.

Signed-off-by: Zhen Lei 
---
 drivers/perf/arm_smmuv3_pmu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
index e5e505a0804fe53..9a305ac51208cd2 100644
--- a/drivers/perf/arm_smmuv3_pmu.c
+++ b/drivers/perf/arm_smmuv3_pmu.c
@@ -950,6 +950,7 @@ static void __exit arm_smmu_pmu_exit(void)
 module_exit(arm_smmu_pmu_exit);
 
 MODULE_DESCRIPTION("PMU driver for ARM SMMUv3 Performance Monitors Extension");
+MODULE_SOFTDEP("pre: arm_smmu_v3");
 MODULE_AUTHOR("Neil Leeder ");
 MODULE_AUTHOR("Shameer Kolothum ");
 MODULE_LICENSE("GPL v2");
-- 
1.8.3


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


[PATCH v2 0/3] perf/smmuv3: Don't reserve the PMCG register spaces

2021-01-26 Thread Zhen Lei
v1 --> v2:
According to Robin Murphy's suggestion: https://lkml.org/lkml/2021/1/20/470
Don't reserve the PMCG register spaces, and reserve the entire SMMU register 
space.

v1:
Since the PMCG may implement its resigters space(4KB Page0 and 4KB Page1)
within the SMMUv3 64KB Page0. In this case, when the SMMUv3 driver reserves the
64KB Page0 resource in advance, the PMCG driver try to reserve its Page0 and
Page1 resources, a resource conflict occurs.

commit 52f3fab0067d6fa ("iommu/arm-smmu-v3: Don't reserve implementation
defined register space") reduce the resource reservation range of the SMMUv3
driver, it only reserves the first 0xe00 bytes in the 64KB Page0, to avoid
the above-mentioned resource conflicts.

But the SMMUv3.3 add support for ECMDQ, its registers space is also implemented
in the SMMUv3 64KB Page0. This means we need to build two separate mappings.
New features may be added in the future, and more independent mappings may be
required. The simple problem is complicated because the user expects to map the
entire SMMUv3 64KB Page0.

Therefore, the proper solution is: If the PMCG register resources are located in
the 64KB Page0 of the SMMU, the PMCG driver does not reserve the conflict 
resources
when the SMMUv3 driver has reserved the conflict resources before. Instead, the 
PMCG
driver only performs devm_ioremap() to ensure that it can work properly.

Zhen Lei (3):
  perf/smmuv3: Don't reserve the PMCG register spaces
  perf/smmuv3: Add a MODULE_SOFTDEP() to indicate dependency on SMMU
  iommu/arm-smmu-v3: Reserving the entire SMMU register space

 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 28 
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  2 --
 drivers/perf/arm_smmuv3_pmu.c   | 28 ++--
 3 files changed, 30 insertions(+), 28 deletions(-)

-- 
1.8.3


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


[PATCH 1/1] iommu/arm-smmu-v3: Use DEFINE_RES_MEM() to simplify code

2021-01-22 Thread Zhen Lei
No functional change.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index bca458c00e48a8b..f04c55a7503c790 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -3479,11 +3479,7 @@ static int arm_smmu_set_bus_ops(struct iommu_ops *ops)
 static void __iomem *arm_smmu_ioremap(struct device *dev, resource_size_t 
start,
  resource_size_t size)
 {
-   struct resource res = {
-   .flags = IORESOURCE_MEM,
-   .start = start,
-   .end = start + size - 1,
-   };
+   struct resource res = DEFINE_RES_MEM(start, size);
 
return devm_ioremap_resource(dev, );
 }
-- 
1.8.3


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


[PATCH 0/2] Use another method to avoid resource conflicts between the SMMU and PMCG drivers

2021-01-18 Thread Zhen Lei
Since the PMCG may implement its resigters space(4KB Page0 and 4KB Page1)
within the SMMUv3 64KB Page0. In this case, when the SMMUv3 driver reserves the
64KB Page0 resource in advance, the PMCG driver try to reserve its Page0 and
Page1 resources, a resource conflict occurs.

commit 52f3fab0067d6fa ("iommu/arm-smmu-v3: Don't reserve implementation
defined register space") reduce the resource reservation range of the SMMUv3
driver, it only reserves the first 0xe00 bytes in the 64KB Page0, to avoid
the above-mentioned resource conflicts.

But the SMMUv3.3 add support for ECMDQ, its registers space is also implemented
in the SMMUv3 64KB Page0. This means we need to build two separate mappings.
New features may be added in the future, and more independent mappings may be
required. The simple problem is complicated because the user expects to map the
entire SMMUv3 64KB Page0.

Therefore, the proper solution is: If the PMCG register resources are located in
the 64KB Page0 of the SMMU, the PMCG driver does not reserve the conflict 
resources
when the SMMUv3 driver has reserved the conflict resources before. Instead, the 
PMCG
driver only performs devm_ioremap() to ensure that it can work properly.


Zhen Lei (2):
  perf/smmuv3: Don't reserve the register space that overlaps with the
SMMUv3
  Revert "iommu/arm-smmu-v3: Don't reserve implementation defined
register space"

 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 32 +++---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  3 ---
 drivers/perf/arm_smmuv3_pmu.c   | 42 +++--
 3 files changed, 44 insertions(+), 33 deletions(-)

-- 
1.8.3


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


[PATCH 2/2] Revert "iommu/arm-smmu-v3: Don't reserve implementation defined register space"

2021-01-18 Thread Zhen Lei
This reverts commit 52f3fab0067d6fa9e99c1b7f63265dd48ca76046.

This problem has been fixed by another patch. The original method had side
effects, it was not mapped to the user-specified resource size. The code
will become more complex when ECMDQ is supported later.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 32 -
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  3 ---
 2 files changed, 4 insertions(+), 31 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 8ca7415d785d9bf..477f473842e5272 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -91,8 +91,9 @@ struct arm_smmu_option_prop {
 static inline void __iomem *arm_smmu_page1_fixup(unsigned long offset,
 struct arm_smmu_device *smmu)
 {
-   if (offset > SZ_64K)
-   return smmu->page1 + offset - SZ_64K;
+   if ((offset > SZ_64K) &&
+   (smmu->options & ARM_SMMU_OPT_PAGE0_REGS_ONLY))
+   offset -= SZ_64K;
 
return smmu->base + offset;
 }
@@ -3486,18 +3487,6 @@ static int arm_smmu_set_bus_ops(struct iommu_ops *ops)
return err;
 }
 
-static void __iomem *arm_smmu_ioremap(struct device *dev, resource_size_t 
start,
- resource_size_t size)
-{
-   struct resource res = {
-   .flags = IORESOURCE_MEM,
-   .start = start,
-   .end = start + size - 1,
-   };
-
-   return devm_ioremap_resource(dev, );
-}
-
 static int arm_smmu_device_probe(struct platform_device *pdev)
 {
int irq, ret;
@@ -3533,23 +3522,10 @@ static int arm_smmu_device_probe(struct platform_device 
*pdev)
}
ioaddr = res->start;
 
-   /*
-* Don't map the IMPLEMENTATION DEFINED regions, since they may contain
-* the PMCG registers which are reserved by the PMU driver.
-*/
-   smmu->base = arm_smmu_ioremap(dev, ioaddr, ARM_SMMU_REG_SZ);
+   smmu->base = devm_ioremap_resource(dev, res);
if (IS_ERR(smmu->base))
return PTR_ERR(smmu->base);
 
-   if (arm_smmu_resource_size(smmu) > SZ_64K) {
-   smmu->page1 = arm_smmu_ioremap(dev, ioaddr + SZ_64K,
-  ARM_SMMU_REG_SZ);
-   if (IS_ERR(smmu->page1))
-   return PTR_ERR(smmu->page1);
-   } else {
-   smmu->page1 = smmu->base;
-   }
-
/* Interrupt lines */
 
irq = platform_get_irq_byname_optional(pdev, "combined");
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 96c2e9565e00282..0c3090c60840c22 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -152,8 +152,6 @@
 #define ARM_SMMU_PRIQ_IRQ_CFG1 0xd8
 #define ARM_SMMU_PRIQ_IRQ_CFG2 0xdc
 
-#define ARM_SMMU_REG_SZ0xe00
-
 /* Common MSI config fields */
 #define MSI_CFG0_ADDR_MASK GENMASK_ULL(51, 2)
 #define MSI_CFG2_SHGENMASK(5, 4)
@@ -584,7 +582,6 @@ struct arm_smmu_strtab_cfg {
 struct arm_smmu_device {
struct device   *dev;
void __iomem*base;
-   void __iomem*page1;
 
 #define ARM_SMMU_FEAT_2_LVL_STRTAB (1 << 0)
 #define ARM_SMMU_FEAT_2_LVL_CDTAB  (1 << 1)
-- 
1.8.3


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


[PATCH 1/2] perf/smmuv3: Don't reserve the register space that overlaps with the SMMUv3

2021-01-18 Thread Zhen Lei
Some SMMUv3 implementation embed the Perf Monitor Group Registers (PMCG)
inside the first 64kB region of the SMMU. Since SMMU and PMCG are managed
by two separate drivers, and this driver depends on ARM_SMMU_V3, so the
SMMU driver reserves the corresponding resource first, this driver should
not reserve the corresponding resource again. Otherwise, a resource
reservation conflict is reported during boot.

Signed-off-by: Zhen Lei 
---
 drivers/perf/arm_smmuv3_pmu.c | 42 --
 1 file changed, 40 insertions(+), 2 deletions(-)

diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
index 74474bb322c3f26..dcce085431c6ce8 100644
--- a/drivers/perf/arm_smmuv3_pmu.c
+++ b/drivers/perf/arm_smmuv3_pmu.c
@@ -761,6 +761,44 @@ static void smmu_pmu_get_acpi_options(struct smmu_pmu 
*smmu_pmu)
dev_notice(smmu_pmu->dev, "option mask 0x%x\n", smmu_pmu->options);
 }
 
+static void __iomem *
+smmu_pmu_get_and_ioremap_resource(struct platform_device *pdev,
+ unsigned int index,
+ struct resource **out_res)
+{
+   int ret;
+   void __iomem *base;
+   struct resource *res;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, index);
+   if (!res) {
+   dev_err(>dev, "invalid resource\n");
+   return IOMEM_ERR_PTR(-EINVAL);
+   }
+   if (out_res)
+   *out_res = res;
+
+   ret = region_intersects(res->start, resource_size(res),
+   IORESOURCE_MEM, IORES_DESC_NONE);
+   if (ret == REGION_INTERSECTS) {
+   /*
+* The resource has already been reserved by the SMMUv3 driver.
+* Don't reserve it again, just do devm_ioremap().
+*/
+   base = devm_ioremap(>dev, res->start, resource_size(res));
+   } else {
+   /*
+* The resource may have not been reserved by any driver, or
+* has been reserved but not type IORESOURCE_MEM. In the latter
+* case, devm_ioremap_resource() reports a conflict and returns
+* IOMEM_ERR_PTR(-EBUSY).
+*/
+   base = devm_ioremap_resource(>dev, res);
+   }
+
+   return base;
+}
+
 static int smmu_pmu_probe(struct platform_device *pdev)
 {
struct smmu_pmu *smmu_pmu;
@@ -793,7 +831,7 @@ static int smmu_pmu_probe(struct platform_device *pdev)
.capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
};
 
-   smmu_pmu->reg_base = devm_platform_get_and_ioremap_resource(pdev, 0, 
_0);
+   smmu_pmu->reg_base = smmu_pmu_get_and_ioremap_resource(pdev, 0, _0);
if (IS_ERR(smmu_pmu->reg_base))
return PTR_ERR(smmu_pmu->reg_base);
 
@@ -801,7 +839,7 @@ static int smmu_pmu_probe(struct platform_device *pdev)
 
/* Determine if page 1 is present */
if (cfgr & SMMU_PMCG_CFGR_RELOC_CTRS) {
-   smmu_pmu->reloc_base = devm_platform_ioremap_resource(pdev, 1);
+   smmu_pmu->reloc_base = smmu_pmu_get_and_ioremap_resource(pdev, 
1, NULL);
if (IS_ERR(smmu_pmu->reloc_base))
return PTR_ERR(smmu_pmu->reloc_base);
} else {
-- 
1.8.3


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


[PATCH 1/1] iommu/arm-smmu-v3: add support for BBML

2020-11-25 Thread Zhen Lei
When changing from a set of pages/smaller blocks to a larger block for an
address, the software should follow the sequence of BBML processing.

When changing from a block to a set of pages/smaller blocks for an
address, there's no need to use nT bit. If an address in the large block
is accessed before page table switching, the TLB caches the large block
mapping. After the page table is switched and before TLB invalidation
finished, new access requests are still based on large block mapping.
After the block or page is invalidated, the system reads the small block
or page mapping from the memory; If the address in the large block is not
accessed before page table switching, the TLB has no cache. After the
page table is switched, a new access is initiated to read the small block
or page mapping from the memory.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c |  2 +
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  2 +
 drivers/iommu/io-pgtable-arm.c  | 46 -
 include/linux/io-pgtable.h  |  1 +
 4 files changed, 40 insertions(+), 11 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index e634bbe60573..14a1a11565fb 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1977,6 +1977,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain 
*domain,
.coherent_walk  = smmu->features & ARM_SMMU_FEAT_COHERENCY,
.tlb= _smmu_flush_ops,
.iommu_dev  = smmu->dev,
+   .bbml   = smmu->bbml,
};
 
if (smmu_domain->non_strict)
@@ -3291,6 +3292,7 @@ static int arm_smmu_device_hw_probe(struct 
arm_smmu_device *smmu)
 
/* IDR3 */
reg = readl_relaxed(smmu->base + ARM_SMMU_IDR3);
+   smmu->bbml = FIELD_GET(IDR3_BBML, reg);
if (FIELD_GET(IDR3_RIL, reg))
smmu->features |= ARM_SMMU_FEAT_RANGE_INV;
 
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index d4b7f40ccb02..aa7eb460fa09 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -51,6 +51,7 @@
 #define IDR1_SIDSIZE   GENMASK(5, 0)
 
 #define ARM_SMMU_IDR3  0xc
+#define IDR3_BBML  GENMASK(12, 11)
 #define IDR3_RIL   (1 << 10)
 
 #define ARM_SMMU_IDR5  0x14
@@ -617,6 +618,7 @@ struct arm_smmu_device {
 
int gerr_irq;
int combined_irq;
+   int bbml;
 
unsigned long   ias; /* IPA */
unsigned long   oas; /* PA */
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index a7a9bc08dcd1..341581337ad0 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -72,6 +72,7 @@
 
 #define ARM_LPAE_PTE_NSTABLE   (((arm_lpae_iopte)1) << 63)
 #define ARM_LPAE_PTE_XN(((arm_lpae_iopte)3) << 53)
+#define ARM_LPAE_PTE_nT(((arm_lpae_iopte)1) << 16)
 #define ARM_LPAE_PTE_AF(((arm_lpae_iopte)1) << 10)
 #define ARM_LPAE_PTE_SH_NS (((arm_lpae_iopte)0) << 8)
 #define ARM_LPAE_PTE_SH_OS (((arm_lpae_iopte)2) << 8)
@@ -255,7 +256,7 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable 
*data,
 
 static void __arm_lpae_init_pte(struct arm_lpae_io_pgtable *data,
phys_addr_t paddr, arm_lpae_iopte prot,
-   int lvl, arm_lpae_iopte *ptep)
+   int lvl, arm_lpae_iopte *ptep, arm_lpae_iopte 
nT)
 {
arm_lpae_iopte pte = prot;
 
@@ -265,37 +266,60 @@ static void __arm_lpae_init_pte(struct 
arm_lpae_io_pgtable *data,
pte |= ARM_LPAE_PTE_TYPE_BLOCK;
 
pte |= paddr_to_iopte(paddr, data);
+   pte |= nT;
 
__arm_lpae_set_pte(ptep, pte, >iop.cfg);
 }
 
+static void __arm_lpae_free_pgtable(struct arm_lpae_io_pgtable *data, int lvl,
+   arm_lpae_iopte *ptep);
 static int arm_lpae_init_pte(struct arm_lpae_io_pgtable *data,
 unsigned long iova, phys_addr_t paddr,
 arm_lpae_iopte prot, int lvl,
 arm_lpae_iopte *ptep)
 {
arm_lpae_iopte pte = *ptep;
+   struct io_pgtable_cfg *cfg = >iop.cfg;
 
if (iopte_leaf(pte, lvl, data->iop.fmt)) {
/* We require an unmap first */
WARN_ON(!selftest_running);
return -EEXIST;
} else if (iopte_type(pte, lvl) == ARM_LPAE_PTE_TYPE_TABLE) {
-   

[PATCH v3 0/2] improve the concurrency of arm_smmu_atc_inv_domain()

2019-08-22 Thread Zhen Lei
v2 --> v3:
As Will Deacon's suggestion, I changed the lock type of
arm_smmu_domain.devices_lock from spinlock_t to rwlock_t, and I saw that the
performance is all right. And further use nr_ats_masters to quickly check have
no obvious effect, so I drop it.

Here is the performance data tested on my board:
Withou any change:
Jobs: 24 (f=24): [0.1% done] [9798M/0K /s] [2392K/0  iops] [09h:59m:13s]
Jobs: 24 (f=24): [0.1% done] [9782M/0K /s] [2388K/0  iops] [09h:59m:12s]
Jobs: 24 (f=24): [0.2% done] [9825M/0K /s] [2399K/0  iops] [09h:59m:11s]
Jobs: 24 (f=24): [0.2% done] [9836M/0K /s] [2401K/0  iops] [09h:59m:10s]

Change lock type from spinlock_t to rwlock_t:
Jobs: 24 (f=24): [0.1% done] [10996M/0K /s] [2685K/0  iops] [09h:59m:13s]
Jobs: 24 (f=24): [0.1% done] [10817M/0K /s] [2641K/0  iops] [09h:59m:12s]
Jobs: 24 (f=24): [0.2% done] [11083M/0K /s] [2706K/0  iops] [09h:59m:11s]
Jobs: 24 (f=24): [0.2% done] [10603M/0K /s] [2589K/0  iops] [09h:59m:10s]

Use nr_ats_masters:
Jobs: 24 (f=24): [0.2% done] [11105M/0K /s] [2711K/0  iops] [eta 09h:58m:40s]
Jobs: 24 (f=24): [0.2% done] [10511M/0K /s] [2566K/0  iops] [eta 09h:58m:39s]
Jobs: 24 (f=24): [0.2% done] [10560M/0K /s] [2578K/0  iops] [eta 09h:58m:38s]
Jobs: 24 (f=24): [0.2% done] [10494M/0K /s] [2562K/0  iops] [eta 09h:58m:37s]
Jobs: 24 (f=24): [0.2% done] [10528M/0K /s] [2570K/0  iops] [eta 09h:58m:36s]
Jobs: 24 (f=24): [0.3% done] [10638M/0K /s] [2597K/0  iops] [eta 09h:58m:35s]
Jobs: 24 (f=24): [0.3% done] [11158M/0K /s] [2724K/0  iops] [eta 09h:58m:34s]
Jobs: 24 (f=24): [0.3% done] [11386M/0K /s] [2780K/0  iops] [eta 09h:58m:32s]
Jobs: 24 (f=24): [0.3% done] [8M/0K /s] [2714K/0  iops] [eta 09h:58m:32s]
Jobs: 24 (f=24): [0.3% done] [11031M/0K /s] [2693K/0  iops] [eta 09h:58m:31s]
Jobs: 24 (f=24): [0.3% done] [11361M/0K /s] [2774K/0  iops] [eta 09h:58m:30s]

v1 --> v2:
1. change the type of nr_ats_masters from atomic_t to int, and move its
   ind/dec operation from arm_smmu_enable_ats()/arm_smmu_disable_ats() to
   arm_smmu_attach_dev()/arm_smmu_detach_dev(), and protected by
   "spin_lock_irqsave(_domain->devices_lock, flags);"

Zhen Lei (2):
  iommu/arm-smmu-v3: don't add a master into smmu_domain before it's
ready
  iommu/arm-smmu-v3: change the lock type of
arm_smmu_domain.devices_lock

 drivers/iommu/arm-smmu-v3.c | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

-- 
1.8.3


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


[PATCH v3 1/2] iommu/arm-smmu-v3: don't add a master into smmu_domain before it's ready

2019-08-22 Thread Zhen Lei
Once a master has been added into smmu_domain->devices, it may immediately
be scaned in arm_smmu_unmap()-->arm_smmu_atc_inv_domain(). From a logical
point of view, the master should be added into smmu_domain after it has
completely initialized.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm-smmu-v3.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index c5c93e48b4dbdf7..e0dcc5d27291f8b 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -1958,10 +1958,6 @@ static int arm_smmu_attach_dev(struct iommu_domain 
*domain, struct device *dev)
 
master->domain = smmu_domain;
 
-   spin_lock_irqsave(_domain->devices_lock, flags);
-   list_add(>domain_head, _domain->devices);
-   spin_unlock_irqrestore(_domain->devices_lock, flags);
-
if (smmu_domain->stage != ARM_SMMU_DOMAIN_BYPASS)
arm_smmu_enable_ats(master);
 
@@ -1969,6 +1965,10 @@ static int arm_smmu_attach_dev(struct iommu_domain 
*domain, struct device *dev)
arm_smmu_write_ctx_desc(smmu, _domain->s1_cfg);
 
arm_smmu_install_ste_for_dev(master);
+
+   spin_lock_irqsave(_domain->devices_lock, flags);
+   list_add(>domain_head, _domain->devices);
+   spin_unlock_irqrestore(_domain->devices_lock, flags);
 out_unlock:
mutex_unlock(_domain->init_mutex);
return ret;
-- 
1.8.3


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


[PATCH v3 2/2] iommu/arm-smmu-v3: change the lock type of arm_smmu_domain.devices_lock

2019-08-22 Thread Zhen Lei
A master add into or remove from smmu_domain->devices only happened in
arm_smmu_attach_dev()/arm_smmu_detach_dev(), the frequency of these
operations is very low. But we traverse smmu_domain->devices list in
arm_smmu_atc_inv_domain() are frequent. So change the protection from
spinlock to rwlock can improve concurrency, especially for the smmu
domain without ATS masters.

By the way, the cmdq has its own lock, so this change is safe.

Here is the performance data tested on my board:
Before:
Jobs: 24 (f=24): [0.1% done] [9798M/0K /s] [2392K/0  iops] [09h:59m:13s]
Jobs: 24 (f=24): [0.1% done] [9782M/0K /s] [2388K/0  iops] [09h:59m:12s]
Jobs: 24 (f=24): [0.2% done] [9825M/0K /s] [2399K/0  iops] [09h:59m:11s]
Jobs: 24 (f=24): [0.2% done] [9836M/0K /s] [2401K/0  iops] [09h:59m:10s]

After:
Jobs: 24 (f=24): [0.1% done] [10996M/0K /s] [2685K/0  iops] [09h:59m:13s]
Jobs: 24 (f=24): [0.1% done] [10817M/0K /s] [2641K/0  iops] [09h:59m:12s]
Jobs: 24 (f=24): [0.2% done] [11083M/0K /s] [2706K/0  iops] [09h:59m:11s]
Jobs: 24 (f=24): [0.2% done] [10603M/0K /s] [2589K/0  iops] [09h:59m:10s]

Signed-off-by: Zhen Lei 
Suggested-by: Will Deacon 
---
 drivers/iommu/arm-smmu-v3.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index e0dcc5d27291f8b..eded2e7a5a0c444 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -641,7 +641,7 @@ struct arm_smmu_domain {
struct iommu_domain domain;
 
struct list_headdevices;
-   spinlock_t  devices_lock;
+   rwlock_tdevices_lock;
 };
 
 struct arm_smmu_option_prop {
@@ -1536,10 +1536,10 @@ static int arm_smmu_atc_inv_domain(struct 
arm_smmu_domain *smmu_domain,
 
arm_smmu_atc_inv_to_cmd(ssid, iova, size, );
 
-   spin_lock_irqsave(_domain->devices_lock, flags);
+   read_lock_irqsave(_domain->devices_lock, flags);
list_for_each_entry(master, _domain->devices, domain_head)
ret |= arm_smmu_atc_inv_master(master, );
-   spin_unlock_irqrestore(_domain->devices_lock, flags);
+   read_unlock_irqrestore(_domain->devices_lock, flags);
 
return ret ? -ETIMEDOUT : 0;
 }
@@ -1648,7 +1648,7 @@ static struct iommu_domain 
*arm_smmu_domain_alloc(unsigned type)
 
mutex_init(_domain->init_mutex);
INIT_LIST_HEAD(_domain->devices);
-   spin_lock_init(_domain->devices_lock);
+   rwlock_init(_domain->devices_lock);
 
return _domain->domain;
 }
@@ -1911,9 +1911,9 @@ static void arm_smmu_detach_dev(struct arm_smmu_master 
*master)
if (!smmu_domain)
return;
 
-   spin_lock_irqsave(_domain->devices_lock, flags);
+   write_lock_irqsave(_domain->devices_lock, flags);
list_del(>domain_head);
-   spin_unlock_irqrestore(_domain->devices_lock, flags);
+   write_unlock_irqrestore(_domain->devices_lock, flags);
 
master->domain = NULL;
arm_smmu_install_ste_for_dev(master);
@@ -1966,9 +1966,9 @@ static int arm_smmu_attach_dev(struct iommu_domain 
*domain, struct device *dev)
 
arm_smmu_install_ste_for_dev(master);
 
-   spin_lock_irqsave(_domain->devices_lock, flags);
+   write_lock_irqsave(_domain->devices_lock, flags);
list_add(>domain_head, _domain->devices);
-   spin_unlock_irqrestore(_domain->devices_lock, flags);
+   write_unlock_irqrestore(_domain->devices_lock, flags);
 out_unlock:
mutex_unlock(_domain->init_mutex);
return ret;
-- 
1.8.3


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


[PATCH v2 0/2] iommu/iova: enhance the rcache optimization

2019-08-15 Thread Zhen Lei
v1 --> v2
1. I did not chagne the patches but added this cover-letter.
2. Add a batch of reviewers base on
   9257b4a206fc ("iommu/iova: introduce per-cpu caching to iova allocation")
3. I described the problem I met in patch 2, but I hope below brief description
   can help people to quickly understand.
   Suppose there are six rcache sizes, each size can maximum hold 1 IOVAs.
   
   |  4K   |  8K  | 16K  |  32K | 64K  | 128K |
   
   | 1 | 9000 | 8500 | 8600 | 9200 | 7000 |
   
   As the above map displayed, the whole rcache buffered too many IOVAs. Now, 
the
   worst case can be coming, suppose we need 2 4K IOVAs at one time. That 
means
   1 IOVAs can be allocated from rcache, but another 1 IOVAs should be 
   allocated from RB tree base on alloc_iova() function. But the RB tree 
currently
   have at least (9000 + 8500 + 8600 + 9200 + 7000) = 42300 nodes. The average 
speed
   of RB tree traverse will be very slow. For my test scenario, the 4K size 
IOVAs are
   frequently used, but others are not. So similarly, when the 2 4K IOVAs 
are
   continuous freed, the first 1 IOVAs can be quickly buffered, but the 
other
   1 IOVAs can not.

Zhen Lei (2):
  iommu/iova: introduce iova_magazine_compact_pfns()
  iommu/iova: enhance the rcache optimization

 drivers/iommu/iova.c | 100 +++
 include/linux/iova.h |   1 +
 2 files changed, 95 insertions(+), 6 deletions(-)

-- 
1.8.3




[PATCH v2 1/2] iommu/iova: introduce iova_magazine_compact_pfns()

2019-08-15 Thread Zhen Lei
iova_magazine_free_pfns() can only free the whole magazine buffer, add
iova_magazine_compact_pfns() to support free part of it.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/iova.c | 17 -
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 3e1a8a6755723a9..4b7a9efa0ef40af 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -795,18 +795,19 @@ static void iova_magazine_free(struct iova_magazine *mag)
kfree(mag);
 }
 
-static void
-iova_magazine_free_pfns(struct iova_magazine *mag, struct iova_domain *iovad)
+static void iova_magazine_compact_pfns(struct iova_magazine *mag,
+  struct iova_domain *iovad,
+  unsigned long newsize)
 {
unsigned long flags;
int i;
 
-   if (!mag)
+   if (!mag || mag->size <= newsize)
return;
 
spin_lock_irqsave(>iova_rbtree_lock, flags);
 
-   for (i = 0 ; i < mag->size; ++i) {
+   for (i = newsize; i < mag->size; ++i) {
struct iova *iova = private_find_iova(iovad, mag->pfns[i]);
 
BUG_ON(!iova);
@@ -815,7 +816,13 @@ static void iova_magazine_free(struct iova_magazine *mag)
 
spin_unlock_irqrestore(>iova_rbtree_lock, flags);
 
-   mag->size = 0;
+   mag->size = newsize;
+}
+
+static void
+iova_magazine_free_pfns(struct iova_magazine *mag, struct iova_domain *iovad)
+{
+   iova_magazine_compact_pfns(mag, iovad, 0);
 }
 
 static bool iova_magazine_full(struct iova_magazine *mag)
-- 
1.8.3


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


[PATCH v2 2/2] iommu/iova: enhance the rcache optimization

2019-08-15 Thread Zhen Lei
The rcache method caches the freed IOVAs, to improve the performance of
IOVAs allocation and release. This is usually okay, but it maybe declined
in some special scenarios.

For example, currently the IOVA_RANGE_CACHE_MAX_SIZE is 6, and for ecch
size, contains: MAX_GLOBAL_MAGS=32 shareable depot magazines, each vcpu
has two magazines(cpu_rcaches->loaded and cpu_rcaches->prev). In an
extreme case, it can max cache ((num_possible_cpus() * 2 + 32) * 128 * 6)
IOVAs, it's very large. The worst case happens when the depot magazines
of a certain size(usually 4K) is full, further free_iova_fast() invoking
will cause iova_magazine_free_pfns() to be called. As the above saied,
too many IOVAs buffered, so that the RB tree is very large, the
iova_magazine_free_pfns()-->private_find_iova(), and the missed iova
allocation: alloc_iova()-->__alloc_and_insert_iova_range() will spend too
much time. And that the current rcache method have no cleanup operation,
the buffered IOVAs will only increase but not decrease.

For my FIO stress test scenario, the performance drop about 35%, and can
not recover even if re-execute the test cases.
Jobs: 21 (f=21): [2.3% done] [8887M/0K /s] [2170K/0 iops]
Jobs: 21 (f=21): [2.3% done] [8902M/0K /s] [2173K/0 iops]
Jobs: 21 (f=21): [2.3% done] [6010M/0K /s] [1467K/0 iops]
Jobs: 21 (f=21): [2.3% done] [5397M/0K /s] [1318K/0 iops]

So that, I add the statistic about the rcache, when the above case
happened, release the IOVAs which are not hit.
Jobs: 21 (f=21): [100.0% done] [10324M/0K /s] [2520K/0 iops]
Jobs: 21 (f=21): [100.0% done] [10290M/0K /s] [2512K/0 iops]
Jobs: 21 (f=21): [100.0% done] [10035M/0K /s] [2450K/0 iops]
Jobs: 21 (f=21): [100.0% done] [10214M/0K /s] [2494K/0 iops]

Signed-off-by: Zhen Lei 
---
 drivers/iommu/iova.c | 83 +++-
 include/linux/iova.h |  1 +
 2 files changed, 83 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 4b7a9efa0ef40af..f3828f4add25375 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -23,6 +23,8 @@ static unsigned long iova_rcache_get(struct iova_domain 
*iovad,
 unsigned long limit_pfn);
 static void init_iova_rcaches(struct iova_domain *iovad);
 static void free_iova_rcaches(struct iova_domain *iovad);
+static void iova_compact_rcache(struct iova_domain *iovad,
+   struct iova_rcache *curr_rcache);
 static void fq_destroy_all_entries(struct iova_domain *iovad);
 static void fq_flush_timeout(struct timer_list *t);
 
@@ -781,6 +783,8 @@ struct iova_magazine {
 
 struct iova_cpu_rcache {
spinlock_t lock;
+   bool prev_mag_hit;
+   unsigned long nr_hit;
struct iova_magazine *loaded;
struct iova_magazine *prev;
 };
@@ -934,6 +938,7 @@ static bool __iova_rcache_insert(struct iova_domain *iovad,
if (mag_to_free) {
iova_magazine_free_pfns(mag_to_free, iovad);
iova_magazine_free(mag_to_free);
+   iova_compact_rcache(iovad, rcache);
}
 
return can_insert;
@@ -971,18 +976,22 @@ static unsigned long __iova_rcache_get(struct iova_rcache 
*rcache,
} else if (!iova_magazine_empty(cpu_rcache->prev)) {
swap(cpu_rcache->prev, cpu_rcache->loaded);
has_pfn = true;
+   cpu_rcache->prev_mag_hit = true;
} else {
spin_lock(>lock);
if (rcache->depot_size > 0) {
iova_magazine_free(cpu_rcache->loaded);
cpu_rcache->loaded = 
rcache->depot[--rcache->depot_size];
has_pfn = true;
+   rcache->depot_mags_hit = true;
}
spin_unlock(>lock);
}
 
-   if (has_pfn)
+   if (has_pfn) {
+   cpu_rcache->nr_hit++;
iova_pfn = iova_magazine_pop(cpu_rcache->loaded, limit_pfn);
+   }
 
spin_unlock_irqrestore(_rcache->lock, flags);
 
@@ -1049,5 +1058,77 @@ void free_cpu_cached_iovas(unsigned int cpu, struct 
iova_domain *iovad)
}
 }
 
+static void iova_compact_percpu_mags(struct iova_domain *iovad,
+struct iova_rcache *rcache)
+{
+   unsigned int cpu;
+
+   for_each_possible_cpu(cpu) {
+   unsigned long flags;
+   struct iova_cpu_rcache *cpu_rcache;
+
+   cpu_rcache = per_cpu_ptr(rcache->cpu_rcaches, cpu);
+
+   spin_lock_irqsave(_rcache->lock, flags);
+   if (!cpu_rcache->prev_mag_hit)
+   iova_magazine_free_pfns(cpu_rcache->prev, iovad);
+
+   if (cpu_rcache->nr_hit < IOVA_MAG_SIZE)
+   iova_magazine_compact_pfns(cpu_rcache->loaded,
+  iovad,
+  

[PATCH v2 0/2] add nr_ats_masters for quickly check

2019-08-14 Thread Zhen Lei
v1 --> v2:
1. change the type of nr_ats_masters from atomic_t to int, and move its
   ind/dec operation from arm_smmu_enable_ats()/arm_smmu_disable_ats() to
   arm_smmu_attach_dev()/arm_smmu_detach_dev(), and protected by
   "spin_lock_irqsave(_domain->devices_lock, flags);"

Zhen Lei (2):
  iommu/arm-smmu-v3: don't add a master into smmu_domain before it's
ready
  iommu/arm-smmu-v3: add nr_ats_masters for quickly check

 drivers/iommu/arm-smmu-v3.c | 22 +-
 1 file changed, 17 insertions(+), 5 deletions(-)

-- 
1.8.3




[PATCH v2 2/2] iommu/arm-smmu-v3: add nr_ats_masters for quickly check

2019-08-14 Thread Zhen Lei
When (smmu_domain->smmu->features & ARM_SMMU_FEAT_ATS) is true, even if a
smmu domain does not contain any ats master, the operations of
arm_smmu_atc_inv_to_cmd() and lock protection in arm_smmu_atc_inv_domain()
are always executed. This will impact performance, especially in
multi-core and stress scenarios. For my FIO test scenario, about 8%
performance reduced.

In fact, we can use a struct member to record how many ats masters that
the smmu contains. And check that without traverse the list and check all
masters one by one in the lock protection.

Fixes: 9ce27afc0830 ("iommu/arm-smmu-v3: Add support for PCI ATS")
Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm-smmu-v3.c | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 29056d9bb12aa01..154334d3310c9b8 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -631,6 +631,7 @@ struct arm_smmu_domain {
 
struct io_pgtable_ops   *pgtbl_ops;
boolnon_strict;
+   int nr_ats_masters;
 
enum arm_smmu_domain_stage  stage;
union {
@@ -1531,7 +1532,16 @@ static int arm_smmu_atc_inv_domain(struct 
arm_smmu_domain *smmu_domain,
struct arm_smmu_cmdq_ent cmd;
struct arm_smmu_master *master;
 
-   if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_ATS))
+   /*
+* The protectiom of spinlock(_domain->devices_lock) is omitted.
+* Because for a given master, its map/unmap operations should only be
+* happened after it has been attached and before it has been detached.
+* So that, if at least one master need to be atc invalidated, the
+* value of smmu_domain->nr_ats_masters can not be zero.
+*
+* This can alleviate performance loss in multi-core scenarios.
+*/
+   if (!smmu_domain->nr_ats_masters)
return 0;
 
arm_smmu_atc_inv_to_cmd(ssid, iova, size, );
@@ -1913,6 +1923,7 @@ static void arm_smmu_detach_dev(struct arm_smmu_master 
*master)
 
spin_lock_irqsave(_domain->devices_lock, flags);
list_del(>domain_head);
+   smmu_domain->nr_ats_masters--;
spin_unlock_irqrestore(_domain->devices_lock, flags);
 
master->domain = NULL;
@@ -1968,6 +1979,7 @@ static int arm_smmu_attach_dev(struct iommu_domain 
*domain, struct device *dev)
 
spin_lock_irqsave(_domain->devices_lock, flags);
list_add(>domain_head, _domain->devices);
+   smmu_domain->nr_ats_masters++;
spin_unlock_irqrestore(_domain->devices_lock, flags);
 out_unlock:
mutex_unlock(_domain->init_mutex);
-- 
1.8.3


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


[PATCH v2 1/2] iommu/arm-smmu-v3: don't add a master into smmu_domain before it's ready

2019-08-14 Thread Zhen Lei
Once a master has been added into smmu_domain->devices, it may immediately
be scaned in arm_smmu_unmap()-->arm_smmu_atc_inv_domain(). From a logical
point of view, the master should be added into smmu_domain after it has
been completely initialized.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm-smmu-v3.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index a9a9fabd396804a..29056d9bb12aa01 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -1958,10 +1958,6 @@ static int arm_smmu_attach_dev(struct iommu_domain 
*domain, struct device *dev)
 
master->domain = smmu_domain;
 
-   spin_lock_irqsave(_domain->devices_lock, flags);
-   list_add(>domain_head, _domain->devices);
-   spin_unlock_irqrestore(_domain->devices_lock, flags);
-
if (smmu_domain->stage != ARM_SMMU_DOMAIN_BYPASS)
arm_smmu_enable_ats(master);
 
@@ -1969,6 +1965,10 @@ static int arm_smmu_attach_dev(struct iommu_domain 
*domain, struct device *dev)
arm_smmu_write_ctx_desc(smmu, _domain->s1_cfg);
 
arm_smmu_install_ste_for_dev(master);
+
+   spin_lock_irqsave(_domain->devices_lock, flags);
+   list_add(>domain_head, _domain->devices);
+   spin_unlock_irqrestore(_domain->devices_lock, flags);
 out_unlock:
mutex_unlock(_domain->init_mutex);
return ret;
-- 
1.8.3




[PATCH 2/2] iommu/iova: enhance the rcache optimization

2019-08-01 Thread Zhen Lei
The rcache method caches the freed IOVAs, to improve the performance of
IOVAs allocation and release. This is usually okay, but it maybe declined
in some special scenarios.

For example, currently the IOVA_RANGE_CACHE_MAX_SIZE is 6, and for ecch
size, contains: MAX_GLOBAL_MAGS=32 shareable depot magazines, each vcpu
has two magazines(cpu_rcaches->loaded and cpu_rcaches->prev). In an
extreme case, it can max cache ((num_possible_cpus() * 2 + 32) * 128 * 6)
IOVAs, it's very large. The worst case happens when the depot magazines
of a certain size(usually 4K) is full, further free_iova_fast() invoking
will cause iova_magazine_free_pfns() to be called. As the above saied,
too many IOVAs buffered, so that the RB tree is very large, the
iova_magazine_free_pfns()-->private_find_iova(), and the missed iova
allocation: alloc_iova()-->__alloc_and_insert_iova_range() will spend too
much time. And that the current rcache method have no cleanup operation,
the buffered IOVAs will only increase but not decrease.

For my FIO stress test scenario, the performance drop about 35%, and can
not recover even if re-execute the test cases.
Jobs: 21 (f=21): [2.3% done] [8887M/0K /s] [2170K/0 iops]
Jobs: 21 (f=21): [2.3% done] [8902M/0K /s] [2173K/0 iops]
Jobs: 21 (f=21): [2.3% done] [6010M/0K /s] [1467K/0 iops]
Jobs: 21 (f=21): [2.3% done] [5397M/0K /s] [1318K/0 iops]

So that, I add the statistic about the rcache, when the above case
happened, release the IOVAs which are not hit.
Jobs: 21 (f=21): [100.0% done] [10324M/0K /s] [2520K/0 iops]
Jobs: 21 (f=21): [100.0% done] [10290M/0K /s] [2512K/0 iops]
Jobs: 21 (f=21): [100.0% done] [10035M/0K /s] [2450K/0 iops]
Jobs: 21 (f=21): [100.0% done] [10214M/0K /s] [2494K/0 iops]

Signed-off-by: Zhen Lei 
---
 drivers/iommu/iova.c | 83 +++-
 include/linux/iova.h |  1 +
 2 files changed, 83 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 4b7a9efa0ef40af..f3828f4add25375 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -23,6 +23,8 @@ static unsigned long iova_rcache_get(struct iova_domain 
*iovad,
 unsigned long limit_pfn);
 static void init_iova_rcaches(struct iova_domain *iovad);
 static void free_iova_rcaches(struct iova_domain *iovad);
+static void iova_compact_rcache(struct iova_domain *iovad,
+   struct iova_rcache *curr_rcache);
 static void fq_destroy_all_entries(struct iova_domain *iovad);
 static void fq_flush_timeout(struct timer_list *t);
 
@@ -781,6 +783,8 @@ struct iova_magazine {
 
 struct iova_cpu_rcache {
spinlock_t lock;
+   bool prev_mag_hit;
+   unsigned long nr_hit;
struct iova_magazine *loaded;
struct iova_magazine *prev;
 };
@@ -934,6 +938,7 @@ static bool __iova_rcache_insert(struct iova_domain *iovad,
if (mag_to_free) {
iova_magazine_free_pfns(mag_to_free, iovad);
iova_magazine_free(mag_to_free);
+   iova_compact_rcache(iovad, rcache);
}
 
return can_insert;
@@ -971,18 +976,22 @@ static unsigned long __iova_rcache_get(struct iova_rcache 
*rcache,
} else if (!iova_magazine_empty(cpu_rcache->prev)) {
swap(cpu_rcache->prev, cpu_rcache->loaded);
has_pfn = true;
+   cpu_rcache->prev_mag_hit = true;
} else {
spin_lock(>lock);
if (rcache->depot_size > 0) {
iova_magazine_free(cpu_rcache->loaded);
cpu_rcache->loaded = 
rcache->depot[--rcache->depot_size];
has_pfn = true;
+   rcache->depot_mags_hit = true;
}
spin_unlock(>lock);
}
 
-   if (has_pfn)
+   if (has_pfn) {
+   cpu_rcache->nr_hit++;
iova_pfn = iova_magazine_pop(cpu_rcache->loaded, limit_pfn);
+   }
 
spin_unlock_irqrestore(_rcache->lock, flags);
 
@@ -1049,5 +1058,77 @@ void free_cpu_cached_iovas(unsigned int cpu, struct 
iova_domain *iovad)
}
 }
 
+static void iova_compact_percpu_mags(struct iova_domain *iovad,
+struct iova_rcache *rcache)
+{
+   unsigned int cpu;
+
+   for_each_possible_cpu(cpu) {
+   unsigned long flags;
+   struct iova_cpu_rcache *cpu_rcache;
+
+   cpu_rcache = per_cpu_ptr(rcache->cpu_rcaches, cpu);
+
+   spin_lock_irqsave(_rcache->lock, flags);
+   if (!cpu_rcache->prev_mag_hit)
+   iova_magazine_free_pfns(cpu_rcache->prev, iovad);
+
+   if (cpu_rcache->nr_hit < IOVA_MAG_SIZE)
+   iova_magazine_compact_pfns(cpu_rcache->loaded,
+  iovad,
+  

[PATCH 1/2] iommu/iova: introduce iova_magazine_compact_pfns()

2019-08-01 Thread Zhen Lei
iova_magazine_free_pfns() can only free the whole magazine buffer, add
iova_magazine_compact_pfns() to support free part of it.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/iova.c | 17 -
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 3e1a8a6755723a9..4b7a9efa0ef40af 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -795,18 +795,19 @@ static void iova_magazine_free(struct iova_magazine *mag)
kfree(mag);
 }
 
-static void
-iova_magazine_free_pfns(struct iova_magazine *mag, struct iova_domain *iovad)
+static void iova_magazine_compact_pfns(struct iova_magazine *mag,
+  struct iova_domain *iovad,
+  unsigned long newsize)
 {
unsigned long flags;
int i;
 
-   if (!mag)
+   if (!mag || mag->size <= newsize)
return;
 
spin_lock_irqsave(>iova_rbtree_lock, flags);
 
-   for (i = 0 ; i < mag->size; ++i) {
+   for (i = newsize; i < mag->size; ++i) {
struct iova *iova = private_find_iova(iovad, mag->pfns[i]);
 
BUG_ON(!iova);
@@ -815,7 +816,13 @@ static void iova_magazine_free(struct iova_magazine *mag)
 
spin_unlock_irqrestore(>iova_rbtree_lock, flags);
 
-   mag->size = 0;
+   mag->size = newsize;
+}
+
+static void
+iova_magazine_free_pfns(struct iova_magazine *mag, struct iova_domain *iovad)
+{
+   iova_magazine_compact_pfns(mag, iovad, 0);
 }
 
 static bool iova_magazine_full(struct iova_magazine *mag)
-- 
1.8.3


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


[PATCH] iommu/arm-smmu-v3: add nr_ats_masters to avoid unnecessary operations

2019-08-01 Thread Zhen Lei
When (smmu_domain->smmu->features & ARM_SMMU_FEAT_ATS) is true, even if a
smmu domain does not contain any ats master, the operations of
arm_smmu_atc_inv_to_cmd() and lock protection in arm_smmu_atc_inv_domain()
are always executed. This will impact performance, especially in
multi-core and stress scenarios. For my FIO test scenario, about 8%
performance reduced.

In fact, we can use a atomic member to record how many ats masters the
smmu contains. And check that without traverse the list and check all
masters one by one in the lock protection.

Fixes: 9ce27afc0830 ("iommu/arm-smmu-v3: Add support for PCI ATS")
Signed-off-by: Zhen Lei 
---
 drivers/iommu/arm-smmu-v3.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index a9a9fabd396804a..1b370d9aca95f94 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -631,6 +631,7 @@ struct arm_smmu_domain {
 
struct io_pgtable_ops   *pgtbl_ops;
boolnon_strict;
+   atomic_tnr_ats_masters;
 
enum arm_smmu_domain_stage  stage;
union {
@@ -1531,7 +1532,7 @@ static int arm_smmu_atc_inv_domain(struct arm_smmu_domain 
*smmu_domain,
struct arm_smmu_cmdq_ent cmd;
struct arm_smmu_master *master;
 
-   if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_ATS))
+   if (!atomic_read(_domain->nr_ats_masters))
return 0;
 
arm_smmu_atc_inv_to_cmd(ssid, iova, size, );
@@ -1869,6 +1870,7 @@ static int arm_smmu_enable_ats(struct arm_smmu_master 
*master)
size_t stu;
struct pci_dev *pdev;
struct arm_smmu_device *smmu = master->smmu;
+   struct arm_smmu_domain *smmu_domain = master->domain;
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(master->dev);
 
if (!(smmu->features & ARM_SMMU_FEAT_ATS) || !dev_is_pci(master->dev) ||
@@ -1887,12 +1889,15 @@ static int arm_smmu_enable_ats(struct arm_smmu_master 
*master)
return ret;
 
master->ats_enabled = true;
+   atomic_inc(_domain->nr_ats_masters);
+
return 0;
 }
 
 static void arm_smmu_disable_ats(struct arm_smmu_master *master)
 {
struct arm_smmu_cmdq_ent cmd;
+   struct arm_smmu_domain *smmu_domain = master->domain;
 
if (!master->ats_enabled || !dev_is_pci(master->dev))
return;
@@ -1901,6 +1906,7 @@ static void arm_smmu_disable_ats(struct arm_smmu_master 
*master)
arm_smmu_atc_inv_master(master, );
pci_disable_ats(to_pci_dev(master->dev));
master->ats_enabled = false;
+   atomic_dec(_domain->nr_ats_masters);
 }
 
 static void arm_smmu_detach_dev(struct arm_smmu_master *master)
@@ -1915,10 +1921,10 @@ static void arm_smmu_detach_dev(struct arm_smmu_master 
*master)
list_del(>domain_head);
spin_unlock_irqrestore(_domain->devices_lock, flags);
 
-   master->domain = NULL;
arm_smmu_install_ste_for_dev(master);
 
arm_smmu_disable_ats(master);
+   master->domain = NULL;
 }
 
 static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
-- 
1.8.3




[PATCH v9 5/7] iommu/vt-d: add support for IOMMU default DMA mode build options

2019-06-13 Thread Zhen Lei
The default DMA mode of INTEL IOMMU is LAZY, this patch make it can be
set to STRICT at build time. It can be overridden by boot option.

There is no functional change.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/Kconfig   | 2 +-
 drivers/iommu/intel-iommu.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index bfbcaa24e283aad..fd297b0e0330d27 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -79,7 +79,7 @@ choice
prompt "IOMMU default DMA mode"
depends on IOMMU_API
default IOMMU_DEFAULT_PASSTHROUGH if (PPC_POWERNV && PCI)
-   default IOMMU_DEFAULT_LAZY if S390_IOMMU
+   default IOMMU_DEFAULT_LAZY if (INTEL_IOMMU || S390_IOMMU)
default IOMMU_DEFAULT_STRICT
help
  This option allows an IOMMU DMA mode to be chosen at build time, to
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 162b3236e72c3c8..ec5515b7831b23f 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -354,7 +354,7 @@ static int domain_detach_iommu(struct dmar_domain *domain,
 
 static int dmar_map_gfx = 1;
 static int dmar_forcedac;
-static int intel_iommu_strict;
+static int intel_iommu_strict = IS_ENABLED(CONFIG_IOMMU_DEFAULT_STRICT);
 static int intel_iommu_superpage = 1;
 static int intel_iommu_sm;
 static int iommu_identity_mapping;
-- 
1.8.3


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


[PATCH v9 7/7] ia64: hide build option IOMMU_DEFAULT_PASSTHROUGH

2019-06-13 Thread Zhen Lei
The DMA mode PASSTHROUGH is not used on ia64.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 70741fd73b07785..63506f1cad3d149 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -91,7 +91,7 @@ choice
 
 config IOMMU_DEFAULT_PASSTHROUGH
bool "passthrough"
-   depends on !S390_IOMMU
+   depends on (!S390_IOMMU && !IA64)
help
  In this mode, the DMA access through IOMMU without any addresses
  translation. That means, the wrong or illegal DMA access can not
-- 
1.8.3


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


[PATCH v9 3/7] s390/pci: add support for IOMMU default DMA mode build options

2019-06-13 Thread Zhen Lei
The default DMA mode is LAZY on s390, this patch make it can be set to
STRICT at build time. It can be overridden by boot option.

There is no functional change.

Signed-off-by: Zhen Lei 
Acked-by: Sebastian Ott 
---
 arch/s390/pci/pci_dma.c | 2 +-
 drivers/iommu/Kconfig   | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
index 9e52d1527f71495..784ad1e0acecfb1 100644
--- a/arch/s390/pci/pci_dma.c
+++ b/arch/s390/pci/pci_dma.c
@@ -17,7 +17,7 @@
 
 static struct kmem_cache *dma_region_table_cache;
 static struct kmem_cache *dma_page_table_cache;
-static int s390_iommu_strict;
+static int s390_iommu_strict = IS_ENABLED(CONFIG_IOMMU_DEFAULT_STRICT);
 
 static int zpci_refresh_global(struct zpci_dev *zdev)
 {
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index fe715fb295c6ed2..a8dd69d175fb3c6 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -78,6 +78,7 @@ config IOMMU_DEBUGFS
 choice
prompt "IOMMU default DMA mode"
depends on IOMMU_API
+   default IOMMU_DEFAULT_LAZY if S390_IOMMU
default IOMMU_DEFAULT_STRICT
help
  This option allows an IOMMU DMA mode to be chosen at build time, to
@@ -89,6 +90,7 @@ choice
 
 config IOMMU_DEFAULT_PASSTHROUGH
bool "passthrough"
+   depends on !S390_IOMMU
help
  In this mode, the DMA access through IOMMU without any addresses
  translation. That means, the wrong or illegal DMA access can not
-- 
1.8.3


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


[PATCH v9 2/7] x86/dma: use IS_ENABLED() to simplify the code

2019-06-13 Thread Zhen Lei
Remove the ifdefs around CONFIG_IOMMU_DEFAULT_PASSTHROUGH to improve
readablity.

Signed-off-by: Zhen Lei 
---
 arch/x86/kernel/pci-dma.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index dcd272dbd0a9330..8c82b2e28a0fe2d 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -43,11 +43,7 @@
  * It is also possible to disable by default in kernel config, and enable with
  * iommu=nopt at boot time.
  */
-#ifdef CONFIG_IOMMU_DEFAULT_PASSTHROUGH
-int iommu_pass_through __read_mostly = 1;
-#else
-int iommu_pass_through __read_mostly;
-#endif
+int iommu_pass_through __read_mostly = 
IS_ENABLED(CONFIG_IOMMU_DEFAULT_PASSTHROUGH);
 
 extern struct iommu_table_entry __iommu_table[], __iommu_table_end[];
 
-- 
1.8.3


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


[PATCH v9 6/7] iommu/amd: add support for IOMMU default DMA mode build options

2019-06-13 Thread Zhen Lei
The default DMA mode of AMD IOMMU is LAZY, this patch make it can be set
to STRICT at build time. It can be overridden by boot option.

There is no functional change.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/Kconfig  | 2 +-
 drivers/iommu/amd_iommu_init.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index fd297b0e0330d27..70741fd73b07785 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -79,7 +79,7 @@ choice
prompt "IOMMU default DMA mode"
depends on IOMMU_API
default IOMMU_DEFAULT_PASSTHROUGH if (PPC_POWERNV && PCI)
-   default IOMMU_DEFAULT_LAZY if (INTEL_IOMMU || S390_IOMMU)
+   default IOMMU_DEFAULT_LAZY if (AMD_IOMMU || INTEL_IOMMU || S390_IOMMU)
default IOMMU_DEFAULT_STRICT
help
  This option allows an IOMMU DMA mode to be chosen at build time, to
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 07d84dbab564e4d..b7d5c1757425946 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -154,7 +154,7 @@ struct ivmd_header {
   to handle */
 LIST_HEAD(amd_iommu_unity_map);/* a list of required unity 
mappings
   we find in ACPI */
-bool amd_iommu_unmap_flush;/* if true, flush on every unmap */
+bool amd_iommu_unmap_flush = IS_ENABLED(CONFIG_IOMMU_DEFAULT_STRICT);  /* if 
true, flush on every unmap */
 
 LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the
   system */
-- 
1.8.3


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


[PATCH v9 1/7] iommu: enhance IOMMU default DMA mode build options

2019-06-13 Thread Zhen Lei
First, add build option IOMMU_DEFAULT_{LAZY|STRICT}, so that we have the
opportunity to set {lazy|strict} mode as default at build time. Then put
the three config options in an choice, make people can only choose one of
the three at a time.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/Kconfig | 44 
 drivers/iommu/iommu.c |  3 ++-
 2 files changed, 38 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 83664db5221df02..fe715fb295c6ed2 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -75,16 +75,44 @@ config IOMMU_DEBUGFS
  debug/iommu directory, and then populate a subdirectory with
  entries as required.
 
-config IOMMU_DEFAULT_PASSTHROUGH
-   bool "IOMMU passthrough by default"
+choice
+   prompt "IOMMU default DMA mode"
depends on IOMMU_API
-help
- Enable passthrough by default, removing the need to pass in
- iommu.passthrough=on or iommu=pt through command line. If this
- is enabled, you can still disable with iommu.passthrough=off
- or iommu=nopt depending on the architecture.
+   default IOMMU_DEFAULT_STRICT
+   help
+ This option allows an IOMMU DMA mode to be chosen at build time, to
+ override the default DMA mode of each ARCH, removing the need to
+ pass in kernel parameters through command line. You can still use
+ ARCH specific boot options to override this option again.
 
- If unsure, say N here.
+ If unsure, keep the default.
+
+config IOMMU_DEFAULT_PASSTHROUGH
+   bool "passthrough"
+   help
+ In this mode, the DMA access through IOMMU without any addresses
+ translation. That means, the wrong or illegal DMA access can not
+ be caught, no error information will be reported.
+
+config IOMMU_DEFAULT_LAZY
+   bool "lazy"
+   help
+ Support lazy mode, where for every IOMMU DMA unmap operation, the
+ flush operation of IOTLB and the free operation of IOVA are deferred.
+ They are only guaranteed to be done before the related IOVA will be
+ reused.
+
+config IOMMU_DEFAULT_STRICT
+   bool "strict"
+   help
+ For every IOMMU DMA unmap operation, the flush operation of IOTLB and
+ the free operation of IOVA are guaranteed to be done in the unmap
+ function.
+
+ This mode is safer than the two above, but it maybe slower in some
+ high performace scenarios.
+
+endchoice
 
 config OF_IOMMU
def_bool y
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index f9cacce909d3ae9..05171dd0bd03aee 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -31,7 +31,8 @@
 #else
 static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_DMA;
 #endif
-static bool iommu_dma_strict __read_mostly = true;
+static bool iommu_dma_strict __read_mostly =
+   IS_ENABLED(CONFIG_IOMMU_DEFAULT_STRICT);
 
 struct iommu_group {
struct kobject kobj;
-- 
1.8.3


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


[PATCH v9 4/7] powernv/iommu: add support for IOMMU default DMA mode build options

2019-06-13 Thread Zhen Lei
The default DMA mode is PASSTHROUGH on powernv, this patch make it can be
set to STRICT at build time. It can be overridden by boot option.

There is no functional change.

Signed-off-by: Zhen Lei 
---
 arch/powerpc/platforms/powernv/pci-ioda.c | 3 ++-
 drivers/iommu/Kconfig | 2 ++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c 
b/arch/powerpc/platforms/powernv/pci-ioda.c
index 10cc42b9e541c46..27e25e8e3a9c637 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -81,7 +81,8 @@ void pe_level_printk(const struct pnv_ioda_pe *pe, const char 
*level,
va_end(args);
 }
 
-static bool pnv_iommu_bypass_disabled __read_mostly;
+static bool pnv_iommu_bypass_disabled __read_mostly =
+   !IS_ENABLED(CONFIG_IOMMU_DEFAULT_PASSTHROUGH);
 static bool pci_reset_phbs __read_mostly;
 
 static int __init iommu_setup(char *str)
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index a8dd69d175fb3c6..bfbcaa24e283aad 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -78,6 +78,7 @@ config IOMMU_DEBUGFS
 choice
prompt "IOMMU default DMA mode"
depends on IOMMU_API
+   default IOMMU_DEFAULT_PASSTHROUGH if (PPC_POWERNV && PCI)
default IOMMU_DEFAULT_LAZY if S390_IOMMU
default IOMMU_DEFAULT_STRICT
help
@@ -98,6 +99,7 @@ config IOMMU_DEFAULT_PASSTHROUGH
 
 config IOMMU_DEFAULT_LAZY
bool "lazy"
+   depends on !PPC_POWERNV
help
  Support lazy mode, where for every IOMMU DMA unmap operation, the
  flush operation of IOTLB and the free operation of IOVA are deferred.
-- 
1.8.3


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


[PATCH v9 0/7] iommu: enhance IOMMU default DMA mode build options

2019-06-13 Thread Zhen Lei
v8--> v9
1. Fix some text editing errors

v7--> v8
1. Split into multiple small patches base on ARCHs or IOMMU drivers.
2. Hide the unsupported build options on the related ARCH or IOMMU.

v6 --> v7:
1. Fix some text editing errors

v5 --> v6:
1. give up adding boot option iommu.dma_mode

v4 --> v5:
As Hanjun and Thomas Gleixner's suggestion:
1. Keep the old ARCH specific boot options no change.
2. Keep build option CONFIG_IOMMU_DEFAULT_PASSTHROUGH no change.

v4:
As Robin Murphy's suggestion:
"It's also not necessarily obvious to the user how this interacts with
IOMMU_DEFAULT_PASSTHROUGH, so if we really do go down this route, maybe it
would be better to refactor the whole lot into a single selection of something
like IOMMU_DEFAULT_MODE anyway."

In this version, I tried to normalize the IOMMU dma mode boot options for all
ARCHs. When IOMMU is enabled, there are 3 dma modes: paasthrough(bypass),
lazy(mapping but defer the IOTLB invalidation), strict. But currently each
ARCHs defined their private boot options, different with each other. For
example, to enable/disable "passthrough", ARM64 use iommu.passthrough=1/0,
X86 use iommu=pt/nopt, PPC/POWERNV use iommu=nobypass.

Zhen Lei (7):
  iommu: enhance IOMMU default DMA mode build options
  x86/dma: use IS_ENABLED() to simplify the code
  s390/pci: add support for IOMMU default DMA mode build options
  powernv/iommu: add support for IOMMU default DMA mode build options
  iommu/vt-d: add support for IOMMU default DMA mode build options
  iommu/amd: add support for IOMMU default DMA mode build options
  ia64: hide build option IOMMU_DEFAULT_PASSTHROUGH

 arch/powerpc/platforms/powernv/pci-ioda.c |  3 +-
 arch/s390/pci/pci_dma.c   |  2 +-
 arch/x86/kernel/pci-dma.c |  6 +---
 drivers/iommu/Kconfig | 48 +--
 drivers/iommu/amd_iommu_init.c|  2 +-
 drivers/iommu/intel-iommu.c   |  2 +-
 drivers/iommu/iommu.c |  3 +-
 7 files changed, 48 insertions(+), 18 deletions(-)

-- 
1.8.3


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


[PATCH v8 7/7] ia64: hide build option IOMMU_DEFAULT_PASSTHROUGH

2019-05-29 Thread Zhen Lei
The DMA mode PASSTHROUGH is not used on ia64.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index f6c030433d38048..f7400e35628dce4 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -89,7 +89,7 @@ choice
 
 config IOMMU_DEFAULT_PASSTHROUGH
bool "passthrough"
-   depends on !S390_IOMMU
+   depends on (!S390_IOMMU && !IA64)
help
  In this mode, the DMA access through IOMMU without any addresses
  translation. That means, the wrong or illegal DMA access can not
-- 
1.8.3




[PATCH v8 4/7] powernv/iommu: add support for IOMMU default DMA mode build options

2019-05-29 Thread Zhen Lei
The default DMA mode is PASSTHROUGH on powernv, this patch make it can be
set to STRICT at build time. It can be overridden by boot option.

There is no functional change.

Signed-off-by: Zhen Lei 
---
 arch/powerpc/platforms/powernv/pci-ioda.c | 3 ++-
 drivers/iommu/Kconfig | 2 ++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c 
b/arch/powerpc/platforms/powernv/pci-ioda.c
index 126602b4e39972d..40208b9019be890 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -85,7 +85,8 @@ void pe_level_printk(const struct pnv_ioda_pe *pe, const char 
*level,
va_end(args);
 }
 
-static bool pnv_iommu_bypass_disabled __read_mostly;
+static bool pnv_iommu_bypass_disabled __read_mostly =
+   !IS_ENABLED(CONFIG_IOMMU_DEFAULT_PASSTHROUGH);
 static bool pci_reset_phbs __read_mostly;
 
 static int __init iommu_setup(char *str)
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 9b48c2fc20e14d3..b5af859956c4fda 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -78,6 +78,7 @@ config IOMMU_DEBUGFS
 choice
prompt "IOMMU default DMA mode"
depends on IOMMU_API
+   default IOMMU_DEFAULT_PASSTHROUGH if (PPC_POWERNV && PCI)
default IOMMU_DEFAULT_LAZY if S390_IOMMU
default IOMMU_DEFAULT_STRICT
help
@@ -98,6 +99,7 @@ config IOMMU_DEFAULT_PASSTHROUGH
 
 config IOMMU_DEFAULT_LAZY
bool "lazy"
+   depends on !PPC_POWERNV
help
  Support lazy mode, where for every IOMMU DMA unmap operation, the
  flush operation of IOTLB and the free operation of IOVA are deferred.
-- 
1.8.3




[PATCH v8 2/7] x86/dma: use IS_ENABLED() to simplify the code

2019-05-29 Thread Zhen Lei
This patch removes the ifdefs around CONFIG_IOMMU_DEFAULT_PASSTHROUGH to
improve readablity.

Signed-off-by: Zhen Lei 
---
 arch/x86/kernel/pci-dma.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index dcd272dbd0a9330..9f2b19c35a060df 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -43,11 +43,8 @@
  * It is also possible to disable by default in kernel config, and enable with
  * iommu=nopt at boot time.
  */
-#ifdef CONFIG_IOMMU_DEFAULT_PASSTHROUGH
-int iommu_pass_through __read_mostly = 1;
-#else
-int iommu_pass_through __read_mostly;
-#endif
+int iommu_pass_through __read_mostly =
+   IS_ENABLED(CONFIG_IOMMU_DEFAULT_PASSTHROUGH);
 
 extern struct iommu_table_entry __iommu_table[], __iommu_table_end[];
 
-- 
1.8.3




[PATCH v8 6/7] iommu/amd: add support for IOMMU default DMA mode build options

2019-05-29 Thread Zhen Lei
The default DMA mode of AMD IOMMU is LAZY, this patch make it can be set
to STRICT at build time. It can be overridden by boot option.

There is no functional change.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/Kconfig  | 2 +-
 drivers/iommu/amd_iommu_init.c | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index af580274b7c5270..f6c030433d38048 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -79,7 +79,7 @@ choice
prompt "IOMMU default DMA mode"
depends on IOMMU_API
default IOMMU_DEFAULT_PASSTHROUGH if (PPC_POWERNV && PCI)
-   default IOMMU_DEFAULT_LAZY if (INTEL_IOMMU || S390_IOMMU)
+   default IOMMU_DEFAULT_LAZY if (AMD_IOMMU || INTEL_IOMMU || S390_IOMMU)
default IOMMU_DEFAULT_STRICT
help
  This option allows IOMMU DMA mode to be chose at build time, to
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index f977df90d2a4912..6b0bfa43f6faa32 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -166,7 +166,8 @@ struct ivmd_header {
   to handle */
 LIST_HEAD(amd_iommu_unity_map);/* a list of required unity 
mappings
   we find in ACPI */
-bool amd_iommu_unmap_flush;/* if true, flush on every unmap */
+bool amd_iommu_unmap_flush = IS_ENABLED(CONFIG_IOMMU_DEFAULT_STRICT);
+   /* if true, flush on every unmap */
 
 LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the
   system */
-- 
1.8.3




[PATCH v8 0/7] iommu: enhance IOMMU default DMA mode build options

2019-05-29 Thread Zhen Lei
v7--> v8
1. Split into multiple small patches base on ARCHs or IOMMU drivers.
2. Hide the unsupported build options on the related ARCH or IOMMU.

v6 --> v7:
1. Fix some text editing errors

v5 --> v6:
1. give up adding boot option iommu.dma_mode

v4 --> v5:
As Hanjun and Thomas Gleixner's suggestion:
1. Keep the old ARCH specific boot options no change.
2. Keep build option CONFIG_IOMMU_DEFAULT_PASSTHROUGH no change.

v4:
As Robin Murphy's suggestion:
"It's also not necessarily obvious to the user how this interacts with
IOMMU_DEFAULT_PASSTHROUGH, so if we really do go down this route, maybe it
would be better to refactor the whole lot into a single selection of something
like IOMMU_DEFAULT_MODE anyway."

In this version, I tried to normalize the IOMMU dma mode boot options for all
ARCHs. When IOMMU is enabled, there are 3 dma modes: paasthrough(bypass),
lazy(mapping but defer the IOTLB invalidation), strict. But currently each
ARCHs defined their private boot options, different with each other. For
example, to enable/disable "passthrough", ARM64 use iommu.passthrough=1/0,
X86 use iommu=pt/nopt, PPC/POWERNV use iommu=nobypass.

Zhen Lei (7):
  iommu: enhance IOMMU default DMA mode build options
  x86/dma: use IS_ENABLED() to simplify the code
  s390/pci: add support for IOMMU default DMA mode build options
  powernv/iommu: add support for IOMMU default DMA mode build options
  iommu/vt-d: add support for IOMMU default DMA mode build options
  iommu/amd: add support for IOMMU default DMA mode build options
  ia64: hide build option IOMMU_DEFAULT_PASSTHROUGH

 arch/powerpc/platforms/powernv/pci-ioda.c |  3 +-
 arch/s390/pci/pci_dma.c   |  2 +-
 arch/x86/kernel/pci-dma.c |  7 ++---
 drivers/iommu/Kconfig | 46 ++-
 drivers/iommu/amd_iommu_init.c|  3 +-
 drivers/iommu/intel-iommu.c   |  2 +-
 drivers/iommu/iommu.c |  3 +-
 7 files changed, 49 insertions(+), 17 deletions(-)

-- 
1.8.3




[PATCH v8 5/7] iommu/vt-d: add support for IOMMU default DMA mode build options

2019-05-29 Thread Zhen Lei
The default DMA mode of INTEL IOMMU is LAZY, this patch make it can be
set to STRICT at build time. It can be overridden by boot option.

There is no functional change.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/Kconfig   | 2 +-
 drivers/iommu/intel-iommu.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index b5af859956c4fda..af580274b7c5270 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -79,7 +79,7 @@ choice
prompt "IOMMU default DMA mode"
depends on IOMMU_API
default IOMMU_DEFAULT_PASSTHROUGH if (PPC_POWERNV && PCI)
-   default IOMMU_DEFAULT_LAZY if S390_IOMMU
+   default IOMMU_DEFAULT_LAZY if (INTEL_IOMMU || S390_IOMMU)
default IOMMU_DEFAULT_STRICT
help
  This option allows IOMMU DMA mode to be chose at build time, to
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index a209199f3af6460..50d74ea0acdbdca 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -362,7 +362,7 @@ static int domain_detach_iommu(struct dmar_domain *domain,
 
 static int dmar_map_gfx = 1;
 static int dmar_forcedac;
-static int intel_iommu_strict;
+static int intel_iommu_strict = IS_ENABLED(CONFIG_IOMMU_DEFAULT_STRICT);
 static int intel_iommu_superpage = 1;
 static int intel_iommu_sm;
 static int iommu_identity_mapping;
-- 
1.8.3




[PATCH v8 3/7] s390/pci: add support for IOMMU default DMA mode build options

2019-05-29 Thread Zhen Lei
The default DMA mode is LAZY on s390, this patch make it can be set to
STRICT at build time. It can be overridden by boot option.

There is no functional change.

Signed-off-by: Zhen Lei 
---
 arch/s390/pci/pci_dma.c | 2 +-
 drivers/iommu/Kconfig   | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
index 9e52d1527f71495..784ad1e0acecfb1 100644
--- a/arch/s390/pci/pci_dma.c
+++ b/arch/s390/pci/pci_dma.c
@@ -17,7 +17,7 @@
 
 static struct kmem_cache *dma_region_table_cache;
 static struct kmem_cache *dma_page_table_cache;
-static int s390_iommu_strict;
+static int s390_iommu_strict = IS_ENABLED(CONFIG_IOMMU_DEFAULT_STRICT);
 
 static int zpci_refresh_global(struct zpci_dev *zdev)
 {
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index d6a1a45f80ffbf5..9b48c2fc20e14d3 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -78,6 +78,7 @@ config IOMMU_DEBUGFS
 choice
prompt "IOMMU default DMA mode"
depends on IOMMU_API
+   default IOMMU_DEFAULT_LAZY if S390_IOMMU
default IOMMU_DEFAULT_STRICT
help
  This option allows IOMMU DMA mode to be chose at build time, to
@@ -87,6 +88,7 @@ choice
 
 config IOMMU_DEFAULT_PASSTHROUGH
bool "passthrough"
+   depends on !S390_IOMMU
help
  In this mode, the DMA access through IOMMU without any addresses
  translation. That means, the wrong or illegal DMA access can not
-- 
1.8.3




[PATCH v8 1/7] iommu: enhance IOMMU default DMA mode build options

2019-05-29 Thread Zhen Lei
First, add build option IOMMU_DEFAULT_{LAZY|STRICT}, so that we have the
opportunity to set {lazy|strict} mode as default at build time. Then put
the three config options in an choice, make people can only choose one of
the three at a time.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/Kconfig | 42 +++---
 drivers/iommu/iommu.c |  3 ++-
 2 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 83664db5221df02..d6a1a45f80ffbf5 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -75,17 +75,45 @@ config IOMMU_DEBUGFS
  debug/iommu directory, and then populate a subdirectory with
  entries as required.
 
-config IOMMU_DEFAULT_PASSTHROUGH
-   bool "IOMMU passthrough by default"
+choice
+   prompt "IOMMU default DMA mode"
depends on IOMMU_API
-help
- Enable passthrough by default, removing the need to pass in
- iommu.passthrough=on or iommu=pt through command line. If this
- is enabled, you can still disable with iommu.passthrough=off
- or iommu=nopt depending on the architecture.
+   default IOMMU_DEFAULT_STRICT
+   help
+ This option allows IOMMU DMA mode to be chose at build time, to
+ override the default DMA mode of each ARCHs, removing the need to
+ pass in kernel parameters through command line. You can still use
+ ARCHs specific boot options to override this option again.
+
+config IOMMU_DEFAULT_PASSTHROUGH
+   bool "passthrough"
+   help
+ In this mode, the DMA access through IOMMU without any addresses
+ translation. That means, the wrong or illegal DMA access can not
+ be caught, no error information will be reported.
 
  If unsure, say N here.
 
+config IOMMU_DEFAULT_LAZY
+   bool "lazy"
+   help
+ Support lazy mode, where for every IOMMU DMA unmap operation, the
+ flush operation of IOTLB and the free operation of IOVA are deferred.
+ They are only guaranteed to be done before the related IOVA will be
+ reused.
+
+config IOMMU_DEFAULT_STRICT
+   bool "strict"
+   help
+ For every IOMMU DMA unmap operation, the flush operation of IOTLB and
+ the free operation of IOVA are guaranteed to be done in the unmap
+ function.
+
+ This mode is safer than the two above, but it maybe slower in some
+ high performace scenarios.
+
+endchoice
+
 config OF_IOMMU
def_bool y
depends on OF && IOMMU_API
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 67ee6623f9b2a4d..56bce221285b15f 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -43,7 +43,8 @@
 #else
 static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_DMA;
 #endif
-static bool iommu_dma_strict __read_mostly = true;
+static bool iommu_dma_strict __read_mostly =
+   IS_ENABLED(CONFIG_IOMMU_DEFAULT_STRICT);
 
 struct iommu_group {
struct kobject kobj;
-- 
1.8.3




[PATCH v7 1/1] iommu: enhance IOMMU dma mode build options

2019-05-20 Thread Zhen Lei
First, add build option IOMMU_DEFAULT_{LAZY|STRICT}, so that we have the
opportunity to set {lazy|strict} mode as default at build time. Then put
the three config options in an choice, make people can only choose one of
the three at a time.

The default IOMMU dma modes on each ARCHs have no change.

Signed-off-by: Zhen Lei 
---
 arch/ia64/kernel/pci-dma.c|  2 +-
 arch/powerpc/platforms/powernv/pci-ioda.c |  3 ++-
 arch/s390/pci/pci_dma.c   |  2 +-
 arch/x86/kernel/pci-dma.c |  7 ++---
 drivers/iommu/Kconfig | 44 ++-
 drivers/iommu/amd_iommu_init.c|  3 ++-
 drivers/iommu/intel-iommu.c   |  2 +-
 drivers/iommu/iommu.c |  3 ++-
 8 files changed, 48 insertions(+), 18 deletions(-)

diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c
index fe988c49f01ce6a..655511dbf3c3b34 100644
--- a/arch/ia64/kernel/pci-dma.c
+++ b/arch/ia64/kernel/pci-dma.c
@@ -22,7 +22,7 @@
 int force_iommu __read_mostly;
 #endif

-int iommu_pass_through;
+int iommu_pass_through = IS_ENABLED(CONFIG_IOMMU_DEFAULT_PASSTHROUGH);

 static int __init pci_iommu_init(void)
 {
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c 
b/arch/powerpc/platforms/powernv/pci-ioda.c
index 3ead4c237ed0ec9..383e082a9bb985c 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -85,7 +85,8 @@ void pe_level_printk(const struct pnv_ioda_pe *pe, const char 
*level,
va_end(args);
 }

-static bool pnv_iommu_bypass_disabled __read_mostly;
+static bool pnv_iommu_bypass_disabled __read_mostly =
+   !IS_ENABLED(CONFIG_IOMMU_DEFAULT_PASSTHROUGH);
 static bool pci_reset_phbs __read_mostly;

 static int __init iommu_setup(char *str)
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
index 9e52d1527f71495..784ad1e0acecfb1 100644
--- a/arch/s390/pci/pci_dma.c
+++ b/arch/s390/pci/pci_dma.c
@@ -17,7 +17,7 @@

 static struct kmem_cache *dma_region_table_cache;
 static struct kmem_cache *dma_page_table_cache;
-static int s390_iommu_strict;
+static int s390_iommu_strict = IS_ENABLED(CONFIG_IOMMU_DEFAULT_STRICT);

 static int zpci_refresh_global(struct zpci_dev *zdev)
 {
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index d460998ae828514..fb2bab42a0a3173 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -43,11 +43,8 @@
  * It is also possible to disable by default in kernel config, and enable with
  * iommu=nopt at boot time.
  */
-#ifdef CONFIG_IOMMU_DEFAULT_PASSTHROUGH
-int iommu_pass_through __read_mostly = 1;
-#else
-int iommu_pass_through __read_mostly;
-#endif
+int iommu_pass_through __read_mostly =
+   IS_ENABLED(CONFIG_IOMMU_DEFAULT_PASSTHROUGH);

 extern struct iommu_table_entry __iommu_table[], __iommu_table_end[];

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 6f07f3b21816c64..8a1f1793cde76b4 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -74,17 +74,47 @@ config IOMMU_DEBUGFS
  debug/iommu directory, and then populate a subdirectory with
  entries as required.

-config IOMMU_DEFAULT_PASSTHROUGH
-   bool "IOMMU passthrough by default"
+choice
+   prompt "IOMMU default DMA mode"
depends on IOMMU_API
-help
- Enable passthrough by default, removing the need to pass in
- iommu.passthrough=on or iommu=pt through command line. If this
- is enabled, you can still disable with iommu.passthrough=off
- or iommu=nopt depending on the architecture.
+   default IOMMU_DEFAULT_PASSTHROUGH if (PPC_POWERNV && PCI)
+   default IOMMU_DEFAULT_LAZY if (AMD_IOMMU || INTEL_IOMMU || S390_IOMMU)
+   default IOMMU_DEFAULT_STRICT
+   help
+ This option allows IOMMU DMA mode to be chose at build time, to
+ override the default DMA mode of each ARCHs, removing the need to
+ pass in kernel parameters through command line. You can still use
+ ARCHs specific boot options to override this option again.
+
+config IOMMU_DEFAULT_PASSTHROUGH
+   bool "passthrough"
+   help
+ In this mode, the DMA access through IOMMU without any addresses
+ translation. That means, the wrong or illegal DMA access can not
+ be caught, no error information will be reported.

  If unsure, say N here.

+config IOMMU_DEFAULT_LAZY
+   bool "lazy"
+   help
+ Support lazy mode, where for every IOMMU DMA unmap operation, the
+ flush operation of IOTLB and the free operation of IOVA are deferred.
+ They are only guaranteed to be done before the related IOVA will be
+ reused.
+
+config IOMMU_DEFAULT_STRICT
+   bool "strict"
+   help
+ For every IOMMU DMA unmap operation, the flush operation of IOTLB and
+   

[PATCH v7 0/1] iommu: enhance IOMMU dma mode build options

2019-05-20 Thread Zhen Lei
v6 --> v7:
1. Fix some text editing errors

v5 --> v6:
1. give up adding boot option iommu.dma_mode

v4 --> v5:
As Hanjun and Thomas Gleixner's suggestion:
1. Keep the old ARCH specific boot options no change.
2. Keep build option CONFIG_IOMMU_DEFAULT_PASSTHROUGH no change.

v4:
As Robin Murphy's suggestion:
"It's also not necessarily obvious to the user how this interacts with
IOMMU_DEFAULT_PASSTHROUGH, so if we really do go down this route, maybe it
would be better to refactor the whole lot into a single selection of something
like IOMMU_DEFAULT_MODE anyway."

In this version, I tried to normalize the IOMMU dma mode boot options for all
ARCHs. When IOMMU is enabled, there are 3 dma modes: paasthrough(bypass),
lazy(mapping but defer the IOTLB invalidation), strict. But currently each
ARCHs defined their private boot options, different with each other. For
example, to enable/disable "passthrough", ARM64 use iommu.passthrough=1/0,
X86 use iommu=pt/nopt, PPC/POWERNV use iommu=nobypass.

Zhen Lei (1):
  iommu: enhance IOMMU dma mode build options

 arch/ia64/kernel/pci-dma.c|  2 +-
 arch/powerpc/platforms/powernv/pci-ioda.c |  3 ++-
 arch/s390/pci/pci_dma.c   |  2 +-
 arch/x86/kernel/pci-dma.c |  7 ++---
 drivers/iommu/Kconfig | 44 ++-
 drivers/iommu/amd_iommu_init.c|  3 ++-
 drivers/iommu/intel-iommu.c   |  2 +-
 drivers/iommu/iommu.c |  3 ++-
 8 files changed, 48 insertions(+), 18 deletions(-)

-- 
1.8.3


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


[PATCH v6 1/1] iommu: enhance IOMMU dma mode build options

2019-04-18 Thread Zhen Lei
First, add build option IOMMU_DEFAULT_{LAZY|STRICT}, so that we have the
opportunity to set {lazy|strict} mode as default at build time. Then put
the three config options in an choice, make people can only choose one of
the three at a time.

The default IOMMU dma modes on each ARCHs have no change.

Signed-off-by: Zhen Lei 
---
 arch/ia64/kernel/pci-dma.c|  2 +-
 arch/powerpc/platforms/powernv/pci-ioda.c |  3 ++-
 arch/s390/pci/pci_dma.c   |  2 +-
 arch/x86/kernel/pci-dma.c |  7 ++---
 drivers/iommu/Kconfig | 44 ++-
 drivers/iommu/amd_iommu_init.c|  3 ++-
 drivers/iommu/intel-iommu.c   |  2 +-
 drivers/iommu/iommu.c |  3 ++-
 8 files changed, 48 insertions(+), 18 deletions(-)

diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c
index fe988c49f01ce6a..655511dbf3c3b34 100644
--- a/arch/ia64/kernel/pci-dma.c
+++ b/arch/ia64/kernel/pci-dma.c
@@ -22,7 +22,7 @@
 int force_iommu __read_mostly;
 #endif

-int iommu_pass_through;
+int iommu_pass_through = IS_ENABLED(CONFIG_IOMMU_DEFAULT_PASSTHROUGH);

 static int __init pci_iommu_init(void)
 {
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c 
b/arch/powerpc/platforms/powernv/pci-ioda.c
index 3ead4c237ed0ec9..383e082a9bb985c 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -85,7 +85,8 @@ void pe_level_printk(const struct pnv_ioda_pe *pe, const char 
*level,
va_end(args);
 }

-static bool pnv_iommu_bypass_disabled __read_mostly;
+static bool pnv_iommu_bypass_disabled __read_mostly =
+   !IS_ENABLED(CONFIG_IOMMU_DEFAULT_PASSTHROUGH);
 static bool pci_reset_phbs __read_mostly;

 static int __init iommu_setup(char *str)
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
index 9e52d1527f71495..784ad1e0acecfb1 100644
--- a/arch/s390/pci/pci_dma.c
+++ b/arch/s390/pci/pci_dma.c
@@ -17,7 +17,7 @@

 static struct kmem_cache *dma_region_table_cache;
 static struct kmem_cache *dma_page_table_cache;
-static int s390_iommu_strict;
+static int s390_iommu_strict = IS_ENABLED(CONFIG_IOMMU_DEFAULT_STRICT);

 static int zpci_refresh_global(struct zpci_dev *zdev)
 {
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index d460998ae828514..fb2bab42a0a3173 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -43,11 +43,8 @@
  * It is also possible to disable by default in kernel config, and enable with
  * iommu=nopt at boot time.
  */
-#ifdef CONFIG_IOMMU_DEFAULT_PASSTHROUGH
-int iommu_pass_through __read_mostly = 1;
-#else
-int iommu_pass_through __read_mostly;
-#endif
+int iommu_pass_through __read_mostly =
+   IS_ENABLED(CONFIG_IOMMU_DEFAULT_PASSTHROUGH);

 extern struct iommu_table_entry __iommu_table[], __iommu_table_end[];

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 6f07f3b21816c64..8a1f1793cde76b4 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -74,17 +74,47 @@ config IOMMU_DEBUGFS
  debug/iommu directory, and then populate a subdirectory with
  entries as required.

-config IOMMU_DEFAULT_PASSTHROUGH
-   bool "IOMMU passthrough by default"
+choice
+   prompt "IOMMU dma mode"
depends on IOMMU_API
-help
- Enable passthrough by default, removing the need to pass in
- iommu.passthrough=on or iommu=pt through command line. If this
- is enabled, you can still disable with iommu.passthrough=off
- or iommu=nopt depending on the architecture.
+   default IOMMU_DEFAULT_PASSTHROUGH if (PPC_POWERNV && PCI)
+   default IOMMU_DEFAULT_LAZY if (AMD_IOMMU || INTEL_IOMMU || S390_IOMMU)
+   default IOMMU_DEFAULT_STRICT
+   help
+ This option allows IOMMU dma mode to be chose at build time, to
+ override the default dma mode of each ARCHs, removing the need to
+ pass in kernel parameters through command line. You can still use
+ ARCHs specific boot options to override this option again.
+
+config IOMMU_DEFAULT_PASSTHROUGH
+   bool "passthrough"
+   help
+ In this mode, the dma access through IOMMU without any addresses
+ transformation. That means, the wrong or illegal dma access can not
+ be caught, no error information will be reported.

  If unsure, say N here.

+config IOMMU_DEFAULT_LAZY
+   bool "lazy"
+   help
+ Support lazy mode, where for every IOMMU DMA unmap operation, the
+ flush operation of IOTLB and the free operation of IOVA are deferred.
+ They are only guaranteed to be done before the related IOVA will be
+ reused.
+
+config IOMMU_DEFAULT_STRICT
+   bool "strict"
+   help
+ For every IOMMU DMA unmap operation, the flush operation of IOTLB and
+ the fre

[PATCH v6 0/1] iommu: enhance IOMMU dma mode build options

2019-04-18 Thread Zhen Lei
v5 --> v6:
1. give up adding boot option iommu.dma_mode

v4 --> v5:
As Hanjun and Thomas Gleixner's suggestion:
1. Keep the old ARCH specific boot options no change.
2. Keep build option CONFIG_IOMMU_DEFAULT_PASSTHROUGH no change.

v4:
As Robin Murphy's suggestion:
"It's also not necessarily obvious to the user how this interacts with
IOMMU_DEFAULT_PASSTHROUGH, so if we really do go down this route, maybe it
would be better to refactor the whole lot into a single selection of something
like IOMMU_DEFAULT_MODE anyway."

In this version, I tried to normalize the IOMMU dma mode boot options for all
ARCHs. When IOMMU is enabled, there are 3 dma modes: paasthrough(bypass),
lazy(mapping but defer the IOTLB invalidation), strict. But currently each
ARCHs defined their private boot options, different with each other. For
example, to enable/disable "passthrough", ARM64 use iommu.passthrough=1/0,
X86 use iommu=pt/nopt, PPC/POWERNV use iommu=nobypass.

Zhen Lei (1):
  iommu: enhance IOMMU dma mode build options

 arch/ia64/kernel/pci-dma.c|  2 +-
 arch/powerpc/platforms/powernv/pci-ioda.c |  3 ++-
 arch/s390/pci/pci_dma.c   |  2 +-
 arch/x86/kernel/pci-dma.c |  7 ++---
 drivers/iommu/Kconfig | 44 ++-
 drivers/iommu/amd_iommu_init.c|  3 ++-
 drivers/iommu/intel-iommu.c   |  2 +-
 drivers/iommu/iommu.c |  3 ++-
 8 files changed, 48 insertions(+), 18 deletions(-)

-- 
1.8.3


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


[PATCH v5 6/6] x86/iommu: add support for generic boot option iommu.dma_mode

2019-04-09 Thread Zhen Lei
The following equivalence or replacement relationship exists:
iommu=pt <--> iommu.dma_mode=passthrough.
iommu=nopt can be replaced with iommu.dma_mode=lazy.
intel_iommu=strict <--> iommu.dma_mode=strict.
amd_iommu=fullflush <--> iommu.dma_mode=strict.

Signed-off-by: Zhen Lei 
---
 Documentation/admin-guide/kernel-parameters.txt |  6 ++---
 arch/ia64/include/asm/iommu.h   |  2 --
 arch/ia64/kernel/pci-dma.c  |  2 --
 arch/x86/include/asm/iommu.h|  1 -
 arch/x86/kernel/pci-dma.c   | 35 -
 drivers/iommu/Kconfig   |  2 +-
 drivers/iommu/amd_iommu.c   | 10 +++
 drivers/iommu/amd_iommu_init.c  |  4 +--
 drivers/iommu/amd_iommu_types.h |  6 -
 drivers/iommu/intel-iommu.c |  9 +++
 10 files changed, 31 insertions(+), 46 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt 
b/Documentation/admin-guide/kernel-parameters.txt
index 176f96032d9d62a..ca6edc529d6a614 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1815,9 +1815,9 @@
options(such as CONFIG_IOMMU_DEFAULT_PASSTHROUGH) to
choose which mode to be used.
Note: For historical reasons, ARM64/S390/PPC/X86 have
-   their specific options. Currently, only ARM64/S390/PPC
-   support this boot option, and hope other ARCHs to use
-   this as generic boot option.
+   their specific options, but strongly recommended switch
+   to use this one, the new ARCHs should use this generic
+   boot option.
passthrough
Configure DMA to bypass the IOMMU by default.
lazy
diff --git a/arch/ia64/include/asm/iommu.h b/arch/ia64/include/asm/iommu.h
index 7429a72f3f92199..92aceef63710861 100644
--- a/arch/ia64/include/asm/iommu.h
+++ b/arch/ia64/include/asm/iommu.h
@@ -8,10 +8,8 @@
 extern void no_iommu_init(void);
 #ifdef CONFIG_INTEL_IOMMU
 extern int force_iommu, no_iommu;
-extern int iommu_pass_through;
 extern int iommu_detected;
 #else
-#define iommu_pass_through (0)
 #define no_iommu   (1)
 #define iommu_detected (0)
 #endif
diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c
index fe988c49f01ce6a..f5d49cd3fbb01a9 100644
--- a/arch/ia64/kernel/pci-dma.c
+++ b/arch/ia64/kernel/pci-dma.c
@@ -22,8 +22,6 @@
 int force_iommu __read_mostly;
 #endif
 
-int iommu_pass_through;
-
 static int __init pci_iommu_init(void)
 {
if (iommu_detected)
diff --git a/arch/x86/include/asm/iommu.h b/arch/x86/include/asm/iommu.h
index baedab8ac5385f7..b91623d521d9f0f 100644
--- a/arch/x86/include/asm/iommu.h
+++ b/arch/x86/include/asm/iommu.h
@@ -4,7 +4,6 @@
 
 extern int force_iommu, no_iommu;
 extern int iommu_detected;
-extern int iommu_pass_through;
 
 /* 10 seconds */
 #define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000)
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index d460998ae828514..fc64928e47cb860 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -6,6 +6,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -34,21 +35,6 @@
 /* Set this to 1 if there is a HW IOMMU in the system */
 int iommu_detected __read_mostly = 0;
 
-/*
- * This variable becomes 1 if iommu=pt is passed on the kernel command line.
- * If this variable is 1, IOMMU implementations do no DMA translation for
- * devices and allow every device to access to whole physical memory. This is
- * useful if a user wants to use an IOMMU only for KVM device assignment to
- * guests and not for driver dma translation.
- * It is also possible to disable by default in kernel config, and enable with
- * iommu=nopt at boot time.
- */
-#ifdef CONFIG_IOMMU_DEFAULT_PASSTHROUGH
-int iommu_pass_through __read_mostly = 1;
-#else
-int iommu_pass_through __read_mostly;
-#endif
-
 extern struct iommu_table_entry __iommu_table[], __iommu_table_end[];
 
 /* Dummy device used for NULL arguments (normally ISA). */
@@ -139,10 +125,23 @@ static __init int iommu_setup(char *p)
if (!strncmp(p, "soft", 4))
swiotlb = 1;
 #endif
+
+   /*
+* IOMMU implementations do no DMA translation for devices and
+* allow every device to access to whole physical memory. This
+* is useful if a user wants to use an IOMMU only for KVM
+* device assignment to guests and not for driver dma
+* translation.
+*/
if (!strncmp(p, "pt", 2))
-   iommu_pass_through = 1;
-  

  1   2   3   >