diff options
author | Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> | 2020-01-13 23:56:37 +0100 |
---|---|---|
committer | Vinod Koul <vkoul@kernel.org> | 2020-01-14 07:35:52 +0100 |
commit | fd6a3ac8e87cedd83d6aad4bbc2682a903fb5d01 (patch) | |
tree | e1aeff28f9a2e152fed22f187dbbf99bae740ffe /drivers/soundwire | |
parent | soundwire: cadence: remove useless variable incrementation (diff) | |
download | linux-fd6a3ac8e87cedd83d6aad4bbc2682a903fb5d01.tar.xz linux-fd6a3ac8e87cedd83d6aad4bbc2682a903fb5d01.zip |
soundwire: bus: fix device number leak on errors
If the programming of the dev_number fails due to an IO error, a new
device_number will be assigned, resulting in a leak.
Make sure we only assign a device_number once per Slave device.
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20200113225637.17313-1-pierre-louis.bossart@linux.intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Diffstat (limited to 'drivers/soundwire')
-rw-r--r-- | drivers/soundwire/bus.c | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 66fd09e36b73..6106577fb3ed 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -456,26 +456,35 @@ err: static int sdw_assign_device_num(struct sdw_slave *slave) { int ret, dev_num; + bool new_device = false; /* check first if device number is assigned, if so reuse that */ if (!slave->dev_num) { - mutex_lock(&slave->bus->bus_lock); - dev_num = sdw_get_device_num(slave); - mutex_unlock(&slave->bus->bus_lock); - if (dev_num < 0) { - dev_err(slave->bus->dev, "Get dev_num failed: %d\n", - dev_num); - return dev_num; + if (!slave->dev_num_sticky) { + mutex_lock(&slave->bus->bus_lock); + dev_num = sdw_get_device_num(slave); + mutex_unlock(&slave->bus->bus_lock); + if (dev_num < 0) { + dev_err(slave->bus->dev, "Get dev_num failed: %d\n", + dev_num); + return dev_num; + } + slave->dev_num = dev_num; + slave->dev_num_sticky = dev_num; + new_device = true; + } else { + slave->dev_num = slave->dev_num_sticky; } - } else { + } + + if (!new_device) dev_info(slave->bus->dev, - "Slave already registered dev_num:%d\n", + "Slave already registered, reusing dev_num:%d\n", slave->dev_num); - /* Clear the slave->dev_num to transfer message on device 0 */ - dev_num = slave->dev_num; - slave->dev_num = 0; - } + /* Clear the slave->dev_num to transfer message on device 0 */ + dev_num = slave->dev_num; + slave->dev_num = 0; ret = sdw_write(slave, SDW_SCP_DEVNUMBER, dev_num); if (ret < 0) { @@ -485,7 +494,7 @@ static int sdw_assign_device_num(struct sdw_slave *slave) } /* After xfer of msg, restore dev_num */ - slave->dev_num = dev_num; + slave->dev_num = slave->dev_num_sticky; return 0; } |