Skip to content

Commit 740f4bd

Browse files
committed
Merge tag 'scmi-updates-6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into soc/drivers
Arm SCMI updates for v6.8 Few minor updates: 1. Addition of protocol versioning checks to warn if the firmware version is newer or greater than the version supported by the kernel driver 2. Increment of the maximum OPP count in the perf protocol from 16 to 32 as needed by a few recent/future qualcomm platforms 3. Optimisation of set performance operations by returning error immediately and avoiding to send the command to the platform(which would return error eventually) if the domain doesn't support perf operations. Similarly, the fastchannel handling is also optimised by avoiding to initialise the corresponding set operations fastchannels. 4. Extension of extended names helper to accomodate recently added new flags parameter to be able to properly configure the command used to query the extended name of a resource. * tag 'scmi-updates-6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux: firmware: arm_scmi: Add protocol versioning checks firmware: arm_scmi: Increase the maximum opp count in the perf protocol firmware: arm_scmi: Fix NULL pointer dereference during fastchannel init firmware: arm_scmi: Add optional flags to extended names helper firmware: arm_scmi: Populate fastchannel info only if set operations are allowed firmware: arm_scmi: Check beforehand if the perf domain set operations are allowed Link: https://lore.kernel.org/r/20231213115953.3578115-1-sudeep.holla@arm.com Signed-off-by: Arnd Bergmann <arnd@arndb.de>
2 parents 6fe341a + b5efc28 commit 740f4bd

11 files changed

Lines changed: 105 additions & 39 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: 6 additions & 2 deletions
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,
@@ -318,7 +321,7 @@ static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph,
318321
if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x2) {
319322
if (SUPPORTS_EXTENDED_NAMES(attributes))
320323
ph->hops->extended_name_get(ph, CLOCK_NAME_GET, clk_id,
321-
clk->name,
324+
NULL, clk->name,
322325
SCMI_MAX_STR_SIZE);
323326

324327
if (SUPPORTS_RATE_CHANGED_NOTIF(attributes))
@@ -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: 19 additions & 5 deletions
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
}
@@ -1438,26 +1442,30 @@ struct scmi_msg_resp_domain_name_get {
14381442
* @ph: A protocol handle reference.
14391443
* @cmd_id: The specific command ID to use.
14401444
* @res_id: The specific resource ID to use.
1445+
* @flags: A pointer to specific flags to use, if any.
14411446
* @name: A pointer to the preallocated area where the retrieved name will be
14421447
* stored as a NULL terminated string.
14431448
* @len: The len in bytes of the @name char array.
14441449
*
14451450
* Return: 0 on Succcess
14461451
*/
14471452
static int scmi_common_extended_name_get(const struct scmi_protocol_handle *ph,
1448-
u8 cmd_id, u32 res_id, char *name,
1449-
size_t len)
1453+
u8 cmd_id, u32 res_id, u32 *flags,
1454+
char *name, size_t len)
14501455
{
14511456
int ret;
1457+
size_t txlen;
14521458
struct scmi_xfer *t;
14531459
struct scmi_msg_resp_domain_name_get *resp;
14541460

1455-
ret = ph->xops->xfer_get_init(ph, cmd_id, sizeof(res_id),
1456-
sizeof(*resp), &t);
1461+
txlen = !flags ? sizeof(res_id) : sizeof(res_id) + sizeof(*flags);
1462+
ret = ph->xops->xfer_get_init(ph, cmd_id, txlen, sizeof(*resp), &t);
14571463
if (ret)
14581464
goto out;
14591465

14601466
put_unaligned_le32(res_id, t->tx.buf);
1467+
if (flags)
1468+
put_unaligned_le32(*flags, t->tx.buf + sizeof(res_id));
14611469
resp = t->rx.buf;
14621470

14631471
ret = ph->xops->do_xfer(ph, t);
@@ -1845,6 +1853,12 @@ scmi_alloc_init_protocol_instance(struct scmi_info *info,
18451853
devres_close_group(handle->dev, pi->gid);
18461854
dev_dbg(handle->dev, "Initialized protocol: 0x%X\n", pi->proto->id);
18471855

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+
18481862
return pi;
18491863

18501864
clean:

drivers/firmware/arm_scmi/perf.c

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@
2424
#include "protocols.h"
2525
#include "notify.h"
2626

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

2932
enum scmi_performance_protocol_cmd {
3033
PERF_DOMAIN_ATTRIBUTES = 0x3,
@@ -288,7 +291,7 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph,
288291
if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x3 &&
289292
SUPPORTS_EXTENDED_NAMES(flags))
290293
ph->hops->extended_name_get(ph, PERF_DOMAIN_NAME_GET,
291-
dom_info->id, dom_info->info.name,
294+
dom_info->id, NULL, dom_info->info.name,
292295
SCMI_MAX_STR_SIZE);
293296

294297
if (dom_info->level_indexing_mode) {
@@ -504,6 +507,9 @@ static int scmi_perf_limits_set(const struct scmi_protocol_handle *ph,
504507
if (IS_ERR(dom))
505508
return PTR_ERR(dom);
506509

510+
if (!dom->set_limits)
511+
return -EOPNOTSUPP;
512+
507513
if (PROTOCOL_REV_MAJOR(pi->version) >= 0x3 && !max_perf && !min_perf)
508514
return -EINVAL;
509515

@@ -654,6 +660,9 @@ static int scmi_perf_level_set(const struct scmi_protocol_handle *ph,
654660
if (IS_ERR(dom))
655661
return PTR_ERR(dom);
656662

663+
if (!dom->info.set_perf)
664+
return -EOPNOTSUPP;
665+
657666
if (dom->level_indexing_mode) {
658667
struct scmi_opp *opp;
659668

@@ -753,7 +762,7 @@ static int scmi_perf_level_limits_notify(const struct scmi_protocol_handle *ph,
753762
}
754763

755764
static void scmi_perf_domain_init_fc(const struct scmi_protocol_handle *ph,
756-
u32 domain, struct scmi_fc_info **p_fc)
765+
struct perf_dom_info *dom)
757766
{
758767
struct scmi_fc_info *fc;
759768

@@ -762,24 +771,26 @@ static void scmi_perf_domain_init_fc(const struct scmi_protocol_handle *ph,
762771
return;
763772

764773
ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL,
765-
PERF_LEVEL_SET, 4, domain,
766-
&fc[PERF_FC_LEVEL].set_addr,
767-
&fc[PERF_FC_LEVEL].set_db);
768-
769-
ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL,
770-
PERF_LEVEL_GET, 4, domain,
774+
PERF_LEVEL_GET, 4, dom->id,
771775
&fc[PERF_FC_LEVEL].get_addr, NULL);
772776

773777
ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL,
774-
PERF_LIMITS_SET, 8, domain,
775-
&fc[PERF_FC_LIMIT].set_addr,
776-
&fc[PERF_FC_LIMIT].set_db);
777-
778-
ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL,
779-
PERF_LIMITS_GET, 8, domain,
778+
PERF_LIMITS_GET, 8, dom->id,
780779
&fc[PERF_FC_LIMIT].get_addr, NULL);
781780

782-
*p_fc = fc;
781+
if (dom->info.set_perf)
782+
ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL,
783+
PERF_LEVEL_SET, 4, dom->id,
784+
&fc[PERF_FC_LEVEL].set_addr,
785+
&fc[PERF_FC_LEVEL].set_db);
786+
787+
if (dom->set_limits)
788+
ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL,
789+
PERF_LIMITS_SET, 8, dom->id,
790+
&fc[PERF_FC_LIMIT].set_addr,
791+
&fc[PERF_FC_LIMIT].set_db);
792+
793+
dom->fc_info = fc;
783794
}
784795

785796
static int scmi_dvfs_device_opps_add(const struct scmi_protocol_handle *ph,
@@ -1089,14 +1100,14 @@ static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph)
10891100
scmi_perf_describe_levels_get(ph, dom, version);
10901101

10911102
if (dom->perf_fastchannels)
1092-
scmi_perf_domain_init_fc(ph, dom->id, &dom->fc_info);
1103+
scmi_perf_domain_init_fc(ph, dom);
10931104
}
10941105

10951106
ret = devm_add_action_or_reset(ph->dev, scmi_perf_xa_destroy, pinfo);
10961107
if (ret)
10971108
return ret;
10981109

1099-
return ph->set_priv(ph, pinfo);
1110+
return ph->set_priv(ph, pinfo, version);
11001111
}
11011112

11021113
static const struct scmi_protocol scmi_perf = {
@@ -1105,6 +1116,7 @@ static const struct scmi_protocol scmi_perf = {
11051116
.instance_init = &scmi_perf_protocol_init,
11061117
.ops = &perf_proto_ops,
11071118
.events = &perf_protocol_events,
1119+
.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION,
11081120
};
11091121

11101122
DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(perf, scmi_perf)

drivers/firmware/arm_scmi/power.c

Lines changed: 6 additions & 2 deletions
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,
@@ -133,7 +136,7 @@ scmi_power_domain_attributes_get(const struct scmi_protocol_handle *ph,
133136
if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x3 &&
134137
SUPPORTS_EXTENDED_NAMES(flags)) {
135138
ph->hops->extended_name_get(ph, POWER_DOMAIN_NAME_GET,
136-
domain, dom_info->name,
139+
domain, NULL, dom_info->name,
137140
SCMI_MAX_STR_SIZE);
138141
}
139142

@@ -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: 6 additions & 2 deletions
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,
@@ -270,7 +273,7 @@ scmi_powercap_domain_attributes_get(const struct scmi_protocol_handle *ph,
270273
*/
271274
if (!ret && SUPPORTS_EXTENDED_NAMES(flags))
272275
ph->hops->extended_name_get(ph, POWERCAP_DOMAIN_NAME_GET,
273-
domain, dom_info->name,
276+
domain, NULL, dom_info->name,
274277
SCMI_MAX_STR_SIZE);
275278

276279
return ret;
@@ -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: 9 additions & 2 deletions
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

@@ -256,7 +257,8 @@ struct scmi_fc_info {
256257
*/
257258
struct scmi_proto_helpers_ops {
258259
int (*extended_name_get)(const struct scmi_protocol_handle *ph,
259-
u8 cmd_id, u32 res_id, char *name, size_t len);
260+
u8 cmd_id, u32 res_id, u32 *flags, char *name,
261+
size_t len);
260262
void *(*iter_response_init)(const struct scmi_protocol_handle *ph,
261263
struct scmi_iterator_ops *ops,
262264
unsigned int max_resources, u8 msg_id,
@@ -310,6 +312,10 @@ typedef int (*scmi_prot_init_ph_fn_t)(const struct scmi_protocol_handle *);
310312
* @ops: Optional reference to the operations provided by the protocol and
311313
* exposed in scmi_protocol.h.
312314
* @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.
313319
*/
314320
struct scmi_protocol {
315321
const u8 id;
@@ -318,6 +324,7 @@ struct scmi_protocol {
318324
const scmi_prot_init_ph_fn_t instance_deinit;
319325
const void *ops;
320326
const struct scmi_protocol_events *events;
327+
unsigned int supported_version;
321328
};
322329

323330
#define DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(name, proto) \

0 commit comments

Comments
 (0)