diff options
author | Chris Lesiak <chris.lesiak@licor.com> | 2007-03-16 17:38:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-03-16 22:25:04 -0400 |
commit | a836f5856ae46ccb2464ea76031ea05ae967b832 (patch) | |
tree | eb0153e3b91381840d478d3e8c5b021dc12b92f9 | |
parent | 65b8291c4000e5f38fc94fb2ca0cb7e8683c8a1b (diff) |
[PATCH] spi: destroy workqueue after spi_unregister_master
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>
-rw-r--r-- | drivers/spi/spi_bitbang.c | 26 | ||||
-rw-r--r-- | include/linux/spi/spi_bitbang.h | 1 |
2 files changed, 2 insertions, 25 deletions
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index 24a330d82395..88425e1af4d3 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c | |||
@@ -302,10 +302,6 @@ static void bitbang_work(struct work_struct *work) | |||
302 | setup_transfer = NULL; | 302 | setup_transfer = NULL; |
303 | 303 | ||
304 | list_for_each_entry (t, &m->transfers, transfer_list) { | 304 | list_for_each_entry (t, &m->transfers, transfer_list) { |
305 | if (bitbang->shutdown) { | ||
306 | status = -ESHUTDOWN; | ||
307 | break; | ||
308 | } | ||
309 | 305 | ||
310 | /* override or restore speed and wordsize */ | 306 | /* override or restore speed and wordsize */ |
311 | if (t->speed_hz || t->bits_per_word) { | 307 | if (t->speed_hz || t->bits_per_word) { |
@@ -410,8 +406,6 @@ int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m) | |||
410 | m->status = -EINPROGRESS; | 406 | m->status = -EINPROGRESS; |
411 | 407 | ||
412 | bitbang = spi_master_get_devdata(spi->master); | 408 | bitbang = spi_master_get_devdata(spi->master); |
413 | if (bitbang->shutdown) | ||
414 | return -ESHUTDOWN; | ||
415 | 409 | ||
416 | spin_lock_irqsave(&bitbang->lock, flags); | 410 | spin_lock_irqsave(&bitbang->lock, flags); |
417 | if (!spi->max_speed_hz) | 411 | if (!spi->max_speed_hz) |
@@ -507,28 +501,12 @@ EXPORT_SYMBOL_GPL(spi_bitbang_start); | |||
507 | */ | 501 | */ |
508 | int spi_bitbang_stop(struct spi_bitbang *bitbang) | 502 | int spi_bitbang_stop(struct spi_bitbang *bitbang) |
509 | { | 503 | { |
510 | unsigned limit = 500; | 504 | spi_unregister_master(bitbang->master); |
511 | |||
512 | spin_lock_irq(&bitbang->lock); | ||
513 | bitbang->shutdown = 0; | ||
514 | while (!list_empty(&bitbang->queue) && limit--) { | ||
515 | spin_unlock_irq(&bitbang->lock); | ||
516 | 505 | ||
517 | dev_dbg(bitbang->master->cdev.dev, "wait for queue\n"); | 506 | WARN_ON(!list_empty(&bitbang->queue)); |
518 | msleep(10); | ||
519 | |||
520 | spin_lock_irq(&bitbang->lock); | ||
521 | } | ||
522 | spin_unlock_irq(&bitbang->lock); | ||
523 | if (!list_empty(&bitbang->queue)) { | ||
524 | dev_err(bitbang->master->cdev.dev, "queue didn't empty\n"); | ||
525 | return -EBUSY; | ||
526 | } | ||
527 | 507 | ||
528 | destroy_workqueue(bitbang->workqueue); | 508 | destroy_workqueue(bitbang->workqueue); |
529 | 509 | ||
530 | spi_unregister_master(bitbang->master); | ||
531 | |||
532 | return 0; | 510 | return 0; |
533 | } | 511 | } |
534 | EXPORT_SYMBOL_GPL(spi_bitbang_stop); | 512 | EXPORT_SYMBOL_GPL(spi_bitbang_stop); |
diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h index 2e8c048b9b80..9dbca629dcfb 100644 --- a/include/linux/spi/spi_bitbang.h +++ b/include/linux/spi/spi_bitbang.h | |||
@@ -25,7 +25,6 @@ struct spi_bitbang { | |||
25 | spinlock_t lock; | 25 | spinlock_t lock; |
26 | struct list_head queue; | 26 | struct list_head queue; |
27 | u8 busy; | 27 | u8 busy; |
28 | u8 shutdown; | ||
29 | u8 use_dma; | 28 | u8 use_dma; |
30 | 29 | ||
31 | struct spi_master *master; | 30 | struct spi_master *master; |