aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorMichal Nazarewicz <m.nazarewicz@samsung.com>2010-01-28 07:05:26 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-02 17:54:49 -0500
commit7f1ee82695654faf0a93fc0abf3b08eb354ef1f6 (patch)
tree4bae5a33bf617e72e8e255a0832871fce9547cf4 /drivers/usb/gadget
parent9f445cb29918dc488b7a9a92ef018599cce33df7 (diff)
USB: mass_storage: eject LUNs on thread exit
Adds a fallback which forces all LUNs ejection (including non-removable and with prevent_medium_removal flag) when mass storage function (MSF) worker thread exits and gadget fails to handle the situation. Previously, if thread_exits was not specified mass storage function (MSF) did nothing when exiting thread as it's unclear for *function* what to do when it's thread terminates so responsibility of handling this situation was left to the *gadget* using the function. The g_mass_storage handled the situation by unregistering itself (the same thing that file storage gadget does). However, g_multi did nothing and so MSF did not eject LUNs which prevented file system unmounting. Signed-off-by: Michal Nazarewicz <m.nazarewicz@samsung.com> Reviewed-by: Kyungmin Park <kyungmin.park@samsung.com> Cc: David Brownell <dbrownell@users.sourceforge.net> Cc: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget')
-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 a37640eba434..0a18d446e9dd 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);
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c
index 19619fbf20ac..705cc1f76327 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);
135static unsigned long msg_registered = 0; 135static unsigned long msg_registered = 0;
136static void msg_cleanup(void); 136static void msg_cleanup(void);
137 137
138static int msg_thread_exits(struct fsg_common *common)
139{
140 msg_cleanup();
141 return 0;
142}
143
138static int __init msg_do_config(struct usb_configuration *c) 144static int __init msg_do_config(struct usb_configuration *c)
139{ 145{
140 struct fsg_common *common; 146 struct fsg_common *common;
@@ -147,7 +153,7 @@ static int __init msg_do_config(struct usb_configuration *c)
147 } 153 }
148 154
149 fsg_config_from_params(&config, &mod_data); 155 fsg_config_from_params(&config, &mod_data);
150 config.thread_exits = (void(*)(struct fsg_common*))&msg_cleanup; 156 config.thread_exits = msg_thread_exits;
151 common = fsg_common_init(0, c->cdev, &config); 157 common = fsg_common_init(0, c->cdev, &config);
152 if (IS_ERR(common)) 158 if (IS_ERR(common))
153 return PTR_ERR(common); 159 return PTR_ERR(common);