diff options
Diffstat (limited to 'drivers/soundwire')
-rw-r--r-- | drivers/soundwire/stream.c | 80 |
1 files changed, 48 insertions, 32 deletions
diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index 512e7936d57c..03cfac0129af 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -1811,6 +1811,7 @@ int sdw_stream_add_master(struct sdw_bus *bus, struct sdw_stream_runtime *stream) { struct sdw_master_runtime *m_rt; + bool alloc_master_rt = true; int ret; mutex_lock(&bus->bus_lock); @@ -1832,8 +1833,10 @@ int sdw_stream_add_master(struct sdw_bus *bus, * it first), if so skip allocation and go to configuration */ m_rt = sdw_master_rt_find(bus, stream); - if (m_rt) + if (m_rt) { + alloc_master_rt = false; goto skip_alloc_master_rt; + } m_rt = sdw_master_rt_alloc(bus, stream); if (!m_rt) { @@ -1841,30 +1844,32 @@ int sdw_stream_add_master(struct sdw_bus *bus, ret = -ENOMEM; goto unlock; } +skip_alloc_master_rt: + + ret = sdw_master_port_alloc(m_rt, num_ports); + if (ret) + goto alloc_error; + + stream->m_rt_count++; ret = sdw_master_rt_config(m_rt, stream_config); if (ret < 0) goto unlock; -skip_alloc_master_rt: ret = sdw_config_stream(bus->dev, stream, stream_config, false); if (ret) - goto stream_error; - - ret = sdw_master_port_alloc(m_rt, num_ports); - if (ret) - goto stream_error; + goto unlock; ret = sdw_master_port_config(m_rt, port_config); - if (ret) - goto stream_error; - - stream->m_rt_count++; goto unlock; -stream_error: - sdw_master_rt_free(m_rt, stream); +alloc_error: + /* + * we only cleanup what was allocated in this routine + */ + if (alloc_master_rt) + sdw_master_rt_free(m_rt, stream); unlock: mutex_unlock(&bus->bus_lock); return ret; @@ -1926,6 +1931,9 @@ int sdw_stream_add_slave(struct sdw_slave *slave, { struct sdw_slave_runtime *s_rt; struct sdw_master_runtime *m_rt; + bool alloc_master_rt = true; + bool alloc_slave_rt = true; + int ret; mutex_lock(&slave->bus->bus_lock); @@ -1935,8 +1943,10 @@ int sdw_stream_add_slave(struct sdw_slave *slave, * and go to configuration */ m_rt = sdw_master_rt_find(slave->bus, stream); - if (m_rt) + if (m_rt) { + alloc_master_rt = false; goto skip_alloc_master_rt; + } /* * If this API is invoked by Slave first then m_rt is not valid. @@ -1946,35 +1956,37 @@ int sdw_stream_add_slave(struct sdw_slave *slave, if (!m_rt) { dev_err(&slave->dev, "Master runtime alloc failed for stream:%s\n", stream->name); ret = -ENOMEM; - goto error; + goto unlock; } - ret = sdw_master_rt_config(m_rt, stream_config); - if (ret < 0) - goto stream_error; skip_alloc_master_rt: s_rt = sdw_slave_rt_alloc(slave, m_rt); if (!s_rt) { dev_err(&slave->dev, "Slave runtime alloc failed for stream:%s\n", stream->name); + alloc_slave_rt = false; ret = -ENOMEM; - goto stream_error; + goto alloc_error; } - ret = sdw_slave_rt_config(s_rt, stream_config); + ret = sdw_slave_port_alloc(slave, s_rt, num_ports); if (ret) - goto stream_error; + goto alloc_error; - ret = sdw_config_stream(&slave->dev, stream, stream_config, true); + ret = sdw_master_rt_config(m_rt, stream_config); if (ret) - goto stream_error; + goto unlock; - ret = sdw_slave_port_alloc(slave, s_rt, num_ports); + ret = sdw_slave_rt_config(s_rt, stream_config); if (ret) - goto stream_error; + goto unlock; + + ret = sdw_config_stream(&slave->dev, stream, stream_config, true); + if (ret) + goto unlock; ret = sdw_slave_port_config(slave, s_rt, port_config); if (ret) - goto stream_error; + goto unlock; /* * Change stream state to CONFIGURED on first Slave add. @@ -1983,15 +1995,19 @@ skip_alloc_master_rt: * change stream state to CONFIGURED. */ stream->state = SDW_STREAM_CONFIGURED; - goto error; + goto unlock; -stream_error: +alloc_error: /* - * we hit error so cleanup the stream, release all Slave(s) and - * Master runtime + * we only cleanup what was allocated in this routine. The 'else if' + * is intentional, the 'master_rt_free' will call sdw_slave_rt_free() + * internally. */ - sdw_master_rt_free(m_rt, stream); -error: + if (alloc_master_rt) + sdw_master_rt_free(m_rt, stream); + else if (alloc_slave_rt) + sdw_slave_rt_free(slave, stream); +unlock: mutex_unlock(&slave->bus->bus_lock); return ret; } |