diff options
Diffstat (limited to 'drivers/usb/gadget/storage_common.c')
-rw-r--r-- | drivers/usb/gadget/storage_common.c | 105 |
1 files changed, 80 insertions, 25 deletions
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index 04c462ff0ea6..484acfb1a7c5 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c | |||
@@ -57,10 +57,12 @@ | |||
57 | #include <asm/unaligned.h> | 57 | #include <asm/unaligned.h> |
58 | 58 | ||
59 | 59 | ||
60 | /* Thanks to NetChip Technologies for donating this product ID. | 60 | /* |
61 | * Thanks to NetChip Technologies for donating this product ID. | ||
61 | * | 62 | * |
62 | * DO NOT REUSE THESE IDs with any other driver!! Ever!! | 63 | * DO NOT REUSE THESE IDs with any other driver!! Ever!! |
63 | * Instead: allocate your own, using normal USB-IF procedures. */ | 64 | * Instead: allocate your own, using normal USB-IF procedures. |
65 | */ | ||
64 | #define FSG_VENDOR_ID 0x0525 /* NetChip */ | 66 | #define FSG_VENDOR_ID 0x0525 /* NetChip */ |
65 | #define FSG_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */ | 67 | #define FSG_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */ |
66 | 68 | ||
@@ -84,14 +86,27 @@ | |||
84 | #define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args) | 86 | #define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args) |
85 | #define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args) | 87 | #define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args) |
86 | 88 | ||
87 | /* Keep those macros in sync with thos in | 89 | /* |
88 | * include/linux/ubs/composite.h or else GCC will complain. If they | 90 | * Keep those macros in sync with those in |
91 | * include/linux/usb/composite.h or else GCC will complain. If they | ||
89 | * are identical (the same names of arguments, white spaces in the | 92 | * are identical (the same names of arguments, white spaces in the |
90 | * same places) GCC will allow redefinition otherwise (even if some | 93 | * same places) GCC will allow redefinition otherwise (even if some |
91 | * white space is removed or added) warning will be issued. No | 94 | * white space is removed or added) warning will be issued. |
92 | * checking if those symbols is defined is performed because warning | 95 | * |
93 | * is desired when those macros were defined by someone else to mean | 96 | * Those macros are needed here because File Storage Gadget does not |
94 | * something else. */ | 97 | * include the composite.h header. For composite gadgets those macros |
98 | * are redundant since composite.h is included any way. | ||
99 | * | ||
100 | * One could check whether those macros are already defined (which | ||
101 | * would indicate composite.h had been included) or not (which would | ||
102 | * indicate we were in FSG) but this is not done because a warning is | ||
103 | * desired if definitions here differ from the ones in composite.h. | ||
104 | * | ||
105 | * We want the definitions to match and be the same in File Storage | ||
106 | * Gadget as well as Mass Storage Function (and so composite gadgets | ||
107 | * using MSF). If someone changes them in composite.h it will produce | ||
108 | * a warning in this file when building MSF. | ||
109 | */ | ||
95 | #define DBG(d, fmt, args...) dev_dbg(&(d)->gadget->dev , fmt , ## args) | 110 | #define DBG(d, fmt, args...) dev_dbg(&(d)->gadget->dev , fmt , ## args) |
96 | #define VDBG(d, fmt, args...) dev_vdbg(&(d)->gadget->dev , fmt , ## args) | 111 | #define VDBG(d, fmt, args...) dev_vdbg(&(d)->gadget->dev , fmt , ## args) |
97 | #define ERROR(d, fmt, args...) dev_err(&(d)->gadget->dev , fmt , ## args) | 112 | #define ERROR(d, fmt, args...) dev_err(&(d)->gadget->dev , fmt , ## args) |
@@ -269,6 +284,7 @@ struct fsg_lun { | |||
269 | unsigned int prevent_medium_removal:1; | 284 | unsigned int prevent_medium_removal:1; |
270 | unsigned int registered:1; | 285 | unsigned int registered:1; |
271 | unsigned int info_valid:1; | 286 | unsigned int info_valid:1; |
287 | unsigned int nofua:1; | ||
272 | 288 | ||
273 | u32 sense_data; | 289 | u32 sense_data; |
274 | u32 sense_data_info; | 290 | u32 sense_data_info; |
@@ -313,9 +329,11 @@ struct fsg_buffhd { | |||
313 | enum fsg_buffer_state state; | 329 | enum fsg_buffer_state state; |
314 | struct fsg_buffhd *next; | 330 | struct fsg_buffhd *next; |
315 | 331 | ||
316 | /* The NetChip 2280 is faster, and handles some protocol faults | 332 | /* |
333 | * The NetChip 2280 is faster, and handles some protocol faults | ||
317 | * better, if we don't submit any short bulk-out read requests. | 334 | * better, if we don't submit any short bulk-out read requests. |
318 | * So we will record the intended request length here. */ | 335 | * So we will record the intended request length here. |
336 | */ | ||
319 | unsigned int bulk_out_intended_length; | 337 | unsigned int bulk_out_intended_length; |
320 | 338 | ||
321 | struct usb_request *inreq; | 339 | struct usb_request *inreq; |
@@ -395,8 +413,10 @@ fsg_intf_desc = { | |||
395 | .iInterface = FSG_STRING_INTERFACE, | 413 | .iInterface = FSG_STRING_INTERFACE, |
396 | }; | 414 | }; |
397 | 415 | ||
398 | /* Three full-speed endpoint descriptors: bulk-in, bulk-out, | 416 | /* |
399 | * and interrupt-in. */ | 417 | * Three full-speed endpoint descriptors: bulk-in, bulk-out, and |
418 | * interrupt-in. | ||
419 | */ | ||
400 | 420 | ||
401 | static struct usb_endpoint_descriptor | 421 | static struct usb_endpoint_descriptor |
402 | fsg_fs_bulk_in_desc = { | 422 | fsg_fs_bulk_in_desc = { |
@@ -459,7 +479,7 @@ static struct usb_descriptor_header *fsg_fs_function[] = { | |||
459 | * | 479 | * |
460 | * That means alternate endpoint descriptors (bigger packets) | 480 | * That means alternate endpoint descriptors (bigger packets) |
461 | * and a "device qualifier" ... plus more construction options | 481 | * and a "device qualifier" ... plus more construction options |
462 | * for the config descriptor. | 482 | * for the configuration descriptor. |
463 | */ | 483 | */ |
464 | static struct usb_endpoint_descriptor | 484 | static struct usb_endpoint_descriptor |
465 | fsg_hs_bulk_in_desc = { | 485 | fsg_hs_bulk_in_desc = { |
@@ -547,8 +567,10 @@ static struct usb_gadget_strings fsg_stringtab = { | |||
547 | 567 | ||
548 | /*-------------------------------------------------------------------------*/ | 568 | /*-------------------------------------------------------------------------*/ |
549 | 569 | ||
550 | /* If the next two routines are called while the gadget is registered, | 570 | /* |
551 | * the caller must own fsg->filesem for writing. */ | 571 | * If the next two routines are called while the gadget is registered, |
572 | * the caller must own fsg->filesem for writing. | ||
573 | */ | ||
552 | 574 | ||
553 | static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) | 575 | static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) |
554 | { | 576 | { |
@@ -587,8 +609,10 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) | |||
587 | goto out; | 609 | goto out; |
588 | } | 610 | } |
589 | 611 | ||
590 | /* If we can't read the file, it's no good. | 612 | /* |
591 | * If we can't write the file, use it read-only. */ | 613 | * If we can't read the file, it's no good. |
614 | * If we can't write the file, use it read-only. | ||
615 | */ | ||
592 | if (!filp->f_op || !(filp->f_op->read || filp->f_op->aio_read)) { | 616 | if (!filp->f_op || !(filp->f_op->read || filp->f_op->aio_read)) { |
593 | LINFO(curlun, "file not readable: %s\n", filename); | 617 | LINFO(curlun, "file not readable: %s\n", filename); |
594 | goto out; | 618 | goto out; |
@@ -646,8 +670,10 @@ static void fsg_lun_close(struct fsg_lun *curlun) | |||
646 | 670 | ||
647 | /*-------------------------------------------------------------------------*/ | 671 | /*-------------------------------------------------------------------------*/ |
648 | 672 | ||
649 | /* Sync the file data, don't bother with the metadata. | 673 | /* |
650 | * This code was copied from fs/buffer.c:sys_fdatasync(). */ | 674 | * Sync the file data, don't bother with the metadata. |
675 | * This code was copied from fs/buffer.c:sys_fdatasync(). | ||
676 | */ | ||
651 | static int fsg_lun_fsync_sub(struct fsg_lun *curlun) | 677 | static int fsg_lun_fsync_sub(struct fsg_lun *curlun) |
652 | { | 678 | { |
653 | struct file *filp = curlun->filp; | 679 | struct file *filp = curlun->filp; |
@@ -689,6 +715,14 @@ static ssize_t fsg_show_ro(struct device *dev, struct device_attribute *attr, | |||
689 | : curlun->initially_ro); | 715 | : curlun->initially_ro); |
690 | } | 716 | } |
691 | 717 | ||
718 | static ssize_t fsg_show_nofua(struct device *dev, struct device_attribute *attr, | ||
719 | char *buf) | ||
720 | { | ||
721 | struct fsg_lun *curlun = fsg_lun_from_dev(dev); | ||
722 | |||
723 | return sprintf(buf, "%u\n", curlun->nofua); | ||
724 | } | ||
725 | |||
692 | static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr, | 726 | static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr, |
693 | char *buf) | 727 | char *buf) |
694 | { | 728 | { |
@@ -723,26 +757,47 @@ static ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr, | |||
723 | ssize_t rc = count; | 757 | ssize_t rc = count; |
724 | struct fsg_lun *curlun = fsg_lun_from_dev(dev); | 758 | struct fsg_lun *curlun = fsg_lun_from_dev(dev); |
725 | struct rw_semaphore *filesem = dev_get_drvdata(dev); | 759 | struct rw_semaphore *filesem = dev_get_drvdata(dev); |
726 | int i; | 760 | unsigned long ro; |
727 | 761 | ||
728 | if (sscanf(buf, "%d", &i) != 1) | 762 | if (strict_strtoul(buf, 2, &ro)) |
729 | return -EINVAL; | 763 | return -EINVAL; |
730 | 764 | ||
731 | /* Allow the write-enable status to change only while the backing file | 765 | /* |
732 | * is closed. */ | 766 | * Allow the write-enable status to change only while the |
767 | * backing file is closed. | ||
768 | */ | ||
733 | down_read(filesem); | 769 | down_read(filesem); |
734 | if (fsg_lun_is_open(curlun)) { | 770 | if (fsg_lun_is_open(curlun)) { |
735 | LDBG(curlun, "read-only status change prevented\n"); | 771 | LDBG(curlun, "read-only status change prevented\n"); |
736 | rc = -EBUSY; | 772 | rc = -EBUSY; |
737 | } else { | 773 | } else { |
738 | curlun->ro = !!i; | 774 | curlun->ro = ro; |
739 | curlun->initially_ro = !!i; | 775 | curlun->initially_ro = ro; |
740 | LDBG(curlun, "read-only status set to %d\n", curlun->ro); | 776 | LDBG(curlun, "read-only status set to %d\n", curlun->ro); |
741 | } | 777 | } |
742 | up_read(filesem); | 778 | up_read(filesem); |
743 | return rc; | 779 | return rc; |
744 | } | 780 | } |
745 | 781 | ||
782 | static ssize_t fsg_store_nofua(struct device *dev, | ||
783 | struct device_attribute *attr, | ||
784 | const char *buf, size_t count) | ||
785 | { | ||
786 | struct fsg_lun *curlun = fsg_lun_from_dev(dev); | ||
787 | unsigned long nofua; | ||
788 | |||
789 | if (strict_strtoul(buf, 2, &nofua)) | ||
790 | return -EINVAL; | ||
791 | |||
792 | /* Sync data when switching from async mode to sync */ | ||
793 | if (!nofua && curlun->nofua) | ||
794 | fsg_lun_fsync_sub(curlun); | ||
795 | |||
796 | curlun->nofua = nofua; | ||
797 | |||
798 | return count; | ||
799 | } | ||
800 | |||
746 | static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr, | 801 | static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr, |
747 | const char *buf, size_t count) | 802 | const char *buf, size_t count) |
748 | { | 803 | { |