Skip to content

Commit 0fac05f

Browse files
cris-masudeep-holla
authored andcommitted
firmware: arm_scmi: Rework protocol version negotiation logic
Protocol version negotiation can be used by an agent to request the server to downgrade the version effectively utilized by a specific protocol during the current session, if the latest version used by the server is newer than the latest version known to the client. In order for the negotiation process to be fully effective at preventing any possible version incompatibility, it must happen early on, well before the specific protocol initialization phase takes place. Delegate protocol version querying to the core SCMI stack and rework the protocol negotiation logic in order to execute the needed negotiation exchanges upfront, right before the initialization phase takes place. Signed-off-by: Cristian Marussi <cristian.marussi@arm.com> Message-Id: <20251227164132.1311988-2-cristian.marussi@arm.com> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
1 parent 6c2fd7a commit 0fac05f

2 files changed

Lines changed: 81 additions & 16 deletions

File tree

drivers/firmware/arm_scmi/driver.c

Lines changed: 77 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2112,6 +2112,76 @@ static int scmi_protocol_version_negotiate(struct scmi_protocol_handle *ph)
21122112
return ret;
21132113
}
21142114

2115+
/**
2116+
* scmi_protocol_version_initialize - Initialize protocol version
2117+
* @dev: A device reference.
2118+
* @pi: A reference to the protocol instance being initialized
2119+
*
2120+
* At first retrieve the newest protocol version supported by the platform for
2121+
* this specific protoocol.
2122+
*
2123+
* Negotiation is attempted only when the platform advertised a protocol
2124+
* version newer than the most recent version known to this agent, since
2125+
* backward compatibility is NOT assured in general between versions.
2126+
*
2127+
* Failing to negotiate a fallback version or to query supported version at
2128+
* all will result in an attempt to use the newest version known to this agent
2129+
* even though compatibility is NOT assured.
2130+
*
2131+
* Versions are defined as:
2132+
*
2133+
* pi->version: the version supported by the platform as returned by the query.
2134+
* pi->proto->supported_version: the newest version supported by this agent
2135+
* for this protocol.
2136+
* pi->negotiated_version: The version successfully negotiated with the platform.
2137+
* ph->version: The final version effectively chosen for this session.
2138+
*/
2139+
static void scmi_protocol_version_initialize(struct device *dev,
2140+
struct scmi_protocol_instance *pi)
2141+
{
2142+
struct scmi_protocol_handle *ph = &pi->ph;
2143+
int ret;
2144+
2145+
/*
2146+
* Query and store platform supported protocol version: this is usually
2147+
* the newest version the platfom can support.
2148+
*/
2149+
ret = version_get(ph, &pi->version);
2150+
if (ret) {
2151+
dev_warn(dev,
2152+
"Failed to query supported version for protocol 0x%X.\n",
2153+
pi->proto->id);
2154+
goto best_effort;
2155+
}
2156+
2157+
/* Need to negotiate at all ? */
2158+
if (pi->version <= pi->proto->supported_version) {
2159+
ph->version = pi->version;
2160+
return;
2161+
}
2162+
2163+
/* Attempt negotiation */
2164+
ret = scmi_protocol_version_negotiate(ph);
2165+
if (!ret) {
2166+
ph->version = pi->negotiated_version;
2167+
dev_info(dev,
2168+
"Protocol 0x%X successfully negotiated version 0x%X\n",
2169+
pi->proto->id, ph->version);
2170+
return;
2171+
}
2172+
2173+
dev_warn(dev,
2174+
"Detected UNSUPPORTED higher version 0x%X for protocol 0x%X.\n",
2175+
pi->version, pi->proto->id);
2176+
2177+
best_effort:
2178+
/* Fallback to use newest version known to this agent */
2179+
ph->version = pi->proto->supported_version;
2180+
dev_warn(dev,
2181+
"Trying version 0x%X. Backward compatibility is NOT assured.\n",
2182+
ph->version);
2183+
}
2184+
21152185
/**
21162186
* scmi_alloc_init_protocol_instance - Allocate and initialize a protocol
21172187
* instance descriptor.
@@ -2157,6 +2227,13 @@ scmi_alloc_init_protocol_instance(struct scmi_info *info,
21572227
pi->ph.set_priv = scmi_set_protocol_priv;
21582228
pi->ph.get_priv = scmi_get_protocol_priv;
21592229
refcount_set(&pi->users, 1);
2230+
2231+
/*
2232+
* Initialize effectively used protocol version performing any
2233+
* possibly needed negotiations.
2234+
*/
2235+
scmi_protocol_version_initialize(handle->dev, pi);
2236+
21602237
/* proto->init is assured NON NULL by scmi_protocol_register */
21612238
ret = pi->proto->instance_init(&pi->ph);
21622239
if (ret)
@@ -2184,22 +2261,6 @@ scmi_alloc_init_protocol_instance(struct scmi_info *info,
21842261
devres_close_group(handle->dev, pi->gid);
21852262
dev_dbg(handle->dev, "Initialized protocol: 0x%X\n", pi->proto->id);
21862263

2187-
if (pi->version > proto->supported_version) {
2188-
ret = scmi_protocol_version_negotiate(&pi->ph);
2189-
if (!ret) {
2190-
dev_info(handle->dev,
2191-
"Protocol 0x%X successfully negotiated version 0x%X\n",
2192-
proto->id, pi->negotiated_version);
2193-
} else {
2194-
dev_warn(handle->dev,
2195-
"Detected UNSUPPORTED higher version 0x%X for protocol 0x%X.\n",
2196-
pi->version, pi->proto->id);
2197-
dev_warn(handle->dev,
2198-
"Trying version 0x%X. Backward compatibility is NOT assured.\n",
2199-
pi->proto->supported_version);
2200-
}
2201-
}
2202-
22032264
return pi;
22042265

22052266
clean:

drivers/firmware/arm_scmi/protocols.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ struct scmi_proto_helpers_ops;
159159
* struct scmi_protocol_handle - Reference to an initialized protocol instance
160160
*
161161
* @dev: A reference to the associated SCMI instance device (handle->dev).
162+
* @version: The protocol version currently effectively in use by this
163+
* initialized instance of the protocol as determined at the end of
164+
* any possibly needed negotiations performed by the core.
162165
* @xops: A reference to a struct holding refs to the core xfer operations that
163166
* can be used by the protocol implementation to generate SCMI messages.
164167
* @set_priv: A method to set protocol private data for this instance.
@@ -177,6 +180,7 @@ struct scmi_proto_helpers_ops;
177180
*/
178181
struct scmi_protocol_handle {
179182
struct device *dev;
183+
unsigned int version;
180184
const struct scmi_xfer_ops *xops;
181185
const struct scmi_proto_helpers_ops *hops;
182186
int (*set_priv)(const struct scmi_protocol_handle *ph, void *priv,

0 commit comments

Comments
 (0)