diff options
author | Michal Nazarewicz <m.nazarewicz@samsung.com> | 2009-11-09 08:15:26 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-12-11 14:55:23 -0500 |
commit | c85efcb9657a7c15e24c1d4745826a80f9a53bbe (patch) | |
tree | e113af4f96b9a232fb8b8c40066d3cb973b45448 | |
parent | 915c8befccbe5d81d441b53ab7a9a98caf0c67d4 (diff) |
USB: g_mass_storage: thread_exits callback added
thread_exits callback has been added to fsg_common structure.
This callback is called when MSF's thread exits (is terminated
by a signal or function is unregistered). It's then gadget's
responsibility to unregister the gadget.
Signed-off-by: Michal Nazarewicz <m.nazarewicz@samsung.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/gadget/f_mass_storage.c | 23 | ||||
-rw-r--r-- | drivers/usb/gadget/mass_storage.c | 20 |
2 files changed, 29 insertions, 14 deletions
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index a6cec37768a9..a37640eba434 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c | |||
@@ -367,6 +367,11 @@ struct fsg_common { | |||
367 | struct completion thread_notifier; | 367 | struct completion thread_notifier; |
368 | struct task_struct *thread_task; | 368 | struct task_struct *thread_task; |
369 | 369 | ||
370 | /* Callback function to call when thread exits. */ | ||
371 | void (*thread_exits)(struct fsg_common *common); | ||
372 | /* Gadget's private data. */ | ||
373 | void *private_data; | ||
374 | |||
370 | /* Vendor (8 chars), product (16 chars), release (4 | 375 | /* Vendor (8 chars), product (16 chars), release (4 |
371 | * hexadecimal digits) and NUL byte */ | 376 | * hexadecimal digits) and NUL byte */ |
372 | char inquiry_string[8 + 16 + 4 + 1]; | 377 | char inquiry_string[8 + 16 + 4 + 1]; |
@@ -387,6 +392,11 @@ struct fsg_config { | |||
387 | const char *lun_name_format; | 392 | const char *lun_name_format; |
388 | const char *thread_name; | 393 | const char *thread_name; |
389 | 394 | ||
395 | /* Callback function to call when thread exits. */ | ||
396 | void (*thread_exits)(struct fsg_common *common); | ||
397 | /* Gadget's private data. */ | ||
398 | void *private_data; | ||
399 | |||
390 | const char *vendor_name; /* 8 characters or less */ | 400 | const char *vendor_name; /* 8 characters or less */ |
391 | const char *product_name; /* 16 characters or less */ | 401 | const char *product_name; /* 16 characters or less */ |
392 | u16 release; | 402 | u16 release; |
@@ -2605,11 +2615,8 @@ static int fsg_main_thread(void *common_) | |||
2605 | common->thread_task = NULL; | 2615 | common->thread_task = NULL; |
2606 | spin_unlock_irq(&common->lock); | 2616 | spin_unlock_irq(&common->lock); |
2607 | 2617 | ||
2608 | /* XXX */ | 2618 | if (common->thread_exits) |
2609 | /* If we are exiting because of a signal, unregister the | 2619 | common->thread_exits(common); |
2610 | * gadget driver. */ | ||
2611 | /* if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags)) */ | ||
2612 | /* usb_gadget_unregister_driver(&fsg_driver); */ | ||
2613 | 2620 | ||
2614 | /* Let the unbind and cleanup routines know the thread has exited */ | 2621 | /* Let the unbind and cleanup routines know the thread has exited */ |
2615 | complete_and_exit(&common->thread_notifier, 0); | 2622 | complete_and_exit(&common->thread_notifier, 0); |
@@ -2672,6 +2679,8 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, | |||
2672 | common->free_storage_on_release = 0; | 2679 | common->free_storage_on_release = 0; |
2673 | } | 2680 | } |
2674 | 2681 | ||
2682 | common->private_data = cfg->private_data; | ||
2683 | |||
2675 | common->gadget = gadget; | 2684 | common->gadget = gadget; |
2676 | common->ep0 = gadget->ep0; | 2685 | common->ep0 = gadget->ep0; |
2677 | common->ep0req = cdev->req; | 2686 | common->ep0req = cdev->req; |
@@ -2791,6 +2800,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, | |||
2791 | 2800 | ||
2792 | 2801 | ||
2793 | /* Tell the thread to start working */ | 2802 | /* Tell the thread to start working */ |
2803 | common->thread_exits = cfg->thread_exits; | ||
2794 | common->thread_task = | 2804 | common->thread_task = |
2795 | kthread_create(fsg_main_thread, common, | 2805 | kthread_create(fsg_main_thread, common, |
2796 | OR(cfg->thread_name, "file-storage")); | 2806 | OR(cfg->thread_name, "file-storage")); |
@@ -3057,6 +3067,9 @@ fsg_config_from_params(struct fsg_config *cfg, | |||
3057 | cfg->product_name = 0; | 3067 | cfg->product_name = 0; |
3058 | cfg->release = 0xffff; | 3068 | cfg->release = 0xffff; |
3059 | 3069 | ||
3070 | cfg->thread_exits = 0; | ||
3071 | cfg->private_data = 0; | ||
3072 | |||
3060 | /* Finalise */ | 3073 | /* Finalise */ |
3061 | cfg->can_stall = params->stall; | 3074 | cfg->can_stall = params->stall; |
3062 | } | 3075 | } |
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index e43ca8f4be14..19619fbf20ac 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c | |||
@@ -132,9 +132,13 @@ static struct fsg_module_parameters mod_data = { | |||
132 | }; | 132 | }; |
133 | FSG_MODULE_PARAMETERS(/* no prefix */, mod_data); | 133 | FSG_MODULE_PARAMETERS(/* no prefix */, mod_data); |
134 | 134 | ||
135 | static unsigned long msg_registered = 0; | ||
136 | static void msg_cleanup(void); | ||
137 | |||
135 | static int __init msg_do_config(struct usb_configuration *c) | 138 | static int __init msg_do_config(struct usb_configuration *c) |
136 | { | 139 | { |
137 | struct fsg_common *common; | 140 | struct fsg_common *common; |
141 | struct fsg_config config; | ||
138 | int ret; | 142 | int ret; |
139 | 143 | ||
140 | if (gadget_is_otg(c->cdev->gadget)) { | 144 | if (gadget_is_otg(c->cdev->gadget)) { |
@@ -142,7 +146,9 @@ static int __init msg_do_config(struct usb_configuration *c) | |||
142 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; | 146 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; |
143 | } | 147 | } |
144 | 148 | ||
145 | common = fsg_common_from_params(0, c->cdev, &mod_data); | 149 | fsg_config_from_params(&config, &mod_data); |
150 | config.thread_exits = (void(*)(struct fsg_common*))&msg_cleanup; | ||
151 | common = fsg_common_init(0, c->cdev, &config); | ||
146 | if (IS_ERR(common)) | 152 | if (IS_ERR(common)) |
147 | return PTR_ERR(common); | 153 | return PTR_ERR(common); |
148 | 154 | ||
@@ -201,11 +207,7 @@ static int __init msg_bind(struct usb_composite_dev *cdev) | |||
201 | return status; | 207 | return status; |
202 | 208 | ||
203 | dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); | 209 | dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); |
204 | return 0; | 210 | set_bit(0, &msg_registered); |
205 | } | ||
206 | |||
207 | static int __exit msg_unbind(struct usb_composite_dev *cdev) | ||
208 | { | ||
209 | return 0; | 211 | return 0; |
210 | } | 212 | } |
211 | 213 | ||
@@ -218,7 +220,6 @@ static struct usb_composite_driver msg_driver = { | |||
218 | .dev = &msg_device_desc, | 220 | .dev = &msg_device_desc, |
219 | .strings = dev_strings, | 221 | .strings = dev_strings, |
220 | .bind = msg_bind, | 222 | .bind = msg_bind, |
221 | .unbind = __exit_p(msg_unbind), | ||
222 | }; | 223 | }; |
223 | 224 | ||
224 | MODULE_DESCRIPTION(DRIVER_DESC); | 225 | MODULE_DESCRIPTION(DRIVER_DESC); |
@@ -231,8 +232,9 @@ static int __init msg_init(void) | |||
231 | } | 232 | } |
232 | module_init(msg_init); | 233 | module_init(msg_init); |
233 | 234 | ||
234 | static void __exit msg_cleanup(void) | 235 | static void msg_cleanup(void) |
235 | { | 236 | { |
236 | usb_composite_unregister(&msg_driver); | 237 | if (test_and_clear_bit(0, &msg_registered)) |
238 | usb_composite_unregister(&msg_driver); | ||
237 | } | 239 | } |
238 | module_exit(msg_cleanup); | 240 | module_exit(msg_cleanup); |