Skip to content

Commit b5efc28

Browse files
cris-masudeep-holla
authored andcommitted
firmware: arm_scmi: Add protocol versioning checks
Platform and agent supported protocols versions do not necessarily match. When talking to an older SCMI platform, supporting only older protocol versions, the kernel SCMI agent will downgrade the version of the used protocol to match the platform and avoid compatibility issues. In the case where the kernel/OSPM agent happens to communicate with a newer platform which can support newer protocol versions unknown to the agent, and potentially backward incompatible, the agent currently carries on, silently, in a best-effort approach. Note that the SCMI specification doesn't provide means to explicitly detect the protocol versions used by the agents, neither it is required to support multiple, older, protocol versions. Add an explicit protocol version check to let the agent detect when this version mismatch happens and warn the user about this condition. Signed-off-by: Cristian Marussi <cristian.marussi@arm.com> Link: https://lore.kernel.org/r/20231201135858.2367651-1-cristian.marussi@arm.com Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
1 parent c3f17d5 commit b5efc28

11 files changed

Lines changed: 63 additions & 11 deletions

File tree

drivers/firmware/arm_scmi/base.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
#include "common.h"
1414
#include "notify.h"
1515

16+
/* Updated only after ALL the mandatory features for that version are merged */
17+
#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x20000
18+
1619
#define SCMI_BASE_NUM_SOURCES 1
1720
#define SCMI_BASE_MAX_CMD_ERR_COUNT 1024
1821

@@ -385,7 +388,7 @@ static int scmi_base_protocol_init(const struct scmi_protocol_handle *ph)
385388

386389
rev->major_ver = PROTOCOL_REV_MAJOR(version),
387390
rev->minor_ver = PROTOCOL_REV_MINOR(version);
388-
ph->set_priv(ph, rev);
391+
ph->set_priv(ph, rev, version);
389392

390393
ret = scmi_base_attributes_get(ph);
391394
if (ret)
@@ -423,6 +426,7 @@ static const struct scmi_protocol scmi_base = {
423426
.instance_init = &scmi_base_protocol_init,
424427
.ops = NULL,
425428
.events = &base_protocol_events,
429+
.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
426430
};
427431

428432
DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(base, scmi_base)

drivers/firmware/arm_scmi/clock.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#include "protocols.h"
1313
#include "notify.h"
1414

15+
/* Updated only after ALL the mandatory features for that version are merged */
16+
#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x20001
17+
1518
enum scmi_clock_protocol_cmd {
1619
CLOCK_ATTRIBUTES = 0x3,
1720
CLOCK_DESCRIBE_RATES = 0x4,
@@ -961,7 +964,7 @@ static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph)
961964
}
962965

963966
cinfo->version = version;
964-
return ph->set_priv(ph, cinfo);
967+
return ph->set_priv(ph, cinfo, version);
965968
}
966969

967970
static const struct scmi_protocol scmi_clock = {
@@ -970,6 +973,7 @@ static const struct scmi_protocol scmi_clock = {
970973
.instance_init = &scmi_clock_protocol_init,
971974
.ops = &clk_proto_ops,
972975
.events = &clk_protocol_events,
976+
.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
973977
};
974978

975979
DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(clock, scmi_clock)

drivers/firmware/arm_scmi/driver.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ struct scmi_xfers_info {
8585
* @gid: A reference for per-protocol devres management.
8686
* @users: A refcount to track effective users of this protocol.
8787
* @priv: Reference for optional protocol private data.
88+
* @version: Protocol version supported by the platform as detected at runtime.
8889
* @ph: An embedded protocol handle that will be passed down to protocol
8990
* initialization code to identify this instance.
9091
*
@@ -97,6 +98,7 @@ struct scmi_protocol_instance {
9798
void *gid;
9899
refcount_t users;
99100
void *priv;
101+
unsigned int version;
100102
struct scmi_protocol_handle ph;
101103
};
102104

@@ -1392,15 +1394,17 @@ static int version_get(const struct scmi_protocol_handle *ph, u32 *version)
13921394
*
13931395
* @ph: A reference to the protocol handle.
13941396
* @priv: The private data to set.
1397+
* @version: The detected protocol version for the core to register.
13951398
*
13961399
* Return: 0 on Success
13971400
*/
13981401
static int scmi_set_protocol_priv(const struct scmi_protocol_handle *ph,
1399-
void *priv)
1402+
void *priv, u32 version)
14001403
{
14011404
struct scmi_protocol_instance *pi = ph_to_pi(ph);
14021405

14031406
pi->priv = priv;
1407+
pi->version = version;
14041408

14051409
return 0;
14061410
}
@@ -1849,6 +1853,12 @@ scmi_alloc_init_protocol_instance(struct scmi_info *info,
18491853
devres_close_group(handle->dev, pi->gid);
18501854
dev_dbg(handle->dev, "Initialized protocol: 0x%X\n", pi->proto->id);
18511855

1856+
if (pi->version > proto->supported_version)
1857+
dev_warn(handle->dev,
1858+
"Detected UNSUPPORTED higher version 0x%X for protocol 0x%X."
1859+
"Backward compatibility is NOT assured.\n",
1860+
pi->version, pi->proto->id);
1861+
18521862
return pi;
18531863

18541864
clean:

drivers/firmware/arm_scmi/perf.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
#include "protocols.h"
2525
#include "notify.h"
2626

27+
/* Updated only after ALL the mandatory features for that version are merged */
28+
#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x40000
29+
2730
#define MAX_OPPS 32
2831

2932
enum scmi_performance_protocol_cmd {
@@ -1104,7 +1107,7 @@ static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph)
11041107
if (ret)
11051108
return ret;
11061109

1107-
return ph->set_priv(ph, pinfo);
1110+
return ph->set_priv(ph, pinfo, version);
11081111
}
11091112

11101113
static const struct scmi_protocol scmi_perf = {
@@ -1113,6 +1116,7 @@ static const struct scmi_protocol scmi_perf = {
11131116
.instance_init = &scmi_perf_protocol_init,
11141117
.ops = &perf_proto_ops,
11151118
.events = &perf_protocol_events,
1119+
.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
11161120
};
11171121

11181122
DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(perf, scmi_perf)

drivers/firmware/arm_scmi/power.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
#include "protocols.h"
1414
#include "notify.h"
1515

16+
/* Updated only after ALL the mandatory features for that version are merged */
17+
#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x30000
18+
1619
enum scmi_power_protocol_cmd {
1720
POWER_DOMAIN_ATTRIBUTES = 0x3,
1821
POWER_STATE_SET = 0x4,
@@ -328,7 +331,7 @@ static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph)
328331

329332
pinfo->version = version;
330333

331-
return ph->set_priv(ph, pinfo);
334+
return ph->set_priv(ph, pinfo, version);
332335
}
333336

334337
static const struct scmi_protocol scmi_power = {
@@ -337,6 +340,7 @@ static const struct scmi_protocol scmi_power = {
337340
.instance_init = &scmi_power_protocol_init,
338341
.ops = &power_proto_ops,
339342
.events = &power_protocol_events,
343+
.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
340344
};
341345

342346
DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(power, scmi_power)

drivers/firmware/arm_scmi/powercap.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
#include "protocols.h"
1818
#include "notify.h"
1919

20+
/* Updated only after ALL the mandatory features for that version are merged */
21+
#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x20000
22+
2023
enum scmi_powercap_protocol_cmd {
2124
POWERCAP_DOMAIN_ATTRIBUTES = 0x3,
2225
POWERCAP_CAP_GET = 0x4,
@@ -975,7 +978,7 @@ scmi_powercap_protocol_init(const struct scmi_protocol_handle *ph)
975978
}
976979

977980
pinfo->version = version;
978-
return ph->set_priv(ph, pinfo);
981+
return ph->set_priv(ph, pinfo, version);
979982
}
980983

981984
static const struct scmi_protocol scmi_powercap = {
@@ -984,6 +987,7 @@ static const struct scmi_protocol scmi_powercap = {
984987
.instance_init = &scmi_powercap_protocol_init,
985988
.ops = &powercap_proto_ops,
986989
.events = &powercap_protocol_events,
990+
.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
987991
};
988992

989993
DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(powercap, scmi_powercap)

drivers/firmware/arm_scmi/protocols.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ struct scmi_protocol_handle {
174174
struct device *dev;
175175
const struct scmi_xfer_ops *xops;
176176
const struct scmi_proto_helpers_ops *hops;
177-
int (*set_priv)(const struct scmi_protocol_handle *ph, void *priv);
177+
int (*set_priv)(const struct scmi_protocol_handle *ph, void *priv,
178+
u32 version);
178179
void *(*get_priv)(const struct scmi_protocol_handle *ph);
179180
};
180181

@@ -311,6 +312,10 @@ typedef int (*scmi_prot_init_ph_fn_t)(const struct scmi_protocol_handle *);
311312
* @ops: Optional reference to the operations provided by the protocol and
312313
* exposed in scmi_protocol.h.
313314
* @events: An optional reference to the events supported by this protocol.
315+
* @supported_version: The highest version currently supported for this
316+
* protocol by the agent. Each protocol implementation
317+
* in the agent is supposed to downgrade to match the
318+
* protocol version supported by the platform.
314319
*/
315320
struct scmi_protocol {
316321
const u8 id;
@@ -319,6 +324,7 @@ struct scmi_protocol {
319324
const scmi_prot_init_ph_fn_t instance_deinit;
320325
const void *ops;
321326
const struct scmi_protocol_events *events;
327+
unsigned int supported_version;
322328
};
323329

324330
#define DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(name, proto) \

drivers/firmware/arm_scmi/reset.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
#include "protocols.h"
1414
#include "notify.h"
1515

16+
/* Updated only after ALL the mandatory features for that version are merged */
17+
#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x30000
18+
1619
enum scmi_reset_protocol_cmd {
1720
RESET_DOMAIN_ATTRIBUTES = 0x3,
1821
RESET = 0x4,
@@ -343,7 +346,7 @@ static int scmi_reset_protocol_init(const struct scmi_protocol_handle *ph)
343346
}
344347

345348
pinfo->version = version;
346-
return ph->set_priv(ph, pinfo);
349+
return ph->set_priv(ph, pinfo, version);
347350
}
348351

349352
static const struct scmi_protocol scmi_reset = {
@@ -352,6 +355,7 @@ static const struct scmi_protocol scmi_reset = {
352355
.instance_init = &scmi_reset_protocol_init,
353356
.ops = &reset_proto_ops,
354357
.events = &reset_protocol_events,
358+
.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
355359
};
356360

357361
DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(reset, scmi_reset)

drivers/firmware/arm_scmi/sensors.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
#include "protocols.h"
1515
#include "notify.h"
1616

17+
/* Updated only after ALL the mandatory features for that version are merged */
18+
#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x30000
19+
1720
#define SCMI_MAX_NUM_SENSOR_AXIS 63
1821
#define SCMIv2_SENSOR_PROTOCOL 0x10000
1922

@@ -1138,7 +1141,7 @@ static int scmi_sensors_protocol_init(const struct scmi_protocol_handle *ph)
11381141
if (ret)
11391142
return ret;
11401143

1141-
return ph->set_priv(ph, sinfo);
1144+
return ph->set_priv(ph, sinfo, version);
11421145
}
11431146

11441147
static const struct scmi_protocol scmi_sensors = {
@@ -1147,6 +1150,7 @@ static const struct scmi_protocol scmi_sensors = {
11471150
.instance_init = &scmi_sensors_protocol_init,
11481151
.ops = &sensor_proto_ops,
11491152
.events = &sensor_protocol_events,
1153+
.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
11501154
};
11511155

11521156
DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(sensors, scmi_sensors)

drivers/firmware/arm_scmi/system.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
#include "protocols.h"
1414
#include "notify.h"
1515

16+
/* Updated only after ALL the mandatory features for that version are merged */
17+
#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x20000
18+
1619
#define SCMI_SYSTEM_NUM_SOURCES 1
1720

1821
enum scmi_system_protocol_cmd {
@@ -144,7 +147,7 @@ static int scmi_system_protocol_init(const struct scmi_protocol_handle *ph)
144147
if (PROTOCOL_REV_MAJOR(pinfo->version) >= 0x2)
145148
pinfo->graceful_timeout_supported = true;
146149

147-
return ph->set_priv(ph, pinfo);
150+
return ph->set_priv(ph, pinfo, version);
148151
}
149152

150153
static const struct scmi_protocol scmi_system = {
@@ -153,6 +156,7 @@ static const struct scmi_protocol scmi_system = {
153156
.instance_init = &scmi_system_protocol_init,
154157
.ops = NULL,
155158
.events = &system_protocol_events,
159+
.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
156160
};
157161

158162
DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(system, scmi_system)

0 commit comments

Comments
 (0)