Commit c6056101 authored by Pierre-Louis Bossart's avatar Pierre-Louis Bossart Committed by Vinod Koul
Browse files

soundwire: bus: allow device number to be unique at system level



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: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: default avatarRander Wang <rander.wang@intel.com>
Signed-off-by: default avatarBard 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: default avatarVinod Koul <vkoul@kernel.org>
parent 88de0a8f
Loading
Loading
Loading
Loading
+17 −6
Original line number Diff line number Diff line
@@ -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)
{
@@ -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);

@@ -638,11 +641,19 @@ static int sdw_get_device_num(struct sdw_slave *slave)
{
	int bit;

	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;
		}
	}

	/*
	 * Do not update dev_num in Slave data structure here,
+4 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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,