From 376aab6ea7be382929e810d0f21a378e65321fab Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 15 Aug 2008 00:40:44 -0700 Subject: [PATCH] --- yaml --- r: 108491 b: refs/heads/master c: e48880e02e7e7ead9daa47fe3a20486f550668d3 h: refs/heads/master i: 108489: 009ccd86cbefcc2602fe122b8c9b100f67537968 108487: e0d91ee3d84c0beb0e7a6a264dcac4081acc0733 v: v3 --- [refs] | 2 +- trunk/drivers/spi/spi.c | 40 +++++++++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/[refs] b/[refs] index aa7153b541fc..7555c47f19c1 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 7d455e0030eeab820773e7786605be4d9e56a04b +refs/heads/master: e48880e02e7e7ead9daa47fe3a20486f550668d3 diff --git a/trunk/drivers/spi/spi.c b/trunk/drivers/spi/spi.c index 964124b60db2..75e86865234c 100644 --- a/trunk/drivers/spi/spi.c +++ b/trunk/drivers/spi/spi.c @@ -226,10 +226,11 @@ EXPORT_SYMBOL_GPL(spi_alloc_device); * Companion function to spi_alloc_device. Devices allocated with * spi_alloc_device can be added onto the spi bus with this function. * - * Returns 0 on success; non-zero on failure + * Returns 0 on success; negative errno on failure */ int spi_add_device(struct spi_device *spi) { + static DEFINE_MUTEX(spi_add_lock); struct device *dev = spi->master->dev.parent; int status; @@ -246,26 +247,43 @@ int spi_add_device(struct spi_device *spi) "%s.%u", spi->master->dev.bus_id, spi->chip_select); - /* drivers may modify this initial i/o setup */ + + /* We need to make sure there's no other device with this + * chipselect **BEFORE** we call setup(), else we'll trash + * its configuration. Lock against concurrent add() calls. + */ + mutex_lock(&spi_add_lock); + + if (bus_find_device_by_name(&spi_bus_type, NULL, spi->dev.bus_id) + != NULL) { + dev_err(dev, "chipselect %d already in use\n", + spi->chip_select); + status = -EBUSY; + goto done; + } + + /* Drivers may modify this initial i/o setup, but will + * normally rely on the device being setup. Devices + * using SPI_CS_HIGH can't coexist well otherwise... + */ status = spi->master->setup(spi); if (status < 0) { dev_err(dev, "can't %s %s, status %d\n", "setup", spi->dev.bus_id, status); - return status; + goto done; } - /* driver core catches callers that misbehave by defining - * devices that already exist. - */ + /* Device may be bound to an active driver when this returns */ status = device_add(&spi->dev); - if (status < 0) { + if (status < 0) dev_err(dev, "can't %s %s, status %d\n", "add", spi->dev.bus_id, status); - return status; - } + else + dev_dbg(dev, "registered child %s\n", spi->dev.bus_id); - dev_dbg(dev, "registered child %s\n", spi->dev.bus_id); - return 0; +done: + mutex_unlock(&spi_add_lock); + return status; } EXPORT_SYMBOL_GPL(spi_add_device);