diff options
-rw-r--r-- | drivers/usb/gadget/f_mass_storage.c | 26 | ||||
-rw-r--r-- | drivers/usb/gadget/mass_storage.c | 8 |
2 files changed, 28 insertions, 6 deletions
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index a37640e..0a18d44 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -368,7 +368,7 @@ struct fsg_common { struct task_struct *thread_task; /* Callback function to call when thread exits. */ - void (*thread_exits)(struct fsg_common *common); + int (*thread_exits)(struct fsg_common *common); /* Gadget's private data. */ void *private_data; @@ -392,8 +392,12 @@ struct fsg_config { const char *lun_name_format; const char *thread_name; - /* Callback function to call when thread exits. */ - void (*thread_exits)(struct fsg_common *common); + /* Callback function to call when thread exits. If no + * callback is set or it returns value lower then zero MSF + * will force eject all LUNs it operates on (including those + * marked as non-removable or with prevent_medium_removal flag + * set). */ + int (*thread_exits)(struct fsg_common *common); /* Gadget's private data. */ void *private_data; @@ -2615,8 +2619,20 @@ static int fsg_main_thread(void *common_) common->thread_task = NULL; spin_unlock_irq(&common->lock); - if (common->thread_exits) - common->thread_exits(common); + if (!common->thread_exits || common->thread_exits(common) < 0) { + struct fsg_lun *curlun = common->luns; + unsigned i = common->nluns; + + down_write(&common->filesem); + for (; i--; ++curlun) { + if (!fsg_lun_is_open(curlun)) + continue; + + fsg_lun_close(curlun); + curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT; + } + up_write(&common->filesem); + } /* Let the unbind and cleanup routines know the thread has exited */ complete_and_exit(&common->thread_notifier, 0); diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index 19619fb..705cc1f 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -135,6 +135,12 @@ FSG_MODULE_PARAMETERS(/* no prefix */, mod_data); static unsigned long msg_registered = 0; static void msg_cleanup(void); +static int msg_thread_exits(struct fsg_common *common) +{ + msg_cleanup(); + return 0; +} + static int __init msg_do_config(struct usb_configuration *c) { struct fsg_common *common; @@ -147,7 +153,7 @@ static int __init msg_do_config(struct usb_configuration *c) } fsg_config_from_params(&config, &mod_data); - config.thread_exits = (void(*)(struct fsg_common*))&msg_cleanup; + config.thread_exits = msg_thread_exits; common = fsg_common_init(0, c->cdev, &config); if (IS_ERR(common)) return PTR_ERR(common); |