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
4751static 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 */
424429static DEFINE_MUTEX (board_lock );
425430
@@ -2051,11 +2056,10 @@ static int of_spi_register_master(struct spi_controller *ctlr)
20512056 */
20522057int 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 */
21912216void 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}
22072248EXPORT_SYMBOL_GPL (spi_unregister_controller );
22082249
0 commit comments