Commit 07cb8c32 authored by Cristian Marussi's avatar Cristian Marussi Committed by Sudeep Holla
Browse files

firmware: arm_scmi: Add polling support to raw mode



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: default avatarCristian Marussi <cristian.marussi@arm.com>
Message-Id: <20250310180811.1463539-1-cristian.marussi@arm.com>
Signed-off-by: default avatarSudeep Holla <sudeep.holla@arm.com>
parent 9593804c
Loading
Loading
Loading
Loading
+91 −0
Original line number Diff line number Diff line
@@ -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
+2 −1
Original line number Diff line number Diff line
@@ -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);
+67 −5
Original line number Diff line number Diff line
@@ -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);
		}
	}