Skip to content

Commit

Permalink
soundwire: bus: allow device number to be unique at system level
Browse files Browse the repository at this point in the history
The SoundWire specification allows the device number to be allocated
at will. When a system includes multiple SoundWire links, the device
number scope is limited to the link to which the device is attached.

However, for integration/debug it can be convenient to have a unique
device number across the system. This patch adds a 'dev_num_ida_min'
field at the bus level, which when set will be used to allocate an
IDA.

The allocation happens when a hardware device reports as ATTACHED. If
any error happens during the enumeration, the allocated IDA is not
freed - the device number will be reused if/when the device re-joins
the bus. The IDA is only freed when the Linux device is unregistered.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Rander Wang <rander.wang@intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Link: https://lore.kernel.org/r/20220823045004.2670658-3-yung-chuan.liao@linux.intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
  • Loading branch information
Pierre-Louis Bossart authored and Vinod Koul committed Aug 30, 2022
1 parent 88de0a8 commit c605610
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
23 changes: 17 additions & 6 deletions drivers/soundwire/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "sysfs_local.h"

static DEFINE_IDA(sdw_bus_ida);
static DEFINE_IDA(sdw_peripheral_ida);

static int sdw_get_id(struct sdw_bus *bus)
{
Expand Down Expand Up @@ -156,9 +157,11 @@ static int sdw_delete_slave(struct device *dev, void *data)

mutex_lock(&bus->bus_lock);

if (slave->dev_num) /* clear dev_num if assigned */
if (slave->dev_num) { /* clear dev_num if assigned */
clear_bit(slave->dev_num, bus->assigned);

if (bus->dev_num_ida_min)
ida_free(&sdw_peripheral_ida, slave->dev_num);
}
list_del_init(&slave->node);
mutex_unlock(&bus->bus_lock);

Expand Down Expand Up @@ -638,10 +641,18 @@ static int sdw_get_device_num(struct sdw_slave *slave)
{
int bit;

bit = find_first_zero_bit(slave->bus->assigned, SDW_MAX_DEVICES);
if (bit == SDW_MAX_DEVICES) {
bit = -ENODEV;
goto err;
if (slave->bus->dev_num_ida_min) {
bit = ida_alloc_range(&sdw_peripheral_ida,
slave->bus->dev_num_ida_min, SDW_MAX_DEVICES,
GFP_KERNEL);
if (bit < 0)
goto err;
} else {
bit = find_first_zero_bit(slave->bus->assigned, SDW_MAX_DEVICES);
if (bit == SDW_MAX_DEVICES) {
bit = -ENODEV;
goto err;
}
}

/*
Expand Down
4 changes: 4 additions & 0 deletions include/linux/soundwire/sdw.h
Original file line number Diff line number Diff line change
Expand Up @@ -889,6 +889,9 @@ struct sdw_master_ops {
* meaningful if multi_link is set. If set to 1, hardware-based
* synchronization will be used even if a stream only uses a single
* SoundWire segment.
* @dev_num_ida_min: if set, defines the minimum values for the IDA
* used to allocate system-unique device numbers. This value needs to be
* identical across all SoundWire bus in the system.
*/
struct sdw_bus {
struct device *dev;
Expand All @@ -913,6 +916,7 @@ struct sdw_bus {
u32 bank_switch_timeout;
bool multi_link;
int hw_sync_min_links;
int dev_num_ida_min;
};

int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent,
Expand Down

0 comments on commit c605610

Please sign in to comment.