diff options
author | Mark Brown <broonie@linaro.org> | 2014-01-23 13:07:00 (GMT) |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-01-23 13:07:00 (GMT) |
commit | 7e2c225d585cd6d7481ff4ec446a67334ef11f4d (patch) | |
tree | addcb9cdff0dbf2f8a390d48a1460e64ae2008cd /drivers/spi | |
parent | 7e22e91102c6b9df7c4ae2168910e19d2bb14cd6 (diff) | |
parent | 13a4279880229240af38486611c94587492b24d3 (diff) | |
download | linux-7e2c225d585cd6d7481ff4ec446a67334ef11f4d.tar.xz |
Merge remote-tracking branch 'spi/fix/core' into spi-linus
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 349ebba..965dd8a 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; } @@ -591,8 +599,10 @@ static int spi_transfer_one_message(struct spi_master *master, goto out; } - if (ret > 0) + if (ret > 0) { + ret = 0; wait_for_completion(&master->xfer_completion); + } trace_spi_transfer_stop(msg, xfer); @@ -632,7 +642,7 @@ out: * * Called by SPI drivers using the core transfer_one_message() * implementation to notify it that the current interrupt driven - * transfer has finised and the next one may be scheduled. + * transfer has finished and the next one may be scheduled. */ void spi_finalize_current_transfer(struct spi_master *master) { @@ -735,7 +745,9 @@ static void spi_pump_messages(struct kthread_work *work) ret = master->transfer_one_message(master, master->cur_msg); if (ret) { dev_err(&master->dev, - "failed to transfer one message from queue\n"); + "failed to transfer one message from queue: %d\n", ret); + master->cur_msg->status = ret; + spi_finalize_current_message(master); return; } } |