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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'scmi-updates-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into soc/drivers

Arm SCMI updates/fixes for v6.18

These SCMI changes bring a mix of improvements, fixes, and cleanups:

1. Device Tree bindings - allow multiple SCMI instances by suffixing
node names (Nikunj Kela).
2. Code hardening - constify both scmi_{transport,voltage_proto}_ops
so they reside in read-only memory (Christophe JAILLET).
3. VirtIO transport initialization - set DRIVER_OK before SCMI probing
to prevent potential stalls; while recent rework removes the practical
risk, this ensures correctness (Junnan Wu).
4. Quirk handling - fix a critical bug by preventing writes to string
constants, avoiding faults in read-only memory (Johan Hovold).
5. i.MX SCMI MISC protocol - extend support to discover board info,
retrieve configuration and build data, and document the new
MISC_BOARD_INFO command; all handled gracefully if unsupported (Peng Fan).
6. Logging cleanup - simplify device tree node name logging by using
the %pOF format to print full paths (Krzysztof Kozlowski).

* tag 'scmi-updates-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux:
firmware: arm_scmi: Simplify printks with pOF format
firmware: arm_scmi: imx: Discover MISC board info from the system manager
firmware: arm_scmi: imx: Support retrieving MISC protocol configuration info
firmware: arm_scmi: imx: Discover MISC build info from the system manager
firmware: arm_scmi: imx: Add documentation for MISC_BOARD_INFO
firmware: arm_scmi: quirk: Prevent writes to string constants
firmware: arm_scmi: Fix function name typo in scmi_perf_proto_ops struct
firmware: arm_scmi: Mark VirtIO ready before registering scmi_virtio_driver
firmware: arm_scmi: Constify struct scmi_transport_ops
firmware: arm_scmi: Constify struct scmi_voltage_proto_ops
dt-bindings: firmware: arm,scmi: Allow multiple instances

Link: https://lore.kernel.org/r/20250915101341.2987516-1-sudeep.holla@arm.com
Signed-off-by: Arnd Bergmann <arnd@arndb.de>

+162 -20
+1 -1
Documentation/devicetree/bindings/firmware/arm,scmi.yaml
··· 27 27 28 28 properties: 29 29 $nodename: 30 - const: scmi 30 + pattern: '^scmi(-[0-9]+)?$' 31 31 32 32 compatible: 33 33 oneOf:
+6 -7
drivers/firmware/arm_scmi/bus.c
··· 401 401 402 402 static void __scmi_device_destroy(struct scmi_device *scmi_dev) 403 403 { 404 - pr_debug("(%s) Destroying SCMI device '%s' for protocol 0x%x (%s)\n", 405 - of_node_full_name(scmi_dev->dev.parent->of_node), 404 + pr_debug("(%pOF) Destroying SCMI device '%s' for protocol 0x%x (%s)\n", 405 + scmi_dev->dev.parent->of_node, 406 406 dev_name(&scmi_dev->dev), scmi_dev->protocol_id, 407 407 scmi_dev->name); 408 408 ··· 474 474 if (retval) 475 475 goto put_dev; 476 476 477 - pr_debug("(%s) Created SCMI device '%s' for protocol 0x%x (%s)\n", 478 - of_node_full_name(parent->of_node), 479 - dev_name(&scmi_dev->dev), protocol, name); 477 + pr_debug("(%pOF) Created SCMI device '%s' for protocol 0x%x (%s)\n", 478 + parent->of_node, dev_name(&scmi_dev->dev), protocol, name); 480 479 481 480 return scmi_dev; 482 481 put_dev: ··· 492 493 493 494 sdev = __scmi_device_create(np, parent, protocol, name); 494 495 if (!sdev) 495 - pr_err("(%s) Failed to create device for protocol 0x%x (%s)\n", 496 - of_node_full_name(parent->of_node), protocol, name); 496 + pr_err("(%pOF) Failed to create device for protocol 0x%x (%s)\n", 497 + parent->of_node, protocol, name); 497 498 498 499 return sdev; 499 500 }
+10 -5
drivers/firmware/arm_scmi/quirks.c
··· 71 71 */ 72 72 73 73 #include <linux/ctype.h> 74 + #include <linux/cleanup.h> 74 75 #include <linux/device.h> 75 76 #include <linux/export.h> 76 77 #include <linux/hashtable.h> ··· 90 89 struct scmi_quirk { 91 90 bool enabled; 92 91 const char *name; 93 - char *vendor; 94 - char *sub_vendor_id; 95 - char *impl_ver_range; 92 + const char *vendor; 93 + const char *sub_vendor_id; 94 + const char *impl_ver_range; 96 95 u32 start_range; 97 96 u32 end_range; 98 97 struct static_key_false *key; ··· 218 217 219 218 static int scmi_quirk_range_parse(struct scmi_quirk *quirk) 220 219 { 221 - const char *last, *first = quirk->impl_ver_range; 220 + const char *last, *first __free(kfree) = NULL; 222 221 size_t len; 223 222 char *sep; 224 223 int ret; ··· 229 228 if (!len) 230 229 return 0; 231 230 231 + first = kmemdup(quirk->impl_ver_range, len + 1, GFP_KERNEL); 232 + if (!first) 233 + return -ENOMEM; 234 + 232 235 last = first + len - 1; 233 - sep = strchr(quirk->impl_ver_range, '-'); 236 + sep = strchr(first, '-'); 234 237 if (sep) 235 238 *sep = '\0'; 236 239
+3 -4
drivers/firmware/arm_scmi/transports/mailbox.c
··· 127 127 (num_mb == 1 && num_sh != 1) || (num_mb == 3 && num_sh != 2) || 128 128 (num_mb == 4 && num_sh != 2)) { 129 129 dev_warn(cdev, 130 - "Invalid channel descriptor for '%s' - mbs:%d shm:%d\n", 131 - of_node_full_name(np), num_mb, num_sh); 130 + "Invalid channel descriptor for '%pOF' - mbs:%d shm:%d\n", 131 + np, num_mb, num_sh); 132 132 return -EINVAL; 133 133 } 134 134 ··· 140 140 of_parse_phandle(np, "shmem", 1); 141 141 142 142 if (!np_tx || !np_rx || np_tx == np_rx) { 143 - dev_warn(cdev, "Invalid shmem descriptor for '%s'\n", 144 - of_node_full_name(np)); 143 + dev_warn(cdev, "Invalid shmem descriptor for '%pOF'\n", np); 145 144 ret = -EINVAL; 146 145 } 147 146 }
+1 -1
drivers/firmware/arm_scmi/transports/optee.c
··· 498 498 mutex_unlock(&channel->mu); 499 499 } 500 500 501 - static struct scmi_transport_ops scmi_optee_ops = { 501 + static const struct scmi_transport_ops scmi_optee_ops = { 502 502 .chan_available = scmi_optee_chan_available, 503 503 .chan_setup = scmi_optee_chan_setup, 504 504 .chan_free = scmi_optee_chan_free,
+3
drivers/firmware/arm_scmi/transports/virtio.c
··· 871 871 /* Ensure initialized scmi_vdev is visible */ 872 872 smp_store_mb(scmi_vdev, vdev); 873 873 874 + /* Set device ready */ 875 + virtio_device_ready(vdev); 876 + 874 877 ret = platform_driver_register(&scmi_virtio_driver); 875 878 if (ret) { 876 879 vdev->priv = NULL;
+111
drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c
··· 25 25 enum scmi_imx_misc_protocol_cmd { 26 26 SCMI_IMX_MISC_CTRL_SET = 0x3, 27 27 SCMI_IMX_MISC_CTRL_GET = 0x4, 28 + SCMI_IMX_MISC_DISCOVER_BUILD_INFO = 0x6, 28 29 SCMI_IMX_MISC_CTRL_NOTIFY = 0x8, 30 + SCMI_IMX_MISC_CFG_INFO_GET = 0xC, 31 + SCMI_IMX_MISC_BOARD_INFO = 0xE, 29 32 }; 30 33 31 34 struct scmi_imx_misc_info { ··· 66 63 struct scmi_imx_misc_ctrl_get_out { 67 64 __le32 num; 68 65 __le32 val[]; 66 + }; 67 + 68 + struct scmi_imx_misc_buildinfo_out { 69 + __le32 buildnum; 70 + __le32 buildcommit; 71 + #define MISC_MAX_BUILDDATE 16 72 + u8 builddate[MISC_MAX_BUILDDATE]; 73 + #define MISC_MAX_BUILDTIME 16 74 + u8 buildtime[MISC_MAX_BUILDTIME]; 75 + }; 76 + 77 + struct scmi_imx_misc_board_info_out { 78 + __le32 attributes; 79 + #define MISC_MAX_BRDNAME 16 80 + u8 brdname[MISC_MAX_BRDNAME]; 81 + }; 82 + 83 + struct scmi_imx_misc_cfg_info_out { 84 + __le32 msel; 85 + #define MISC_MAX_CFGNAME 16 86 + u8 cfgname[MISC_MAX_CFGNAME]; 69 87 }; 70 88 71 89 static int scmi_imx_misc_attributes_get(const struct scmi_protocol_handle *ph, ··· 296 272 return ret; 297 273 } 298 274 275 + static int scmi_imx_misc_build_info_discover(const struct scmi_protocol_handle *ph) 276 + { 277 + char date[MISC_MAX_BUILDDATE], time[MISC_MAX_BUILDTIME]; 278 + struct scmi_imx_misc_buildinfo_out *out; 279 + struct scmi_xfer *t; 280 + int ret; 281 + 282 + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_MISC_DISCOVER_BUILD_INFO, 0, 283 + sizeof(*out), &t); 284 + if (ret) 285 + return ret; 286 + 287 + ret = ph->xops->do_xfer(ph, t); 288 + if (!ret) { 289 + out = t->rx.buf; 290 + strscpy(date, out->builddate, MISC_MAX_BUILDDATE); 291 + strscpy(time, out->buildtime, MISC_MAX_BUILDTIME); 292 + dev_info(ph->dev, "SM Version\t= Build %u, Commit %08x %s %s\n", 293 + le32_to_cpu(out->buildnum), le32_to_cpu(out->buildcommit), 294 + date, time); 295 + } 296 + 297 + ph->xops->xfer_put(ph, t); 298 + 299 + return ret; 300 + } 301 + 302 + static int scmi_imx_misc_board_info(const struct scmi_protocol_handle *ph) 303 + { 304 + struct scmi_imx_misc_board_info_out *out; 305 + char name[MISC_MAX_BRDNAME]; 306 + struct scmi_xfer *t; 307 + int ret; 308 + 309 + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_MISC_BOARD_INFO, 0, sizeof(*out), &t); 310 + if (ret) 311 + return ret; 312 + 313 + ret = ph->xops->do_xfer(ph, t); 314 + if (!ret) { 315 + out = t->rx.buf; 316 + strscpy(name, out->brdname, MISC_MAX_BRDNAME); 317 + dev_info(ph->dev, "Board\t\t= %s, attr=0x%08x\n", 318 + name, le32_to_cpu(out->attributes)); 319 + } 320 + 321 + ph->xops->xfer_put(ph, t); 322 + 323 + return ret; 324 + } 325 + 326 + static int scmi_imx_misc_cfg_info_get(const struct scmi_protocol_handle *ph) 327 + { 328 + struct scmi_imx_misc_cfg_info_out *out; 329 + char name[MISC_MAX_CFGNAME]; 330 + struct scmi_xfer *t; 331 + int ret; 332 + 333 + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_MISC_CFG_INFO_GET, 0, sizeof(*out), &t); 334 + if (ret) 335 + return ret; 336 + 337 + ret = ph->xops->do_xfer(ph, t); 338 + if (!ret) { 339 + out = t->rx.buf; 340 + strscpy(name, out->cfgname, MISC_MAX_CFGNAME); 341 + dev_info(ph->dev, "SM Config\t= %s, mSel = %u\n", 342 + name, le32_to_cpu(out->msel)); 343 + } 344 + 345 + ph->xops->xfer_put(ph, t); 346 + 347 + return ret; 348 + } 349 + 299 350 static const struct scmi_imx_misc_proto_ops scmi_imx_misc_proto_ops = { 300 351 .misc_ctrl_set = scmi_imx_misc_ctrl_set, 301 352 .misc_ctrl_get = scmi_imx_misc_ctrl_get, ··· 396 297 397 298 ret = scmi_imx_misc_attributes_get(ph, minfo); 398 299 if (ret) 300 + return ret; 301 + 302 + ret = scmi_imx_misc_build_info_discover(ph); 303 + if (ret && ret != -EOPNOTSUPP) 304 + return ret; 305 + 306 + ret = scmi_imx_misc_board_info(ph); 307 + if (ret && ret != -EOPNOTSUPP) 308 + return ret; 309 + 310 + ret = scmi_imx_misc_cfg_info_get(ph); 311 + if (ret && ret != -EOPNOTSUPP) 399 312 return ret; 400 313 401 314 return ph->set_priv(ph, minfo, version);
+25
drivers/firmware/arm_scmi/vendors/imx/imx95.rst
··· 1660 1660 |Name |Description | 1661 1661 +--------------------+---------------------------------------------------------+ 1662 1662 |int32 status |SUCCESS: system log return | 1663 + | |NOT_SUPPORTED: system log not available | 1663 1664 +--------------------+---------------------------------------------------------+ 1664 1665 |uint32 numLogflags |Descriptor for the log data returned by this call. | 1665 1666 | |Bits[31:20] Number of remaining log words. | ··· 1669 1668 | |call | 1670 1669 +--------------------+---------------------------------------------------------+ 1671 1670 |uint32 syslog[N] |Log data array, N is defined in bits[11:0] of numLogflags| 1671 + +--------------------+---------------------------------------------------------+ 1672 + 1673 + MISC_BOARD_INFO 1674 + ~~~~~~~~~~~~~~~ 1675 + 1676 + message_id: 0xE 1677 + protocol_id: 0x84 1678 + 1679 + +--------------------+---------------------------------------------------------+ 1680 + |Return values | 1681 + +--------------------+---------------------------------------------------------+ 1682 + |Name |Description | 1683 + +--------------------+---------------------------------------------------------+ 1684 + |int32 status |SUCCESS: config name return | 1685 + | |NOT_SUPPORTED: name not available | 1686 + +--------------------+---------------------------------------------------------+ 1687 + |uint32 attributes |Board-specific attributes reserved for future expansion | 1688 + | |without breaking backwards compatibility. The firmware | 1689 + | |sets the value to 0 | 1690 + +--------------------+---------------------------------------------------------+ 1691 + |uint8 boardname[16] |Board name. NULL terminated ASCII string, up to 16 bytes | 1692 + | |in length. This is System Manager(SM) firmware-exported | 1693 + | |board-name and may not align with the board name in the | 1694 + | |device tree. | 1672 1695 +--------------------+---------------------------------------------------------+ 1673 1696 1674 1697 NEGOTIATE_PROTOCOL_VERSION
+1 -1
drivers/firmware/arm_scmi/voltage.c
··· 393 393 return vinfo->num_domains; 394 394 } 395 395 396 - static struct scmi_voltage_proto_ops voltage_proto_ops = { 396 + static const struct scmi_voltage_proto_ops voltage_proto_ops = { 397 397 .num_domains_get = scmi_voltage_domains_num_get, 398 398 .info_get = scmi_voltage_info_get, 399 399 .config_set = scmi_voltage_config_set,
+1 -1
include/linux/scmi_protocol.h
··· 153 153 * for a given device 154 154 * @fast_switch_rate_limit: gets the minimum time (us) required between 155 155 * successive fast_switching requests 156 - * @power_scale_mw_get: indicates if the power values provided are in milliWatts 156 + * @power_scale_get: indicates if the power values provided are in milliWatts 157 157 * or in some other (abstract) scale 158 158 */ 159 159 struct scmi_perf_proto_ops {