@@ -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_port_alloc(slave, s_rt, num_ports);
+ if (ret)
+ goto alloc_error;
+
+ ret = sdw_master_rt_config(m_rt, stream_config);
+ if (ret)
+ goto unlock;
+
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 stream_error;
-
- ret = sdw_slave_port_alloc(slave, s_rt, num_ports);
- if (ret)
- goto stream_error;
+ 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 @@ int sdw_stream_add_slave(struct sdw_slave *slave,
* 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;
}
@@ -2018,4 +2034,3 @@ int sdw_stream_remove_slave(struct sdw_slave *slave,
return 0;
}
EXPORT_SYMBOL(sdw_stream_remove_slave);
-