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 <sunil.m@techveda.org>
Signed-off-by: Karthik Tummala <karthik@techveda.org>
Tested-by: Karthik Tummala <karthik@techveda.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Suniel Mahesh 2017-08-03 10:05:57 +05:30 committed by Mark Brown
parent e0bcb680b1
commit 9b61e30221

View file

@ -40,9 +40,13 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/idr.h>
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <trace/events/spi.h> #include <trace/events/spi.h>
#define SPI_DYN_FIRST_BUS_NUM 0
static DEFINE_IDR(spi_master_idr);
static void spidev_release(struct device *dev) static void spidev_release(struct device *dev)
{ {
@ -420,6 +424,7 @@ static LIST_HEAD(spi_controller_list);
/* /*
* Used to protect add/del opertion for board_info list and * Used to protect add/del opertion for board_info list and
* spi_controller list, and their matching process * spi_controller list, and their matching process
* also used to protect object of type struct idr
*/ */
static DEFINE_MUTEX(board_lock); static DEFINE_MUTEX(board_lock);
@ -2051,11 +2056,10 @@ static int of_spi_register_master(struct spi_controller *ctlr)
*/ */
int spi_register_controller(struct spi_controller *ctlr) int spi_register_controller(struct spi_controller *ctlr)
{ {
static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
struct device *dev = ctlr->dev.parent; struct device *dev = ctlr->dev.parent;
struct boardinfo *bi; struct boardinfo *bi;
int status = -ENODEV; int status = -ENODEV;
int dynamic = 0; int id;
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
@ -2071,17 +2075,29 @@ int spi_register_controller(struct spi_controller *ctlr)
*/ */
if (ctlr->num_chipselect == 0) if (ctlr->num_chipselect == 0)
return -EINVAL; return -EINVAL;
if ((ctlr->bus_num < 0) && ctlr->dev.of_node) /* allocate dynamic bus number using Linux idr */
ctlr->bus_num = of_alias_get_id(ctlr->dev.of_node, "spi"); if ((ctlr->bus_num < 0) && ctlr->dev.of_node) {
id = of_alias_get_id(ctlr->dev.of_node, "spi");
/* convention: dynamically assigned bus IDs count down from the max */ if (id >= 0) {
ctlr->bus_num = id;
mutex_lock(&board_lock);
id = idr_alloc(&spi_master_idr, ctlr, ctlr->bus_num,
ctlr->bus_num + 1, GFP_KERNEL);
mutex_unlock(&board_lock);
if (WARN(id < 0, "couldn't get idr"))
return id == -ENOSPC ? -EBUSY : id;
}
}
if (ctlr->bus_num < 0) { if (ctlr->bus_num < 0) {
/* FIXME switch to an IDR based scheme, something like mutex_lock(&board_lock);
* I2C now uses, so we can't run out of "dynamic" IDs id = idr_alloc(&spi_master_idr, ctlr,
*/ SPI_DYN_FIRST_BUS_NUM, 0, GFP_KERNEL);
ctlr->bus_num = atomic_dec_return(&dyn_bus_id); mutex_unlock(&board_lock);
dynamic = 1; if (WARN(id < 0, "couldn't get idr"))
return id;
ctlr->bus_num = id;
} }
INIT_LIST_HEAD(&ctlr->queue); INIT_LIST_HEAD(&ctlr->queue);
@ -2099,11 +2115,16 @@ int spi_register_controller(struct spi_controller *ctlr)
*/ */
dev_set_name(&ctlr->dev, "spi%u", ctlr->bus_num); dev_set_name(&ctlr->dev, "spi%u", ctlr->bus_num);
status = device_add(&ctlr->dev); status = device_add(&ctlr->dev);
if (status < 0) if (status < 0) {
/* free bus id */
mutex_lock(&board_lock);
idr_remove(&spi_master_idr, ctlr->bus_num);
mutex_unlock(&board_lock);
goto done; goto done;
dev_dbg(dev, "registered %s %s%s\n", }
dev_dbg(dev, "registered %s %s\n",
spi_controller_is_slave(ctlr) ? "slave" : "master", spi_controller_is_slave(ctlr) ? "slave" : "master",
dev_name(&ctlr->dev), dynamic ? " (dynamic)" : ""); dev_name(&ctlr->dev));
/* If we're using a queued driver, start the queue */ /* If we're using a queued driver, start the queue */
if (ctlr->transfer) if (ctlr->transfer)
@ -2112,6 +2133,10 @@ int spi_register_controller(struct spi_controller *ctlr)
status = spi_controller_initialize_queue(ctlr); status = spi_controller_initialize_queue(ctlr);
if (status) { if (status) {
device_del(&ctlr->dev); device_del(&ctlr->dev);
/* free bus id */
mutex_lock(&board_lock);
idr_remove(&spi_master_idr, ctlr->bus_num);
mutex_unlock(&board_lock);
goto done; goto done;
} }
} }
@ -2190,8 +2215,20 @@ static int __unregister(struct device *dev, void *null)
*/ */
void spi_unregister_controller(struct spi_controller *ctlr) void spi_unregister_controller(struct spi_controller *ctlr)
{ {
struct spi_controller *found;
int dummy; int dummy;
/* First make sure that this controller was ever added */
mutex_lock(&board_lock);
found = idr_find(&spi_master_idr, ctlr->bus_num);
mutex_unlock(&board_lock);
if (found != ctlr) {
dev_dbg(&ctlr->dev,
"attempting to delete unregistered controller [%s]\n",
dev_name(&ctlr->dev));
return;
}
if (ctlr->queued) { if (ctlr->queued) {
if (spi_destroy_queue(ctlr)) if (spi_destroy_queue(ctlr))
dev_err(&ctlr->dev, "queue remove failed\n"); dev_err(&ctlr->dev, "queue remove failed\n");
@ -2203,6 +2240,10 @@ void spi_unregister_controller(struct spi_controller *ctlr)
dummy = device_for_each_child(&ctlr->dev, NULL, __unregister); dummy = device_for_each_child(&ctlr->dev, NULL, __unregister);
device_unregister(&ctlr->dev); device_unregister(&ctlr->dev);
/* free bus id */
mutex_lock(&board_lock);
idr_remove(&spi_master_idr, ctlr->bus_num);
mutex_unlock(&board_lock);
} }
EXPORT_SYMBOL_GPL(spi_unregister_controller); EXPORT_SYMBOL_GPL(spi_unregister_controller);