firmware: arm_scmi: Ensure that the message-id supports fastchannel

Currently the perf and powercap protocol relies on the protocol domain
attributes, which just ensures that one fastchannel per domain, before
instantiating fastchannels for all possible message-ids. Fix this by
ensuring that each message-id supports fastchannel before initialization.

Logs:
  |  scmi: Failed to get FC for protocol 13 [MSG_ID:6 / RES_ID:0] - ret:-95. Using regular messaging
  |  scmi: Failed to get FC for protocol 13 [MSG_ID:6 / RES_ID:1] - ret:-95. Using regular messaging
  |  scmi: Failed to get FC for protocol 13 [MSG_ID:6 / RES_ID:2] - ret:-95. Using regular messaging

CC: stable@vger.kernel.org
Reported-by: Johan Hovold <johan+linaro@kernel.org>
Closes: https://lore.kernel.org/lkml/ZoQjAWse2YxwyRJv@hovoldconsulting.com/
Fixes: 6f9ea4dabd ("firmware: arm_scmi: Generalize the fast channel support")
Reviewed-by: Johan Hovold <johan+linaro@kernel.org>
Tested-by: Johan Hovold <johan+linaro@kernel.org>
Signed-off-by: Sibi Sankar <quic_sibis@quicinc.com>
[Cristian: Modified the condition checked to establish support or not]
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
Message-Id: <20250429141108.406045-2-cristian.marussi@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
This commit is contained in:
Sibi Sankar 2025-04-29 15:11:06 +01:00 committed by Sudeep Holla
parent b0a1c9d489
commit 94a263f981
2 changed files with 45 additions and 33 deletions

View File

@ -1729,6 +1729,39 @@ static int scmi_common_get_max_msg_size(const struct scmi_protocol_handle *ph)
return info->desc->max_msg_size;
}
/**
* scmi_protocol_msg_check - Check protocol message attributes
*
* @ph: A reference to the protocol handle.
* @message_id: The ID of the message to check.
* @attributes: A parameter to optionally return the retrieved message
* attributes, in case of Success.
*
* An helper to check protocol message attributes for a specific protocol
* and message pair.
*
* Return: 0 on SUCCESS
*/
static int scmi_protocol_msg_check(const struct scmi_protocol_handle *ph,
u32 message_id, u32 *attributes)
{
int ret;
struct scmi_xfer *t;
ret = xfer_get_init(ph, PROTOCOL_MESSAGE_ATTRIBUTES,
sizeof(__le32), 0, &t);
if (ret)
return ret;
put_unaligned_le32(message_id, t->tx.buf);
ret = do_xfer(ph, t);
if (!ret && attributes)
*attributes = get_unaligned_le32(t->rx.buf);
xfer_put(ph, t);
return ret;
}
/**
* struct scmi_iterator - Iterator descriptor
* @msg: A reference to the message TX buffer; filled by @prepare_message with
@ -1870,6 +1903,7 @@ scmi_common_fastchannel_init(const struct scmi_protocol_handle *ph,
int ret;
u32 flags;
u64 phys_addr;
u32 attributes;
u8 size;
void __iomem *addr;
struct scmi_xfer *t;
@ -1878,6 +1912,15 @@ scmi_common_fastchannel_init(const struct scmi_protocol_handle *ph,
struct scmi_msg_resp_desc_fc *resp;
const struct scmi_protocol_instance *pi = ph_to_pi(ph);
/* Check if the MSG_ID supports fastchannel */
ret = scmi_protocol_msg_check(ph, message_id, &attributes);
if (ret || !MSG_SUPPORTS_FASTCHANNEL(attributes)) {
dev_dbg(ph->dev,
"Skip FC init for 0x%02X/%d domain:%d - ret:%d\n",
pi->proto->id, message_id, domain, ret);
return;
}
if (!p_addr) {
ret = -EINVAL;
goto err_out;
@ -1995,39 +2038,6 @@ static void scmi_common_fastchannel_db_ring(struct scmi_fc_db_info *db)
SCMI_PROTO_FC_RING_DB(64);
}
/**
* scmi_protocol_msg_check - Check protocol message attributes
*
* @ph: A reference to the protocol handle.
* @message_id: The ID of the message to check.
* @attributes: A parameter to optionally return the retrieved message
* attributes, in case of Success.
*
* An helper to check protocol message attributes for a specific protocol
* and message pair.
*
* Return: 0 on SUCCESS
*/
static int scmi_protocol_msg_check(const struct scmi_protocol_handle *ph,
u32 message_id, u32 *attributes)
{
int ret;
struct scmi_xfer *t;
ret = xfer_get_init(ph, PROTOCOL_MESSAGE_ATTRIBUTES,
sizeof(__le32), 0, &t);
if (ret)
return ret;
put_unaligned_le32(message_id, t->tx.buf);
ret = do_xfer(ph, t);
if (!ret && attributes)
*attributes = get_unaligned_le32(t->rx.buf);
xfer_put(ph, t);
return ret;
}
static const struct scmi_proto_helpers_ops helpers_ops = {
.extended_name_get = scmi_common_extended_name_get,
.get_max_msg_size = scmi_common_get_max_msg_size,

View File

@ -31,6 +31,8 @@
#define SCMI_PROTOCOL_VENDOR_BASE 0x80
#define MSG_SUPPORTS_FASTCHANNEL(x) ((x) & BIT(0))
enum scmi_common_cmd {
PROTOCOL_VERSION = 0x0,
PROTOCOL_ATTRIBUTES = 0x1,