aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/f_mass_storage.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/f_mass_storage.c')
-rw-r--r--drivers/usb/gadget/f_mass_storage.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index a37640eba43..0a18d446e9d 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -368,7 +368,7 @@ struct fsg_common {
368 struct task_struct *thread_task; 368 struct task_struct *thread_task;
369 369
370 /* Callback function to call when thread exits. */ 370 /* Callback function to call when thread exits. */
371 void (*thread_exits)(struct fsg_common *common); 371 int (*thread_exits)(struct fsg_common *common);
372 /* Gadget's private data. */ 372 /* Gadget's private data. */
373 void *private_data; 373 void *private_data;
374 374
@@ -392,8 +392,12 @@ struct fsg_config {
392 const char *lun_name_format; 392 const char *lun_name_format;
393 const char *thread_name; 393 const char *thread_name;
394 394
395 /* Callback function to call when thread exits. */ 395 /* Callback function to call when thread exits. If no
396 void (*thread_exits)(struct fsg_common *common); 396 * callback is set or it returns value lower then zero MSF
397 * will force eject all LUNs it operates on (including those
398 * marked as non-removable or with prevent_medium_removal flag
399 * set). */
400 int (*thread_exits)(struct fsg_common *common);
397 /* Gadget's private data. */ 401 /* Gadget's private data. */
398 void *private_data; 402 void *private_data;
399 403
@@ -2615,8 +2619,20 @@ static int fsg_main_thread(void *common_)
2615 common->thread_task = NULL; 2619 common->thread_task = NULL;
2616 spin_unlock_irq(&common->lock); 2620 spin_unlock_irq(&common->lock);
2617 2621
2618 if (common->thread_exits) 2622 if (!common->thread_exits || common->thread_exits(common) < 0) {
2619 common->thread_exits(common); 2623 struct fsg_lun *curlun = common->luns;
2624 unsigned i = common->nluns;
2625
2626 down_write(&common->filesem);
2627 for (; i--; ++curlun) {
2628 if (!fsg_lun_is_open(curlun))
2629 continue;
2630
2631 fsg_lun_close(curlun);
2632 curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
2633 }
2634 up_write(&common->filesem);
2635 }
2620 2636
2621 /* Let the unbind and cleanup routines know the thread has exited */ 2637 /* Let the unbind and cleanup routines know the thread has exited */
2622 complete_and_exit(&common->thread_notifier, 0); 2638 complete_and_exit(&common->thread_notifier, 0);