diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2007-06-07 17:12:25 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-07-12 19:34:31 -0400 |
commit | ed76cacbea08ebfdb678c8687f98237cb7c67bb6 (patch) | |
tree | bb3c3f759e36d1ae3c6c5b422ec74304e4ce2502 /drivers/usb/storage | |
parent | 3fc154b6b8134b98bb94d60cad9a46ec1ffbe372 (diff) |
USB: usb-storage: use kthread_stop() for the control thread
This patch (as923) makes usb-storage's control thread use
kthread_should_stop()/kthread_stop(). The scanning thread can't be
similarly converted until the core kthread implementation allows
threads to call do_exit().
The advantage of this change is that we can now be certain the control
thread has terminated before storage_disconnect() returns. This will
simplify the locking requirements when autosuspend support is added.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/storage')
-rw-r--r-- | drivers/usb/storage/usb.c | 38 | ||||
-rw-r--r-- | drivers/usb/storage/usb.h | 1 |
2 files changed, 14 insertions, 25 deletions
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 00521f1d6a6b..cf3fc91234e7 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c | |||
@@ -425,23 +425,15 @@ SkipForAbort: | |||
425 | mutex_unlock(&us->dev_mutex); | 425 | mutex_unlock(&us->dev_mutex); |
426 | } /* for (;;) */ | 426 | } /* for (;;) */ |
427 | 427 | ||
428 | scsi_host_put(host); | 428 | /* Wait until we are told to stop */ |
429 | 429 | for (;;) { | |
430 | /* notify the exit routine that we're actually exiting now | 430 | set_current_state(TASK_INTERRUPTIBLE); |
431 | * | 431 | if (kthread_should_stop()) |
432 | * complete()/wait_for_completion() is similar to up()/down(), | 432 | break; |
433 | * except that complete() is safe in the case where the structure | 433 | schedule(); |
434 | * is getting deleted in a parallel mode of execution (i.e. just | 434 | } |
435 | * after the down() -- that's necessary for the thread-shutdown | 435 | __set_current_state(TASK_RUNNING); |
436 | * case. | 436 | return 0; |
437 | * | ||
438 | * complete_and_exit() goes even further than this -- it is safe in | ||
439 | * the case that the thread of the caller is going away (not just | ||
440 | * the structure) -- this is necessary for the module-remove case. | ||
441 | * This is important in preemption kernels, which transfer the flow | ||
442 | * of execution immediately upon a complete(). | ||
443 | */ | ||
444 | complete_and_exit(&threads_gone, 0); | ||
445 | } | 437 | } |
446 | 438 | ||
447 | /*********************************************************************** | 439 | /*********************************************************************** |
@@ -809,19 +801,13 @@ static int usb_stor_acquire_resources(struct us_data *us) | |||
809 | } | 801 | } |
810 | 802 | ||
811 | /* Start up our control thread */ | 803 | /* Start up our control thread */ |
812 | th = kthread_create(usb_stor_control_thread, us, "usb-storage"); | 804 | th = kthread_run(usb_stor_control_thread, us, "usb-storage"); |
813 | if (IS_ERR(th)) { | 805 | if (IS_ERR(th)) { |
814 | printk(KERN_WARNING USB_STORAGE | 806 | printk(KERN_WARNING USB_STORAGE |
815 | "Unable to start control thread\n"); | 807 | "Unable to start control thread\n"); |
816 | return PTR_ERR(th); | 808 | return PTR_ERR(th); |
817 | } | 809 | } |
818 | 810 | us->ctl_thread = th; | |
819 | /* Take a reference to the host for the control thread and | ||
820 | * count it among all the threads we have launched. Then | ||
821 | * start it up. */ | ||
822 | scsi_host_get(us_to_host(us)); | ||
823 | atomic_inc(&total_threads); | ||
824 | wake_up_process(th); | ||
825 | 811 | ||
826 | return 0; | 812 | return 0; |
827 | } | 813 | } |
@@ -838,6 +824,8 @@ static void usb_stor_release_resources(struct us_data *us) | |||
838 | US_DEBUGP("-- sending exit command to thread\n"); | 824 | US_DEBUGP("-- sending exit command to thread\n"); |
839 | set_bit(US_FLIDX_DISCONNECTING, &us->flags); | 825 | set_bit(US_FLIDX_DISCONNECTING, &us->flags); |
840 | up(&us->sema); | 826 | up(&us->sema); |
827 | if (us->ctl_thread) | ||
828 | kthread_stop(us->ctl_thread); | ||
841 | 829 | ||
842 | /* Call the destructor routine, if it exists */ | 830 | /* Call the destructor routine, if it exists */ |
843 | if (us->extra_destructor) { | 831 | if (us->extra_destructor) { |
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index 6dac1ffdde86..6445665b1577 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h | |||
@@ -144,6 +144,7 @@ struct us_data { | |||
144 | unsigned char *sensebuf; /* sense data buffer */ | 144 | unsigned char *sensebuf; /* sense data buffer */ |
145 | dma_addr_t cr_dma; /* buffer DMA addresses */ | 145 | dma_addr_t cr_dma; /* buffer DMA addresses */ |
146 | dma_addr_t iobuf_dma; | 146 | dma_addr_t iobuf_dma; |
147 | struct task_struct *ctl_thread; /* the control thread */ | ||
147 | 148 | ||
148 | /* mutual exclusion and synchronization structures */ | 149 | /* mutual exclusion and synchronization structures */ |
149 | struct semaphore sema; /* to sleep thread on */ | 150 | struct semaphore sema; /* to sleep thread on */ |