aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/gadget/f_mass_storage.c26
-rw-r--r--drivers/usb/gadget/mass_storage.c8
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);