Skip to content

Commit 9b61e30

Browse files
sunielmaheshbroonie
authored andcommitted
spi: Pick spi bus number from Linux idr or spi alias
Modify existing code, for automatically picking the spi bus number based on Linux idr scheme as mentioned in FIXME. This patch does the following: (a) Remove the now unnecessary code which was allocating bus numbers using ATOMIC_INIT and atomic_dec_return macros. (b) If we have an alias, pick the bus number from alias ID (c) Convert to linux idr interface Signed-off-by: Suniel Mahesh <[email protected]> Signed-off-by: Karthik Tummala <[email protected]> Tested-by: Karthik Tummala <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent e0bcb68 commit 9b61e30

File tree

1 file changed

+56
-15
lines changed

1 file changed

+56
-15
lines changed

drivers/spi/spi.c

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,13 @@
4040
#include <linux/ioport.h>
4141
#include <linux/acpi.h>
4242
#include <linux/highmem.h>
43+
#include <linux/idr.h>
4344

4445
#define CREATE_TRACE_POINTS
4546
#include <trace/events/spi.h>
47+
#define SPI_DYN_FIRST_BUS_NUM 0
48+
49+
static DEFINE_IDR(spi_master_idr);
4650

4751
static void spidev_release(struct device *dev)
4852
{
@@ -420,6 +424,7 @@ static LIST_HEAD(spi_controller_list);
420424
/*
421425
* Used to protect add/del opertion for board_info list and
422426
* spi_controller list, and their matching process
427+
* also used to protect object of type struct idr
423428
*/
424429
static DEFINE_MUTEX(board_lock);
425430

@@ -2051,11 +2056,10 @@ static int of_spi_register_master(struct spi_controller *ctlr)
20512056
*/
20522057
int spi_register_controller(struct spi_controller *ctlr)
20532058
{
2054-
static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
20552059
struct device *dev = ctlr->dev.parent;
20562060
struct boardinfo *bi;
20572061
int status = -ENODEV;
2058-
int dynamic = 0;
2062+
int id;
20592063

20602064
if (!dev)
20612065
return -ENODEV;
@@ -2071,17 +2075,29 @@ int spi_register_controller(struct spi_controller *ctlr)
20712075
*/
20722076
if (ctlr->num_chipselect == 0)
20732077
return -EINVAL;
2074-
2075-
if ((ctlr->bus_num < 0) && ctlr->dev.of_node)
2076-
ctlr->bus_num = of_alias_get_id(ctlr->dev.of_node, "spi");
2077-
2078-
/* convention: dynamically assigned bus IDs count down from the max */
2078+
2079+
/* allocate dynamic bus number using Linux idr */
2080+
if ((ctlr->bus_num < 0) && ctlr->dev.of_node) {
2081+
id = of_alias_get_id(ctlr->dev.of_node, "spi");
2082+
if (id >= 0) {
2083+
ctlr->bus_num = id;
2084+
mutex_lock(&board_lock);
2085+
id = idr_alloc(&spi_master_idr, ctlr, ctlr->bus_num,
2086+
ctlr->bus_num + 1, GFP_KERNEL);
2087+
mutex_unlock(&board_lock);
2088+
if (WARN(id < 0, "couldn't get idr"))
2089+
return id == -ENOSPC ? -EBUSY : id;
2090+
}
2091+
}
20792092
if (ctlr->bus_num < 0) {
2080-
/* FIXME switch to an IDR based scheme, something like
2081-
* I2C now uses, so we can't run out of "dynamic" IDs
2082-
*/
2083-
ctlr->bus_num = atomic_dec_return(&dyn_bus_id);
2084-
dynamic = 1;
2093+
mutex_lock(&board_lock);
2094+
id = idr_alloc(&spi_master_idr, ctlr,
2095+
SPI_DYN_FIRST_BUS_NUM, 0, GFP_KERNEL);
2096+
mutex_unlock(&board_lock);
2097+
if (WARN(id < 0, "couldn't get idr"))
2098+
return id;
2099+
2100+
ctlr->bus_num = id;
20852101
}
20862102

20872103
INIT_LIST_HEAD(&ctlr->queue);
@@ -2099,11 +2115,16 @@ int spi_register_controller(struct spi_controller *ctlr)
20992115
*/
21002116
dev_set_name(&ctlr->dev, "spi%u", ctlr->bus_num);
21012117
status = device_add(&ctlr->dev);
2102-
if (status < 0)
2118+
if (status < 0) {
2119+
/* free bus id */
2120+
mutex_lock(&board_lock);
2121+
idr_remove(&spi_master_idr, ctlr->bus_num);
2122+
mutex_unlock(&board_lock);
21032123
goto done;
2104-
dev_dbg(dev, "registered %s %s%s\n",
2124+
}
2125+
dev_dbg(dev, "registered %s %s\n",
21052126
spi_controller_is_slave(ctlr) ? "slave" : "master",
2106-
dev_name(&ctlr->dev), dynamic ? " (dynamic)" : "");
2127+
dev_name(&ctlr->dev));
21072128

21082129
/* If we're using a queued driver, start the queue */
21092130
if (ctlr->transfer)
@@ -2112,6 +2133,10 @@ int spi_register_controller(struct spi_controller *ctlr)
21122133
status = spi_controller_initialize_queue(ctlr);
21132134
if (status) {
21142135
device_del(&ctlr->dev);
2136+
/* free bus id */
2137+
mutex_lock(&board_lock);
2138+
idr_remove(&spi_master_idr, ctlr->bus_num);
2139+
mutex_unlock(&board_lock);
21152140
goto done;
21162141
}
21172142
}
@@ -2190,8 +2215,20 @@ static int __unregister(struct device *dev, void *null)
21902215
*/
21912216
void spi_unregister_controller(struct spi_controller *ctlr)
21922217
{
2218+
struct spi_controller *found;
21932219
int dummy;
21942220

2221+
/* First make sure that this controller was ever added */
2222+
mutex_lock(&board_lock);
2223+
found = idr_find(&spi_master_idr, ctlr->bus_num);
2224+
mutex_unlock(&board_lock);
2225+
if (found != ctlr) {
2226+
dev_dbg(&ctlr->dev,
2227+
"attempting to delete unregistered controller [%s]\n",
2228+
dev_name(&ctlr->dev));
2229+
return;
2230+
}
2231+
21952232
if (ctlr->queued) {
21962233
if (spi_destroy_queue(ctlr))
21972234
dev_err(&ctlr->dev, "queue remove failed\n");
@@ -2203,6 +2240,10 @@ void spi_unregister_controller(struct spi_controller *ctlr)
22032240

22042241
dummy = device_for_each_child(&ctlr->dev, NULL, __unregister);
22052242
device_unregister(&ctlr->dev);
2243+
/* free bus id */
2244+
mutex_lock(&board_lock);
2245+
idr_remove(&spi_master_idr, ctlr->bus_num);
2246+
mutex_unlock(&board_lock);
22062247
}
22072248
EXPORT_SYMBOL_GPL(spi_unregister_controller);
22082249

0 commit comments

Comments
 (0)