Commit 7e2c225d authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branch 'spi/fix/core' into spi-linus

parents 7e22e911 13a42798
...@@ -370,6 +370,17 @@ static void spi_dev_set_name(struct spi_device *spi) ...@@ -370,6 +370,17 @@ static void spi_dev_set_name(struct spi_device *spi)
spi->chip_select); 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_add_device - Add spi_device allocated with spi_alloc_device
* @spi: spi_device to register * @spi: spi_device to register
...@@ -384,7 +395,6 @@ int spi_add_device(struct spi_device *spi) ...@@ -384,7 +395,6 @@ int spi_add_device(struct spi_device *spi)
static DEFINE_MUTEX(spi_add_lock); static DEFINE_MUTEX(spi_add_lock);
struct spi_master *master = spi->master; struct spi_master *master = spi->master;
struct device *dev = master->dev.parent; struct device *dev = master->dev.parent;
struct device *d;
int status; int status;
/* Chipselects are numbered 0..max; validate. */ /* Chipselects are numbered 0..max; validate. */
...@@ -404,12 +414,10 @@ int spi_add_device(struct spi_device *spi) ...@@ -404,12 +414,10 @@ int spi_add_device(struct spi_device *spi)
*/ */
mutex_lock(&spi_add_lock); mutex_lock(&spi_add_lock);
d = bus_find_device_by_name(&spi_bus_type, NULL, dev_name(&spi->dev)); status = bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check);
if (d != NULL) { if (status) {
dev_err(dev, "chipselect %d already in use\n", dev_err(dev, "chipselect %d already in use\n",
spi->chip_select); spi->chip_select);
put_device(d);
status = -EBUSY;
goto done; goto done;
} }
...@@ -591,8 +599,10 @@ static int spi_transfer_one_message(struct spi_master *master, ...@@ -591,8 +599,10 @@ static int spi_transfer_one_message(struct spi_master *master,
goto out; goto out;
} }
if (ret > 0) if (ret > 0) {
ret = 0;
wait_for_completion(&master->xfer_completion); wait_for_completion(&master->xfer_completion);
}
trace_spi_transfer_stop(msg, xfer); trace_spi_transfer_stop(msg, xfer);
...@@ -632,7 +642,7 @@ static int spi_transfer_one_message(struct spi_master *master, ...@@ -632,7 +642,7 @@ static int spi_transfer_one_message(struct spi_master *master,
* *
* Called by SPI drivers using the core transfer_one_message() * Called by SPI drivers using the core transfer_one_message()
* implementation to notify it that the current interrupt driven * 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) void spi_finalize_current_transfer(struct spi_master *master)
{ {
...@@ -735,7 +745,9 @@ static void spi_pump_messages(struct kthread_work *work) ...@@ -735,7 +745,9 @@ static void spi_pump_messages(struct kthread_work *work)
ret = master->transfer_one_message(master, master->cur_msg); ret = master->transfer_one_message(master, master->cur_msg);
if (ret) { if (ret) {
dev_err(&master->dev, 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; return;
} }
} }
......
...@@ -277,15 +277,17 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) ...@@ -277,15 +277,17 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
* @unprepare_transfer_hardware: there are currently no more messages on the * @unprepare_transfer_hardware: there are currently no more messages on the
* queue so the subsystem notifies the driver that it may relax the * queue so the subsystem notifies the driver that it may relax the
* hardware by issuing this call * hardware by issuing this call
* @set_cs: assert or deassert chip select, true to assert. May be called * @set_cs: set the logic level of the chip select line. May be called
* from interrupt context. * from interrupt context.
* @prepare_message: set up the controller to transfer a single message, * @prepare_message: set up the controller to transfer a single message,
* for example doing DMA mapping. Called from threaded * for example doing DMA mapping. Called from threaded
* context. * context.
* @transfer_one: transfer a single spi_transfer. When the * @transfer_one: transfer a single spi_transfer.
* driver is finished with this transfer it must call * - return 0 if the transfer is finished,
* spi_finalize_current_transfer() so the subsystem can issue * - return 1 if the transfer is still in progress. When
* the next transfer * the driver is finished with this transfer it must
* call spi_finalize_current_transfer() so the subsystem
* can issue the next transfer
* @unprepare_message: undo any work done by prepare_message(). * @unprepare_message: undo any work done by prepare_message().
* @cs_gpios: Array of GPIOs to use as chip select lines; one per CS * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
* number. Any individual value may be -ENOENT for CS lines that * number. Any individual value may be -ENOENT for CS lines that
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment