Skip to content

Commit 34f60ff

Browse files
committed
Merge tag 'scmi-updates-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into soc/drivers
Arm SCMI updates for v7.0 A set of cleanups, refactoring, and fixes to the Arm SCMI stack: 1. Rework protocol version negotiation by moving version discovery and downgrade handling into the SCMI core and performing negotiation early, before protocol initialization. Remove legacy per-protocol versioning logic now made redundant by centralized SCMI handling. 2. Increase the internal MAX_OPPS limit in the SCMI performance protocol to 64, allowing platforms with larger OPP tables to be fully supported. 3. Reduce duplicated boilerplate in pinctrl and related protocols by consolidating validation and lookup logic in protocol get info helpers. 4. Refactor reset protocol domain handling by introducing a shared lookup helper, ensuring consistent validation and error reporting. 5. Fix potential undefined behaviour by properly initializing pointers annotated with the __free attribute. * tag 'scmi-updates-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux: firmware: arm_scmi: Remove legacy protocol versioning logic firmware: arm_scmi: Rework protocol version negotiation logic firmware: arm_scmi: Increase performance MAX_OPPS limit to 64 firmware: arm_scmi: Move boiler plate code into the get info functions firmware: arm_scmi: Refactor reset domain handling firmware: arm_scmi: Fix uninitialized pointers with __free attr Signed-off-by: Arnd Bergmann <arnd@arndb.de>
2 parents 7a39124 + 24a0ffe commit 34f60ff

17 files changed

Lines changed: 238 additions & 282 deletions

File tree

drivers/firmware/arm_scmi/base.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -375,18 +375,13 @@ static int scmi_base_protocol_init(const struct scmi_protocol_handle *ph)
375375
{
376376
int id, ret;
377377
u8 *prot_imp;
378-
u32 version;
379378
char name[SCMI_SHORT_NAME_MAX_SIZE];
380379
struct device *dev = ph->dev;
381380
struct scmi_revision_info *rev = scmi_revision_area_get(ph);
382381

383-
ret = ph->xops->version_get(ph, &version);
384-
if (ret)
385-
return ret;
386-
387-
rev->major_ver = PROTOCOL_REV_MAJOR(version);
388-
rev->minor_ver = PROTOCOL_REV_MINOR(version);
389-
ph->set_priv(ph, rev, version);
382+
rev->major_ver = PROTOCOL_REV_MAJOR(ph->version);
383+
rev->minor_ver = PROTOCOL_REV_MINOR(ph->version);
384+
ph->set_priv(ph, rev);
390385

391386
ret = scmi_base_attributes_get(ph);
392387
if (ret)

drivers/firmware/arm_scmi/clock.c

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,6 @@ struct scmi_clock_rate_notify_payld {
157157
};
158158

159159
struct clock_info {
160-
u32 version;
161160
int num_clocks;
162161
int max_async_req;
163162
bool notify_rate_changed_cmd;
@@ -346,8 +345,7 @@ scmi_clock_get_permissions(const struct scmi_protocol_handle *ph, u32 clk_id,
346345
}
347346

348347
static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph,
349-
u32 clk_id, struct clock_info *cinfo,
350-
u32 version)
348+
u32 clk_id, struct clock_info *cinfo)
351349
{
352350
int ret;
353351
u32 attributes;
@@ -370,7 +368,7 @@ static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph,
370368
attributes = le32_to_cpu(attr->attributes);
371369
strscpy(clk->name, attr->name, SCMI_SHORT_NAME_MAX_SIZE);
372370
/* clock_enable_latency field is present only since SCMI v3.1 */
373-
if (PROTOCOL_REV_MAJOR(version) >= 0x2)
371+
if (PROTOCOL_REV_MAJOR(ph->version) >= 0x2)
374372
latency = le32_to_cpu(attr->clock_enable_latency);
375373
clk->enable_latency = latency ? : U32_MAX;
376374
}
@@ -381,7 +379,7 @@ static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph,
381379
* If supported overwrite short name with the extended one;
382380
* on error just carry on and use already provided short name.
383381
*/
384-
if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x2) {
382+
if (!ret && PROTOCOL_REV_MAJOR(ph->version) >= 0x2) {
385383
if (SUPPORTS_EXTENDED_NAMES(attributes))
386384
ph->hops->extended_name_get(ph, CLOCK_NAME_GET, clk_id,
387385
NULL, clk->name,
@@ -393,7 +391,7 @@ static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph,
393391
if (cinfo->notify_rate_change_requested_cmd &&
394392
SUPPORTS_RATE_CHANGE_REQUESTED_NOTIF(attributes))
395393
clk->rate_change_requested_notifications = true;
396-
if (PROTOCOL_REV_MAJOR(version) >= 0x3) {
394+
if (PROTOCOL_REV_MAJOR(ph->version) >= 0x3) {
397395
if (SUPPORTS_PARENT_CLOCK(attributes))
398396
scmi_clock_possible_parents(ph, clk_id, clk);
399397
if (SUPPORTS_GET_PERMISSIONS(attributes))
@@ -1068,16 +1066,11 @@ static const struct scmi_protocol_events clk_protocol_events = {
10681066

10691067
static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph)
10701068
{
1071-
u32 version;
10721069
int clkid, ret;
10731070
struct clock_info *cinfo;
10741071

1075-
ret = ph->xops->version_get(ph, &version);
1076-
if (ret)
1077-
return ret;
1078-
10791072
dev_dbg(ph->dev, "Clock Version %d.%d\n",
1080-
PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
1073+
PROTOCOL_REV_MAJOR(ph->version), PROTOCOL_REV_MINOR(ph->version));
10811074

10821075
cinfo = devm_kzalloc(ph->dev, sizeof(*cinfo), GFP_KERNEL);
10831076
if (!cinfo)
@@ -1095,21 +1088,20 @@ static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph)
10951088
for (clkid = 0; clkid < cinfo->num_clocks; clkid++) {
10961089
struct scmi_clock_info *clk = cinfo->clk + clkid;
10971090

1098-
ret = scmi_clock_attributes_get(ph, clkid, cinfo, version);
1091+
ret = scmi_clock_attributes_get(ph, clkid, cinfo);
10991092
if (!ret)
11001093
scmi_clock_describe_rates_get(ph, clkid, clk);
11011094
}
11021095

1103-
if (PROTOCOL_REV_MAJOR(version) >= 0x3) {
1096+
if (PROTOCOL_REV_MAJOR(ph->version) >= 0x3) {
11041097
cinfo->clock_config_set = scmi_clock_config_set_v2;
11051098
cinfo->clock_config_get = scmi_clock_config_get_v2;
11061099
} else {
11071100
cinfo->clock_config_set = scmi_clock_config_set;
11081101
cinfo->clock_config_get = scmi_clock_config_get;
11091102
}
11101103

1111-
cinfo->version = version;
1112-
return ph->set_priv(ph, cinfo, version);
1104+
return ph->set_priv(ph, cinfo);
11131105
}
11141106

11151107
static const struct scmi_protocol scmi_clock = {

drivers/firmware/arm_scmi/driver.c

Lines changed: 78 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1627,17 +1627,15 @@ static int version_get(const struct scmi_protocol_handle *ph, u32 *version)
16271627
*
16281628
* @ph: A reference to the protocol handle.
16291629
* @priv: The private data to set.
1630-
* @version: The detected protocol version for the core to register.
16311630
*
16321631
* Return: 0 on Success
16331632
*/
16341633
static int scmi_set_protocol_priv(const struct scmi_protocol_handle *ph,
1635-
void *priv, u32 version)
1634+
void *priv)
16361635
{
16371636
struct scmi_protocol_instance *pi = ph_to_pi(ph);
16381637

16391638
pi->priv = priv;
1640-
pi->version = version;
16411639

16421640
return 0;
16431641
}
@@ -1657,7 +1655,6 @@ static void *scmi_get_protocol_priv(const struct scmi_protocol_handle *ph)
16571655
}
16581656

16591657
static const struct scmi_xfer_ops xfer_ops = {
1660-
.version_get = version_get,
16611658
.xfer_get_init = xfer_get_init,
16621659
.reset_rx_to_maxsz = reset_rx_to_maxsz,
16631660
.do_xfer = do_xfer,
@@ -2112,6 +2109,76 @@ static int scmi_protocol_version_negotiate(struct scmi_protocol_handle *ph)
21122109
return ret;
21132110
}
21142111

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

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-
22032261
return pi;
22042262

22052263
clean:

0 commit comments

Comments
 (0)