diff options
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi.c | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 964124b60db2..75e86865234c 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -226,10 +226,11 @@ EXPORT_SYMBOL_GPL(spi_alloc_device); | |||
226 | * Companion function to spi_alloc_device. Devices allocated with | 226 | * Companion function to spi_alloc_device. Devices allocated with |
227 | * spi_alloc_device can be added onto the spi bus with this function. | 227 | * spi_alloc_device can be added onto the spi bus with this function. |
228 | * | 228 | * |
229 | * Returns 0 on success; non-zero on failure | 229 | * Returns 0 on success; negative errno on failure |
230 | */ | 230 | */ |
231 | int spi_add_device(struct spi_device *spi) | 231 | int spi_add_device(struct spi_device *spi) |
232 | { | 232 | { |
233 | static DEFINE_MUTEX(spi_add_lock); | ||
233 | struct device *dev = spi->master->dev.parent; | 234 | struct device *dev = spi->master->dev.parent; |
234 | int status; | 235 | int status; |
235 | 236 | ||
@@ -246,26 +247,43 @@ int spi_add_device(struct spi_device *spi) | |||
246 | "%s.%u", spi->master->dev.bus_id, | 247 | "%s.%u", spi->master->dev.bus_id, |
247 | spi->chip_select); | 248 | spi->chip_select); |
248 | 249 | ||
249 | /* drivers may modify this initial i/o setup */ | 250 | |
251 | /* We need to make sure there's no other device with this | ||
252 | * chipselect **BEFORE** we call setup(), else we'll trash | ||
253 | * its configuration. Lock against concurrent add() calls. | ||
254 | */ | ||
255 | mutex_lock(&spi_add_lock); | ||
256 | |||
257 | if (bus_find_device_by_name(&spi_bus_type, NULL, spi->dev.bus_id) | ||
258 | != NULL) { | ||
259 | dev_err(dev, "chipselect %d already in use\n", | ||
260 | spi->chip_select); | ||
261 | status = -EBUSY; | ||
262 | goto done; | ||
263 | } | ||
264 | |||
265 | /* Drivers may modify this initial i/o setup, but will | ||
266 | * normally rely on the device being setup. Devices | ||
267 | * using SPI_CS_HIGH can't coexist well otherwise... | ||
268 | */ | ||
250 | status = spi->master->setup(spi); | 269 | status = spi->master->setup(spi); |
251 | if (status < 0) { | 270 | if (status < 0) { |
252 | dev_err(dev, "can't %s %s, status %d\n", | 271 | dev_err(dev, "can't %s %s, status %d\n", |
253 | "setup", spi->dev.bus_id, status); | 272 | "setup", spi->dev.bus_id, status); |
254 | return status; | 273 | goto done; |
255 | } | 274 | } |
256 | 275 | ||
257 | /* driver core catches callers that misbehave by defining | 276 | /* Device may be bound to an active driver when this returns */ |
258 | * devices that already exist. | ||
259 | */ | ||
260 | status = device_add(&spi->dev); | 277 | status = device_add(&spi->dev); |
261 | if (status < 0) { | 278 | if (status < 0) |
262 | dev_err(dev, "can't %s %s, status %d\n", | 279 | dev_err(dev, "can't %s %s, status %d\n", |
263 | "add", spi->dev.bus_id, status); | 280 | "add", spi->dev.bus_id, status); |
264 | return status; | 281 | else |
265 | } | 282 | dev_dbg(dev, "registered child %s\n", spi->dev.bus_id); |
266 | 283 | ||
267 | dev_dbg(dev, "registered child %s\n", spi->dev.bus_id); | 284 | done: |
268 | return 0; | 285 | mutex_unlock(&spi_add_lock); |
286 | return status; | ||
269 | } | 287 | } |
270 | EXPORT_SYMBOL_GPL(spi_add_device); | 288 | EXPORT_SYMBOL_GPL(spi_add_device); |
271 | 289 | ||