summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-10-30 11:30:28 +0000
committerMark Brown <broonie@kernel.org>2026-10-30 11:30:28 +0000
commit506ca150016d59cd308d0ec622760958df57e205 (patch)
treee0d4d520d882d48773fac2be37c777c86e1ac41b
parent7c58608f4a4b62134f725aa0f0bc51c8158b24f3 (diff)
parentc64a20a250d5eb8bb43ceffadb24aa852a7158b5 (diff)
downloadlinux-next-506ca150016d59cd308d0ec622760958df57e205.tar.gz
linux-next-506ca150016d59cd308d0ec622760958df57e205.zip
Merge branch 'for-linux-next' of https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git
-rw-r--r--arch/arm64/boot/dts/arm/corstone1000-a320.dtsi2
-rw-r--r--drivers/firmware/arm_ffa/driver.c11
-rw-r--r--drivers/firmware/arm_scmi/Kconfig2
-rw-r--r--drivers/firmware/arm_scmi/bus.c110
-rw-r--r--drivers/firmware/arm_scmi/driver.c4
-rw-r--r--drivers/firmware/arm_scmi/notify.c4
-rw-r--r--drivers/firmware/arm_scmi/transports/Kconfig2
-rw-r--r--drivers/firmware/arm_scmi/transports/mailbox.c7
-rw-r--r--drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c18
-rw-r--r--drivers/irqchip/Kconfig2
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx-scmi.c2
-rw-r--r--include/linux/arm-smccc.h7
-rw-r--r--include/linux/firmware/imx/sm.h6
13 files changed, 113 insertions, 64 deletions
diff --git a/arch/arm64/boot/dts/arm/corstone1000-a320.dtsi b/arch/arm64/boot/dts/arm/corstone1000-a320.dtsi
index f0937914350c..f895a024fc92 100644
--- a/arch/arm64/boot/dts/arm/corstone1000-a320.dtsi
+++ b/arch/arm64/boot/dts/arm/corstone1000-a320.dtsi
@@ -73,7 +73,7 @@
#size-cells = <1>;
interrupt-controller;
reg = <0x1c000000 0x10000>,
- <0x1c040000 0x80000>;
+ <0x1c040000 0x100000>;
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>;
};
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 28abc808fd32..ae8cc3a2ba2e 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -1223,6 +1223,7 @@ struct notifier_cb_info {
ffa_fwk_notifier_cb fwk_cb;
ffa_notifier_cb cb;
void *cb_data;
+ u16 notify_id;
};
static int
@@ -1302,7 +1303,8 @@ notifier_hnode_get_by_vmid(u16 notify_id, int vmid)
struct notifier_cb_info *node;
hash_for_each_possible(drv_info->notifier_hash, node, hnode, notify_id)
- if (node->fwk_cb && vmid == node->dev->vm_id)
+ if (node->notify_id == notify_id && node->fwk_cb &&
+ vmid == node->dev->vm_id)
return node;
return NULL;
@@ -1317,7 +1319,8 @@ notifier_hnode_get_by_vmid_uuid(u16 notify_id, int vmid, const uuid_t *uuid)
return notifier_hnode_get_by_vmid(notify_id, vmid);
hash_for_each_possible(drv_info->notifier_hash, node, hnode, notify_id)
- if (node->fwk_cb && vmid == node->dev->vm_id &&
+ if (node->notify_id == notify_id && node->fwk_cb &&
+ vmid == node->dev->vm_id &&
uuid_equal(&node->dev->uuid, uuid))
return node;
@@ -1330,7 +1333,8 @@ notifier_hnode_get_by_type(u16 notify_id, enum notify_type type)
struct notifier_cb_info *node;
hash_for_each_possible(drv_info->notifier_hash, node, hnode, notify_id)
- if (node->cb && type == ffa_notify_type_get(node->dev->vm_id))
+ if (node->notify_id == notify_id && node->cb &&
+ type == ffa_notify_type_get(node->dev->vm_id))
return node;
return NULL;
@@ -1422,6 +1426,7 @@ static int __ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu,
cb_info->dev = dev;
cb_info->cb_data = cb_data;
+ cb_info->notify_id = notify_id;
if (is_framework)
cb_info->fwk_cb = cb;
else
diff --git a/drivers/firmware/arm_scmi/Kconfig b/drivers/firmware/arm_scmi/Kconfig
index 783c24a20e29..9f6241efd592 100644
--- a/drivers/firmware/arm_scmi/Kconfig
+++ b/drivers/firmware/arm_scmi/Kconfig
@@ -52,7 +52,7 @@ config ARM_SCMI_RAW_MODE_SUPPORT_COEX
Allow SCMI Raw transmission mode to coexist with normal SCMI stack.
This will allow regular SCMI drivers to register with the core and
- operate normally, thing which could make an SCMI test suite using the
+ operate normally, things which could make an SCMI test suite using the
SCMI Raw mode support unreliable. If unsure, say N.
config ARM_SCMI_DEBUG_COUNTERS
diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index 25197197db8e..7613ea2893ef 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -36,6 +36,12 @@ struct scmi_requested_dev {
/* Track globally the SCMI SystemPower protocol device. */
static struct scmi_device *scmi_syspower_registered;
+static bool scmi_raw_mode_only(void)
+{
+ return IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT) &&
+ !IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX);
+}
+
/**
* scmi_protocol_device_request - Helper to request a device
*
@@ -60,8 +66,7 @@ static int scmi_protocol_device_request(const struct scmi_device_id *id_table)
pr_debug("Requesting SCMI device (%s) for protocol %x\n",
id_table->name, id_table->protocol_id);
- if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT) &&
- !IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX)) {
+ if (scmi_raw_mode_only()) {
pr_warn("SCMI Raw mode active. Rejecting '%s'/0x%02X\n",
id_table->name, id_table->protocol_id);
return -EINVAL;
@@ -181,12 +186,43 @@ static void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table
}
}
+/* Standard protocols table */
+static const struct scmi_device_id scmi_std_id_table[] = {
+ { SCMI_PROTOCOL_POWER, "genpd" },
+ { SCMI_PROTOCOL_SYSTEM, "syspower" },
+ { SCMI_PROTOCOL_PERF, "perf" },
+ { SCMI_PROTOCOL_PERF, "cpufreq" },
+ { SCMI_PROTOCOL_CLOCK, "clocks" },
+ { SCMI_PROTOCOL_SENSOR, "hwmon" },
+ { SCMI_PROTOCOL_SENSOR, "iiodev" },
+ { SCMI_PROTOCOL_RESET, "reset" },
+ { SCMI_PROTOCOL_VOLTAGE, "regulator" },
+ { SCMI_PROTOCOL_POWERCAP, "powercap" },
+ { SCMI_PROTOCOL_PINCTRL, "pinctrl" },
+ { },
+};
+
+static bool scmi_device_id_in_std_id_table(const struct scmi_device_id *id)
+{
+ for (int i = 0; scmi_std_id_table[i].name[0]; i++) {
+ if (scmi_std_id_table[i].protocol_id == id->protocol_id &&
+ !strcmp(scmi_std_id_table[i].name, id->name))
+ return true;
+ }
+
+ return false;
+}
+
static int scmi_protocol_table_register(const struct scmi_device_id *id_table)
{
const struct scmi_device_id *entry;
int ret;
for (entry = id_table; entry->name[0]; entry++) {
+ /* Skip standard devices as they are created unconditionally */
+ if (scmi_device_id_in_std_id_table(entry))
+ continue;
+
ret = scmi_protocol_device_request(entry);
if (ret)
goto err_unrequest;
@@ -195,8 +231,11 @@ static int scmi_protocol_table_register(const struct scmi_device_id *id_table)
return 0;
err_unrequest:
- while (entry != id_table)
- scmi_protocol_device_unrequest(--entry);
+ while (entry != id_table) {
+ --entry;
+ if (!scmi_device_id_in_std_id_table(entry))
+ scmi_protocol_device_unrequest(entry);
+ }
return ret;
}
@@ -206,16 +245,23 @@ scmi_protocol_table_unregister(const struct scmi_device_id *id_table)
{
const struct scmi_device_id *entry;
- for (entry = id_table; entry->name[0]; entry++)
- scmi_protocol_device_unrequest(entry);
+ for (entry = id_table; entry->name[0]; entry++) {
+ if (!scmi_device_id_in_std_id_table(entry))
+ scmi_protocol_device_unrequest(entry);
+ }
}
-static bool scmi_device_is_transport(const struct scmi_device *scmi_dev)
+static bool scmi_device_name_is_transport(const char *name)
{
- return !strncmp(scmi_dev->name, SCMI_TRANSPORT_DEVNAME_PREFIX,
+ return !strncmp(name, SCMI_TRANSPORT_DEVNAME_PREFIX,
strlen(SCMI_TRANSPORT_DEVNAME_PREFIX));
}
+static bool scmi_device_is_transport(const struct scmi_device *scmi_dev)
+{
+ return scmi_device_name_is_transport(scmi_dev->name);
+}
+
static int __scmi_dev_match_by_id_table(struct scmi_device *scmi_dev,
const struct scmi_device_id *id_table,
bool skip_transport)
@@ -524,6 +570,11 @@ _scmi_device_create(struct fwnode_handle *fwnode, struct device *parent,
{
struct scmi_device *sdev;
+ /* The perf device is only needed when it provides power domains. */
+ if (protocol == SCMI_PROTOCOL_PERF && !strcmp(name, "perf") &&
+ !fwnode_property_present(fwnode, "#power-domain-cells"))
+ return NULL;
+
sdev = __scmi_device_create(fwnode, parent, protocol, name);
if (!sdev)
pr_err("(%pfwf) Failed to create device - protocol 0x%x (%s)\n",
@@ -532,34 +583,6 @@ _scmi_device_create(struct fwnode_handle *fwnode, struct device *parent,
return sdev;
}
-/* Standard protocols table */
-static const struct scmi_device_id scmi_std_id_table[] = {
- { SCMI_PROTOCOL_POWER, "genpd" },
- { SCMI_PROTOCOL_SYSTEM, "syspower" },
- { SCMI_PROTOCOL_PERF, "perf" },
- { SCMI_PROTOCOL_PERF, "cpufreq" },
- { SCMI_PROTOCOL_CLOCK, "clocks" },
- { SCMI_PROTOCOL_SENSOR, "hwmon" },
- { SCMI_PROTOCOL_SENSOR, "iiodev" },
- { SCMI_PROTOCOL_RESET, "reset" },
- { SCMI_PROTOCOL_VOLTAGE, "regulator" },
- { SCMI_PROTOCOL_POWERCAP, "powercap" },
- { SCMI_PROTOCOL_PINCTRL, "pinctrl" },
- { SCMI_PROTOCOL_PINCTRL, "pinctrl-imx" },
- { },
-};
-
-static bool scmi_device_id_in_std_id_table(const struct scmi_device_id *id)
-{
- for (int i = 0; scmi_std_id_table[i].name[0]; i++) {
- if (scmi_std_id_table[i].protocol_id == id->protocol_id &&
- !strcmp(scmi_std_id_table[i].name, id->name))
- return true;
- }
-
- return false;
-}
-
/**
* scmi_device_create - A method to create one or more SCMI devices
*
@@ -578,10 +601,8 @@ static bool scmi_device_id_in_std_id_table(const struct scmi_device_id *id)
*
* Return: The created device (or one of them if @name was NOT provided and
* multiple devices were created) or NULL if no device was created;
- * note that NULL indicates an error ONLY in case a specific @name
- * was provided: when @name param was not provided, a number of devices
- * could have been potentially created for a whole protocol, unless no
- * device was found to have been requested for that specific protocol.
+ * note that NULL can also indicate that a named device is not needed
+ * for this fwnode, or that no device was requested when @name is NULL.
*/
struct scmi_device *scmi_device_create(struct fwnode_handle *fwnode,
struct device *parent, int protocol,
@@ -591,6 +612,11 @@ struct scmi_device *scmi_device_create(struct fwnode_handle *fwnode,
struct scmi_requested_dev *rdev;
struct scmi_device *sdev, *scmi_dev = NULL;
+ /* Exclusive raw mode still needs transport devices for its channels. */
+ if (scmi_raw_mode_only() &&
+ (!name || !scmi_device_name_is_transport(name)))
+ return NULL;
+
if (name)
return _scmi_device_create(fwnode, parent, protocol, name);
@@ -619,10 +645,6 @@ struct scmi_device *scmi_device_create(struct fwnode_handle *fwnode,
/* Walk the list of requested devices for protocol and create them */
list_for_each_entry(rdev, phead, node) {
- /* Standard proto matches already have their dev created above */
- if (scmi_device_id_in_std_id_table(rdev->id_table))
- continue;
-
sdev = _scmi_device_create(fwnode, parent,
rdev->id_table->protocol_id,
rdev->id_table->name);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 1e6f69b14321..6c6cb7209b13 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -3107,11 +3107,7 @@ static void scmi_debugfs_common_cleanup(void *d)
static const char *scmi_acpi_device_hid(struct acpi_device *adev)
{
-#ifdef CONFIG_ACPI
return adev ? acpi_device_hid(adev) : "unknown";
-#else
- return "unknown";
-#endif
}
static struct scmi_debug_info *scmi_debugfs_common_setup(struct scmi_info *info)
diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c
index fb60fb07c0ed..e5de0d29c346 100644
--- a/drivers/firmware/arm_scmi/notify.c
+++ b/drivers/firmware/arm_scmi/notify.c
@@ -1395,8 +1395,10 @@ static int scmi_notifier_register(const struct scmi_handle *handle,
/* Enable events for not pending handlers */
if (!IS_HNDL_PENDING(hndl)) {
ret = scmi_event_handler_enable_events(hndl);
- if (ret)
+ if (ret) {
+ blocking_notifier_chain_unregister(&hndl->chain, nb);
scmi_put_handler(ni, hndl);
+ }
}
return ret;
diff --git a/drivers/firmware/arm_scmi/transports/Kconfig b/drivers/firmware/arm_scmi/transports/Kconfig
index 0e34fbf25053..6ba0dcb86204 100644
--- a/drivers/firmware/arm_scmi/transports/Kconfig
+++ b/drivers/firmware/arm_scmi/transports/Kconfig
@@ -5,7 +5,7 @@ config ARM_SCMI_HAVE_TRANSPORT
bool
help
This declares whether at least one SCMI transport has been configured.
- Used to trigger a build bug when trying to build SCMI without any
+ Used to trigger a runtime warning when enabling SCMI without any
configured transport.
config ARM_SCMI_HAVE_SHMEM
diff --git a/drivers/firmware/arm_scmi/transports/mailbox.c b/drivers/firmware/arm_scmi/transports/mailbox.c
index 56af2cb0f424..49c472e2ba27 100644
--- a/drivers/firmware/arm_scmi/transports/mailbox.c
+++ b/drivers/firmware/arm_scmi/transports/mailbox.c
@@ -206,8 +206,11 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
smbox->shmem = core->shmem->setup_iomap(cinfo, dev, tx, NULL,
&smbox->io_ops);
- if (IS_ERR(smbox->shmem))
- return PTR_ERR(smbox->shmem);
+ if (IS_ERR(smbox->shmem)) {
+ ret = PTR_ERR(smbox->shmem);
+ devm_kfree(dev, smbox);
+ return ret;
+ }
cl = &smbox->cl;
cl->dev = cdev;
diff --git a/drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c b/drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c
index 637973fb45e6..f00f7acba845 100644
--- a/drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c
+++ b/drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c
@@ -273,10 +273,16 @@ static int scmi_imx_misc_ctrl_get(const struct scmi_protocol_handle *ph,
{
struct scmi_imx_misc_ctrl_get_out *out;
struct scmi_xfer *t;
+ u32 num_values, max_values;
int ret, i;
int max_msg_size = ph->hops->get_max_msg_size(ph);
int max_num = (max_msg_size - sizeof(*out)) / sizeof(__le32);
+ if (!num || !val || !*num)
+ return -EINVAL;
+
+ max_values = *num;
+
ret = scmi_imx_misc_ctrl_validate_id(ph, ctrl_id);
if (ret)
return ret;
@@ -290,16 +296,18 @@ static int scmi_imx_misc_ctrl_get(const struct scmi_protocol_handle *ph,
ret = ph->xops->do_xfer(ph, t);
if (!ret) {
out = t->rx.buf;
- *num = le32_to_cpu(out->num);
+ num_values = le32_to_cpu(out->num);
- if (*num >= max_num ||
- *num * sizeof(__le32) > t->rx.len - sizeof(__le32)) {
+ if (num_values > max_values || num_values >= max_num ||
+ num_values * sizeof(__le32) > t->rx.len - sizeof(__le32)) {
ph->xops->xfer_put(ph, t);
return -EINVAL;
}
- for (i = 0; i < *num; i++)
+ for (i = 0; i < num_values; i++)
val[i] = le32_to_cpu(out->val[i]);
+
+ *num = num_values;
}
ph->xops->xfer_put(ph, t);
@@ -438,7 +446,7 @@ static int iter_misc_syslog_update_state(struct scmi_iterator_state *st,
st->num_returned = RETURNED(r->numlogflags);
st->num_remaining = REMAINING(r->numlogflags);
- *p->size = st->num_returned + st->num_remaining;
+ *p->size = st->desc_index + st->num_returned;
return 0;
}
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 136bab41f801..ca915fca0ef5 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -37,7 +37,7 @@ config ARM_GIC_V3
bool
select IRQ_DOMAIN_HIERARCHY
select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP
- select HAVE_ARM_SMCCC_DISCOVERY
+ select HAVE_ARM_SMCCC_DISCOVERY if ARM64
select IRQ_MSI_IOMMU
config ARM_GIC_ITS_PARENT
diff --git a/drivers/pinctrl/freescale/pinctrl-imx-scmi.c b/drivers/pinctrl/freescale/pinctrl-imx-scmi.c
index 613552e35070..b259a526ccc1 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx-scmi.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx-scmi.c
@@ -354,7 +354,7 @@ static int scmi_pinctrl_imx_probe(struct scmi_device *sdev)
}
static const struct scmi_device_id scmi_id_table[] = {
- { SCMI_PROTOCOL_PINCTRL, "pinctrl-imx" },
+ { SCMI_PROTOCOL_PINCTRL, "pinctrl" },
{ }
};
MODULE_DEVICE_TABLE(scmi, scmi_id_table);
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 4de81848fe2e..75f9d3f1723b 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -324,6 +324,7 @@ enum arm_smccc_conduit {
SMCCC_CONDUIT_HVC,
};
+#ifdef CONFIG_HAVE_ARM_SMCCC_DISCOVERY
/**
* arm_smccc_1_1_get_conduit()
*
@@ -363,6 +364,12 @@ s32 arm_smccc_get_soc_id_version(void);
* When ARM_SMCCC_ARCH_SOC_ID is not present, returns SMCCC_RET_NOT_SUPPORTED.
*/
s32 arm_smccc_get_soc_id_revision(void);
+#else /* CONFIG_HAVE_ARM_SMCCC_DISCOVERY */
+#define arm_smccc_1_1_get_conduit() SMCCC_CONDUIT_NONE
+#define arm_smccc_get_version() 0
+#define arm_smccc_get_soc_id_version() SMCCC_RET_NOT_SUPPORTED
+#define arm_smccc_get_soc_id_revision() SMCCC_RET_NOT_SUPPORTED
+#endif /* CONFIG_HAVE_ARM_SMCCC_DISCOVERY */
#ifndef __ASSEMBLY__
diff --git a/include/linux/firmware/imx/sm.h b/include/linux/firmware/imx/sm.h
index ba5d93bd6158..0aec7da0ae78 100644
--- a/include/linux/firmware/imx/sm.h
+++ b/include/linux/firmware/imx/sm.h
@@ -29,6 +29,12 @@
#define SCMI_IMX952_CTRL_BYPASS_AUDMIX 8U /* WAKE AUDMIX */
#if IS_ENABLED(CONFIG_IMX_SCMI_MISC_DRV)
+/**
+ * scmi_imx_misc_ctrl_get() - Read an i.MX MISC control
+ * @id: Control identifier
+ * @num: On entry, capacity of @val in words; on return, words read
+ * @val: Buffer for the control value
+ */
int scmi_imx_misc_ctrl_get(u32 id, u32 *num, u32 *val);
int scmi_imx_misc_ctrl_set(u32 id, u32 val);
#else