mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] remoteproc: qcom: q6v5: Make handover IRQ one-shot
@ 2026-06-12 11:09 Abel Vesa
  2026-07-10 18:06 ` Bjorn Andersson
  2026-07-31  1:35 ` Shawn Guo
  0 siblings, 2 replies; 4+ messages in thread
From: Abel Vesa @ 2026-06-12 11:09 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier
  Cc: Stephan Gerhold, linux-arm-msm, linux-remoteproc, linux-kernel,
	Abel Vesa

The handover interrupt is expected to be consumed once during each prepare
cycle. If the remote processor keeps signalling handover after the first
event, qcom_q6v5 currently logs the duplicate interrupt repeatedly while
leaving the IRQ enabled.

Track the handover IRQ enable state explicitly and route all handover IRQ
enable/disable operations through idempotent helpers. Request the handover
IRQ with IRQF_NO_AUTOEN so it is only enabled through the helper during
prepare. The handover handler disables it after marking handover as issued,
while unprepare disables and synchronizes it before checking whether
handover was issued.

Signed-off-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
---
 drivers/remoteproc/qcom_q6v5.c | 54 ++++++++++++++++++++++++++++++++++--------
 drivers/remoteproc/qcom_q6v5.h |  4 ++++
 2 files changed, 48 insertions(+), 10 deletions(-)

diff --git a/drivers/remoteproc/qcom_q6v5.c b/drivers/remoteproc/qcom_q6v5.c
index 58d5b85e58cd..c66cca05c250 100644
--- a/drivers/remoteproc/qcom_q6v5.c
+++ b/drivers/remoteproc/qcom_q6v5.c
@@ -36,6 +36,40 @@ static int q6v5_load_state_toggle(struct qcom_q6v5 *q6v5, bool enable)
 	return ret;
 }
 
+static void q6v5_handover_irq_enable(struct qcom_q6v5 *q6v5)
+{
+	unsigned long flags;
+	bool enable = false;
+
+	spin_lock_irqsave(&q6v5->handover_lock, flags);
+	if (!q6v5->handover_irq_enabled) {
+		q6v5->handover_irq_enabled = true;
+		enable = true;
+	}
+	spin_unlock_irqrestore(&q6v5->handover_lock, flags);
+
+	if (enable)
+		enable_irq(q6v5->handover_irq);
+}
+
+static void q6v5_handover_irq_disable(struct qcom_q6v5 *q6v5, bool sync)
+{
+	unsigned long flags;
+	bool disable = false;
+
+	spin_lock_irqsave(&q6v5->handover_lock, flags);
+	if (q6v5->handover_irq_enabled) {
+		q6v5->handover_irq_enabled = false;
+		disable = true;
+	}
+	spin_unlock_irqrestore(&q6v5->handover_lock, flags);
+
+	if (disable)
+		disable_irq_nosync(q6v5->handover_irq);
+	if (sync)
+		synchronize_irq(q6v5->handover_irq);
+}
+
 /**
  * qcom_q6v5_prepare() - reinitialize the qcom_q6v5 context before start
  * @q6v5:	reference to qcom_q6v5 context to be reinitialized
@@ -64,7 +98,7 @@ int qcom_q6v5_prepare(struct qcom_q6v5 *q6v5)
 	q6v5->running = true;
 	q6v5->handover_issued = false;
 
-	enable_irq(q6v5->handover_irq);
+	q6v5_handover_irq_enable(q6v5);
 
 	return 0;
 }
@@ -78,7 +112,8 @@ EXPORT_SYMBOL_GPL(qcom_q6v5_prepare);
  */
 int qcom_q6v5_unprepare(struct qcom_q6v5 *q6v5)
 {
-	disable_irq(q6v5->handover_irq);
+	q6v5_handover_irq_disable(q6v5, true);
+
 	q6v5_load_state_toggle(q6v5, false);
 
 	/* Disable interconnect vote, in case handover never happened */
@@ -164,18 +199,15 @@ static irqreturn_t q6v5_handover_interrupt(int irq, void *data)
 {
 	struct qcom_q6v5 *q6v5 = data;
 
-	if (q6v5->handover_issued) {
-		dev_err(q6v5->dev, "Handover signaled, but it already happened\n");
-		return IRQ_HANDLED;
-	}
+	q6v5->handover_issued = true;
+
+	q6v5_handover_irq_disable(q6v5, false);
 
 	if (q6v5->handover)
 		q6v5->handover(q6v5);
 
 	icc_set_bw(q6v5->path, 0, 0);
 
-	q6v5->handover_issued = true;
-
 	return IRQ_HANDLED;
 }
 
@@ -256,6 +288,8 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev,
 	q6v5->crash_reason = crash_reason;
 	q6v5->handover = handover;
 
+	spin_lock_init(&q6v5->handover_lock);
+
 	init_completion(&q6v5->start_done);
 	init_completion(&q6v5->stop_done);
 
@@ -304,13 +338,13 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev,
 
 	ret = devm_request_threaded_irq(&pdev->dev, q6v5->handover_irq,
 					NULL, q6v5_handover_interrupt,
-					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+					IRQF_TRIGGER_RISING | IRQF_ONESHOT |
+					IRQF_NO_AUTOEN,
 					"q6v5 handover", q6v5);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to acquire handover IRQ\n");
 		return ret;
 	}
-	disable_irq(q6v5->handover_irq);
 
 	q6v5->stop_irq = platform_get_irq_byname(pdev, "stop-ack");
 	if (q6v5->stop_irq < 0)
diff --git a/drivers/remoteproc/qcom_q6v5.h b/drivers/remoteproc/qcom_q6v5.h
index 5a859c41896e..8991ff090579 100644
--- a/drivers/remoteproc/qcom_q6v5.h
+++ b/drivers/remoteproc/qcom_q6v5.h
@@ -5,6 +5,7 @@
 
 #include <linux/kernel.h>
 #include <linux/completion.h>
+#include <linux/spinlock.h>
 #include <linux/soc/qcom/qcom_aoss.h>
 
 struct icc_path;
@@ -29,6 +30,9 @@ struct qcom_q6v5 {
 	int handover_irq;
 	int stop_irq;
 
+	/* Protects handover_irq_enabled against stop/handover races. */
+	spinlock_t handover_lock;
+	bool handover_irq_enabled;
 	bool handover_issued;
 
 	struct completion start_done;

---
base-commit: ec039126b7fac4e3af35ebccaa7c6f9b6875ba81
change-id: 20260612-rproc-q6v5-handover-irq-one-shot-759015d0e4b0

Best regards,
--  
Abel Vesa <abel.vesa@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] remoteproc: qcom: q6v5: Make handover IRQ one-shot
  2026-06-12 11:09 [PATCH] remoteproc: qcom: q6v5: Make handover IRQ one-shot Abel Vesa
@ 2026-07-10 18:06 ` Bjorn Andersson
  2026-07-31  1:35 ` Shawn Guo
  1 sibling, 0 replies; 4+ messages in thread
From: Bjorn Andersson @ 2026-07-10 18:06 UTC (permalink / raw)
  To: Mathieu Poirier, Abel Vesa
  Cc: Stephan Gerhold, linux-arm-msm, linux-remoteproc, linux-kernel


On Fri, 12 Jun 2026 14:09:08 +0300, Abel Vesa wrote:
> The handover interrupt is expected to be consumed once during each prepare
> cycle. If the remote processor keeps signalling handover after the first
> event, qcom_q6v5 currently logs the duplicate interrupt repeatedly while
> leaving the IRQ enabled.
> 
> Track the handover IRQ enable state explicitly and route all handover IRQ
> enable/disable operations through idempotent helpers. Request the handover
> IRQ with IRQF_NO_AUTOEN so it is only enabled through the helper during
> prepare. The handover handler disables it after marking handover as issued,
> while unprepare disables and synchronizes it before checking whether
> handover was issued.
> 
> [...]

Applied, thanks!

[1/1] remoteproc: qcom: q6v5: Make handover IRQ one-shot
      commit: a5c0d4e3d98ffe9d853c8b06018f7782683215fc

Best regards,
-- 
Bjorn Andersson <andersson@kernel.org>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] remoteproc: qcom: q6v5: Make handover IRQ one-shot
  2026-06-12 11:09 [PATCH] remoteproc: qcom: q6v5: Make handover IRQ one-shot Abel Vesa
  2026-07-10 18:06 ` Bjorn Andersson
@ 2026-07-31  1:35 ` Shawn Guo
  2026-07-31  6:34   ` Shawn Guo
  1 sibling, 1 reply; 4+ messages in thread
From: Shawn Guo @ 2026-07-31  1:35 UTC (permalink / raw)
  To: Abel Vesa
  Cc: Bjorn Andersson, Mathieu Poirier, Stephan Gerhold, linux-arm-msm,
	linux-remoteproc, linux-kernel

On Fri, Jun 12, 2026 at 02:09:08PM +0300, Abel Vesa wrote:
> The handover interrupt is expected to be consumed once during each prepare
> cycle. If the remote processor keeps signalling handover after the first
> event, qcom_q6v5 currently logs the duplicate interrupt repeatedly while
> leaving the IRQ enabled.
> 
> Track the handover IRQ enable state explicitly and route all handover IRQ
> enable/disable operations through idempotent helpers. Request the handover
> IRQ with IRQF_NO_AUTOEN so it is only enabled through the helper during
> prepare. The handover handler disables it after marking handover as issued,
> while unprepare disables and synchronizes it before checking whether
> handover was issued.
> 
> Signed-off-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
> ---
>  drivers/remoteproc/qcom_q6v5.c | 54 ++++++++++++++++++++++++++++++++++--------
>  drivers/remoteproc/qcom_q6v5.h |  4 ++++
>  2 files changed, 48 insertions(+), 10 deletions(-)

I seem to see a "regression" on Nord ADSP (probed as attached) with this change.

Before the change:

root@iq10-rrd:~# cat /sys/class/remoteproc/remoteproc0/state
attached
root@iq10-rrd:~# echo stop > /sys/class/remoteproc/remoteproc0/state
[   28.005204] qcom_q6v5_pas 4c00000.remoteproc: Handover signaled, but it already happened
[   28.036754] remoteproc remoteproc0: stopped remote processor adsp
root@iq10-rrd:~# echo start > /sys/class/remoteproc/remoteproc0/state
[   33.603101] remoteproc remoteproc0: powering up adsp
[   33.626128] remoteproc remoteproc0: Booting fw image qcom/nord/adsp.mbn, size 8241816
[   33.640317] PDM: no support for the platform, userspace daemon might be required.
[   33.724070] remoteproc remoteproc0: remote processor adsp is now up

After the change:

root@iq10-rrd:~# cat /sys/class/remoteproc/remoteproc0/state
attached
root@iq10-rrd:~# echo stop > /sys/class/remoteproc/remoteproc0/state
[   40.004874] genpd genpd:0:4c00000.remoteproc: Runtime PM usage count underflow!
[   40.012409] genpd genpd:1:4c00000.remoteproc: Runtime PM usage count underflow!
[   40.050074] remoteproc remoteproc0: stopped remote processor adsp
root@iq10-rrd:~# echo start > /sys/class/remoteproc/remoteproc0/state
[   44.350298] remoteproc remoteproc0: powering up adsp
[   44.375769] remoteproc remoteproc0: Booting fw image qcom/nord/adsp.mbn, size 8241816
[   44.389850] PDM: no support for the platform, userspace daemon might be required.
[   44.397864] ------------[ cut here ]------------
[   44.402633] Unbalanced enable for IRQ 363
[   44.406779] WARNING: kernel/irq/manage.c:775 at __enable_irq+0x4c/0x7c, CPU#9: sh/791
[   44.414837] Modules linked in: bluetooth ecdh_generic kpp ecc usb_f_fs libcomposite qcom_pd_mapper rpmsg_ctrl fastrpc rpmsg_char qrtr_smd qcom_pdr_msg qrtr qcom_q6v5_pas qcom_pil_info rtc_rv8803 phy_nxp_ptn3222 qcom_q6v5 phy_qcom_qmp_combo qcom_sysmon aux_bridge qcom_common i2c_qcom_geni spi_geni_qcom drm_kms_helper qcom_glink_smem typec mdt_loader qmi_helpers phy_snps_eusb2 qcom_cpucp_mbox qcom_wdt qcom_rng socinfo qcomtee cfg80211 rfkill fuse drm backlight
[   44.456498] CPU: 9 UID: 0 PID: 791 Comm: sh Not tainted 7.2.0-rc5-next-20260729+ #114 PREEMPT
[   44.465363] Hardware name: Qualcomm Technologies, Inc. IQ10 RRD (DT)
[   44.471910] pstate: 614000c5 (nZCv daIF +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
[   44.479075] pc : __enable_irq+0x4c/0x7c
[   44.483043] lr : __enable_irq+0x4c/0x7c
[   44.487010] sp : ffff80008688bae0
[   44.490434] x29: ffff80008688bae0 x28: ffff00080bf1d000 x27: ffff000806285528
[   44.497784] x26: ffff000806285000 x25: ffff0008136ac600 x24: ffff0008136ac440
[   44.505134] x23: ffff000806285518 x22: 0000000000000001 x21: 0000000000000000
[   44.512485] x20: 000000000000016b x19: ffff00080c8e1000 x18: 0000000000000006
[   44.519835] x17: 0000000000000018 x16: ffffd80886bb74b4 x15: ffff80008688b4f0
[   44.527185] x14: 0000000000000000 x13: ffff008f3874c000 x12: 00000000000002fa
[   44.534536] x11: 00000000000008ee x10: ffff008f387fc000 x9 : ffff008f3874c000
[   44.541887] x8 : 3fffffffffffdfff x7 : ffff008f387fc000 x6 : bfffffffffffe000
[   44.549238] x5 : ffff008f3891a188 x4 : 0000000000000000 x3 : ffff2886b057d000
[   44.556589] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff00080bf1d000
[   44.563939] Call trace:
[   44.566485]  __enable_irq+0x4c/0x7c (P)
[   44.570454]  enable_irq+0x6c/0xd8
[   44.573879]  qcom_q6v5_prepare+0xb8/0x118 [qcom_q6v5]
[   44.579087]  qcom_pas_start+0x30/0x418 [qcom_q6v5_pas]
[   44.584392]  rproc_start+0x88/0x1b8
[   44.588004]  rproc_boot+0x194/0x3b4
[   44.591613]  state_store+0x40/0x104
[   44.595220]  dev_attr_store+0x18/0x2c
[   44.599006]  sysfs_kf_write+0x7c/0x94
[   44.602792]  kernfs_fop_write_iter+0x130/0x1dc
[   44.607379]  vfs_write+0x240/0x370
[   44.610906]  ksys_write+0x70/0x108
[   44.614430]  __arm64_sys_write+0x1c/0x28
[   44.618486]  invoke_syscall+0x54/0x10c
[   44.622370]  el0_svc_common.constprop.0+0x40/0xe0
[   44.627228]  do_el0_svc+0x1c/0x28
[   44.630655]  el0_svc+0x38/0x1d0
[   44.633908]  el0t_64_sync_handler+0xa0/0xe4
[   44.638233]  el0t_64_sync+0x198/0x19c
[   44.642025] ---[ end trace 0000000000000000 ]---
[   44.708474] remoteproc remoteproc0: remote processor adsp is now up

Shawn

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] remoteproc: qcom: q6v5: Make handover IRQ one-shot
  2026-07-31  1:35 ` Shawn Guo
@ 2026-07-31  6:34   ` Shawn Guo
  0 siblings, 0 replies; 4+ messages in thread
From: Shawn Guo @ 2026-07-31  6:34 UTC (permalink / raw)
  To: Abel Vesa
  Cc: Bjorn Andersson, Mathieu Poirier, Stephan Gerhold, linux-arm-msm,
	linux-remoteproc, linux-kernel

On Fri, Jul 31, 2026 at 09:35:47AM +0800, Shawn Guo wrote:
> On Fri, Jun 12, 2026 at 02:09:08PM +0300, Abel Vesa wrote:
> > The handover interrupt is expected to be consumed once during each prepare
> > cycle. If the remote processor keeps signalling handover after the first
> > event, qcom_q6v5 currently logs the duplicate interrupt repeatedly while
> > leaving the IRQ enabled.
> > 
> > Track the handover IRQ enable state explicitly and route all handover IRQ
> > enable/disable operations through idempotent helpers. Request the handover
> > IRQ with IRQF_NO_AUTOEN so it is only enabled through the helper during
> > prepare. The handover handler disables it after marking handover as issued,
> > while unprepare disables and synchronizes it before checking whether
> > handover was issued.
> > 
> > Signed-off-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
> > ---
> >  drivers/remoteproc/qcom_q6v5.c | 54 ++++++++++++++++++++++++++++++++++--------
> >  drivers/remoteproc/qcom_q6v5.h |  4 ++++
> >  2 files changed, 48 insertions(+), 10 deletions(-)
> 
> I seem to see a "regression" on Nord ADSP (probed as attached) with this change.

I proposed the fixes here:

https://lore.kernel.org/all/20260731025655.2642860-1-shengchao.guo@oss.qualcomm.com/

Shawn

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-07-31  6:34 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-12 11:09 [PATCH] remoteproc: qcom: q6v5: Make handover IRQ one-shot Abel Vesa
2026-07-10 18:06 ` Bjorn Andersson
2026-07-31  1:35 ` Shawn Guo
2026-07-31  6:34   ` Shawn Guo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®