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.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEunHlEgbzHrJD3ZPhAEG6vDF+4pgFAmQ9QqkACgkQAEG6vDF+
 4piUTxAAoScfTHbLJXvPIYiWwtDAn2huYZulwEgyP7IkllcF6s1DO2vFpUnYDg82
 Ew+j+mAfylN5NvXIDI73kfltQJWL0+CKHEtIG3UTeqn9SDJOLDC2P6+HGAoRftdz
 n77ctYyKGL8vgL9gjPh/SVTs74hHbiMLOx7RJJ4udjptEpqT7DriGQneMN8J4F4u
 utgnJiV/21kqDLw1TUA/Z0pJCDXepMHeg6hBZfBw3bW59MN4rlkMk9bUqF2qk8Q3
 vq4stuHZ/USv6Gpv3NLuN3By/+fSJtYrTSTP8jN4NUzjS+trko8CjyPZ19gvUXM8
 dPuQyjyQ5eCWczDLy1mXZWG5ZVDbI1QLcGw70b5fro6/TBiky1zx63khrCTPSVIo
 oy1YajZE4HPmn53AtZ53Ef6fAvlJg35GAXMTd17dvfu0pGTI8qpLPDuEBNVZELbV
 YpMxm4Xk/yfM8p33Vyq7kYrzesHAfXbdkfFWAWchnpwsqW7YxFYiW9ysOM5zeFTa
 KiOyGFD1B6IeiLAMGfnShPkl1RsOY0yiD4KvUFUvoT0WVj0kNMNUK5jJv/g92SHG
 6D4/25ko1Hb4y+W3lwLceY5G7dnxGxh+SXOnEna+vidwcnz10EcvO/u3/S/ufaBq
 xQs43loaN72vivzF4cMpJXpVfXWux3Wr6llosQ5ybJSMflEdq+0=
 =8/Bb
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEiK/NIGsWEZVxh/FrYKtH/8kJUicFAmQ9aAIACgkQYKtH/8kJ
 UifrxA/9HZmzS1B5G0hR8JkENHNrCb6eNfygQo0Xbyrz0240k1cM5GK3APo/oDM8
 RDTIcjh0o2nm4WJ9xvd0SmNQw9+EsrKi19weWVwoXKfYkniKPA+ULArJDXqy7rVT
 +m6s4tOJT2KaWVHZUDhSWRjeWIdv8olhXPxrcVvBpXEBRBrt4bO2UZLvJPXxkiSw
 r8Fih3Wo0QVCOBvxL6PMAQ1IKjqDdQCc1YqnQ+8kOSSfIeE0mVVtxhGAk21Ss8OU
 GCDJ4bSnReENi0KtKTBFTImfF6S2hxAHCTG8KZaR123I3csslRQHhVp+RnVqO61T
 buoFdqmN8Rf9/3pHdzw1rc7+LKX22YFn1n5kKGt1yRXgusJw4hw+EYadSSw0K7g+
 kFplZqfb84Ps5+43xHZZ8jbc5Ifch/xQs2S3X0ysvqgBrZTZbwsEqn/yLOT6TL1/
 g5ykA8lzApBMbk5y/6B7bXUcLtpt60HwXIzFHk0rxmhE9smcjntZ8MvrcbkZjPAY
 136L42P2zn3eBd8kKDzUOU1Q/+YGuwpOQ51ZjEGCOcw8+XanDjUAxCec30L2qThx
 hGrkRY1d2at0pK+xOIQwL/mnyJ52nRzaGXlDBaANhPO/ITAVxgTAPp3MYc6k1hz1
 WRG+t1JE2TChm5t881yUhex87w1pL4MgficgPq1BChExk3fJAPM=
 =maaU
 -----END PGP SIGNATURE-----

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/20230417145743.1904318-1-sudeep.holla@arm.com
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2023-04-17 17:38:41 +02:00
commit 4c87f3ff78
4 changed files with 162 additions and 25 deletions

View File

@ -56,17 +56,38 @@ properties:
description:
Specifies the mailboxes used to communicate with SCMI compliant
firmware.
items:
- const: tx
- const: rx
oneOf:
- items:
- const: tx
- const: rx
minItems: 1
- items:
- const: tx
- const: tx_reply
- const: rx
minItems: 2
mboxes:
description:
List of phandle and mailbox channel specifiers. It should contain
exactly one or two mailboxes, one for transmitting messages("tx")
and another optional for receiving the notifications("rx") if supported.
exactly one, two or three mailboxes; the first one or two for transmitting
messages ("tx") and another optional ("rx") for receiving notifications
and delayed responses, if supported by the platform.
The number of mailboxes needed for transmitting messages depends on the
type of channels exposed by the specific underlying mailbox controller;
one single channel descriptor is enough if such channel is bidirectional,
while two channel descriptors are needed to represent the SCMI ("tx")
channel if the underlying mailbox channels are of unidirectional type.
The effective combination in numbers of mboxes and shmem descriptors let
the SCMI subsystem determine unambiguosly which type of SCMI channels are
made available by the underlying mailbox controller and how to use them.
1 mbox / 1 shmem => SCMI TX over 1 mailbox bidirectional channel
2 mbox / 2 shmem => SCMI TX and RX over 2 mailbox bidirectional channels
2 mbox / 1 shmem => SCMI TX over 2 mailbox unidirectional channels
3 mbox / 2 shmem => SCMI TX and RX over 3 mailbox unidirectional channels
Any other combination of mboxes and shmem is invalid.
minItems: 1
maxItems: 2
maxItems: 3
shmem:
description:
@ -228,13 +249,20 @@ $defs:
maxItems: 1
mbox-names:
items:
- const: tx
- const: rx
oneOf:
- items:
- const: tx
- const: rx
minItems: 1
- items:
- const: tx
- const: tx_reply
- const: rx
minItems: 2
mboxes:
minItems: 1
maxItems: 2
maxItems: 3
shmem:
minItems: 1

View File

@ -14,7 +14,6 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/of.h>
#include "common.h"
@ -436,7 +435,7 @@ struct scmi_device *scmi_device_create(struct device_node *np,
/* Nothing to do. */
if (!phead) {
mutex_unlock(&scmi_requested_devices_mtx);
return scmi_dev;
return NULL;
}
/* Walk the list of requested devices for protocol and create them */

View File

@ -2221,8 +2221,8 @@ static int __scmi_xfer_info_init(struct scmi_info *sinfo,
hash_init(info->pending_xfers);
/* Allocate a bitmask sized to hold MSG_TOKEN_MAX tokens */
info->xfer_alloc_table = devm_kcalloc(dev, BITS_TO_LONGS(MSG_TOKEN_MAX),
sizeof(long), GFP_KERNEL);
info->xfer_alloc_table = devm_bitmap_zalloc(dev, MSG_TOKEN_MAX,
GFP_KERNEL);
if (!info->xfer_alloc_table)
return -ENOMEM;
@ -2289,7 +2289,7 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo)
return ret;
ret = __scmi_xfer_info_init(sinfo, &sinfo->tx_minfo);
if (!ret && idr_find(&sinfo->rx_idr, SCMI_PROTOCOL_BASE))
if (!ret && !idr_is_empty(&sinfo->rx_idr))
ret = __scmi_xfer_info_init(sinfo, &sinfo->rx_minfo);
return ret;
@ -2657,6 +2657,7 @@ static int scmi_probe(struct platform_device *pdev)
struct scmi_handle *handle;
const struct scmi_desc *desc;
struct scmi_info *info;
bool coex = IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX);
struct device *dev = &pdev->dev;
struct device_node *child, *np = dev->of_node;
@ -2731,16 +2732,13 @@ static int scmi_probe(struct platform_device *pdev)
dev_warn(dev, "Failed to setup SCMI debugfs.\n");
if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) {
bool coex =
IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX);
ret = scmi_debugfs_raw_mode_setup(info);
if (!coex) {
if (ret)
goto clear_dev_req_notifier;
/* Bail out anyway when coex enabled */
return ret;
/* Bail out anyway when coex disabled. */
return 0;
}
/* Coex enabled, carry on in any case. */
@ -2764,6 +2762,8 @@ static int scmi_probe(struct platform_device *pdev)
ret = scmi_protocol_acquire(handle, SCMI_PROTOCOL_BASE);
if (ret) {
dev_err(dev, "unable to communicate with SCMI\n");
if (coex)
return 0;
goto notification_exit;
}

View File

@ -19,13 +19,15 @@
* struct scmi_mailbox - Structure representing a SCMI mailbox transport
*
* @cl: Mailbox Client
* @chan: Transmit/Receive mailbox channel
* @chan: Transmit/Receive mailbox uni/bi-directional channel
* @chan_receiver: Optional Receiver mailbox unidirectional channel
* @cinfo: SCMI channel info
* @shmem: Transmit/Receive shared memory area
*/
struct scmi_mailbox {
struct mbox_client cl;
struct mbox_chan *chan;
struct mbox_chan *chan_receiver;
struct scmi_chan_info *cinfo;
struct scmi_shared_mem __iomem *shmem;
};
@ -48,10 +50,98 @@ static void rx_callback(struct mbox_client *cl, void *m)
static bool mailbox_chan_available(struct device_node *of_node, int idx)
{
int num_mb;
/*
* Just check if bidirrectional channels are involved, and check the
* index accordingly; proper full validation will be made later
* in mailbox_chan_setup().
*/
num_mb = of_count_phandle_with_args(of_node, "mboxes", "#mbox-cells");
if (num_mb == 3 && idx == 1)
idx = 2;
return !of_parse_phandle_with_args(of_node, "mboxes",
"#mbox-cells", idx, NULL);
}
/**
* mailbox_chan_validate - Validate transport configuration and map channels
*
* @cdev: Reference to the underlying transport device carrying the
* of_node descriptor to analyze.
* @a2p_rx_chan: A reference to an optional unidirectional channel to use
* for replies on the a2p channel. Set as zero if not present.
* @p2a_chan: A reference to the optional p2a channel.
* Set as zero if not present.
*
* At first, validate the transport configuration as described in terms of
* 'mboxes' and 'shmem', then determin which mailbox channel indexes are
* appropriate to be use in the current configuration.
*
* Return: 0 on Success or error
*/
static int mailbox_chan_validate(struct device *cdev,
int *a2p_rx_chan, int *p2a_chan)
{
int num_mb, num_sh, ret = 0;
struct device_node *np = cdev->of_node;
num_mb = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
num_sh = of_count_phandle_with_args(np, "shmem", NULL);
dev_dbg(cdev, "Found %d mboxes and %d shmems !\n", num_mb, num_sh);
/* Bail out if mboxes and shmem descriptors are inconsistent */
if (num_mb <= 0 || num_sh <= 0 || num_sh > 2 || num_mb > 3 ||
(num_mb == 1 && num_sh != 1) || (num_mb == 3 && num_sh != 2)) {
dev_warn(cdev,
"Invalid channel descriptor for '%s' - mbs:%d shm:%d\n",
of_node_full_name(np), num_mb, num_sh);
return -EINVAL;
}
/* Bail out if provided shmem descriptors do not refer distinct areas */
if (num_sh > 1) {
struct device_node *np_tx, *np_rx;
np_tx = of_parse_phandle(np, "shmem", 0);
np_rx = of_parse_phandle(np, "shmem", 1);
if (!np_tx || !np_rx || np_tx == np_rx) {
dev_warn(cdev, "Invalid shmem descriptor for '%s'\n",
of_node_full_name(np));
ret = -EINVAL;
}
of_node_put(np_tx);
of_node_put(np_rx);
}
/* Calculate channels IDs to use depending on mboxes/shmem layout */
if (!ret) {
switch (num_mb) {
case 1:
*a2p_rx_chan = 0;
*p2a_chan = 0;
break;
case 2:
if (num_sh == 2) {
*a2p_rx_chan = 0;
*p2a_chan = 1;
} else {
*a2p_rx_chan = 1;
*p2a_chan = 0;
}
break;
case 3:
*a2p_rx_chan = 1;
*p2a_chan = 2;
break;
}
}
return ret;
}
static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
bool tx)
{
@ -59,11 +149,18 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
struct device *cdev = cinfo->dev;
struct scmi_mailbox *smbox;
struct device_node *shmem;
int ret, idx = tx ? 0 : 1;
int ret, a2p_rx_chan, p2a_chan, idx = tx ? 0 : 1;
struct mbox_client *cl;
resource_size_t size;
struct resource res;
ret = mailbox_chan_validate(cdev, &a2p_rx_chan, &p2a_chan);
if (ret)
return ret;
if (!tx && !p2a_chan)
return -ENODEV;
smbox = devm_kzalloc(dev, sizeof(*smbox), GFP_KERNEL);
if (!smbox)
return -ENOMEM;
@ -93,15 +190,26 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
cl->tx_block = false;
cl->knows_txdone = tx;
smbox->chan = mbox_request_channel(cl, tx ? 0 : 1);
smbox->chan = mbox_request_channel(cl, tx ? 0 : p2a_chan);
if (IS_ERR(smbox->chan)) {
ret = PTR_ERR(smbox->chan);
if (ret != -EPROBE_DEFER)
dev_err(cdev, "failed to request SCMI %s mailbox\n",
tx ? "Tx" : "Rx");
dev_err(cdev,
"failed to request SCMI %s mailbox\n", desc);
return ret;
}
/* Additional unidirectional channel for TX if needed */
if (tx && a2p_rx_chan) {
smbox->chan_receiver = mbox_request_channel(cl, a2p_rx_chan);
if (IS_ERR(smbox->chan_receiver)) {
ret = PTR_ERR(smbox->chan_receiver);
if (ret != -EPROBE_DEFER)
dev_err(cdev, "failed to request SCMI Tx Receiver mailbox\n");
return ret;
}
}
cinfo->transport_info = smbox;
smbox->cinfo = cinfo;
@ -115,8 +223,10 @@ static int mailbox_chan_free(int id, void *p, void *data)
if (smbox && !IS_ERR(smbox->chan)) {
mbox_free_channel(smbox->chan);
mbox_free_channel(smbox->chan_receiver);
cinfo->transport_info = NULL;
smbox->chan = NULL;
smbox->chan_receiver = NULL;
smbox->cinfo = NULL;
}