Commit 7860701d authored by Cristian Marussi's avatar Cristian Marussi Committed by Sudeep Holla

firmware: arm_scmi: Add per-channel raw injection support

On a system configured with multiple transport channels, expose a few
additional debugfs per-channel entries to allow a user to explicitly select
which transport channel to use for the SCMI message injection.
Signed-off-by: default avatarCristian Marussi <cristian.marussi@arm.com>
Tested-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Tested-by: default avatarVincent Guittot <vincent.guittot@linaro.org>
Link: https://lore.kernel.org/r/20230118121426.492864-18-cristian.marussi@arm.comSigned-off-by: default avatarSudeep Holla <sudeep.holla@arm.com>
parent 9c54633e
...@@ -64,3 +64,46 @@ Description: SCMI Raw stack reset facility; writing a value to this entry ...@@ -64,3 +64,46 @@ Description: SCMI Raw stack reset facility; writing a value to this entry
Can be used to reset and clean the SCMI Raw stack between to Can be used to reset and clean the SCMI Raw stack between to
different test-run. different test-run.
Users: Debugging, any userspace test suite Users: Debugging, any userspace test suite
What: /sys/kernel/debug/scmi/<n>/raw/channels/<m>/message
Date: March 2023
KernelVersion: 6.3
Contact: cristian.marussi@arm.com
Description: SCMI Raw synchronous message injection/snooping facility; write
a complete SCMI synchronous 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.
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).
Note that these per-channel entries rooted at <..>/channels
exist only if the transport is configured to have more than
one channel.
Users: Debugging, any userspace test suite
What: /sys/kernel/debug/scmi/<n>/raw/channels/<m>/message_async
Date: March 2023
KernelVersion: 6.3
Contact: cristian.marussi@arm.com
Description: SCMI Raw asynchronous message injection/snooping facility; 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.
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).
Note that these per-channel entries rooted at <..>/channels
exist only if the transport is configured to have more than
one channel.
Users: Debugging, any userspace test suite
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include "protocols.h" #include "protocols.h"
#include "notify.h" #include "notify.h"
#define SCMI_MAX_CHANNELS 256
#define SCMI_MAX_RESPONSE_TIMEOUT (2 * MSEC_PER_SEC) #define SCMI_MAX_RESPONSE_TIMEOUT (2 * MSEC_PER_SEC)
enum scmi_error_codes { enum scmi_error_codes {
......
...@@ -660,6 +660,7 @@ void scmi_xfer_raw_put(const struct scmi_handle *handle, struct scmi_xfer *xfer) ...@@ -660,6 +660,7 @@ void scmi_xfer_raw_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)
struct scmi_info *info = handle_to_scmi_info(handle); struct scmi_info *info = handle_to_scmi_info(handle);
xfer->flags &= ~SCMI_XFER_FLAG_IS_RAW; xfer->flags &= ~SCMI_XFER_FLAG_IS_RAW;
xfer->flags &= ~SCMI_XFER_FLAG_CHAN_SET;
return __scmi_xfer_put(&info->tx_minfo, xfer); return __scmi_xfer_put(&info->tx_minfo, xfer);
} }
...@@ -896,7 +897,8 @@ static void scmi_handle_notification(struct scmi_chan_info *cinfo, ...@@ -896,7 +897,8 @@ static void scmi_handle_notification(struct scmi_chan_info *cinfo,
if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) { if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) {
xfer->hdr.seq = MSG_XTRACT_TOKEN(msg_hdr); xfer->hdr.seq = MSG_XTRACT_TOKEN(msg_hdr);
scmi_raw_message_report(info->raw, xfer, SCMI_RAW_NOTIF_QUEUE); scmi_raw_message_report(info->raw, xfer, SCMI_RAW_NOTIF_QUEUE,
cinfo->id);
} }
__scmi_xfer_put(minfo, xfer); __scmi_xfer_put(minfo, xfer);
...@@ -955,7 +957,9 @@ static void scmi_handle_response(struct scmi_chan_info *cinfo, ...@@ -955,7 +957,9 @@ static void scmi_handle_response(struct scmi_chan_info *cinfo,
* poll loop. * poll loop.
*/ */
if (!xfer->hdr.poll_completion) if (!xfer->hdr.poll_completion)
scmi_raw_message_report(info->raw, xfer, SCMI_RAW_REPLY_QUEUE); scmi_raw_message_report(info->raw, xfer,
SCMI_RAW_REPLY_QUEUE,
cinfo->id);
} }
scmi_xfer_command_release(info, xfer); scmi_xfer_command_release(info, xfer);
...@@ -1078,7 +1082,8 @@ static int scmi_wait_for_reply(struct device *dev, const struct scmi_desc *desc, ...@@ -1078,7 +1082,8 @@ static int scmi_wait_for_reply(struct device *dev, const struct scmi_desc *desc,
handle_to_scmi_info(cinfo->handle); handle_to_scmi_info(cinfo->handle);
scmi_raw_message_report(info->raw, xfer, scmi_raw_message_report(info->raw, xfer,
SCMI_RAW_REPLY_QUEUE); SCMI_RAW_REPLY_QUEUE,
cinfo->id);
} }
} }
} else { } else {
...@@ -2608,14 +2613,35 @@ static struct scmi_debug_info *scmi_debugfs_common_setup(struct scmi_info *info) ...@@ -2608,14 +2613,35 @@ static struct scmi_debug_info *scmi_debugfs_common_setup(struct scmi_info *info)
static int scmi_debugfs_raw_mode_setup(struct scmi_info *info) static int scmi_debugfs_raw_mode_setup(struct scmi_info *info)
{ {
int ret = 0; int id, num_chans = 0, ret = 0;
struct scmi_chan_info *cinfo;
u8 channels[SCMI_MAX_CHANNELS] = {};
DECLARE_BITMAP(protos, SCMI_MAX_CHANNELS) = {};
if (!info->dbg) if (!info->dbg)
return -EINVAL; return -EINVAL;
/* Enumerate all channels to collect their ids */
idr_for_each_entry(&info->tx_idr, cinfo, id) {
/*
* Cannot happen, but be defensive.
* Zero as num_chans is ok, warn and carry on.
*/
if (num_chans >= SCMI_MAX_CHANNELS || !cinfo) {
dev_warn(info->dev,
"SCMI RAW - Error enumerating channels\n");
break;
}
if (!test_bit(cinfo->id, protos)) {
channels[num_chans++] = cinfo->id;
set_bit(cinfo->id, protos);
}
}
info->raw = scmi_raw_mode_init(&info->handle, info->dbg->top_dentry, info->raw = scmi_raw_mode_init(&info->handle, info->dbg->top_dentry,
info->id, info->desc, info->id, channels, num_chans,
info->tx_minfo.max_msg); info->desc, info->tx_minfo.max_msg);
if (IS_ERR(info->raw)) { if (IS_ERR(info->raw)) {
dev_err(info->dev, "Failed to initialize SCMI RAW Mode !\n"); dev_err(info->dev, "Failed to initialize SCMI RAW Mode !\n");
ret = PTR_ERR(info->raw); ret = PTR_ERR(info->raw);
......
...@@ -138,6 +138,9 @@ struct scmi_xfer { ...@@ -138,6 +138,9 @@ struct scmi_xfer {
int state; int state;
#define SCMI_XFER_FLAG_IS_RAW BIT(0) #define SCMI_XFER_FLAG_IS_RAW BIT(0)
#define SCMI_XFER_IS_RAW(x) ((x)->flags & SCMI_XFER_FLAG_IS_RAW) #define SCMI_XFER_IS_RAW(x) ((x)->flags & SCMI_XFER_FLAG_IS_RAW)
#define SCMI_XFER_FLAG_CHAN_SET BIT(1)
#define SCMI_XFER_IS_CHAN_SET(x) \
((x)->flags & SCMI_XFER_FLAG_CHAN_SET)
int flags; int flags;
/* A lock to protect state and busy fields */ /* A lock to protect state and busy fields */
spinlock_t lock; spinlock_t lock;
......
This diff is collapsed.
...@@ -19,11 +19,12 @@ enum { ...@@ -19,11 +19,12 @@ enum {
void *scmi_raw_mode_init(const struct scmi_handle *handle, void *scmi_raw_mode_init(const struct scmi_handle *handle,
struct dentry *top_dentry, int instance_id, struct dentry *top_dentry, int instance_id,
u8 *channels, int num_chans,
const struct scmi_desc *desc, int tx_max_msg); const struct scmi_desc *desc, int tx_max_msg);
void scmi_raw_mode_cleanup(void *raw); void scmi_raw_mode_cleanup(void *raw);
void scmi_raw_message_report(void *raw, struct scmi_xfer *xfer, void scmi_raw_message_report(void *raw, struct scmi_xfer *xfer,
unsigned int idx); unsigned int idx, unsigned int chan_id);
void scmi_raw_error_report(void *raw, struct scmi_chan_info *cinfo, void scmi_raw_error_report(void *raw, struct scmi_chan_info *cinfo,
u32 msg_hdr, void *priv); u32 msg_hdr, void *priv);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment