diff options
Diffstat (limited to 'drivers/usb/gadget/file_storage.c')
-rw-r--r-- | drivers/usb/gadget/file_storage.c | 52 |
1 files changed, 22 insertions, 30 deletions
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index a41d9d4baee3..ea09aaa3cab6 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
@@ -224,6 +224,7 @@ | |||
224 | #include <linux/fs.h> | 224 | #include <linux/fs.h> |
225 | #include <linux/init.h> | 225 | #include <linux/init.h> |
226 | #include <linux/kernel.h> | 226 | #include <linux/kernel.h> |
227 | #include <linux/kthread.h> | ||
227 | #include <linux/limits.h> | 228 | #include <linux/limits.h> |
228 | #include <linux/list.h> | 229 | #include <linux/list.h> |
229 | #include <linux/module.h> | 230 | #include <linux/module.h> |
@@ -669,7 +670,6 @@ struct fsg_dev { | |||
669 | wait_queue_head_t thread_wqh; | 670 | wait_queue_head_t thread_wqh; |
670 | int thread_wakeup_needed; | 671 | int thread_wakeup_needed; |
671 | struct completion thread_notifier; | 672 | struct completion thread_notifier; |
672 | int thread_pid; | ||
673 | struct task_struct *thread_task; | 673 | struct task_struct *thread_task; |
674 | sigset_t thread_signal_mask; | 674 | sigset_t thread_signal_mask; |
675 | 675 | ||
@@ -1084,7 +1084,6 @@ static void wakeup_thread(struct fsg_dev *fsg) | |||
1084 | static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state) | 1084 | static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state) |
1085 | { | 1085 | { |
1086 | unsigned long flags; | 1086 | unsigned long flags; |
1087 | struct task_struct *thread_task; | ||
1088 | 1087 | ||
1089 | /* Do nothing if a higher-priority exception is already in progress. | 1088 | /* Do nothing if a higher-priority exception is already in progress. |
1090 | * If a lower-or-equal priority exception is in progress, preempt it | 1089 | * If a lower-or-equal priority exception is in progress, preempt it |
@@ -1093,9 +1092,9 @@ static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state) | |||
1093 | if (fsg->state <= new_state) { | 1092 | if (fsg->state <= new_state) { |
1094 | fsg->exception_req_tag = fsg->ep0_req_tag; | 1093 | fsg->exception_req_tag = fsg->ep0_req_tag; |
1095 | fsg->state = new_state; | 1094 | fsg->state = new_state; |
1096 | thread_task = fsg->thread_task; | 1095 | if (fsg->thread_task) |
1097 | if (thread_task) | 1096 | send_sig_info(SIGUSR1, SEND_SIG_FORCED, |
1098 | send_sig_info(SIGUSR1, SEND_SIG_FORCED, thread_task); | 1097 | fsg->thread_task); |
1099 | } | 1098 | } |
1100 | spin_unlock_irqrestore(&fsg->lock, flags); | 1099 | spin_unlock_irqrestore(&fsg->lock, flags); |
1101 | } | 1100 | } |
@@ -3383,11 +3382,6 @@ static int fsg_main_thread(void *fsg_) | |||
3383 | { | 3382 | { |
3384 | struct fsg_dev *fsg = (struct fsg_dev *) fsg_; | 3383 | struct fsg_dev *fsg = (struct fsg_dev *) fsg_; |
3385 | 3384 | ||
3386 | fsg->thread_task = current; | ||
3387 | |||
3388 | /* Release all our userspace resources */ | ||
3389 | daemonize("file-storage-gadget"); | ||
3390 | |||
3391 | /* Allow the thread to be killed by a signal, but set the signal mask | 3385 | /* Allow the thread to be killed by a signal, but set the signal mask |
3392 | * to block everything but INT, TERM, KILL, and USR1. */ | 3386 | * to block everything but INT, TERM, KILL, and USR1. */ |
3393 | siginitsetinv(&fsg->thread_signal_mask, sigmask(SIGINT) | | 3387 | siginitsetinv(&fsg->thread_signal_mask, sigmask(SIGINT) | |
@@ -3400,9 +3394,6 @@ static int fsg_main_thread(void *fsg_) | |||
3400 | * that expects a __user pointer and it will work okay. */ | 3394 | * that expects a __user pointer and it will work okay. */ |
3401 | set_fs(get_ds()); | 3395 | set_fs(get_ds()); |
3402 | 3396 | ||
3403 | /* Wait for the gadget registration to finish up */ | ||
3404 | wait_for_completion(&fsg->thread_notifier); | ||
3405 | |||
3406 | /* The main loop */ | 3397 | /* The main loop */ |
3407 | while (fsg->state != FSG_STATE_TERMINATED) { | 3398 | while (fsg->state != FSG_STATE_TERMINATED) { |
3408 | if (exception_in_progress(fsg) || signal_pending(current)) { | 3399 | if (exception_in_progress(fsg) || signal_pending(current)) { |
@@ -3440,8 +3431,9 @@ static int fsg_main_thread(void *fsg_) | |||
3440 | spin_unlock_irq(&fsg->lock); | 3431 | spin_unlock_irq(&fsg->lock); |
3441 | } | 3432 | } |
3442 | 3433 | ||
3434 | spin_lock_irq(&fsg->lock); | ||
3443 | fsg->thread_task = NULL; | 3435 | fsg->thread_task = NULL; |
3444 | flush_signals(current); | 3436 | spin_unlock_irq(&fsg->lock); |
3445 | 3437 | ||
3446 | /* In case we are exiting because of a signal, unregister the | 3438 | /* In case we are exiting because of a signal, unregister the |
3447 | * gadget driver and close the backing file. */ | 3439 | * gadget driver and close the backing file. */ |
@@ -3831,12 +3823,11 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3831 | 3823 | ||
3832 | /* Create the LUNs, open their backing files, and register the | 3824 | /* Create the LUNs, open their backing files, and register the |
3833 | * LUN devices in sysfs. */ | 3825 | * LUN devices in sysfs. */ |
3834 | fsg->luns = kmalloc(i * sizeof(struct lun), GFP_KERNEL); | 3826 | fsg->luns = kzalloc(i * sizeof(struct lun), GFP_KERNEL); |
3835 | if (!fsg->luns) { | 3827 | if (!fsg->luns) { |
3836 | rc = -ENOMEM; | 3828 | rc = -ENOMEM; |
3837 | goto out; | 3829 | goto out; |
3838 | } | 3830 | } |
3839 | memset(fsg->luns, 0, i * sizeof(struct lun)); | ||
3840 | fsg->nluns = i; | 3831 | fsg->nluns = i; |
3841 | 3832 | ||
3842 | for (i = 0; i < fsg->nluns; ++i) { | 3833 | for (i = 0; i < fsg->nluns; ++i) { |
@@ -3959,10 +3950,12 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3959 | sprintf(&serial[i], "%02X", c); | 3950 | sprintf(&serial[i], "%02X", c); |
3960 | } | 3951 | } |
3961 | 3952 | ||
3962 | if ((rc = kernel_thread(fsg_main_thread, fsg, (CLONE_VM | CLONE_FS | | 3953 | fsg->thread_task = kthread_create(fsg_main_thread, fsg, |
3963 | CLONE_FILES))) < 0) | 3954 | "file-storage-gadget"); |
3955 | if (IS_ERR(fsg->thread_task)) { | ||
3956 | rc = PTR_ERR(fsg->thread_task); | ||
3964 | goto out; | 3957 | goto out; |
3965 | fsg->thread_pid = rc; | 3958 | } |
3966 | 3959 | ||
3967 | INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); | 3960 | INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); |
3968 | INFO(fsg, "Number of LUNs=%d\n", fsg->nluns); | 3961 | INFO(fsg, "Number of LUNs=%d\n", fsg->nluns); |
@@ -3994,7 +3987,12 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3994 | DBG(fsg, "removable=%d, stall=%d, buflen=%u\n", | 3987 | DBG(fsg, "removable=%d, stall=%d, buflen=%u\n", |
3995 | mod_data.removable, mod_data.can_stall, | 3988 | mod_data.removable, mod_data.can_stall, |
3996 | mod_data.buflen); | 3989 | mod_data.buflen); |
3997 | DBG(fsg, "I/O thread pid: %d\n", fsg->thread_pid); | 3990 | DBG(fsg, "I/O thread pid: %d\n", fsg->thread_task->pid); |
3991 | |||
3992 | set_bit(REGISTERED, &fsg->atomic_bitflags); | ||
3993 | |||
3994 | /* Tell the thread to start working */ | ||
3995 | wake_up_process(fsg->thread_task); | ||
3998 | return 0; | 3996 | return 0; |
3999 | 3997 | ||
4000 | autoconf_fail: | 3998 | autoconf_fail: |
@@ -4046,6 +4044,7 @@ static struct usb_gadget_driver fsg_driver = { | |||
4046 | 4044 | ||
4047 | .driver = { | 4045 | .driver = { |
4048 | .name = (char *) shortname, | 4046 | .name = (char *) shortname, |
4047 | .owner = THIS_MODULE, | ||
4049 | // .release = ... | 4048 | // .release = ... |
4050 | // .suspend = ... | 4049 | // .suspend = ... |
4051 | // .resume = ... | 4050 | // .resume = ... |
@@ -4057,10 +4056,9 @@ static int __init fsg_alloc(void) | |||
4057 | { | 4056 | { |
4058 | struct fsg_dev *fsg; | 4057 | struct fsg_dev *fsg; |
4059 | 4058 | ||
4060 | fsg = kmalloc(sizeof *fsg, GFP_KERNEL); | 4059 | fsg = kzalloc(sizeof *fsg, GFP_KERNEL); |
4061 | if (!fsg) | 4060 | if (!fsg) |
4062 | return -ENOMEM; | 4061 | return -ENOMEM; |
4063 | memset(fsg, 0, sizeof *fsg); | ||
4064 | spin_lock_init(&fsg->lock); | 4062 | spin_lock_init(&fsg->lock); |
4065 | init_rwsem(&fsg->filesem); | 4063 | init_rwsem(&fsg->filesem); |
4066 | init_waitqueue_head(&fsg->thread_wqh); | 4064 | init_waitqueue_head(&fsg->thread_wqh); |
@@ -4086,15 +4084,9 @@ static int __init fsg_init(void) | |||
4086 | if ((rc = fsg_alloc()) != 0) | 4084 | if ((rc = fsg_alloc()) != 0) |
4087 | return rc; | 4085 | return rc; |
4088 | fsg = the_fsg; | 4086 | fsg = the_fsg; |
4089 | if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0) { | 4087 | if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0) |
4090 | fsg_free(fsg); | 4088 | fsg_free(fsg); |
4091 | return rc; | 4089 | return rc; |
4092 | } | ||
4093 | set_bit(REGISTERED, &fsg->atomic_bitflags); | ||
4094 | |||
4095 | /* Tell the thread to start working */ | ||
4096 | complete(&fsg->thread_notifier); | ||
4097 | return 0; | ||
4098 | } | 4090 | } |
4099 | module_init(fsg_init); | 4091 | module_init(fsg_init); |
4100 | 4092 | ||