[PATCH v2 3/5] soundwire: Select the correct runtime for lane allocation

From: Bard Liao

Date: Thu Nov 12 2026 - 02:33:41 EST


When multiple master runtimes exist on the same bus,
sdw_compute_bus_params() selects the first runtime for which an
additional lane is available. This can select an already running stream
instead of the stream being prepared.

Changing that runtime's port lanes accounts for its bandwidth again.
If preparing the new stream fails, restoring the bus parameters leaves
the active stream's lanes inconsistent with its bandwidth reservation.
Depreparing the active stream can then underflow the lane bandwidth and
leave lane 0 bandwidth reserved.

Pass the current stream and prepare context to sdw_compute_bus_params()
and restrict lane allocation to that stream's runtime during prepare.
Skip lane allocation during deprepare, when its bandwidth reservation
has already been released. Keep clock recomputation and the existing
group and port filtering unchanged.

Signed-off-by: Bard Liao <yung-chuan.liao@xxxxxxxxxxxxxxx>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@xxxxxxxxxxxxxxx>
---
.../soundwire/generic_bandwidth_allocation.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/soundwire/generic_bandwidth_allocation.c b/drivers/soundwire/generic_bandwidth_allocation.c
index 1250fe21a3ff..e8e68dbe180b 100644
--- a/drivers/soundwire/generic_bandwidth_allocation.c
+++ b/drivers/soundwire/generic_bandwidth_allocation.c
@@ -536,8 +536,11 @@ static int get_manager_lane(struct sdw_bus *bus, struct sdw_master_runtime *m_rt
* sdw_compute_bus_params: Compute bus parameters
*
* @bus: SDW Bus instance
+ * @stream: SoundWire stream being prepared or deprepared
+ * @prepare: True when preparing, false when depreparing
*/
-static int sdw_compute_bus_params(struct sdw_bus *bus)
+static int sdw_compute_bus_params(struct sdw_bus *bus,
+ struct sdw_stream_runtime *stream, bool prepare)
{
struct sdw_master_prop *mstr_prop = &bus->prop;
struct sdw_slave_prop *slave_prop;
@@ -580,6 +583,14 @@ static int sdw_compute_bus_params(struct sdw_bus *bus)
break;

list_for_each_entry(m_rt, &bus->m_rt_list, bus_node) {
+ /*
+ * Select only the current stream's runtime. Check prepare
+ * to avoid computing m_lane during deprepare, when the
+ * stream's bandwidth reservation has already been released.
+ */
+ if (m_rt->stream != stream || !prepare)
+ continue;
+
/*
* Get the first s_rt that will be used to find the available lane that
* can be used. No need to check all Peripherals because we can't use
@@ -627,8 +638,8 @@ static int sdw_compute_bus_params(struct sdw_bus *bus)
}
}
/*
- * Set Manager lanes. Configure the last m_rt in bus->m_rt_list only since
- * we don't want to touch other m_rts that are already working.
+ * Set Manager lanes for the stream being prepared without changing
+ * other runtimes that are already working.
*/
list_for_each_entry(m_p_rt, &m_rt->port_list, port_node) {
m_p_rt->lane = m_lane;
@@ -665,7 +676,7 @@ int sdw_compute_params(struct sdw_bus *bus, struct sdw_stream_runtime *stream,
int ret;

/* Computes clock frequency, frame shape and frame frequency */
- ret = sdw_compute_bus_params(bus);
+ ret = sdw_compute_bus_params(bus, stream, prepare);
if (ret < 0)
return ret;

--
2.43.0