Skip to content

Commit aab1202

Browse files
charleskeepaxvinodkoul
authored andcommitted
soundwire: bus: Add internal slave ID and use for IRQs
Currently the SoundWire IRQ code uses the dev_num to create an IRQ mapping for each slave. However, there is an issue there, the dev_num is only allocated when the slave enumerates on the bus and enumeration may happen before or after probe of the slave driver. In the case enumeration happens after probe of the slave driver then the IRQ mapping will use dev_num before it is set. This could cause multiple slaves to use zero as their IRQ mapping. It is very desirable to have the IRQ mapped before the slave probe is called, so drivers can do resource allocation in probe as normal. To solve these issues add an internal ID created for each slave when it is probed and use that for mapping the IRQ. Signed-off-by: Charles Keepax <[email protected]> Reviewed-by: Pierre-Louis Bossart <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent 5b1a292 commit aab1202

File tree

4 files changed

+21
-3
lines changed

4 files changed

+21
-3
lines changed

drivers/soundwire/bus.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent,
5656
return ret;
5757
}
5858

59+
ida_init(&bus->slave_ida);
60+
5961
ret = sdw_master_device_add(bus, parent, fwnode);
6062
if (ret < 0) {
6163
dev_err(parent, "Failed to add master device at link %d\n",

drivers/soundwire/bus_type.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,17 @@ static int sdw_drv_probe(struct device *dev)
105105
if (ret)
106106
return ret;
107107

108+
ret = ida_alloc_max(&slave->bus->slave_ida, SDW_FW_MAX_DEVICES, GFP_KERNEL);
109+
if (ret < 0) {
110+
dev_err(dev, "Failed to allocated ID: %d\n", ret);
111+
return ret;
112+
}
113+
slave->index = ret;
114+
108115
ret = drv->probe(slave, id);
109116
if (ret) {
110117
dev_pm_domain_detach(dev, false);
118+
ida_free(&slave->bus->slave_ida, slave->index);
111119
return ret;
112120
}
113121

@@ -174,6 +182,8 @@ static int sdw_drv_remove(struct device *dev)
174182

175183
dev_pm_domain_detach(dev, false);
176184

185+
ida_free(&slave->bus->slave_ida, slave->index);
186+
177187
return ret;
178188
}
179189

drivers/soundwire/irq.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ int sdw_irq_create(struct sdw_bus *bus,
3131
{
3232
bus->irq_chip.name = dev_name(bus->dev);
3333

34-
bus->domain = irq_domain_create_linear(fwnode, SDW_MAX_DEVICES,
34+
bus->domain = irq_domain_create_linear(fwnode, SDW_FW_MAX_DEVICES,
3535
&sdw_domain_ops, bus);
3636
if (!bus->domain) {
3737
dev_err(bus->dev, "Failed to add IRQ domain\n");
@@ -50,12 +50,12 @@ static void sdw_irq_dispose_mapping(void *data)
5050
{
5151
struct sdw_slave *slave = data;
5252

53-
irq_dispose_mapping(irq_find_mapping(slave->bus->domain, slave->dev_num));
53+
irq_dispose_mapping(slave->irq);
5454
}
5555

5656
void sdw_irq_create_mapping(struct sdw_slave *slave)
5757
{
58-
slave->irq = irq_create_mapping(slave->bus->domain, slave->dev_num);
58+
slave->irq = irq_create_mapping(slave->bus->domain, slave->index);
5959
if (!slave->irq)
6060
dev_warn(&slave->dev, "Failed to map IRQ\n");
6161

include/linux/soundwire/sdw.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/bug.h>
99
#include <linux/completion.h>
1010
#include <linux/device.h>
11+
#include <linux/idr.h>
1112
#include <linux/irq.h>
1213
#include <linux/irqdomain.h>
1314
#include <linux/lockdep_types.h>
@@ -50,6 +51,7 @@ struct sdw_slave;
5051

5152
#define SDW_FRAME_CTRL_BITS 48
5253
#define SDW_MAX_DEVICES 11
54+
#define SDW_FW_MAX_DEVICES 16
5355

5456
#define SDW_MAX_PORTS 15
5557
#define SDW_VALID_PORT_RANGE(n) ((n) < SDW_MAX_PORTS && (n) >= 1)
@@ -630,6 +632,7 @@ struct sdw_slave_ops {
630632
* struct sdw_slave - SoundWire Slave
631633
* @id: MIPI device ID
632634
* @dev: Linux device
635+
* @index: internal ID for this slave
633636
* @irq: IRQ number
634637
* @status: Status reported by the Slave
635638
* @bus: Bus handle
@@ -661,6 +664,7 @@ struct sdw_slave_ops {
661664
struct sdw_slave {
662665
struct sdw_slave_id id;
663666
struct device dev;
667+
int index;
664668
int irq;
665669
enum sdw_slave_status status;
666670
struct sdw_bus *bus;
@@ -968,6 +972,7 @@ struct sdw_stream_runtime {
968972
* @md: Master device
969973
* @bus_lock_key: bus lock key associated to @bus_lock
970974
* @bus_lock: bus lock
975+
* @slave_ida: IDA for allocating internal slave IDs
971976
* @slaves: list of Slaves on this bus
972977
* @msg_lock_key: message lock key associated to @msg_lock
973978
* @msg_lock: message lock
@@ -1010,6 +1015,7 @@ struct sdw_bus {
10101015
struct sdw_master_device *md;
10111016
struct lock_class_key bus_lock_key;
10121017
struct mutex bus_lock;
1018+
struct ida slave_ida;
10131019
struct list_head slaves;
10141020
struct lock_class_key msg_lock_key;
10151021
struct mutex msg_lock;

0 commit comments

Comments
 (0)