From 2856670f23a92ab72db850d73f30c0b4b6ba5a76 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 26 Jul 2017 16:14:00 +0300 Subject: [PATCH 1/4] spi: core: Propagate error code of add_uevent_var() add_uevent_var() can fail, let caller know about this. Signed-off-by: Andy Shevchenko Signed-off-by: Mark Brown --- drivers/spi/spi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 4fcbb0aa71d36..fe7bba9241ea4 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -321,8 +321,7 @@ static int spi_uevent(struct device *dev, struct kobj_uevent_env *env) if (rc != -ENODEV) return rc; - add_uevent_var(env, "MODALIAS=%s%s", SPI_MODULE_PREFIX, spi->modalias); - return 0; + return add_uevent_var(env, "MODALIAS=%s%s", SPI_MODULE_PREFIX, spi->modalias); } struct bus_type spi_bus_type = { From e0bcb680b152c96ee4b561abbeb18743cdcc5ae3 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 6 Aug 2017 23:15:31 +0300 Subject: [PATCH 2/4] spi: use of_property_read_bool() Use a bit more compact of_property_read_bool() calls instead of the of_find_property() calls -- symmetrically with the of_property_read_u32() calls already done in of_spi_parse_dt(). Signed-off-by: Sergei Shtylyov Signed-off-by: Mark Brown --- drivers/spi/spi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index fe7bba9241ea4..aed78093b1306 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1532,15 +1532,15 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, int rc; /* Mode (clock phase/polarity/etc.) */ - if (of_find_property(nc, "spi-cpha", NULL)) + if (of_property_read_bool(nc, "spi-cpha")) spi->mode |= SPI_CPHA; - if (of_find_property(nc, "spi-cpol", NULL)) + if (of_property_read_bool(nc, "spi-cpol")) spi->mode |= SPI_CPOL; - if (of_find_property(nc, "spi-cs-high", NULL)) + if (of_property_read_bool(nc, "spi-cs-high")) spi->mode |= SPI_CS_HIGH; - if (of_find_property(nc, "spi-3wire", NULL)) + if (of_property_read_bool(nc, "spi-3wire")) spi->mode |= SPI_3WIRE; - if (of_find_property(nc, "spi-lsb-first", NULL)) + if (of_property_read_bool(nc, "spi-lsb-first")) spi->mode |= SPI_LSB_FIRST; /* Device DUAL/QUAD mode */ From 9b61e302210eba55768962f2f11e96bb508c2408 Mon Sep 17 00:00:00 2001 From: Suniel Mahesh Date: Thu, 3 Aug 2017 10:05:57 +0530 Subject: [PATCH 3/4] 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 Signed-off-by: Karthik Tummala Tested-by: Karthik Tummala Signed-off-by: Mark Brown --- drivers/spi/spi.c | 71 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index aed78093b1306..b851888a0a0b6 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -40,9 +40,13 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include +#define SPI_DYN_FIRST_BUS_NUM 0 + +static DEFINE_IDR(spi_master_idr); 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 * spi_controller list, and their matching process + * also used to protect object of type struct idr */ 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) { - static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1); struct device *dev = ctlr->dev.parent; struct boardinfo *bi; int status = -ENODEV; - int dynamic = 0; + int id; if (!dev) return -ENODEV; @@ -2071,17 +2075,29 @@ int spi_register_controller(struct spi_controller *ctlr) */ if (ctlr->num_chipselect == 0) return -EINVAL; - - if ((ctlr->bus_num < 0) && ctlr->dev.of_node) - ctlr->bus_num = of_alias_get_id(ctlr->dev.of_node, "spi"); - - /* convention: dynamically assigned bus IDs count down from the max */ + + /* allocate dynamic bus number using Linux idr */ + if ((ctlr->bus_num < 0) && ctlr->dev.of_node) { + id = of_alias_get_id(ctlr->dev.of_node, "spi"); + 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) { - /* FIXME switch to an IDR based scheme, something like - * I2C now uses, so we can't run out of "dynamic" IDs - */ - ctlr->bus_num = atomic_dec_return(&dyn_bus_id); - dynamic = 1; + mutex_lock(&board_lock); + id = idr_alloc(&spi_master_idr, ctlr, + SPI_DYN_FIRST_BUS_NUM, 0, GFP_KERNEL); + mutex_unlock(&board_lock); + if (WARN(id < 0, "couldn't get idr")) + return id; + + ctlr->bus_num = id; } 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); 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; - dev_dbg(dev, "registered %s %s%s\n", + } + dev_dbg(dev, "registered %s %s\n", 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 (ctlr->transfer) @@ -2112,6 +2133,10 @@ int spi_register_controller(struct spi_controller *ctlr) status = spi_controller_initialize_queue(ctlr); if (status) { 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; } } @@ -2190,8 +2215,20 @@ static int __unregister(struct device *dev, void *null) */ void spi_unregister_controller(struct spi_controller *ctlr) { + struct spi_controller *found; 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 (spi_destroy_queue(ctlr)) 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); 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); From 9a9a047a39d9173b0639017e5ba249443e76dd9e Mon Sep 17 00:00:00 2001 From: Suniel Mahesh Date: Thu, 17 Aug 2017 18:18:22 +0530 Subject: [PATCH 4/4] spi: Kernel coding style fixes Earlier commit: "spi: Pick spi bus number from Linux idr or spi alias" (SHA1:9b61e302210eba55768962f2f11e96bb508c2408) has introduced some checkpatch issues. As pointed by Lukas Wunner this patch does the following: - remove whitespaces - fix warnings, suspect code indent for conditional statements - fix errors, code indent should use tabs - remove spaces at the start of the line Signed-off-by: Suniel Mahesh Signed-off-by: Mark Brown --- drivers/spi/spi.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index b851888a0a0b6..f47d1ccdf2924 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -424,7 +424,7 @@ static LIST_HEAD(spi_controller_list); /* * Used to protect add/del opertion for board_info list and * spi_controller list, and their matching process - * also used to protect object of type struct idr + * also used to protect object of type struct idr */ static DEFINE_MUTEX(board_lock); @@ -2075,7 +2075,6 @@ int spi_register_controller(struct spi_controller *ctlr) */ if (ctlr->num_chipselect == 0) return -EINVAL; - /* allocate dynamic bus number using Linux idr */ if ((ctlr->bus_num < 0) && ctlr->dev.of_node) { id = of_alias_get_id(ctlr->dev.of_node, "spi"); @@ -2090,16 +2089,14 @@ int spi_register_controller(struct spi_controller *ctlr) } } if (ctlr->bus_num < 0) { - mutex_lock(&board_lock); - id = idr_alloc(&spi_master_idr, ctlr, - SPI_DYN_FIRST_BUS_NUM, 0, GFP_KERNEL); - mutex_unlock(&board_lock); - if (WARN(id < 0, "couldn't get idr")) - return id; - - ctlr->bus_num = id; + mutex_lock(&board_lock); + id = idr_alloc(&spi_master_idr, ctlr, SPI_DYN_FIRST_BUS_NUM, 0, + GFP_KERNEL); + mutex_unlock(&board_lock); + if (WARN(id < 0, "couldn't get idr")) + return id; + ctlr->bus_num = id; } - INIT_LIST_HEAD(&ctlr->queue); spin_lock_init(&ctlr->queue_lock); spin_lock_init(&ctlr->bus_lock_spinlock); @@ -2222,18 +2219,16 @@ void spi_unregister_controller(struct spi_controller *ctlr) mutex_lock(&board_lock); found = idr_find(&spi_master_idr, ctlr->bus_num); mutex_unlock(&board_lock); - if (found != ctlr) { - dev_dbg(&ctlr->dev, + if (found != ctlr) { + dev_dbg(&ctlr->dev, "attempting to delete unregistered controller [%s]\n", dev_name(&ctlr->dev)); - return; - } - + return; + } if (ctlr->queued) { if (spi_destroy_queue(ctlr)) dev_err(&ctlr->dev, "queue remove failed\n"); } - mutex_lock(&board_lock); list_del(&ctlr->list); mutex_unlock(&board_lock);