From: "Baek Kyu, Kim" <pocj8ur4in@gmail.com>
To: Vinod Koul <vkoul@kernel.org>,
Bard Liao <yung-chuan.liao@linux.intel.com>
Cc: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>,
Srinivas Kandagatla <srini@kernel.org>,
linux-sound@vger.kernel.org, linux-arm-msm@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH 1/2] soundwire: stream: roll back failed master registration
Date: Tue, 20 Oct 2026 02:02:02 +0900 [thread overview]
Message-ID: <20261019170203.2533974-2-pocj8ur4in@gmail.com> (raw)
In-Reply-To: <20261019170203.2533974-1-pocj8ur4in@gmail.com>
When slaves have already created a master runtime, a failed master port
allocation leaves earlier allocations on its port list. If the second of
two port allocations fails, a retry sees a nonempty list and succeeds with
only one port and without incrementing m_rt_count.
Allocate master ports on a temporary list and publish them only after all
allocations succeed. On configuration failure, release ports allocated by
this call, balance m_rt_count, and restore the previous channel count and
direction. Preserve an existing slave-first runtime and its slaves, while
freeing a runtime created by the failed call. This lets a retry register
the complete set of ports instead of reusing a partial registration.
Fixes: ac3bc88cc56e ("soundwire: stream: separate alloc and config within sdw_stream_add_xxx()")
Fixes: f3016b891c8c ("soundwire: stream: sdw_stream_add_ functions can be called multiple times")
Signed-off-by: Baek Kyu, Kim <pocj8ur4in@gmail.com>
---
Tested with ARM64 QEMU KUnit using the real SoundWire registration APIs
and synthetic slave capabilities. Register a slave with two ports, fail
the second master port allocation, then disable fault injection and retry.
Before the fix the retry succeeds with one port and m_rt_count == 0;
afterwards it succeeds with two ports and m_rt_count == 1. Configuration
failure and existing/new runtime cases were also checked with KASAN and
lockdep enabled. No physical SoundWire hardware was tested.
drivers/soundwire/stream.c | 35 +++++++++++++++++++++++++++++------
1 file changed, 29 insertions(+), 6 deletions(-)
diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c
index f106a877d7b2..8e94dcaf3784 100644
--- a/drivers/soundwire/stream.c
+++ b/drivers/soundwire/stream.c
@@ -1107,17 +1107,24 @@ static void sdw_master_port_free(struct sdw_master_runtime *m_rt)
static int sdw_master_port_alloc(struct sdw_master_runtime *m_rt,
unsigned int num_ports)
{
- struct sdw_port_runtime *p_rt;
+ struct sdw_port_runtime *p_rt, *tmp;
+ LIST_HEAD(port_list);
int i;
- /* Iterate for number of ports to perform initialization */
+ /* Publish the ports only after the entire allocation succeeds. */
for (i = 0; i < num_ports; i++) {
- p_rt = sdw_port_alloc(&m_rt->port_list);
+ p_rt = sdw_port_alloc(&port_list);
if (!p_rt)
- return -ENOMEM;
+ goto free_ports;
}
+ list_splice_tail_init(&port_list, &m_rt->port_list);
return 0;
+
+free_ports:
+ list_for_each_entry_safe(p_rt, tmp, &port_list, port_node)
+ sdw_port_free(p_rt);
+ return -ENOMEM;
}
static int sdw_master_port_config(struct sdw_master_runtime *m_rt,
@@ -2017,6 +2024,9 @@ int sdw_stream_add_master(struct sdw_bus *bus,
{
struct sdw_master_runtime *m_rt;
bool alloc_master_rt = false;
+ bool alloc_master_ports = false;
+ unsigned int old_ch_count;
+ enum sdw_data_direction old_direction;
int ret;
mutex_lock(&bus->bus_lock);
@@ -2056,26 +2066,39 @@ int sdw_stream_add_master(struct sdw_bus *bus,
alloc_master_rt = true;
}
+ old_ch_count = m_rt->ch_count;
+ old_direction = m_rt->direction;
+
if (!sdw_master_port_allocated(m_rt)) {
ret = sdw_master_port_alloc(m_rt, num_ports);
if (ret)
goto alloc_error;
stream->m_rt_count++;
+ alloc_master_ports = true;
}
ret = sdw_master_rt_config(m_rt, stream_config);
if (ret < 0)
- goto unlock;
+ goto config_error;
ret = sdw_config_stream(bus->dev, stream, stream_config, false);
if (ret)
- goto unlock;
+ goto config_error;
ret = sdw_master_port_config(m_rt, port_config);
+ if (ret)
+ goto config_error;
goto unlock;
+config_error:
+ m_rt->ch_count = old_ch_count;
+ m_rt->direction = old_direction;
+ if (alloc_master_ports) {
+ sdw_master_port_free(m_rt);
+ stream->m_rt_count--;
+ }
alloc_error:
/*
* we only cleanup what was allocated in this routine
next prev parent reply other threads:[~2026-10-19 17:02 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-19 17:02 [PATCH 0/2] soundwire: " Baek Kyu, Kim
2026-10-19 17:02 ` Baek Kyu, Kim [this message]
2026-10-19 17:02 ` [PATCH 2/2] soundwire: qcom: restore port reservations on registration failure Baek Kyu, Kim
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=20261019170203.2533974-2-pocj8ur4in@gmail.com \
--to=pocj8ur4in@gmail.com \
--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®