firmware: arm_scmi: Add polling support to raw mode
authorCristian Marussi <cristian.marussi@arm.com>
Mon, 10 Mar 2025 18:08:11 +0000 (18:08 +0000)
committerSudeep Holla <sudeep.holla@arm.com>
Mon, 14 Apr 2025 09:12:13 +0000 (10:12 +0100)
Provide a couple of additional debugfs entries to enable polling-mode on
the waiting path of injected messages: message_poll will cause the system
to poll while waiting for the reply, while message_poll_async will send an
asynchronous message, as usual, and will use polling mode for the immediate
synchronous part of the async command.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
Message-Id: <20250310180811.1463539-1-cristian.marussi@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
Documentation/ABI/testing/debugfs-scmi-raw
drivers/firmware/arm_scmi/driver.c
drivers/firmware/arm_scmi/raw_mode.c

index 97678cc9535c3867b6cc18632bc4351f79bea125..5847b96b3896e57ae0b6861176f2f3416c95625a 100644 (file)
@@ -31,6 +31,42 @@ Description: SCMI Raw asynchronous message injection/snooping facility; write
                (receiving an EOF at each message boundary).
 Users:         Debugging, any userspace test suite
 
+What:          /sys/kernel/debug/scmi/<n>/raw/message_poll
+Date:          June 2025
+KernelVersion: 6.16
+Contact:       cristian.marussi@arm.com
+Description:   SCMI Raw message injection/snooping facility using polling mode;
+               write a complete SCMI command message (header included) in
+               little-endian binary format to have it sent to the configured
+               backend SCMI server for instance <n>, using polling mode on
+               the reception path. (if transport is polling capable)
+               Any subsequently received response can be read from this same
+               entry if it arrived within the configured timeout.
+               Each write to the entry causes one command request to be built
+               and sent while the replies are read back one message at time
+               (receiving an EOF at each message boundary).
+Users:         Debugging, any userspace test suite
+
+What:          /sys/kernel/debug/scmi/<n>/raw/message_poll_async
+Date:          June 2025
+KernelVersion: 6.16
+Contact:       cristian.marussi@arm.com
+Description:   SCMI Raw asynchronous message injection/snooping facility using
+               polling-mode; write a complete SCMI asynchronous command message
+               (header included) in little-endian binary format to have it sent
+               to the configured backend SCMI server for instance <n>, using
+               polling-mode on the reception path of the immediate part of the
+               asynchronous command. (if transport is polling capable)
+               Any subsequently received response can be read from this same
+               entry if it arrived within the configured timeout.
+               Any additional delayed response received afterwards can be read
+               from this same entry too if it arrived within the configured
+               timeout.
+               Each write to the entry causes one command request to be built
+               and sent while the replies are read back one message at time
+               (receiving an EOF at each message boundary).
+Users:         Debugging, any userspace test suite
+
 What:          /sys/kernel/debug/scmi/<n>/raw/errors
 Date:          March 2023
 KernelVersion: 6.3
@@ -115,3 +151,58 @@ Description:       SCMI Raw asynchronous message injection/snooping facility; write
                exist only if the transport is configured to have more than
                one default channel.
 Users:         Debugging, any userspace test suite
+
+
+What:          /sys/kernel/debug/scmi/<n>/raw/channels/<m>/message_poll
+Date:          June 2025
+KernelVersion: 6.16
+Contact:       cristian.marussi@arm.com
+Description:   SCMI Raw message injection/snooping facility using polling mode;
+               write a complete SCMI command message (header included) in
+               little-endian binary format to have it sent to the configured
+               backend SCMI server for instance <n> through the <m> transport
+               channel, using polling mode on the reception path.
+               (if transport is polling capable)
+               Any subsequently received response can be read from this same
+               entry if it arrived on channel <m> within the configured
+               timeout.
+               Each write to the entry causes one command request to be built
+               and sent while the replies are read back one message at time
+               (receiving an EOF at each message boundary).
+               Channel identifier <m> matches the SCMI protocol number which
+               has been associated with this transport channel in the DT
+               description, with base protocol number 0x10 being the default
+               channel for this instance.
+               Note that these per-channel entries rooted at <..>/channels
+               exist only if the transport is configured to have more than
+               one default channel.
+Users:         Debugging, any userspace test suite
+
+What:          /sys/kernel/debug/scmi/<n>/raw/channels/<m>/message_poll_async
+Date:          June 2025
+KernelVersion: 6.16
+Contact:       cristian.marussi@arm.com
+Description:   SCMI Raw asynchronous message injection/snooping facility using
+               polling-mode; write a complete SCMI asynchronous command message
+               (header included) in little-endian binary format to have it sent
+               to the configured backend SCMI server for instance <n> through
+               the <m> transport channel, using polling mode on the reception
+               path of the immediate part of the asynchronous command.
+               (if transport is polling capable)
+               Any subsequently received response can be read from this same
+               entry if it arrived on channel <m> within the configured
+               timeout.
+               Any additional delayed response received afterwards can be read
+               from this same entry too if it arrived within the configured
+               timeout.
+               Each write to the entry causes one command request to be built
+               and sent while the replies are read back one message at time
+               (receiving an EOF at each message boundary).
+               Channel identifier <m> matches the SCMI protocol number which
+               has been associated with this transport channel in the DT
+               description, with base protocol number 0x10 being the default
+               channel for this instance.
+               Note that these per-channel entries rooted at <..>/channels
+               exist only if the transport is configured to have more than
+               one default channel.
+Users:         Debugging, any userspace test suite
index 43cd410d94f04441804f98ae502446ace83b00dd..520aa5846916724c5cfb87f3d27f96512f03d451 100644 (file)
@@ -1184,7 +1184,8 @@ static void scmi_handle_response(struct scmi_chan_info *cinfo,
                 * RX path since it will be already queued at the end of the TX
                 * poll loop.
                 */
-               if (!xfer->hdr.poll_completion)
+               if (!xfer->hdr.poll_completion ||
+                   xfer->hdr.type == MSG_TYPE_DELAYED_RESP)
                        scmi_raw_message_report(info->raw, xfer,
                                                SCMI_RAW_REPLY_QUEUE,
                                                cinfo->id);
index 7cc0d616b8de781fb4de05058bddaa7bb76a9d2f..3d543b1d89479ded5d7e260e5d1afda844264b57 100644 (file)
@@ -671,11 +671,13 @@ static int scmi_do_xfer_raw_start(struct scmi_raw_mode_info *raw,
  * @len: Length of the message in @buf.
  * @chan_id: The channel ID to use.
  * @async: A flag stating if an asynchronous command is required.
+ * @poll: A flag stating if a polling transmission is required.
  *
  * Return: 0 on Success
  */
 static int scmi_raw_message_send(struct scmi_raw_mode_info *raw,
-                                void *buf, size_t len, u8 chan_id, bool async)
+                                void *buf, size_t len, u8 chan_id,
+                                bool async, bool poll)
 {
        int ret;
        struct scmi_xfer *xfer;
@@ -684,6 +686,16 @@ static int scmi_raw_message_send(struct scmi_raw_mode_info *raw,
        if (ret)
                return ret;
 
+       if (poll) {
+               if (is_transport_polling_capable(raw->desc)) {
+                       xfer->hdr.poll_completion = true;
+               } else {
+                       dev_err(raw->handle->dev,
+                               "Failed to send RAW message - Polling NOT supported\n");
+                       return -EINVAL;
+               }
+       }
+
        ret = scmi_do_xfer_raw_start(raw, xfer, chan_id, async);
        if (ret)
                scmi_xfer_raw_put(raw->handle, xfer);
@@ -801,7 +813,7 @@ static ssize_t scmi_dbg_raw_mode_common_read(struct file *filp,
 static ssize_t scmi_dbg_raw_mode_common_write(struct file *filp,
                                              const char __user *buf,
                                              size_t count, loff_t *ppos,
-                                             bool async)
+                                             bool async, bool poll)
 {
        int ret;
        struct scmi_dbg_raw_data *rd = filp->private_data;
@@ -831,7 +843,7 @@ static ssize_t scmi_dbg_raw_mode_common_write(struct file *filp,
        }
 
        ret = scmi_raw_message_send(rd->raw, rd->tx.buf, rd->tx_size,
-                                   rd->chan_id, async);
+                                   rd->chan_id, async, poll);
 
        /* Reset ppos for next message ... */
        rd->tx_size = 0;
@@ -875,7 +887,8 @@ static ssize_t scmi_dbg_raw_mode_message_write(struct file *filp,
                                               const char __user *buf,
                                               size_t count, loff_t *ppos)
 {
-       return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos, false);
+       return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos,
+                                             false, false);
 }
 
 static __poll_t scmi_dbg_raw_mode_message_poll(struct file *filp,
@@ -964,7 +977,8 @@ static ssize_t scmi_dbg_raw_mode_message_async_write(struct file *filp,
                                                     const char __user *buf,
                                                     size_t count, loff_t *ppos)
 {
-       return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos, true);
+       return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos,
+                                             true, false);
 }
 
 static const struct file_operations scmi_dbg_raw_mode_message_async_fops = {
@@ -976,6 +990,40 @@ static const struct file_operations scmi_dbg_raw_mode_message_async_fops = {
        .owner = THIS_MODULE,
 };
 
+static ssize_t scmi_dbg_raw_mode_message_poll_write(struct file *filp,
+                                                   const char __user *buf,
+                                                   size_t count, loff_t *ppos)
+{
+       return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos,
+                                             false, true);
+}
+
+static const struct file_operations scmi_dbg_raw_mode_message_poll_fops = {
+       .open = scmi_dbg_raw_mode_open,
+       .release = scmi_dbg_raw_mode_release,
+       .read = scmi_dbg_raw_mode_message_read,
+       .write = scmi_dbg_raw_mode_message_poll_write,
+       .poll = scmi_dbg_raw_mode_message_poll,
+       .owner = THIS_MODULE,
+};
+
+static ssize_t scmi_dbg_raw_mode_message_poll_async_write(struct file *filp,
+                                                         const char __user *buf,
+                                                         size_t count, loff_t *ppos)
+{
+       return scmi_dbg_raw_mode_common_write(filp, buf, count, ppos,
+                                             true, true);
+}
+
+static const struct file_operations scmi_dbg_raw_mode_message_poll_async_fops = {
+       .open = scmi_dbg_raw_mode_open,
+       .release = scmi_dbg_raw_mode_release,
+       .read = scmi_dbg_raw_mode_message_read,
+       .write = scmi_dbg_raw_mode_message_poll_async_write,
+       .poll = scmi_dbg_raw_mode_message_poll,
+       .owner = THIS_MODULE,
+};
+
 static ssize_t scmi_test_dbg_raw_mode_notif_read(struct file *filp,
                                                 char __user *buf,
                                                 size_t count, loff_t *ppos)
@@ -1199,6 +1247,12 @@ void *scmi_raw_mode_init(const struct scmi_handle *handle,
        debugfs_create_file("message_async", 0600, raw->dentry, raw,
                            &scmi_dbg_raw_mode_message_async_fops);
 
+       debugfs_create_file("message_poll", 0600, raw->dentry, raw,
+                           &scmi_dbg_raw_mode_message_poll_fops);
+
+       debugfs_create_file("message_poll_async", 0600, raw->dentry, raw,
+                           &scmi_dbg_raw_mode_message_poll_async_fops);
+
        debugfs_create_file("notification", 0400, raw->dentry, raw,
                            &scmi_dbg_raw_mode_notification_fops);
 
@@ -1230,6 +1284,14 @@ void *scmi_raw_mode_init(const struct scmi_handle *handle,
                        debugfs_create_file_aux_num("message_async", 0600, chd,
                                            raw, channels[i],
                                            &scmi_dbg_raw_mode_message_async_fops);
+
+                       debugfs_create_file_aux_num("message_poll", 0600, chd,
+                                                   raw, channels[i],
+                                                   &scmi_dbg_raw_mode_message_poll_fops);
+
+                       debugfs_create_file_aux_num("message_poll_async", 0600,
+                                                   chd, raw, channels[i],
+                                                   &scmi_dbg_raw_mode_message_poll_async_fops);
                }
        }