[PATCH 3/8] remoteproc: qcom: sysmon: Suppress notify between cluster siblings

From: Shawn Guo

Date: Sat Aug 15 2026 - 09:26:55 EST


Firmware on clustered remote processors (e.g. Nord's HPASS ADSP0/1/2)
cannot handle the SSCTL peer-shutdown notification sysmon sends
whenever a sibling in the same cluster starts or stops, and the QMI
request instead times out.

Skip sysmon_notify() when the notifying and the notified instance share
the cluster identifier their owning rproc driver put in rproc->cluster.
The suppression is done on the receiving side, so that a cluster member
keeps notifying, and being notified by, remote processors outside its
cluster. Instances whose rproc has no cluster set are completely
unaffected.

Assisted-by: LLM
Signed-off-by: Shawn Guo <shengchao.guo@xxxxxxxxxxxxxxxx>
---
drivers/remoteproc/qcom_sysmon.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/remoteproc/qcom_sysmon.c b/drivers/remoteproc/qcom_sysmon.c
index 61e1038328e8..5d4443ef3bc1 100644
--- a/drivers/remoteproc/qcom_sysmon.c
+++ b/drivers/remoteproc/qcom_sysmon.c
@@ -67,6 +67,7 @@ static const char * const sysmon_state_string[] = {
struct sysmon_event {
const char *subsys_name;
u32 ssr_event;
+ void *cluster;
};

static DEFINE_MUTEX(sysmon_lock);
@@ -473,7 +474,8 @@ static int sysmon_prepare(struct rproc_subdev *subdev)
subdev);
struct sysmon_event event = {
.subsys_name = sysmon->name,
- .ssr_event = SSCTL_SSR_EVENT_BEFORE_POWERUP
+ .ssr_event = SSCTL_SSR_EVENT_BEFORE_POWERUP,
+ .cluster = sysmon->rproc->cluster,
};

mutex_lock(&sysmon->state_lock);
@@ -500,7 +502,8 @@ static int sysmon_start(struct rproc_subdev *subdev)
struct qcom_sysmon *target;
struct sysmon_event event = {
.subsys_name = sysmon->name,
- .ssr_event = SSCTL_SSR_EVENT_AFTER_POWERUP
+ .ssr_event = SSCTL_SSR_EVENT_AFTER_POWERUP,
+ .cluster = sysmon->rproc->cluster,
};

reinit_completion(&sysmon->ssctl_comp);
@@ -536,7 +539,8 @@ static void sysmon_stop(struct rproc_subdev *subdev, bool crashed)
struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon, subdev);
struct sysmon_event event = {
.subsys_name = sysmon->name,
- .ssr_event = SSCTL_SSR_EVENT_BEFORE_SHUTDOWN
+ .ssr_event = SSCTL_SSR_EVENT_BEFORE_SHUTDOWN,
+ .cluster = sysmon->rproc->cluster,
};

sysmon->shutdown_acked = false;
@@ -567,7 +571,8 @@ static void sysmon_unprepare(struct rproc_subdev *subdev)
subdev);
struct sysmon_event event = {
.subsys_name = sysmon->name,
- .ssr_event = SSCTL_SSR_EVENT_AFTER_SHUTDOWN
+ .ssr_event = SSCTL_SSR_EVENT_AFTER_SHUTDOWN,
+ .cluster = sysmon->rproc->cluster,
};

mutex_lock(&sysmon->state_lock);
@@ -588,6 +593,11 @@ static int sysmon_notify(struct notifier_block *nb, unsigned long event,
struct qcom_sysmon *sysmon = container_of(nb, struct qcom_sysmon, nb);
struct sysmon_event *sysmon_event = data;

+ /* Cluster siblings' firmware can't handle peer SSR notify; skip it */
+ if (sysmon->rproc->cluster &&
+ sysmon->rproc->cluster == sysmon_event->cluster)
+ return NOTIFY_DONE;
+
/* Skip non-running rprocs and the originating instance */
if (sysmon->state != SSCTL_SSR_EVENT_AFTER_POWERUP ||
!strcmp(sysmon_event->subsys_name, sysmon->name)) {
--
2.43.0