summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2014-01-09 15:23:55 +0200
committerMark Brown <broonie@linaro.org>2014-01-09 14:07:08 +0000
commitb6fb8d3a1f156c50a35f88b9b55f404034493938 (patch)
treec379808ae918ef30237babce2ded0ff5c372c337
parente120cc0dcf2880a4c5c0a6cb27b655600a1cfa1d (diff)
spi: Check conflicting CS based on spi->chip_select instead of device name
Commit e13ac47bec20 (spi: Use stable dev_name for ACPI enumerated SPI slaves) changed the SPI device naming to be based on ACPI device name instead of carrying bus number and chip select for devices enumerated from ACPI namespace. In case of a buggy BIOS that lists multiple SPI devices sharing the same chip select (even though they should use different) the current code fails to detect that and allows the devices to be added to the bus. Fix this by walking through the bus and comparing spi->chip_select instead of device name. This should work regardless what the device name will be in future. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--drivers/spi/spi.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 0e215237383b..51e00c6436aa 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -370,6 +370,17 @@ static void spi_dev_set_name(struct spi_device *spi)
spi->chip_select);
}
+static int spi_dev_check(struct device *dev, void *data)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct spi_device *new_spi = data;
+
+ if (spi->master == new_spi->master &&
+ spi->chip_select == new_spi->chip_select)
+ return -EBUSY;
+ return 0;
+}
+
/**
* spi_add_device - Add spi_device allocated with spi_alloc_device
* @spi: spi_device to register
@@ -384,7 +395,6 @@ int spi_add_device(struct spi_device *spi)
static DEFINE_MUTEX(spi_add_lock);
struct spi_master *master = spi->master;
struct device *dev = master->dev.parent;
- struct device *d;
int status;
/* Chipselects are numbered 0..max; validate. */
@@ -404,12 +414,10 @@ int spi_add_device(struct spi_device *spi)
*/
mutex_lock(&spi_add_lock);
- d = bus_find_device_by_name(&spi_bus_type, NULL, dev_name(&spi->dev));
- if (d != NULL) {
+ status = bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check);
+ if (status) {
dev_err(dev, "chipselect %d already in use\n",
spi->chip_select);
- put_device(d);
- status = -EBUSY;
goto done;
}