From: Lee Jones <lee@kernel.org>
To: lee@kernel.org, Srinivas Kandagatla <srini@kernel.org>,
Vinod Koul <vkoul@kernel.org>,
Bard Liao <yung-chuan.liao@linux.intel.com>,
Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>,
linux-arm-msm@vger.kernel.org, linux-sound@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH v2 09/10] soundwire: qcom: Serialise ctrl->intr_mask updates
Date: Tue, 3 Nov 2026 09:53:53 +0000 [thread overview]
Message-ID: <20261103095445.81414-10-lee@kernel.org> (raw)
In-Reply-To: <20261103095445.81414-1-lee@kernel.org>
qcom_swrm_irq_handler(), swrm_runtime_suspend(), and
swrm_runtime_resume() concurrently read, modify, and write
ctrl->intr_mask and program the interrupt enable registers without
synchronisation. Overlapping read-modify-write updates can clobber
interrupt mask bits and leave the hardware interrupt mask out of sync.
Add ctrl->intr_lock to serialise accesses to ctrl->intr_mask and its
associated interrupt mask register updates.
Closes: https://sashiko.dev/#/bug/linux-ea523727-6467-42aa-850f-8f838e4b84a8
Signed-off-by: Lee Jones <lee@kernel.org>
---
v1 => v2: Drop Fixes and Stable tags
drivers/soundwire/qcom.c | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
index 785096b232f2..cc1b07e2406d 100644
--- a/drivers/soundwire/qcom.c
+++ b/drivers/soundwire/qcom.c
@@ -202,6 +202,8 @@ struct qcom_swrm_ctrl {
struct completion enumeration;
/* Port alloc/free lock */
struct mutex port_lock;
+ /* Interrupt mask and broadcast completion lock */
+ struct mutex intr_lock;
struct clk *hclk;
int irq;
u32 ee;
@@ -784,7 +786,9 @@ static irqreturn_t qcom_swrm_irq_handler(int irq, void *dev_id)
ctrl->reg_read(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_STATUS],
&intr_sts);
+ mutex_lock(&ctrl->intr_lock);
intr_sts_masked = intr_sts & ctrl->intr_mask;
+ mutex_unlock(&ctrl->intr_lock);
do {
for (i = 0; i < SWRM_INTERRUPT_MAX; i++) {
@@ -820,10 +824,12 @@ static irqreturn_t qcom_swrm_irq_handler(int irq, void *dev_id)
dev_err_ratelimited(ctrl->dev,
"%s: SWR bus clsh detected\n",
__func__);
+ mutex_lock(&ctrl->intr_lock);
ctrl->intr_mask &= ~SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET;
ctrl->reg_write(ctrl,
ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN],
ctrl->intr_mask);
+ mutex_unlock(&ctrl->intr_lock);
break;
case SWRM_INTERRUPT_STATUS_RD_FIFO_OVERFLOW:
ctrl->reg_read(ctrl,
@@ -863,20 +869,24 @@ static irqreturn_t qcom_swrm_irq_handler(int irq, void *dev_id)
dev_err_ratelimited(ctrl->dev,
"%s: SWR Port collision detected\n",
__func__);
+ mutex_lock(&ctrl->intr_lock);
ctrl->intr_mask &= ~SWRM_INTERRUPT_STATUS_DOUT_PORT_COLLISION;
ctrl->reg_write(ctrl,
ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN],
ctrl->intr_mask);
+ mutex_unlock(&ctrl->intr_lock);
break;
case SWRM_INTERRUPT_STATUS_READ_EN_RD_VALID_MISMATCH:
dev_err_ratelimited(ctrl->dev,
"%s: SWR read enable valid mismatch\n",
__func__);
+ mutex_lock(&ctrl->intr_lock);
ctrl->intr_mask &=
~SWRM_INTERRUPT_STATUS_READ_EN_RD_VALID_MISMATCH;
ctrl->reg_write(ctrl,
ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN],
ctrl->intr_mask);
+ mutex_unlock(&ctrl->intr_lock);
break;
case SWRM_INTERRUPT_STATUS_SPECIAL_CMD_ID_FINISHED:
complete(&ctrl->broadcast);
@@ -910,7 +920,9 @@ static irqreturn_t qcom_swrm_irq_handler(int irq, void *dev_id)
intr_sts);
ctrl->reg_read(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_STATUS],
&intr_sts);
+ mutex_lock(&ctrl->intr_lock);
intr_sts_masked = intr_sts & ctrl->intr_mask;
+ mutex_unlock(&ctrl->intr_lock);
} while (intr_sts_masked);
clk_disable_unprepare(ctrl->hclk);
@@ -952,11 +964,13 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
/* Enable Auto enumeration */
ctrl->reg_write(ctrl, SWRM_ENUMERATOR_CFG_ADDR, 1);
+ mutex_lock(&ctrl->intr_lock);
ctrl->intr_mask = SWRM_INTERRUPT_STATUS_RMSK;
/* Mask soundwire interrupts */
if (ctrl->version < SWRM_VERSION_2_0_0)
ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_MASK_ADDR],
- SWRM_INTERRUPT_STATUS_RMSK);
+ ctrl->intr_mask);
+ mutex_unlock(&ctrl->intr_lock);
/* Configure No pings */
ctrl->reg_read(ctrl, SWRM_MCP_CFG_ADDR, &val);
@@ -997,8 +1011,10 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
0xFFFFFFFF);
/* enable CPU IRQs for the selected EE window */
+ mutex_lock(&ctrl->intr_lock);
ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN],
- SWRM_INTERRUPT_STATUS_RMSK);
+ ctrl->intr_mask);
+ mutex_unlock(&ctrl->intr_lock);
/* Set IRQ to PULSE */
ctrl->reg_write(ctrl, SWRM_COMP_CFG_ADDR,
@@ -1686,6 +1702,7 @@ static int qcom_swrm_probe(struct platform_device *pdev)
ctrl->dev = dev;
dev_set_drvdata(&pdev->dev, ctrl);
mutex_init(&ctrl->port_lock);
+ mutex_init(&ctrl->intr_lock);
init_completion(&ctrl->broadcast);
init_completion(&ctrl->enumeration);
@@ -1851,6 +1868,7 @@ static int __maybe_unused swrm_runtime_resume(struct device *dev)
ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CLEAR],
SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET);
+ mutex_lock(&ctrl->intr_lock);
ctrl->intr_mask |= SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET;
if (ctrl->version < SWRM_VERSION_2_0_0)
ctrl->reg_write(ctrl,
@@ -1858,6 +1876,7 @@ static int __maybe_unused swrm_runtime_resume(struct device *dev)
ctrl->intr_mask);
ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN],
ctrl->intr_mask);
+ mutex_unlock(&ctrl->intr_lock);
usleep_range(100, 105);
if (!swrm_wait_for_frame_gen_enabled(ctrl))
@@ -1879,6 +1898,7 @@ static int __maybe_unused swrm_runtime_suspend(struct device *dev)
swrm_wait_for_wr_fifo_done(ctrl);
if (!ctrl->clock_stop_not_supported) {
/* Mask bus clash interrupt */
+ mutex_lock(&ctrl->intr_lock);
ctrl->intr_mask &= ~SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET;
if (ctrl->version < SWRM_VERSION_2_0_0)
ctrl->reg_write(ctrl,
@@ -1886,6 +1906,7 @@ static int __maybe_unused swrm_runtime_suspend(struct device *dev)
ctrl->intr_mask);
ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN],
ctrl->intr_mask);
+ mutex_unlock(&ctrl->intr_lock);
/* Prepare slaves for clock stop */
ret = sdw_bus_prep_clk_stop(&ctrl->bus);
if (ret < 0 && ret != -ENODATA) {
--
2.56.0.385.gac671c819a-goog
next prev parent reply other threads:[~2026-11-03 9:55 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-03 9:53 [PATCH v2 00/10] soundwire: Fix Critical and High issues reported by Sashiko Lee Jones
2026-11-03 9:53 ` [PATCH v2 01/10] soundwire: bus: Hold bus_lock when looking up slave devices Lee Jones
2026-11-03 9:53 ` [PATCH v2 02/10] soundwire: sysfs: Use sysfs_emit_at() in array show callbacks Lee Jones
2026-11-03 9:53 ` [PATCH v2 03/10] soundwire: stream: Prevent m_rt_count underflow in sdw_stream_remove_master() Lee Jones
2026-11-03 9:53 ` [PATCH v2 04/10] soundwire: stream: Clean up allocated runtime resources on config failure Lee Jones
2026-11-03 9:53 ` [PATCH v2 05/10] soundwire: intel_ace2x: Protect bus.bpt_stream with bus_lock Lee Jones
2026-11-03 9:53 ` [PATCH v2 06/10] soundwire: qcom: Prevent pconfig buffer overflow in qcom_swrm_stream_alloc_ports() Lee Jones
2026-11-03 9:53 ` [PATCH v2 07/10] soundwire: qcom: Disable runtime PM and avoid clock underflow in qcom_swrm_remove() Lee Jones
2026-11-03 9:53 ` [PATCH v2 08/10] soundwire: qcom: Check clk_prepare_enable() return value Lee Jones
2026-11-03 9:53 ` Lee Jones [this message]
2026-11-03 9:53 ` [PATCH v2 10/10] soundwire: qcom: Prevent stale broadcast IRQ from completing subsequent command Lee Jones
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261103095445.81414-10-lee@kernel.org \
--to=lee@kernel.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=pierre-louis.bossart@linux.dev \
--cc=srini@kernel.org \
--cc=vkoul@kernel.org \
--cc=yung-chuan.liao@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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®