Skip to content

Commit 54cf6e7

Browse files
cris-masudeep-holla
authored andcommitted
firmware: arm_scmi: Support vendor protocol modules autoloading
SCMI vendor protocols namespace is shared amongst all vendors so that there can be multiple implementation for the same protocol ID by different vendors, exposing completely different functionalities and used by distinct SCMI vendor drivers. For these reasons, at runtime, when some driver asks for a protocol, the proper implementation to use is chosen based on the SCMI vendor/subvendor/ impl_version data as advertised by the platform SCMI server and gathered from the SCMI core during stack initialization: this enables proper runtime selection of vendor protocols even when many different protocols from different vendors are built into the same image via a common defconfig. This same selection mechanism works similarly well even when all the vendor protocols are compiled as loadable modules, as long as all such required protocol modules have been previously loaded by some other means. Add support for the automatic loading of vendor protocol modules, based on protocol/vendor IDs, when an SCMI driver attempts to use such a protocol. Reported-by: Johan Hovold <johan+linaro@kernel.org> Closes: https://lore.kernel.org/lkml/ZytnRc94iKUfMYH0@hovoldconsulting.com/ Signed-off-by: Cristian Marussi <cristian.marussi@arm.com> Message-Id: <20241209164957.1801886-2-cristian.marussi@arm.com> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
1 parent e501bfd commit 54cf6e7

1 file changed

Lines changed: 46 additions & 10 deletions

File tree

drivers/firmware/arm_scmi/driver.c

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <linux/io.h>
2525
#include <linux/io-64-nonatomic-hi-lo.h>
2626
#include <linux/kernel.h>
27+
#include <linux/kmod.h>
2728
#include <linux/ktime.h>
2829
#include <linux/hashtable.h>
2930
#include <linux/list.h>
@@ -43,6 +44,8 @@
4344
#define CREATE_TRACE_POINTS
4445
#include <trace/events/scmi.h>
4546

47+
#define SCMI_VENDOR_MODULE_ALIAS_FMT "scmi-protocol-0x%02x-%s"
48+
4649
static DEFINE_IDA(scmi_id);
4750

4851
static DEFINE_XARRAY(scmi_protocols);
@@ -275,6 +278,44 @@ scmi_vendor_protocol_lookup(int protocol_id, char *vendor_id,
275278
return proto;
276279
}
277280

281+
static const struct scmi_protocol *
282+
scmi_vendor_protocol_get(int protocol_id, struct scmi_revision_info *version)
283+
{
284+
const struct scmi_protocol *proto;
285+
286+
proto = scmi_vendor_protocol_lookup(protocol_id, version->vendor_id,
287+
version->sub_vendor_id,
288+
version->impl_ver);
289+
if (!proto) {
290+
int ret;
291+
292+
pr_debug("Looking for '" SCMI_VENDOR_MODULE_ALIAS_FMT "'\n",
293+
protocol_id, version->vendor_id);
294+
295+
/* Note that vendor_id is mandatory for vendor protocols */
296+
ret = request_module(SCMI_VENDOR_MODULE_ALIAS_FMT,
297+
protocol_id, version->vendor_id);
298+
if (ret) {
299+
pr_warn("Problem loading module for protocol 0x%x\n",
300+
protocol_id);
301+
return NULL;
302+
}
303+
304+
/* Lookup again, once modules loaded */
305+
proto = scmi_vendor_protocol_lookup(protocol_id,
306+
version->vendor_id,
307+
version->sub_vendor_id,
308+
version->impl_ver);
309+
}
310+
311+
if (proto)
312+
pr_info("Loaded SCMI Vendor Protocol 0x%x - %s %s %X\n",
313+
protocol_id, proto->vendor_id ?: "",
314+
proto->sub_vendor_id ?: "", proto->impl_ver);
315+
316+
return proto;
317+
}
318+
278319
static const struct scmi_protocol *
279320
scmi_protocol_get(int protocol_id, struct scmi_revision_info *version)
280321
{
@@ -283,22 +324,15 @@ scmi_protocol_get(int protocol_id, struct scmi_revision_info *version)
283324
if (protocol_id < SCMI_PROTOCOL_VENDOR_BASE)
284325
proto = xa_load(&scmi_protocols, protocol_id);
285326
else
286-
proto = scmi_vendor_protocol_lookup(protocol_id,
287-
version->vendor_id,
288-
version->sub_vendor_id,
289-
version->impl_ver);
327+
proto = scmi_vendor_protocol_get(protocol_id, version);
328+
290329
if (!proto || !try_module_get(proto->owner)) {
291330
pr_warn("SCMI Protocol 0x%x not found!\n", protocol_id);
292331
return NULL;
293332
}
294333

295334
pr_debug("Found SCMI Protocol 0x%x\n", protocol_id);
296335

297-
if (protocol_id >= SCMI_PROTOCOL_VENDOR_BASE)
298-
pr_info("Loaded SCMI Vendor Protocol 0x%x - %s %s %X\n",
299-
protocol_id, proto->vendor_id ?: "",
300-
proto->sub_vendor_id ?: "", proto->impl_ver);
301-
302336
return proto;
303337
}
304338

@@ -366,7 +400,9 @@ int scmi_protocol_register(const struct scmi_protocol *proto)
366400
return ret;
367401
}
368402

369-
pr_debug("Registered SCMI Protocol 0x%x\n", proto->id);
403+
pr_debug("Registered SCMI Protocol 0x%x - %s %s 0x%08X\n",
404+
proto->id, proto->vendor_id, proto->sub_vendor_id,
405+
proto->impl_ver);
370406

371407
return 0;
372408
}

0 commit comments

Comments
 (0)