Loading drivers/spi/spi.c +20 −8 Original line number Original line Diff line number Diff line Loading @@ -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 Loading @@ -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. */ Loading @@ -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; } } Loading Loading @@ -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); Loading Loading @@ -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) { { Loading Loading @@ -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; } } } } Loading include/linux/spi/spi.h +7 −5 Original line number Original line Diff line number Diff line Loading @@ -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 Loading Loading
drivers/spi/spi.c +20 −8 Original line number Original line Diff line number Diff line Loading @@ -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 Loading @@ -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. */ Loading @@ -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; } } Loading Loading @@ -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); Loading Loading @@ -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) { { Loading Loading @@ -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; } } } } Loading
include/linux/spi/spi.h +7 −5 Original line number Original line Diff line number Diff line Loading @@ -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 Loading