aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-09-04 07:02:35 -0400
committerIngo Molnar <mingo@elte.hu>2008-09-04 07:02:35 -0400
commit42390cdec5f6e6e2ee54f308474a6ef7dd16aa5c (patch)
treee9684c84f53272319a5acd4b9c86503f30274a51 /drivers/spi/spi.c
parent11c231a962c740b3216eb6565149ae5a7944cba7 (diff)
parentd210baf53b699fc61aa891c177b71d7082d3b957 (diff)
Merge branch 'linus' into x86/x2apic
Conflicts: arch/x86/kernel/cpu/cyrix.c include/asm-x86/cpufeature.h Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r--drivers/spi/spi.c40
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 */
231int spi_add_device(struct spi_device *spi) 231int 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); 284done:
268 return 0; 285 mutex_unlock(&spi_add_lock);
286 return status;
269} 287}
270EXPORT_SYMBOL_GPL(spi_add_device); 288EXPORT_SYMBOL_GPL(spi_add_device);
271 289