diff options
author | Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> | 2020-08-31 21:43:18 +0800 |
---|---|---|
committer | Vinod Koul <vkoul@kernel.org> | 2020-09-03 16:02:29 +0530 |
commit | 6073755886a463a7a7aecdd0abb32a1d38bdb7e6 (patch) | |
tree | b432fa9a3a5c2e787a3c2831062c07843d1aedde | |
parent | 63642595a78da42f841fabcc3f309f4c1362dc40 (diff) |
soundwire: fix port_ready[] dynamic allocation in mipi_disco
The existing code allocates memory for the total number of ports.
This only works if the ports are contiguous, but will break if e.g. a
Devices uses port0, 1, and 14. The port_ready[] array would contain 3
elements, which would lead to an out-of-bounds access. Conversely in
other cases, the wrong port index would be used leading to timeouts on
prepare.
This can be fixed by allocating for the worst-case of 15
ports (DP0..DP14). In addition since the number is now fixed, we can
use an array instead of a dynamic allocation.
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Rander Wang <rander.wang@linux.intel.com>
Reviewed-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Link: https://lore.kernel.org/r/20200831134318.11443-4-yung-chuan.liao@linux.intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
-rw-r--r-- | drivers/soundwire/mipi_disco.c | 18 | ||||
-rw-r--r-- | drivers/soundwire/slave.c | 4 | ||||
-rw-r--r-- | include/linux/soundwire/sdw.h | 2 |
3 files changed, 6 insertions, 18 deletions
diff --git a/drivers/soundwire/mipi_disco.c b/drivers/soundwire/mipi_disco.c index 4ae62b452b8c..55a9c51c84c1 100644 --- a/drivers/soundwire/mipi_disco.c +++ b/drivers/soundwire/mipi_disco.c @@ -289,7 +289,7 @@ int sdw_slave_read_prop(struct sdw_slave *slave) struct sdw_slave_prop *prop = &slave->prop; struct device *dev = &slave->dev; struct fwnode_handle *port; - int num_of_ports, nval, i, dp0 = 0; + int nval; device_property_read_u32(dev, "mipi-sdw-sw-interface-revision", &prop->mipi_revision); @@ -352,7 +352,6 @@ int sdw_slave_read_prop(struct sdw_slave *slave) return -ENOMEM; sdw_slave_read_dp0(slave, port, prop->dp0_prop); - dp0 = 1; } /* @@ -383,21 +382,6 @@ int sdw_slave_read_prop(struct sdw_slave *slave) sdw_slave_read_dpn(slave, prop->sink_dpn_prop, nval, prop->sink_ports, "sink"); - /* some ports are bidirectional so check total ports by ORing */ - nval = prop->source_ports | prop->sink_ports; - num_of_ports = hweight32(nval) + dp0; /* add DP0 */ - - /* Allocate port_ready based on num_of_ports */ - slave->port_ready = devm_kcalloc(&slave->dev, num_of_ports, - sizeof(*slave->port_ready), - GFP_KERNEL); - if (!slave->port_ready) - return -ENOMEM; - - /* Initialize completion */ - for (i = 0; i < num_of_ports; i++) - init_completion(&slave->port_ready[i]); - return 0; } EXPORT_SYMBOL(sdw_slave_read_prop); diff --git a/drivers/soundwire/slave.c b/drivers/soundwire/slave.c index 0839445ee07b..a762ee24e6fa 100644 --- a/drivers/soundwire/slave.c +++ b/drivers/soundwire/slave.c @@ -25,6 +25,7 @@ static int sdw_slave_add(struct sdw_bus *bus, { struct sdw_slave *slave; int ret; + int i; slave = kzalloc(sizeof(*slave), GFP_KERNEL); if (!slave) @@ -58,6 +59,9 @@ static int sdw_slave_add(struct sdw_bus *bus, init_completion(&slave->probe_complete); slave->probed = false; + for (i = 0; i < SDW_MAX_PORTS; i++) + init_completion(&slave->port_ready[i]); + mutex_lock(&bus->bus_lock); list_add_tail(&slave->node, &bus->slaves); mutex_unlock(&bus->bus_lock); diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 0aa4c6af7554..63e71645fd13 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -619,7 +619,7 @@ struct sdw_slave { struct dentry *debugfs; #endif struct list_head node; - struct completion *port_ready; + struct completion port_ready[SDW_MAX_PORTS]; enum sdw_clk_stop_mode curr_clk_stop_mode; u16 dev_num; u16 dev_num_sticky; |