diff options
Diffstat (limited to 'drivers/usb/gadget/f_mass_storage.c')
| -rw-r--r-- | drivers/usb/gadget/f_mass_storage.c | 55 |
1 files changed, 31 insertions, 24 deletions
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index a37640eba434..f4911c09022e 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 | ||
| @@ -614,7 +618,12 @@ static int fsg_setup(struct usb_function *f, | |||
| 614 | return -EDOM; | 618 | return -EDOM; |
| 615 | VDBG(fsg, "get max LUN\n"); | 619 | VDBG(fsg, "get max LUN\n"); |
| 616 | *(u8 *) req->buf = fsg->common->nluns - 1; | 620 | *(u8 *) req->buf = fsg->common->nluns - 1; |
| 617 | return 1; | 621 | |
| 622 | /* Respond with data/status */ | ||
| 623 | req->length = min((u16)1, w_length); | ||
| 624 | fsg->common->ep0req_name = | ||
| 625 | ctrl->bRequestType & USB_DIR_IN ? "ep0-in" : "ep0-out"; | ||
| 626 | return ep0_queue(fsg->common); | ||
| 618 | } | 627 | } |
| 619 | 628 | ||
| 620 | VDBG(fsg, | 629 | VDBG(fsg, |
| @@ -1041,7 +1050,7 @@ static void invalidate_sub(struct fsg_lun *curlun) | |||
| 1041 | unsigned long rc; | 1050 | unsigned long rc; |
| 1042 | 1051 | ||
| 1043 | rc = invalidate_mapping_pages(inode->i_mapping, 0, -1); | 1052 | rc = invalidate_mapping_pages(inode->i_mapping, 0, -1); |
| 1044 | VLDBG(curlun, "invalidate_inode_pages -> %ld\n", rc); | 1053 | VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc); |
| 1045 | } | 1054 | } |
| 1046 | 1055 | ||
| 1047 | static int do_verify(struct fsg_common *common) | 1056 | static int do_verify(struct fsg_common *common) |
| @@ -2524,14 +2533,6 @@ static void handle_exception(struct fsg_common *common) | |||
| 2524 | 2533 | ||
| 2525 | case FSG_STATE_CONFIG_CHANGE: | 2534 | case FSG_STATE_CONFIG_CHANGE: |
| 2526 | rc = do_set_config(common, new_config); | 2535 | rc = do_set_config(common, new_config); |
| 2527 | if (common->ep0_req_tag != exception_req_tag) | ||
| 2528 | break; | ||
| 2529 | if (rc != 0) { /* STALL on errors */ | ||
| 2530 | DBG(common, "ep0 set halt\n"); | ||
| 2531 | usb_ep_set_halt(common->ep0); | ||
| 2532 | } else { /* Complete the status stage */ | ||
| 2533 | ep0_queue(common); | ||
| 2534 | } | ||
| 2535 | break; | 2536 | break; |
| 2536 | 2537 | ||
| 2537 | case FSG_STATE_EXIT: | 2538 | case FSG_STATE_EXIT: |
| @@ -2615,8 +2616,20 @@ static int fsg_main_thread(void *common_) | |||
| 2615 | common->thread_task = NULL; | 2616 | common->thread_task = NULL; |
| 2616 | spin_unlock_irq(&common->lock); | 2617 | spin_unlock_irq(&common->lock); |
| 2617 | 2618 | ||
| 2618 | if (common->thread_exits) | 2619 | if (!common->thread_exits || common->thread_exits(common) < 0) { |
| 2619 | common->thread_exits(common); | 2620 | struct fsg_lun *curlun = common->luns; |
| 2621 | unsigned i = common->nluns; | ||
| 2622 | |||
| 2623 | down_write(&common->filesem); | ||
| 2624 | for (; i--; ++curlun) { | ||
| 2625 | if (!fsg_lun_is_open(curlun)) | ||
| 2626 | continue; | ||
| 2627 | |||
| 2628 | fsg_lun_close(curlun); | ||
| 2629 | curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT; | ||
| 2630 | } | ||
| 2631 | up_write(&common->filesem); | ||
| 2632 | } | ||
| 2620 | 2633 | ||
| 2621 | /* Let the unbind and cleanup routines know the thread has exited */ | 2634 | /* Let the unbind and cleanup routines know the thread has exited */ |
| 2622 | complete_and_exit(&common->thread_notifier, 0); | 2635 | complete_and_exit(&common->thread_notifier, 0); |
| @@ -2763,10 +2776,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, | |||
| 2763 | if (cfg->release != 0xffff) { | 2776 | if (cfg->release != 0xffff) { |
| 2764 | i = cfg->release; | 2777 | i = cfg->release; |
| 2765 | } else { | 2778 | } else { |
| 2766 | /* The sa1100 controller is not supported */ | 2779 | i = usb_gadget_controller_number(gadget); |
| 2767 | i = gadget_is_sa1100(gadget) | ||
| 2768 | ? -1 | ||
| 2769 | : usb_gadget_controller_number(gadget); | ||
| 2770 | if (i >= 0) { | 2780 | if (i >= 0) { |
| 2771 | i = 0x0300 + i; | 2781 | i = 0x0300 + i; |
| 2772 | } else { | 2782 | } else { |
| @@ -2791,8 +2801,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, | |||
| 2791 | * disable stalls. | 2801 | * disable stalls. |
| 2792 | */ | 2802 | */ |
| 2793 | common->can_stall = cfg->can_stall && | 2803 | common->can_stall = cfg->can_stall && |
| 2794 | !(gadget_is_sh(common->gadget) || | 2804 | !(gadget_is_at91(common->gadget)); |
| 2795 | gadget_is_at91(common->gadget)); | ||
| 2796 | 2805 | ||
| 2797 | 2806 | ||
| 2798 | spin_lock_init(&common->lock); | 2807 | spin_lock_init(&common->lock); |
| @@ -2852,7 +2861,6 @@ error_release: | |||
| 2852 | /* Call fsg_common_release() directly, ref might be not | 2861 | /* Call fsg_common_release() directly, ref might be not |
| 2853 | * initialised */ | 2862 | * initialised */ |
| 2854 | fsg_common_release(&common->ref); | 2863 | fsg_common_release(&common->ref); |
| 2855 | complete(&common->thread_notifier); | ||
| 2856 | return ERR_PTR(rc); | 2864 | return ERR_PTR(rc); |
| 2857 | } | 2865 | } |
| 2858 | 2866 | ||
| @@ -2902,7 +2910,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) | |||
| 2902 | } | 2910 | } |
| 2903 | 2911 | ||
| 2904 | 2912 | ||
| 2905 | static int fsg_bind(struct usb_configuration *c, struct usb_function *f) | 2913 | static int __init fsg_bind(struct usb_configuration *c, struct usb_function *f) |
| 2906 | { | 2914 | { |
| 2907 | struct fsg_dev *fsg = fsg_from_func(f); | 2915 | struct fsg_dev *fsg = fsg_from_func(f); |
| 2908 | struct usb_gadget *gadget = c->cdev->gadget; | 2916 | struct usb_gadget *gadget = c->cdev->gadget; |
| @@ -2946,7 +2954,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) | |||
| 2946 | autoconf_fail: | 2954 | autoconf_fail: |
| 2947 | ERROR(fsg, "unable to autoconfigure all endpoints\n"); | 2955 | ERROR(fsg, "unable to autoconfigure all endpoints\n"); |
| 2948 | rc = -ENOTSUPP; | 2956 | rc = -ENOTSUPP; |
| 2949 | fsg_unbind(c, f); | ||
| 2950 | return rc; | 2957 | return rc; |
| 2951 | } | 2958 | } |
| 2952 | 2959 | ||
