mirror of
https://github.com/torvalds/linux.git
synced 2026-05-23 06:31:58 +02:00
firmware: arm_scmi: Add support for v3.2 NEGOTIATE_PROTOCOL_VERSION
Freshly introduced NEGOTIATE_PROTOCOL_VERSION allows the agent to ascertain upfront if a specific protocol(usually older) version is supported by the platform. It is used by the agent in case the platform has advertised the support of a newer protocol version than the latest version supported by the agent, since backward compatibility cannot be automatically assumed. Emit a warning about possible incompatibility when negotiation was not possible or just print the successfully negotiated protocol. Signed-off-by: Cristian Marussi <cristian.marussi@arm.com> Link: https://lore.kernel.org/r/20240214183006.3403207-3-cristian.marussi@arm.com Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
This commit is contained in:
parent
a9c049f47e
commit
8c80c42ad4
|
|
@ -86,6 +86,12 @@ struct scmi_xfers_info {
|
|||
* @users: A refcount to track effective users of this protocol.
|
||||
* @priv: Reference for optional protocol private data.
|
||||
* @version: Protocol version supported by the platform as detected at runtime.
|
||||
* @negotiated_version: When the platform supports a newer protocol version,
|
||||
* the agent will try to negotiate with the platform the
|
||||
* usage of the newest version known to it, since
|
||||
* backward compatibility is NOT automatically assured.
|
||||
* This field is NON-zero when a successful negotiation
|
||||
* has completed.
|
||||
* @ph: An embedded protocol handle that will be passed down to protocol
|
||||
* initialization code to identify this instance.
|
||||
*
|
||||
|
|
@ -99,6 +105,7 @@ struct scmi_protocol_instance {
|
|||
refcount_t users;
|
||||
void *priv;
|
||||
unsigned int version;
|
||||
unsigned int negotiated_version;
|
||||
struct scmi_protocol_handle ph;
|
||||
};
|
||||
|
||||
|
|
@ -1815,6 +1822,44 @@ scmi_revision_area_get(const struct scmi_protocol_handle *ph)
|
|||
return pi->handle->version;
|
||||
}
|
||||
|
||||
/**
|
||||
* scmi_protocol_version_negotiate - Negotiate protocol version
|
||||
*
|
||||
* @ph: A reference to the protocol handle.
|
||||
*
|
||||
* An helper to negotiate a protocol version different from the latest
|
||||
* advertised as supported from the platform: on Success backward
|
||||
* compatibility is assured by the platform.
|
||||
*
|
||||
* Return: 0 on Success
|
||||
*/
|
||||
static int scmi_protocol_version_negotiate(struct scmi_protocol_handle *ph)
|
||||
{
|
||||
int ret;
|
||||
struct scmi_xfer *t;
|
||||
struct scmi_protocol_instance *pi = ph_to_pi(ph);
|
||||
|
||||
/* At first check if NEGOTIATE_PROTOCOL_VERSION is supported ... */
|
||||
ret = scmi_protocol_msg_check(ph, NEGOTIATE_PROTOCOL_VERSION, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* ... then attempt protocol version negotiation */
|
||||
ret = xfer_get_init(ph, NEGOTIATE_PROTOCOL_VERSION,
|
||||
sizeof(__le32), 0, &t);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
put_unaligned_le32(pi->proto->supported_version, t->tx.buf);
|
||||
ret = do_xfer(ph, t);
|
||||
if (!ret)
|
||||
pi->negotiated_version = pi->proto->supported_version;
|
||||
|
||||
xfer_put(ph, t);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* scmi_alloc_init_protocol_instance - Allocate and initialize a protocol
|
||||
* instance descriptor.
|
||||
|
|
@ -1887,11 +1932,21 @@ scmi_alloc_init_protocol_instance(struct scmi_info *info,
|
|||
devres_close_group(handle->dev, pi->gid);
|
||||
dev_dbg(handle->dev, "Initialized protocol: 0x%X\n", pi->proto->id);
|
||||
|
||||
if (pi->version > proto->supported_version)
|
||||
dev_warn(handle->dev,
|
||||
"Detected UNSUPPORTED higher version 0x%X for protocol 0x%X."
|
||||
"Backward compatibility is NOT assured.\n",
|
||||
pi->version, pi->proto->id);
|
||||
if (pi->version > proto->supported_version) {
|
||||
ret = scmi_protocol_version_negotiate(&pi->ph);
|
||||
if (!ret) {
|
||||
dev_info(handle->dev,
|
||||
"Protocol 0x%X successfully negotiated version 0x%X\n",
|
||||
proto->id, pi->negotiated_version);
|
||||
} else {
|
||||
dev_warn(handle->dev,
|
||||
"Detected UNSUPPORTED higher version 0x%X for protocol 0x%X.\n",
|
||||
pi->version, pi->proto->id);
|
||||
dev_warn(handle->dev,
|
||||
"Trying version 0x%X. Backward compatibility is NOT assured.\n",
|
||||
pi->proto->supported_version);
|
||||
}
|
||||
}
|
||||
|
||||
return pi;
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ enum scmi_common_cmd {
|
|||
PROTOCOL_VERSION = 0x0,
|
||||
PROTOCOL_ATTRIBUTES = 0x1,
|
||||
PROTOCOL_MESSAGE_ATTRIBUTES = 0x2,
|
||||
NEGOTIATE_PROTOCOL_VERSION = 0x10,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user