Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+162 -25
+38 -10
Documentation/devicetree/bindings/firmware/arm,scmi.yaml
··· 56 56 description: 57 57 Specifies the mailboxes used to communicate with SCMI compliant 58 58 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 62 69 63 70 mboxes: 64 71 description: 65 72 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. 68 89 minItems: 1 69 - maxItems: 2 90 + maxItems: 3 70 91 71 92 shmem: 72 93 description: ··· 249 228 maxItems: 1 250 229 251 230 mbox-names: 252 - items: 253 - - const: tx 254 - - const: rx 231 + oneOf: 232 + - items: 233 + - const: tx 234 + - const: rx 235 + minItems: 1 236 + - items: 237 + - const: tx 238 + - const: tx_reply 239 + - const: rx 240 + minItems: 2 255 241 256 242 mboxes: 257 243 minItems: 1 258 - maxItems: 2 244 + maxItems: 3 259 245 260 246 shmem: 261 247 minItems: 1
+1 -2
drivers/firmware/arm_scmi/bus.c
··· 14 14 #include <linux/kernel.h> 15 15 #include <linux/slab.h> 16 16 #include <linux/device.h> 17 - #include <linux/of.h> 18 17 19 18 #include "common.h" 20 19 ··· 435 436 /* Nothing to do. */ 436 437 if (!phead) { 437 438 mutex_unlock(&scmi_requested_devices_mtx); 438 - return scmi_dev; 439 + return NULL; 439 440 } 440 441 441 442 /* Walk the list of requested devices for protocol and create them */
+8 -8
drivers/firmware/arm_scmi/driver.c
··· 2221 2221 hash_init(info->pending_xfers); 2222 2222 2223 2223 /* 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); 2226 2226 if (!info->xfer_alloc_table) 2227 2227 return -ENOMEM; 2228 2228 ··· 2289 2289 return ret; 2290 2290 2291 2291 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)) 2293 2293 ret = __scmi_xfer_info_init(sinfo, &sinfo->rx_minfo); 2294 2294 2295 2295 return ret; ··· 2657 2657 struct scmi_handle *handle; 2658 2658 const struct scmi_desc *desc; 2659 2659 struct scmi_info *info; 2660 + bool coex = IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX); 2660 2661 struct device *dev = &pdev->dev; 2661 2662 struct device_node *child, *np = dev->of_node; 2662 2663 ··· 2732 2731 dev_warn(dev, "Failed to setup SCMI debugfs.\n"); 2733 2732 2734 2733 if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) { 2735 - bool coex = 2736 - IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX); 2737 - 2738 2734 ret = scmi_debugfs_raw_mode_setup(info); 2739 2735 if (!coex) { 2740 2736 if (ret) 2741 2737 goto clear_dev_req_notifier; 2742 2738 2743 - /* Bail out anyway when coex enabled */ 2744 - return ret; 2739 + /* Bail out anyway when coex disabled. */ 2740 + return 0; 2745 2741 } 2746 2742 2747 2743 /* Coex enabled, carry on in any case. */ ··· 2762 2764 ret = scmi_protocol_acquire(handle, SCMI_PROTOCOL_BASE); 2763 2765 if (ret) { 2764 2766 dev_err(dev, "unable to communicate with SCMI\n"); 2767 + if (coex) 2768 + return 0; 2765 2769 goto notification_exit; 2766 2770 } 2767 2771
+115 -5
drivers/firmware/arm_scmi/mailbox.c
··· 19 19 * struct scmi_mailbox - Structure representing a SCMI mailbox transport 20 20 * 21 21 * @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 23 24 * @cinfo: SCMI channel info 24 25 * @shmem: Transmit/Receive shared memory area 25 26 */ 26 27 struct scmi_mailbox { 27 28 struct mbox_client cl; 28 29 struct mbox_chan *chan; 30 + struct mbox_chan *chan_receiver; 29 31 struct scmi_chan_info *cinfo; 30 32 struct scmi_shared_mem __iomem *shmem; 31 33 }; ··· 50 48 51 49 static bool mailbox_chan_available(struct device_node *of_node, int idx) 52 50 { 51 + int num_mb; 52 + 53 + /* 54 + * Just check if bidirrectional channels are involved, and check the 55 + * index accordingly; proper full validation will be made later 56 + * in mailbox_chan_setup(). 57 + */ 58 + num_mb = of_count_phandle_with_args(of_node, "mboxes", "#mbox-cells"); 59 + if (num_mb == 3 && idx == 1) 60 + idx = 2; 61 + 53 62 return !of_parse_phandle_with_args(of_node, "mboxes", 54 63 "#mbox-cells", idx, NULL); 64 + } 65 + 66 + /** 67 + * mailbox_chan_validate - Validate transport configuration and map channels 68 + * 69 + * @cdev: Reference to the underlying transport device carrying the 70 + * of_node descriptor to analyze. 71 + * @a2p_rx_chan: A reference to an optional unidirectional channel to use 72 + * for replies on the a2p channel. Set as zero if not present. 73 + * @p2a_chan: A reference to the optional p2a channel. 74 + * Set as zero if not present. 75 + * 76 + * At first, validate the transport configuration as described in terms of 77 + * 'mboxes' and 'shmem', then determin which mailbox channel indexes are 78 + * appropriate to be use in the current configuration. 79 + * 80 + * Return: 0 on Success or error 81 + */ 82 + static int mailbox_chan_validate(struct device *cdev, 83 + int *a2p_rx_chan, int *p2a_chan) 84 + { 85 + int num_mb, num_sh, ret = 0; 86 + struct device_node *np = cdev->of_node; 87 + 88 + num_mb = of_count_phandle_with_args(np, "mboxes", "#mbox-cells"); 89 + num_sh = of_count_phandle_with_args(np, "shmem", NULL); 90 + dev_dbg(cdev, "Found %d mboxes and %d shmems !\n", num_mb, num_sh); 91 + 92 + /* Bail out if mboxes and shmem descriptors are inconsistent */ 93 + if (num_mb <= 0 || num_sh <= 0 || num_sh > 2 || num_mb > 3 || 94 + (num_mb == 1 && num_sh != 1) || (num_mb == 3 && num_sh != 2)) { 95 + dev_warn(cdev, 96 + "Invalid channel descriptor for '%s' - mbs:%d shm:%d\n", 97 + of_node_full_name(np), num_mb, num_sh); 98 + return -EINVAL; 99 + } 100 + 101 + /* Bail out if provided shmem descriptors do not refer distinct areas */ 102 + if (num_sh > 1) { 103 + struct device_node *np_tx, *np_rx; 104 + 105 + np_tx = of_parse_phandle(np, "shmem", 0); 106 + np_rx = of_parse_phandle(np, "shmem", 1); 107 + if (!np_tx || !np_rx || np_tx == np_rx) { 108 + dev_warn(cdev, "Invalid shmem descriptor for '%s'\n", 109 + of_node_full_name(np)); 110 + ret = -EINVAL; 111 + } 112 + 113 + of_node_put(np_tx); 114 + of_node_put(np_rx); 115 + } 116 + 117 + /* Calculate channels IDs to use depending on mboxes/shmem layout */ 118 + if (!ret) { 119 + switch (num_mb) { 120 + case 1: 121 + *a2p_rx_chan = 0; 122 + *p2a_chan = 0; 123 + break; 124 + case 2: 125 + if (num_sh == 2) { 126 + *a2p_rx_chan = 0; 127 + *p2a_chan = 1; 128 + } else { 129 + *a2p_rx_chan = 1; 130 + *p2a_chan = 0; 131 + } 132 + break; 133 + case 3: 134 + *a2p_rx_chan = 1; 135 + *p2a_chan = 2; 136 + break; 137 + } 138 + } 139 + 140 + return ret; 55 141 } 56 142 57 143 static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, ··· 149 59 struct device *cdev = cinfo->dev; 150 60 struct scmi_mailbox *smbox; 151 61 struct device_node *shmem; 152 - int ret, idx = tx ? 0 : 1; 62 + int ret, a2p_rx_chan, p2a_chan, idx = tx ? 0 : 1; 153 63 struct mbox_client *cl; 154 64 resource_size_t size; 155 65 struct resource res; 66 + 67 + ret = mailbox_chan_validate(cdev, &a2p_rx_chan, &p2a_chan); 68 + if (ret) 69 + return ret; 70 + 71 + if (!tx && !p2a_chan) 72 + return -ENODEV; 156 73 157 74 smbox = devm_kzalloc(dev, sizeof(*smbox), GFP_KERNEL); 158 75 if (!smbox) ··· 190 93 cl->tx_block = false; 191 94 cl->knows_txdone = tx; 192 95 193 - smbox->chan = mbox_request_channel(cl, tx ? 0 : 1); 96 + smbox->chan = mbox_request_channel(cl, tx ? 0 : p2a_chan); 194 97 if (IS_ERR(smbox->chan)) { 195 98 ret = PTR_ERR(smbox->chan); 196 99 if (ret != -EPROBE_DEFER) 197 - dev_err(cdev, "failed to request SCMI %s mailbox\n", 198 - tx ? "Tx" : "Rx"); 100 + dev_err(cdev, 101 + "failed to request SCMI %s mailbox\n", desc); 199 102 return ret; 103 + } 104 + 105 + /* Additional unidirectional channel for TX if needed */ 106 + if (tx && a2p_rx_chan) { 107 + smbox->chan_receiver = mbox_request_channel(cl, a2p_rx_chan); 108 + if (IS_ERR(smbox->chan_receiver)) { 109 + ret = PTR_ERR(smbox->chan_receiver); 110 + if (ret != -EPROBE_DEFER) 111 + dev_err(cdev, "failed to request SCMI Tx Receiver mailbox\n"); 112 + return ret; 113 + } 200 114 } 201 115 202 116 cinfo->transport_info = smbox; ··· 223 115 224 116 if (smbox && !IS_ERR(smbox->chan)) { 225 117 mbox_free_channel(smbox->chan); 118 + mbox_free_channel(smbox->chan_receiver); 226 119 cinfo->transport_info = NULL; 227 120 smbox->chan = NULL; 121 + smbox->chan_receiver = NULL; 228 122 smbox->cinfo = NULL; 229 123 } 230 124