Skip to content

Commit 4c87f3f

Browse files
committed
Merge tag 'scmi-updates-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into soc/drivers
Arm SCMI updates for v6.4 The main and only new addition this time around is the support for unidirectional mailbox channels. SCMI communicates between the agent and the platform using one bidirectional 'a2p' channel used by the agent to send SCMI commands and synchronously receive the related replies, and an optional 'p2a' unidirectional channel used to asynchronously receive delayed responses and notifications emitted from the platform. In order to support platforms that support only unidirectional mailbox hardware channels, the existing bindings are extended to support the same. Both bidirectional and unidirectional channels support for the SCMI mailbox can coexist. The correct and effective combination of defined 'mboxes' and 'shmem' descriptors determines the type of the mailbox channel. This also contains a fix for the transfers allocation on Rx channel especially when the base protocol doesn't use Rx channel while some of the protocols can have dedicated Rx channels. * tag 'scmi-updates-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux: firmware: arm_scmi: Add support for unidirectional mailbox channels dt-bindings: firmware: arm,scmi: Support mailboxes unidirectional channels firmware: arm_scmi: Fix xfers allocation on Rx channel firmware: arm_scmi: Use the bitmap API to allocate bitmaps firmware: arm_scmi: Fix device node validation for mailbox transport firmware: arm_scmi: Fix raw coexistence mode behaviour on failure path firmware: arm_scmi: Remove duplicate include header inclusion firmware: arm_scmi: Return a literal instead of a variable firmware: arm_scmi: Clean up a return statement in scmi_probe Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnd Bergmann <[email protected]>
2 parents 1aa8854 + 9f68ff7 commit 4c87f3f

File tree

4 files changed

+162
-25
lines changed

4 files changed

+162
-25
lines changed

Documentation/devicetree/bindings/firmware/arm,scmi.yaml

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,38 @@ properties:
5656
description:
5757
Specifies the mailboxes used to communicate with SCMI compliant
5858
firmware.
59-
items:
60-
- const: tx
61-
- const: rx
59+
oneOf:
60+
- items:
61+
- const: tx
62+
- const: rx
63+
minItems: 1
64+
- items:
65+
- const: tx
66+
- const: tx_reply
67+
- const: rx
68+
minItems: 2
6269

6370
mboxes:
6471
description:
6572
List of phandle and mailbox channel specifiers. It should contain
66-
exactly one or two mailboxes, one for transmitting messages("tx")
67-
and another optional for receiving the notifications("rx") if supported.
73+
exactly one, two or three mailboxes; the first one or two for transmitting
74+
messages ("tx") and another optional ("rx") for receiving notifications
75+
and delayed responses, if supported by the platform.
76+
The number of mailboxes needed for transmitting messages depends on the
77+
type of channels exposed by the specific underlying mailbox controller;
78+
one single channel descriptor is enough if such channel is bidirectional,
79+
while two channel descriptors are needed to represent the SCMI ("tx")
80+
channel if the underlying mailbox channels are of unidirectional type.
81+
The effective combination in numbers of mboxes and shmem descriptors let
82+
the SCMI subsystem determine unambiguosly which type of SCMI channels are
83+
made available by the underlying mailbox controller and how to use them.
84+
1 mbox / 1 shmem => SCMI TX over 1 mailbox bidirectional channel
85+
2 mbox / 2 shmem => SCMI TX and RX over 2 mailbox bidirectional channels
86+
2 mbox / 1 shmem => SCMI TX over 2 mailbox unidirectional channels
87+
3 mbox / 2 shmem => SCMI TX and RX over 3 mailbox unidirectional channels
88+
Any other combination of mboxes and shmem is invalid.
6889
minItems: 1
69-
maxItems: 2
90+
maxItems: 3
7091

7192
shmem:
7293
description:
@@ -228,13 +249,20 @@ $defs:
228249
maxItems: 1
229250

230251
mbox-names:
231-
items:
232-
- const: tx
233-
- const: rx
252+
oneOf:
253+
- items:
254+
- const: tx
255+
- const: rx
256+
minItems: 1
257+
- items:
258+
- const: tx
259+
- const: tx_reply
260+
- const: rx
261+
minItems: 2
234262

235263
mboxes:
236264
minItems: 1
237-
maxItems: 2
265+
maxItems: 3
238266

239267
shmem:
240268
minItems: 1

drivers/firmware/arm_scmi/bus.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include <linux/kernel.h>
1515
#include <linux/slab.h>
1616
#include <linux/device.h>
17-
#include <linux/of.h>
1817

1918
#include "common.h"
2019

@@ -436,7 +435,7 @@ struct scmi_device *scmi_device_create(struct device_node *np,
436435
/* Nothing to do. */
437436
if (!phead) {
438437
mutex_unlock(&scmi_requested_devices_mtx);
439-
return scmi_dev;
438+
return NULL;
440439
}
441440

442441
/* Walk the list of requested devices for protocol and create them */

drivers/firmware/arm_scmi/driver.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2221,8 +2221,8 @@ static int __scmi_xfer_info_init(struct scmi_info *sinfo,
22212221
hash_init(info->pending_xfers);
22222222

22232223
/* Allocate a bitmask sized to hold MSG_TOKEN_MAX tokens */
2224-
info->xfer_alloc_table = devm_kcalloc(dev, BITS_TO_LONGS(MSG_TOKEN_MAX),
2225-
sizeof(long), GFP_KERNEL);
2224+
info->xfer_alloc_table = devm_bitmap_zalloc(dev, MSG_TOKEN_MAX,
2225+
GFP_KERNEL);
22262226
if (!info->xfer_alloc_table)
22272227
return -ENOMEM;
22282228

@@ -2289,7 +2289,7 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo)
22892289
return ret;
22902290

22912291
ret = __scmi_xfer_info_init(sinfo, &sinfo->tx_minfo);
2292-
if (!ret && idr_find(&sinfo->rx_idr, SCMI_PROTOCOL_BASE))
2292+
if (!ret && !idr_is_empty(&sinfo->rx_idr))
22932293
ret = __scmi_xfer_info_init(sinfo, &sinfo->rx_minfo);
22942294

22952295
return ret;
@@ -2657,6 +2657,7 @@ static int scmi_probe(struct platform_device *pdev)
26572657
struct scmi_handle *handle;
26582658
const struct scmi_desc *desc;
26592659
struct scmi_info *info;
2660+
bool coex = IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX);
26602661
struct device *dev = &pdev->dev;
26612662
struct device_node *child, *np = dev->of_node;
26622663

@@ -2731,16 +2732,13 @@ static int scmi_probe(struct platform_device *pdev)
27312732
dev_warn(dev, "Failed to setup SCMI debugfs.\n");
27322733

27332734
if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) {
2734-
bool coex =
2735-
IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX);
2736-
27372735
ret = scmi_debugfs_raw_mode_setup(info);
27382736
if (!coex) {
27392737
if (ret)
27402738
goto clear_dev_req_notifier;
27412739

2742-
/* Bail out anyway when coex enabled */
2743-
return ret;
2740+
/* Bail out anyway when coex disabled. */
2741+
return 0;
27442742
}
27452743

27462744
/* Coex enabled, carry on in any case. */
@@ -2764,6 +2762,8 @@ static int scmi_probe(struct platform_device *pdev)
27642762
ret = scmi_protocol_acquire(handle, SCMI_PROTOCOL_BASE);
27652763
if (ret) {
27662764
dev_err(dev, "unable to communicate with SCMI\n");
2765+
if (coex)
2766+
return 0;
27672767
goto notification_exit;
27682768
}
27692769

drivers/firmware/arm_scmi/mailbox.c

Lines changed: 115 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919
* struct scmi_mailbox - Structure representing a SCMI mailbox transport
2020
*
2121
* @cl: Mailbox Client
22-
* @chan: Transmit/Receive mailbox channel
22+
* @chan: Transmit/Receive mailbox uni/bi-directional channel
23+
* @chan_receiver: Optional Receiver mailbox unidirectional channel
2324
* @cinfo: SCMI channel info
2425
* @shmem: Transmit/Receive shared memory area
2526
*/
2627
struct scmi_mailbox {
2728
struct mbox_client cl;
2829
struct mbox_chan *chan;
30+
struct mbox_chan *chan_receiver;
2931
struct scmi_chan_info *cinfo;
3032
struct scmi_shared_mem __iomem *shmem;
3133
};
@@ -48,22 +50,117 @@ static void rx_callback(struct mbox_client *cl, void *m)
4850

4951
static bool mailbox_chan_available(struct device_node *of_node, int idx)
5052
{
53+
int num_mb;
54+
55+
/*
56+
* Just check if bidirrectional channels are involved, and check the
57+
* index accordingly; proper full validation will be made later
58+
* in mailbox_chan_setup().
59+
*/
60+
num_mb = of_count_phandle_with_args(of_node, "mboxes", "#mbox-cells");
61+
if (num_mb == 3 && idx == 1)
62+
idx = 2;
63+
5164
return !of_parse_phandle_with_args(of_node, "mboxes",
5265
"#mbox-cells", idx, NULL);
5366
}
5467

68+
/**
69+
* mailbox_chan_validate - Validate transport configuration and map channels
70+
*
71+
* @cdev: Reference to the underlying transport device carrying the
72+
* of_node descriptor to analyze.
73+
* @a2p_rx_chan: A reference to an optional unidirectional channel to use
74+
* for replies on the a2p channel. Set as zero if not present.
75+
* @p2a_chan: A reference to the optional p2a channel.
76+
* Set as zero if not present.
77+
*
78+
* At first, validate the transport configuration as described in terms of
79+
* 'mboxes' and 'shmem', then determin which mailbox channel indexes are
80+
* appropriate to be use in the current configuration.
81+
*
82+
* Return: 0 on Success or error
83+
*/
84+
static int mailbox_chan_validate(struct device *cdev,
85+
int *a2p_rx_chan, int *p2a_chan)
86+
{
87+
int num_mb, num_sh, ret = 0;
88+
struct device_node *np = cdev->of_node;
89+
90+
num_mb = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
91+
num_sh = of_count_phandle_with_args(np, "shmem", NULL);
92+
dev_dbg(cdev, "Found %d mboxes and %d shmems !\n", num_mb, num_sh);
93+
94+
/* Bail out if mboxes and shmem descriptors are inconsistent */
95+
if (num_mb <= 0 || num_sh <= 0 || num_sh > 2 || num_mb > 3 ||
96+
(num_mb == 1 && num_sh != 1) || (num_mb == 3 && num_sh != 2)) {
97+
dev_warn(cdev,
98+
"Invalid channel descriptor for '%s' - mbs:%d shm:%d\n",
99+
of_node_full_name(np), num_mb, num_sh);
100+
return -EINVAL;
101+
}
102+
103+
/* Bail out if provided shmem descriptors do not refer distinct areas */
104+
if (num_sh > 1) {
105+
struct device_node *np_tx, *np_rx;
106+
107+
np_tx = of_parse_phandle(np, "shmem", 0);
108+
np_rx = of_parse_phandle(np, "shmem", 1);
109+
if (!np_tx || !np_rx || np_tx == np_rx) {
110+
dev_warn(cdev, "Invalid shmem descriptor for '%s'\n",
111+
of_node_full_name(np));
112+
ret = -EINVAL;
113+
}
114+
115+
of_node_put(np_tx);
116+
of_node_put(np_rx);
117+
}
118+
119+
/* Calculate channels IDs to use depending on mboxes/shmem layout */
120+
if (!ret) {
121+
switch (num_mb) {
122+
case 1:
123+
*a2p_rx_chan = 0;
124+
*p2a_chan = 0;
125+
break;
126+
case 2:
127+
if (num_sh == 2) {
128+
*a2p_rx_chan = 0;
129+
*p2a_chan = 1;
130+
} else {
131+
*a2p_rx_chan = 1;
132+
*p2a_chan = 0;
133+
}
134+
break;
135+
case 3:
136+
*a2p_rx_chan = 1;
137+
*p2a_chan = 2;
138+
break;
139+
}
140+
}
141+
142+
return ret;
143+
}
144+
55145
static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
56146
bool tx)
57147
{
58148
const char *desc = tx ? "Tx" : "Rx";
59149
struct device *cdev = cinfo->dev;
60150
struct scmi_mailbox *smbox;
61151
struct device_node *shmem;
62-
int ret, idx = tx ? 0 : 1;
152+
int ret, a2p_rx_chan, p2a_chan, idx = tx ? 0 : 1;
63153
struct mbox_client *cl;
64154
resource_size_t size;
65155
struct resource res;
66156

157+
ret = mailbox_chan_validate(cdev, &a2p_rx_chan, &p2a_chan);
158+
if (ret)
159+
return ret;
160+
161+
if (!tx && !p2a_chan)
162+
return -ENODEV;
163+
67164
smbox = devm_kzalloc(dev, sizeof(*smbox), GFP_KERNEL);
68165
if (!smbox)
69166
return -ENOMEM;
@@ -93,15 +190,26 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
93190
cl->tx_block = false;
94191
cl->knows_txdone = tx;
95192

96-
smbox->chan = mbox_request_channel(cl, tx ? 0 : 1);
193+
smbox->chan = mbox_request_channel(cl, tx ? 0 : p2a_chan);
97194
if (IS_ERR(smbox->chan)) {
98195
ret = PTR_ERR(smbox->chan);
99196
if (ret != -EPROBE_DEFER)
100-
dev_err(cdev, "failed to request SCMI %s mailbox\n",
101-
tx ? "Tx" : "Rx");
197+
dev_err(cdev,
198+
"failed to request SCMI %s mailbox\n", desc);
102199
return ret;
103200
}
104201

202+
/* Additional unidirectional channel for TX if needed */
203+
if (tx && a2p_rx_chan) {
204+
smbox->chan_receiver = mbox_request_channel(cl, a2p_rx_chan);
205+
if (IS_ERR(smbox->chan_receiver)) {
206+
ret = PTR_ERR(smbox->chan_receiver);
207+
if (ret != -EPROBE_DEFER)
208+
dev_err(cdev, "failed to request SCMI Tx Receiver mailbox\n");
209+
return ret;
210+
}
211+
}
212+
105213
cinfo->transport_info = smbox;
106214
smbox->cinfo = cinfo;
107215

@@ -115,8 +223,10 @@ static int mailbox_chan_free(int id, void *p, void *data)
115223

116224
if (smbox && !IS_ERR(smbox->chan)) {
117225
mbox_free_channel(smbox->chan);
226+
mbox_free_channel(smbox->chan_receiver);
118227
cinfo->transport_info = NULL;
119228
smbox->chan = NULL;
229+
smbox->chan_receiver = NULL;
120230
smbox->cinfo = NULL;
121231
}
122232

0 commit comments

Comments
 (0)