forked from mirrors/linux
		
	spi: fix IDR collision on systems with both fixed and dynamic SPI bus numbers
On systems where some controllers get a dynamic ID assigned and some have
a fixed number (e.g. from ACPI tables), the current implementation might
run into an IDR collision: in case of a fixed bus number is gotten by a
driver (but not marked busy in IDR tree) and a driver with dynamic bus
number gets the same ID and predictably fails.
Fix this by means of checking-in fixed IDsin IDR as far as dynamic ones
at the moment of the controller registration.
Fixes: 9b61e30221 (spi: Pick spi bus number from Linux idr or spi alias)
Signed-off-by: Kirill Kapranov <kirill.kapranov@compulab.co.il>
Signed-off-by: Mark Brown <broonie@kernel.org>
Cc: stable@vger.kernel.org
			
			
This commit is contained in:
		
							parent
							
								
									401c0d7712
								
							
						
					
					
						commit
						1a4327fbf4
					
				
					 1 changed files with 9 additions and 0 deletions
				
			
		| 
						 | 
					@ -2170,6 +2170,15 @@ int spi_register_controller(struct spi_controller *ctlr)
 | 
				
			||||||
		if (WARN(id < 0, "couldn't get idr"))
 | 
							if (WARN(id < 0, "couldn't get idr"))
 | 
				
			||||||
			return id;
 | 
								return id;
 | 
				
			||||||
		ctlr->bus_num = id;
 | 
							ctlr->bus_num = id;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							/* devices with a fixed bus num must check-in with the num */
 | 
				
			||||||
 | 
							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;
 | 
				
			||||||
 | 
							ctlr->bus_num = id;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	INIT_LIST_HEAD(&ctlr->queue);
 | 
						INIT_LIST_HEAD(&ctlr->queue);
 | 
				
			||||||
	spin_lock_init(&ctlr->queue_lock);
 | 
						spin_lock_init(&ctlr->queue_lock);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue