Skip to content

Commit

Permalink
[PATCH] spi: destroy workqueue after spi_unregister_master
Browse files Browse the repository at this point in the history
Fix a bug in the cleanup of an spi_bitbang bus.

The workqueue associated with the bus was destroyed before the call to
spi_unregister_master.  That meant that spi devices on that bus would be
unable to do IO in their remove method.  The shutdown flag should have been
able to prevent a segfault, but was never getting set.  By waiting to
destroy the workqueue until after the master is unregistered, devices are
able to do IO in their remove methods.  An added benefit is that neither
the shutdown flag nor a wait for the queue of messages to empty is needed.

Signed-off-by: Chris Lesiak <chris.lesiak@licor.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Chris Lesiak authored and Linus Torvalds committed Mar 17, 2007
1 parent 65b8291 commit a836f58
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 25 deletions.
26 changes: 2 additions & 24 deletions drivers/spi/spi_bitbang.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,10 +302,6 @@ static void bitbang_work(struct work_struct *work)
setup_transfer = NULL;

list_for_each_entry (t, &m->transfers, transfer_list) {
if (bitbang->shutdown) {
status = -ESHUTDOWN;
break;
}

/* override or restore speed and wordsize */
if (t->speed_hz || t->bits_per_word) {
Expand Down Expand Up @@ -410,8 +406,6 @@ int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
m->status = -EINPROGRESS;

bitbang = spi_master_get_devdata(spi->master);
if (bitbang->shutdown)
return -ESHUTDOWN;

spin_lock_irqsave(&bitbang->lock, flags);
if (!spi->max_speed_hz)
Expand Down Expand Up @@ -507,28 +501,12 @@ EXPORT_SYMBOL_GPL(spi_bitbang_start);
*/
int spi_bitbang_stop(struct spi_bitbang *bitbang)
{
unsigned limit = 500;

spin_lock_irq(&bitbang->lock);
bitbang->shutdown = 0;
while (!list_empty(&bitbang->queue) && limit--) {
spin_unlock_irq(&bitbang->lock);
spi_unregister_master(bitbang->master);

dev_dbg(bitbang->master->cdev.dev, "wait for queue\n");
msleep(10);

spin_lock_irq(&bitbang->lock);
}
spin_unlock_irq(&bitbang->lock);
if (!list_empty(&bitbang->queue)) {
dev_err(bitbang->master->cdev.dev, "queue didn't empty\n");
return -EBUSY;
}
WARN_ON(!list_empty(&bitbang->queue));

destroy_workqueue(bitbang->workqueue);

spi_unregister_master(bitbang->master);

return 0;
}
EXPORT_SYMBOL_GPL(spi_bitbang_stop);
Expand Down
1 change: 0 additions & 1 deletion include/linux/spi/spi_bitbang.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ struct spi_bitbang {
spinlock_t lock;
struct list_head queue;
u8 busy;
u8 shutdown;
u8 use_dma;

struct spi_master *master;
Expand Down

0 comments on commit a836f58

Please sign in to comment.