diff --git a/drivers/soundwire/bus.h b/drivers/soundwire/bus.h index 44e4f51939176f..476387b704723f 100644 --- a/drivers/soundwire/bus.h +++ b/drivers/soundwire/bus.h @@ -155,6 +155,8 @@ struct sdw_slave_runtime { * * @bus: Bus handle * @stream: Stream runtime handle + * @params_backup: Snapshot of original bus parameters saved before stream + * preparation, used for rollback recovery on failure. * @direction: Data direction for Master * @ch_count: Number of channels handled by the Master for * this stream, can be zero. @@ -166,6 +168,7 @@ struct sdw_slave_runtime { struct sdw_master_runtime { struct sdw_bus *bus; struct sdw_stream_runtime *stream; + struct sdw_bus_params params_backup; enum sdw_data_direction direction; unsigned int ch_count; struct list_head slave_rt_list; diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index b4f68356708fe4..bee5a6ffeebff5 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -1487,14 +1487,15 @@ static int _sdw_prepare_stream(struct sdw_stream_runtime *stream, struct sdw_master_runtime *m_rt; struct sdw_bus *bus; struct sdw_master_prop *prop; - struct sdw_bus_params params; int ret; /* Prepare Master(s) and Slave(s) port(s) associated with stream */ list_for_each_entry(m_rt, &stream->master_list, stream_node) { bus = m_rt->bus; prop = &bus->prop; - memcpy(¶ms, &bus->params, sizeof(params)); + + /* Snapshot the original params before making any changes */ + m_rt->params_backup = bus->params; /* TODO: Support Asynchronous mode */ if ((prop->max_clk_freq % stream->params.rate) != 0) { @@ -1550,7 +1551,13 @@ static int _sdw_prepare_stream(struct sdw_stream_runtime *stream, return ret; restore_params: - memcpy(&bus->params, ¶ms, sizeof(params)); + /* + * Revert all masters to their snapshotted original parameters. + * Any master that was not modified will safely revert to its own original state. + */ + list_for_each_entry(m_rt, &stream->master_list, stream_node) { + m_rt->bus->params = m_rt->params_backup; + } return ret; }