1
Currently, smc/hvc calls are made with parameters set
1
Currently, smc/hvc calls are made with parameters set
2
to zeros. We are using multiple scmi instances within
2
to zeros. We are using multiple scmi instances within
3
a VM and hypervisor associates a tag with each instance
3
a VM. We are sharing the same smc-id(func_id) with all
4
and expects the tag in smc calls from that instance, while
4
scmi instance. The hypervisor needs a way to distinguish
5
sharing the same smc-id(func_id) among the instances.
5
among hvc calls made from different instances.
6
6
7
This patch series introduces new optional dtb bindings which
7
This patch series introduces new compatible string which
8
can be used to pass parameters to smc/hvc calls.
8
can be used to pass shmem channel address as parameters
9
to smc/hvc calls.
10
11
---
12
v5 -> avoid computing page and offset in send function
13
Link: https://lore.kernel.org/all/20230418185659.29745-1-quic_nkela@quicinc.com/
14
15
v4 -> split shmem address into 4KB-pages and offset
16
17
v3 -> pass shmem channel address as parameter
18
19
v2 -> fix the compilation erros on 32bit platform(see below)
20
Reported-by: kernel test robot <lkp@intel.com>
21
Closes: https://lore.kernel.org/oe-kbuild-all/202304100606.kUjhsRYf-lkp@intel.com/
22
23
v1 -> original patches
9
24
10
Nikunj Kela (2):
25
Nikunj Kela (2):
11
dt-bindings: firmware: arm,scmi: support parameter passing in smc/hvc
26
dt-bindings: firmware: arm,scmi: support for parameter in smc/hvc call
12
firmware: arm_scmi: Augment SMC/HVC to allow optional parameters
27
firmware: arm_scmi: Augment SMC/HVC to allow optional parameters
13
28
14
.../bindings/firmware/arm,scmi.yaml | 16 +++++
29
.../bindings/firmware/arm,scmi.yaml | 8 ++++-
15
drivers/firmware/arm_scmi/smc.c | 66 ++++++++++++++++++-
30
drivers/firmware/arm_scmi/driver.c | 1 +
16
2 files changed, 81 insertions(+), 1 deletion(-)
31
drivers/firmware/arm_scmi/smc.c | 30 ++++++++++++++++++-
32
3 files changed, 37 insertions(+), 2 deletions(-)
17
33
18
--
34
--
19
2.17.1
35
2.17.1
diff view generated by jsdifflib
1
Currently, smc/hvc calls are made with smc-id only. The parameters are
1
Currently, smc/hvc calls are made with smc-id only. The parameters are
2
all set to zeros. This patch defines two optional device tree bindings,
2
all set to zeros. This change defines a new compatible string that can
3
that can be used to pass parameters in smc/hvc calls.
3
be used to pass shmem address(4KB-page, offset) as two parameters in
4
SMC/HVC doorbell.
4
5
5
This is useful when multiple scmi instances are used with common smc-id.
6
This is useful when multiple scmi instances are used with common smc-id.
6
7
7
Signed-off-by: Nikunj Kela <quic_nkela@quicinc.com>
8
Signed-off-by: Nikunj Kela <quic_nkela@quicinc.com>
9
Reviewed-by: Rob Herring <robh@kernel.org>
8
---
10
---
9
.../devicetree/bindings/firmware/arm,scmi.yaml | 16 ++++++++++++++++
11
Documentation/devicetree/bindings/firmware/arm,scmi.yaml | 8 +++++++-
10
1 file changed, 16 insertions(+)
12
1 file changed, 7 insertions(+), 1 deletion(-)
11
13
12
diff --git a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
14
diff --git a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
16
--- a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
15
+++ b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
17
+++ b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
16
@@ -XXX,XX +XXX,XX @@ properties:
18
@@ -XXX,XX +XXX,XX @@ properties:
17
description:
19
- description: SCMI compliant firmware with ARM SMC/HVC transport
18
SMC id required when using smc or hvc transports
20
items:
19
21
- const: arm,scmi-smc
20
+ arm,smc32-params:
22
+ - description: SCMI compliant firmware with ARM SMC/HVC transport
21
+ $ref: /schemas/types.yaml#/definitions/uint32-array
23
+ with shmem address(4KB-page, offset) as parameters
22
+ description:
24
+ items:
23
+ An optional parameter list passed in smc32 or hvc32 calls
25
+ - const: arm,scmi-smc-param
24
+ default: 0
26
- description: SCMI compliant firmware with SCMI Virtio transport.
25
+ minItems: 1
27
The virtio transport only supports a single device.
26
+ maxItems: 6
28
items:
27
+
29
@@ -XXX,XX +XXX,XX @@ else:
28
+ arm,smc64-params:
30
properties:
29
+ $ref: /schemas/types.yaml#/definitions/uint64-array
31
compatible:
30
+ description:
32
contains:
31
+ An optional parameter list passed in smc64 or hvc64 calls
33
- const: arm,scmi-smc
32
+ default: 0
34
+ enum:
33
+ minItems: 1
35
+ - arm,scmi-smc
34
+ maxItems: 6
36
+ - arm,scmi-smc-param
35
+
37
then:
36
linaro,optee-channel-id:
38
required:
37
$ref: /schemas/types.yaml#/definitions/uint32
39
- arm,smc-id
38
description:
39
--
40
--
40
2.17.1
41
2.17.1
diff view generated by jsdifflib
1
This patch add support for passing parameters to smc/hvc calls.
1
This change adds support for passing shmem channel address as parameters
2
This patch is useful when multiple scmi instances are using same
2
in smc/hvc call. The address is split into 4KB-page and offset.
3
smc-id and firmware needs to distiguish among the instances.
3
This is useful when multiple scmi instances are using same smc-id
4
and firmware needs to distinguish among the instances.
4
5
5
Signed-off-by: Nikunj Kela <quic_nkela@quicinc.com>
6
Signed-off-by: Nikunj Kela <quic_nkela@quicinc.com>
6
---
7
---
7
drivers/firmware/arm_scmi/smc.c | 66 ++++++++++++++++++++++++++++++++-
8
drivers/firmware/arm_scmi/driver.c | 1 +
8
1 file changed, 65 insertions(+), 1 deletion(-)
9
drivers/firmware/arm_scmi/smc.c | 30 +++++++++++++++++++++++++++++-
10
2 files changed, 30 insertions(+), 1 deletion(-)
9
11
12
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/drivers/firmware/arm_scmi/driver.c
15
+++ b/drivers/firmware/arm_scmi/driver.c
16
@@ -XXX,XX +XXX,XX @@ static const struct of_device_id scmi_of_match[] = {
17
#endif
18
#ifdef CONFIG_ARM_SCMI_TRANSPORT_SMC
19
    { .compatible = "arm,scmi-smc", .data = &scmi_smc_desc},
20
+    { .compatible = "arm,scmi-smc-param", .data = &scmi_smc_desc},
21
#endif
22
#ifdef CONFIG_ARM_SCMI_TRANSPORT_VIRTIO
23
    { .compatible = "arm,scmi-virtio", .data = &scmi_virtio_desc},
10
diff --git a/drivers/firmware/arm_scmi/smc.c b/drivers/firmware/arm_scmi/smc.c
24
diff --git a/drivers/firmware/arm_scmi/smc.c b/drivers/firmware/arm_scmi/smc.c
11
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
12
--- a/drivers/firmware/arm_scmi/smc.c
26
--- a/drivers/firmware/arm_scmi/smc.c
13
+++ b/drivers/firmware/arm_scmi/smc.c
27
+++ b/drivers/firmware/arm_scmi/smc.c
14
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@
15
29
16
#include "common.h"
30
#include "common.h"
17
31
18
+#define MAX_PARAM_COUNT 6
32
+/*
33
+ * The shmem address is split into 4K page and offset.
34
+ * This is to make sure the parameters fit in 32bit arguments of the
35
+ * smc/hvc call to keep it uniform across smc32/smc64 conventions.
36
+ * This however limits the shmem address to 44 bit.
37
+ *
38
+ * These optional parameters can be used to distinguish among multiple
39
+ * scmi instances that are using the same smc-id.
40
+ * The page parameter is passed in r1/x1/w1 register and the offset parameter
41
+ * is passed in r2/x2/w2 register.
42
+ */
19
+
43
+
20
+/**
44
+#define SHMEM_SIZE (SZ_4K)
21
+ * scmi_smc_param_t - parameter type for SCMI smc/hvc call
45
+#define SHMEM_SHIFT 12
22
+ */
46
+#define SHMEM_PAGE(x) (_UL((x) >> SHMEM_SHIFT))
23
+typedef union {
47
+#define SHMEM_OFFSET(x) ((x) & (SHMEM_SIZE - 1))
24
+    u64 x;
25
+    u32 w;
26
+} scmi_smc_param_t;
27
+
48
+
28
/**
49
/**
29
* struct scmi_smc - Structure representing a SCMI smc transport
50
* struct scmi_smc - Structure representing a SCMI smc transport
30
*
51
*
31
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@
32
* @inflight: Atomic flag to protect access to Tx/Rx shared memory area.
53
* @inflight: Atomic flag to protect access to Tx/Rx shared memory area.
33
*     Used when operating in atomic mode.
54
*     Used when operating in atomic mode.
34
* @func_id: smc/hvc call function id
55
* @func_id: smc/hvc call function id
35
+ * @is_smc64: A flag, indicating smc64 calling convention.
56
+ * @param_page: 4K page number of the shmem channel
36
+ * @params: Optional, smc/hvc call parameters.
57
+ * @param_offset: Offset within the 4K page of the shmem channel
37
*/
58
*/
38
59
39
struct scmi_smc {
60
struct scmi_smc {
40
@@ -XXX,XX +XXX,XX @@ struct scmi_smc {
61
@@ -XXX,XX +XXX,XX @@ struct scmi_smc {
41
#define INFLIGHT_NONE    MSG_TOKEN_MAX
62
#define INFLIGHT_NONE    MSG_TOKEN_MAX
42
    atomic_t inflight;
63
    atomic_t inflight;
43
    u32 func_id;
64
    u32 func_id;
44
+    bool is_smc64;
65
+    u32 param_page;
45
+    scmi_smc_param_t params[MAX_PARAM_COUNT];
66
+    u32 param_offset;
46
};
67
};
47
68
48
+static void populate_smc_params(struct device *dev, struct scmi_smc *scmi_info)
69
static irqreturn_t smc_msg_done_isr(int irq, void *data)
49
+{
70
@@ -XXX,XX +XXX,XX @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
50
+    struct device_node *np = dev->of_node;
71
    if (ret < 0)
51
+    u64 params64[MAX_PARAM_COUNT] = { 0 };
72
        return ret;
52
+    u32 params32[MAX_PARAM_COUNT] = { 0 };
73
53
+    int i, count;
74
+    if (of_device_is_compatible(dev->of_node, "arm,scmi-smc-param")) {
54
+
75
+        scmi_info->param_page = SHMEM_PAGE(res.start);
55
+    if (scmi_info->is_smc64) {
76
+        scmi_info->param_offset = SHMEM_OFFSET(res.start);
56
+        count = of_property_read_variable_u64_array(np,
57
+                             "arm,smc64-params",
58
+                             &params64[0], 1,
59
+                             MAX_PARAM_COUNT);
60
+        if (count == -EINVAL) /* if property is not defined */
61
+            return;
62
+
63
+        if (count > 0)    /* populate the parameters */
64
+            for (i = 0; i < count; i++)
65
+                scmi_info->params[i].x = params64[i];
66
+        else
67
+            goto param_err;
68
+    } else {
69
+        count = of_property_read_variable_u32_array(np,
70
+                             "arm,smc32-params",
71
+                             &params32[0], 1,
72
+                             MAX_PARAM_COUNT);
73
+        if (count == -EINVAL) /* if property is not defined */
74
+            return;
75
+
76
+        if (count > 0)    /* populate the parameters */
77
+            for (i = 0; i < count; i++)
78
+                scmi_info->params[i].w = params32[i];
79
+        else
80
+            goto param_err;
81
+    }
77
+    }
82
+
78
    /*
83
+    return;
79
     * If there is an interrupt named "a2p", then the service and
84
+
80
     * completion of a message is signaled by an interrupt rather than by
85
+param_err:
86
+    dev_warn(dev, "failed to read smc/hvc call parameters\n");
87
+}
88
+
89
static irqreturn_t smc_msg_done_isr(int irq, void *data)
90
{
91
    struct scmi_smc *scmi_info = data;
92
@@ -XXX,XX +XXX,XX @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
93
    }
94
95
    scmi_info->func_id = func_id;
96
+    scmi_info->is_smc64 = ARM_SMCCC_IS_64(func_id);
97
+    populate_smc_params(dev, scmi_info);
98
    scmi_info->cinfo = cinfo;
99
    smc_channel_lock_init(scmi_info);
100
    cinfo->transport_info = scmi_info;
101
@@ -XXX,XX +XXX,XX @@ static int smc_send_message(struct scmi_chan_info *cinfo,
81
@@ -XXX,XX +XXX,XX @@ static int smc_send_message(struct scmi_chan_info *cinfo,
102
{
82
{
103
    struct scmi_smc *scmi_info = cinfo->transport_info;
83
    struct scmi_smc *scmi_info = cinfo->transport_info;
104
    struct arm_smccc_res res;
84
    struct arm_smccc_res res;
105
+    scmi_smc_param_t *p = scmi_info->params;
85
+    unsigned long page = scmi_info->param_page;
86
+    unsigned long offset = scmi_info->param_offset;
106
87
107
    /*
88
    /*
108
     * Channel will be released only once response has been
89
     * Channel will be released only once response has been
109
@@ -XXX,XX +XXX,XX @@ static int smc_send_message(struct scmi_chan_info *cinfo,
90
@@ -XXX,XX +XXX,XX @@ static int smc_send_message(struct scmi_chan_info *cinfo,
110
91
111
    shmem_tx_prepare(scmi_info->shmem, xfer, cinfo);
92
    shmem_tx_prepare(scmi_info->shmem, xfer, cinfo);
112
93
113
-    arm_smccc_1_1_invoke(scmi_info->func_id, 0, 0, 0, 0, 0, 0, 0, &res);
94
-    arm_smccc_1_1_invoke(scmi_info->func_id, 0, 0, 0, 0, 0, 0, 0, &res);
114
+    if (scmi_info->is_smc64)
95
+    arm_smccc_1_1_invoke(scmi_info->func_id, page, offset, 0, 0, 0, 0, 0,
115
+        arm_smccc_1_1_invoke(scmi_info->func_id, p[0].x, p[1].x, p[2].x,
96
+             &res);
116
+                 p[3].x, p[4].x, p[5].x, 0, &res);
117
+    else
118
+        arm_smccc_1_1_invoke(scmi_info->func_id, p[0].w, p[1].w, p[2].w,
119
+                 p[3].w, p[4].w, p[5].w, 0, &res);
120
+
121
97
122
    /* Only SMCCC_RET_NOT_SUPPORTED is valid error code */
98
    /* Only SMCCC_RET_NOT_SUPPORTED is valid error code */
123
    if (res.a0) {
99
    if (res.a0) {
124
--
100
--
125
2.17.1
101
2.17.1
diff view generated by jsdifflib