diff options
author | Scott Wood <scottwood@freescale.com> | 2014-04-08 01:00:49 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2014-04-08 19:58:35 (GMT) |
commit | 47d2261a3fa71cde24263559a4219a25e50d8c89 (patch) | |
tree | 28774d5b330ccf1b777a3af222d8356918328013 /drivers/usb/gadget | |
parent | fb7f27080adc65cd5f341bdf56a1d0c14f316c1b (diff) | |
parent | 5fb9d37f27351e42f002e372074249f92cbdf815 (diff) | |
download | linux-fsl-qoriq-47d2261a3fa71cde24263559a4219a25e50d8c89.tar.xz |
Merge branch 'merge' into sdk-v1.6.x
This reverts v3.13-rc3+ (78fd82238d0e5716) to v3.12, except for
commits which I noticed which appear relevant to the SDK.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Conflicts:
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_interrupts.S
arch/powerpc/kvm/e500.c
arch/powerpc/kvm/e500mc.c
arch/powerpc/sysdev/fsl_soc.h
drivers/Kconfig
drivers/cpufreq/ppc-corenet-cpufreq.c
drivers/dma/fsldma.c
drivers/dma/s3c24xx-dma.c
drivers/misc/Makefile
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mtd/devices/m25p80.c
drivers/net/ethernet/freescale/gianfar.h
drivers/platform/Kconfig
drivers/platform/Makefile
drivers/spi/spi-fsl-espi.c
include/crypto/algapi.h
include/linux/netdev_features.h
include/linux/skbuff.h
include/net/ip.h
net/core/ethtool.c
Diffstat (limited to 'drivers/usb/gadget')
28 files changed, 834 insertions, 2085 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index f66d96a..48cddf3 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -58,20 +58,6 @@ config USB_GADGET_DEBUG trying to track down. Never enable these messages for a production build. -config USB_GADGET_VERBOSE - bool "Verbose debugging Messages (DEVELOPMENT)" - depends on USB_GADGET_DEBUG - help - Many controller and gadget drivers will print verbose debugging - messages if you use this option to ask for those messages. - - Avoid enabling these messages, even if you're actively - debugging such a driver. Many drivers will emit so many - messages that the driver timings are affected, which will - either create new failure modes or remove the one you're - trying to track down. Never enable these messages for a - production build. - config USB_GADGET_DEBUG_FILES boolean "Debugging information files (DEVELOPMENT)" depends on PROC_FS @@ -539,9 +525,6 @@ config USB_F_SUBSET config USB_F_RNDIS tristate -config USB_F_MASS_STORAGE - tristate - choice tristate "USB Gadget Drivers" default USB_ETH @@ -679,17 +662,6 @@ config USB_CONFIGFS_PHONET help The Phonet protocol implementation for USB device. -config USB_CONFIGFS_MASS_STORAGE - boolean "Mass storage" - depends on USB_CONFIGFS - depends on BLOCK - select USB_F_MASS_STORAGE - help - The Mass Storage Gadget acts as a USB Mass Storage disk drive. - As its storage repository it can use a regular file or a block - device (in much the same way as the "loop" device driver), - specified as a module parameter or sysfs option. - config USB_ZERO tristate "Gadget Zero (DEVELOPMENT)" select USB_LIBCOMPOSITE @@ -906,7 +878,6 @@ config USB_MASS_STORAGE tristate "Mass Storage Gadget" depends on BLOCK select USB_LIBCOMPOSITE - select USB_F_MASS_STORAGE help The Mass Storage Gadget acts as a USB Mass Storage disk drive. As its storage repository it can use a regular file or a block @@ -1030,7 +1001,6 @@ config USB_G_ACM_MS select USB_LIBCOMPOSITE select USB_U_SERIAL select USB_F_ACM - select USB_F_MASS_STORAGE help This driver provides two functions in one configuration: a mass storage, and a CDC ACM (serial port) link. @@ -1045,8 +1015,8 @@ config USB_G_MULTI select USB_LIBCOMPOSITE select USB_U_SERIAL select USB_U_ETHER + select USB_U_RNDIS select USB_F_ACM - select USB_F_MASS_STORAGE help The Multifunction Composite Gadget provides Ethernet (RNDIS and/or CDC Ethernet), mass storage and ACM serial link @@ -1065,8 +1035,6 @@ config USB_G_MULTI config USB_G_MULTI_RNDIS bool "RNDIS + CDC Serial + Storage configuration" depends on USB_G_MULTI - select USB_U_RNDIS - select USB_F_RNDIS default y help This option enables a configuration with RNDIS, CDC Serial and @@ -1080,7 +1048,6 @@ config USB_G_MULTI_CDC bool "CDC Ethernet + CDC Serial + Storage configuration" depends on USB_G_MULTI default n - select USB_F_ECM help This option enables a configuration with CDC Ethernet (ECM), CDC Serial and Mass Storage functions available in the Multifunction diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index f1af396..386db9d 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -1,8 +1,7 @@ # # USB peripheral controller drivers # -ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG -ccflags-$(CONFIG_USB_GADGET_VERBOSE) += -DVERBOSE_DEBUG +ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG obj-$(CONFIG_USB_GADGET) += udc-core.o obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o @@ -61,8 +60,6 @@ usb_f_ecm_subset-y := f_subset.o obj-$(CONFIG_USB_F_SUBSET) += usb_f_ecm_subset.o usb_f_rndis-y := f_rndis.o obj-$(CONFIG_USB_F_RNDIS) += usb_f_rndis.o -usb_f_mass_storage-y := f_mass_storage.o storage_common.o -obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o # # USB gadget drivers diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c index 7bfa134..4b947bb 100644 --- a/drivers/usb/gadget/acm_ms.c +++ b/drivers/usb/gadget/acm_ms.c @@ -31,7 +31,16 @@ #define ACM_MS_VENDOR_NUM 0x1d6b /* Linux Foundation */ #define ACM_MS_PRODUCT_NUM 0x0106 /* Composite Gadget: ACM + MS*/ -#include "f_mass_storage.h" +/*-------------------------------------------------------------------------*/ + +/* + * Kbuild is not very cooperative with respect to linking separately + * compiled library objects into one module. So for now we won't use + * separate compilation ... ensuring init/exit sections work to shrink + * the runtime footprint, and giving us at least some parts of what + * a "gcc --combine ... part1.c part2.c part3.c ... " build would. + */ +#include "f_mass_storage.c" /*-------------------------------------------------------------------------*/ USB_GADGET_COMPOSITE_OPTIONS(); @@ -95,35 +104,18 @@ static struct usb_gadget_strings *dev_strings[] = { /****************************** Configurations ******************************/ static struct fsg_module_parameters fsg_mod_data = { .stall = 1 }; -#ifdef CONFIG_USB_GADGET_DEBUG_FILES - -static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS; - -#else - -/* - * Number of buffers we will use. - * 2 is usually enough for good buffering pipeline - */ -#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS - -#endif /* CONFIG_USB_DEBUG */ - FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); +static struct fsg_common fsg_common; + /*-------------------------------------------------------------------------*/ static struct usb_function *f_acm; static struct usb_function_instance *f_acm_inst; - -static struct usb_function_instance *fi_msg; -static struct usb_function *f_msg; - /* * We _always_ have both ACM and mass storage functions. */ static int __init acm_ms_do_config(struct usb_configuration *c) { - struct fsg_opts *opts; int status; if (gadget_is_otg(c->cdev->gadget)) { @@ -131,37 +123,31 @@ static int __init acm_ms_do_config(struct usb_configuration *c) c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - opts = fsg_opts_from_func_inst(fi_msg); + f_acm_inst = usb_get_function_instance("acm"); + if (IS_ERR(f_acm_inst)) + return PTR_ERR(f_acm_inst); f_acm = usb_get_function(f_acm_inst); - if (IS_ERR(f_acm)) - return PTR_ERR(f_acm); - - f_msg = usb_get_function(fi_msg); - if (IS_ERR(f_msg)) { - status = PTR_ERR(f_msg); - goto put_acm; + if (IS_ERR(f_acm)) { + status = PTR_ERR(f_acm); + goto err_func; } status = usb_add_function(c, f_acm); if (status < 0) - goto put_msg; - - status = fsg_common_run_thread(opts->common); - if (status) - goto remove_acm; + goto err_conf; - status = usb_add_function(c, f_msg); - if (status) - goto remove_acm; + status = fsg_bind_config(c->cdev, c, &fsg_common); + if (status < 0) + goto err_fsg; return 0; -remove_acm: +err_fsg: usb_remove_function(c, f_acm); -put_msg: - usb_put_function(f_msg); -put_acm: +err_conf: usb_put_function(f_acm); +err_func: + usb_put_function_instance(f_acm_inst); return status; } @@ -177,82 +163,45 @@ static struct usb_configuration acm_ms_config_driver = { static int __init acm_ms_bind(struct usb_composite_dev *cdev) { struct usb_gadget *gadget = cdev->gadget; - struct fsg_opts *opts; - struct fsg_config config; int status; - - f_acm_inst = usb_get_function_instance("acm"); - if (IS_ERR(f_acm_inst)) - return PTR_ERR(f_acm_inst); - - fi_msg = usb_get_function_instance("mass_storage"); - if (IS_ERR(fi_msg)) { - status = PTR_ERR(fi_msg); - goto fail_get_msg; - } + void *retp; /* set up mass storage function */ - fsg_config_from_params(&config, &fsg_mod_data, fsg_num_buffers); - opts = fsg_opts_from_func_inst(fi_msg); - - opts->no_configfs = true; - status = fsg_common_set_num_buffers(opts->common, fsg_num_buffers); - if (status) - goto fail; - - status = fsg_common_set_nluns(opts->common, config.nluns); - if (status) - goto fail_set_nluns; - - status = fsg_common_set_cdev(opts->common, cdev, config.can_stall); - if (status) - goto fail_set_cdev; - - fsg_common_set_sysfs(opts->common, true); - status = fsg_common_create_luns(opts->common, &config); - if (status) - goto fail_set_cdev; + retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data); + if (IS_ERR(retp)) { + status = PTR_ERR(retp); + return PTR_ERR(retp); + } - fsg_common_set_inquiry_string(opts->common, config.vendor_name, - config.product_name); /* * Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. */ status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) - goto fail_string_ids; + goto fail1; device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; /* register our configuration */ status = usb_add_config(cdev, &acm_ms_config_driver, acm_ms_do_config); if (status < 0) - goto fail_string_ids; + goto fail1; usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC); + fsg_common_put(&fsg_common); return 0; /* error recovery */ -fail_string_ids: - fsg_common_remove_luns(opts->common); -fail_set_cdev: - fsg_common_free_luns(opts->common); -fail_set_nluns: - fsg_common_free_buffers(opts->common); -fail: - usb_put_function_instance(fi_msg); -fail_get_msg: - usb_put_function_instance(f_acm_inst); +fail1: + fsg_common_put(&fsg_common); return status; } static int __exit acm_ms_unbind(struct usb_composite_dev *cdev) { - usb_put_function(f_msg); - usb_put_function_instance(fi_msg); usb_put_function(f_acm); usb_put_function_instance(f_acm_inst); return 0; diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 54a1e29..a9a4346 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -3078,6 +3078,8 @@ static void udc_pci_remove(struct pci_dev *pdev) if (dev->active) pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + udc_remove(dev); } diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 2018ba1..d4f0f33 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -354,7 +354,7 @@ static u8 encode_bMaxPower(enum usb_device_speed speed, return DIV_ROUND_UP(val, 8); default: return DIV_ROUND_UP(val, 2); - } + }; } static int config_buf(struct usb_configuration *config, @@ -593,7 +593,6 @@ static void reset_config(struct usb_composite_dev *cdev) bitmap_zero(f->endpoints, 32); } cdev->config = NULL; - cdev->delayed_status = 0; } static int set_config(struct usb_composite_dev *cdev, diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 2588511..8f0d614 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -557,7 +557,7 @@ static struct config_group *function_make( fi = usb_get_function_instance(func_name); if (IS_ERR(fi)) - return ERR_CAST(fi); + return ERR_PTR(PTR_ERR(fi)); ret = config_item_set_name(&fi->group.cg_item, name); if (ret) { @@ -991,14 +991,6 @@ static struct configfs_subsystem gadget_subsys = { .su_mutex = __MUTEX_INITIALIZER(gadget_subsys.su_mutex), }; -void unregister_gadget_item(struct config_item *item) -{ - struct gadget_info *gi = to_gadget_info(item); - - unregister_gadget(gi); -} -EXPORT_SYMBOL(unregister_gadget_item); - static int __init gadget_cfs_init(void) { int ret; diff --git a/drivers/usb/gadget/configfs.h b/drivers/usb/gadget/configfs.h deleted file mode 100644 index a7b564a..0000000 --- a/drivers/usb/gadget/configfs.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef USB__GADGET__CONFIGFS__H -#define USB__GADGET__CONFIGFS__H - -void unregister_gadget_item(struct config_item *item); - -#endif /* USB__GADGET__CONFIGFS__H */ diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 8f4dae3..b8a2376 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -544,7 +544,7 @@ static int dummy_enable(struct usb_ep *_ep, default: val = "ctrl"; break; - } val; }), + }; val; }), max, ep->stream_en ? "enabled" : "disabled"); /* at this point real hardware should be NAKing transfers @@ -2271,7 +2271,7 @@ static inline ssize_t show_urb(char *buf, size_t size, struct urb *urb) default: s = "?"; break; - } s; }), + }; s; }), ep, ep ? (usb_pipein(urb->pipe) ? "in" : "out") : "", ({ char *s; \ switch (usb_pipetype(urb->pipe)) { \ @@ -2287,7 +2287,7 @@ static inline ssize_t show_urb(char *buf, size_t size, struct urb *urb) default: \ s = "-iso"; \ break; \ - } s; }), + }; s; }), urb->actual_length, urb->transfer_buffer_length); } diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 241fc87..44cf775 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -373,7 +373,7 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len) if (req->buf == NULL) req->buf = (void *)0xDEADBABE; - reinit_completion(&ffs->ep0req_completion); + INIT_COMPLETION(ffs->ep0req_completion); ret = usb_ep_queue(ffs->gadget->ep0, req, GFP_ATOMIC); if (unlikely(ret < 0)) @@ -1304,7 +1304,7 @@ static struct ffs_data *ffs_data_new(void) { struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL); if (unlikely(!ffs)) - return NULL; + return 0; ENTER(); diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index b963939..a01d7d3 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -213,14 +213,12 @@ #include <linux/spinlock.h> #include <linux/string.h> #include <linux/freezer.h> -#include <linux/module.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> #include <linux/usb/composite.h> #include "gadget_chips.h" -#include "configfs.h" /*------------------------------------------------------------------------*/ @@ -230,30 +228,26 @@ static const char fsg_string_interface[] = "Mass Storage"; -#include "storage_common.h" -#include "f_mass_storage.h" +#include "storage_common.c" -/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */ -static struct usb_string fsg_strings[] = { - {FSG_STRING_INTERFACE, fsg_string_interface}, - {} -}; - -static struct usb_gadget_strings fsg_stringtab = { - .language = 0x0409, /* en-us */ - .strings = fsg_strings, -}; - -static struct usb_gadget_strings *fsg_strings_array[] = { - &fsg_stringtab, - NULL, -}; /*-------------------------------------------------------------------------*/ struct fsg_dev; struct fsg_common; +/* FSF callback functions */ +struct fsg_operations { + /* + * Callback function to call when thread exits. If no + * callback is set or it returns value lower then zero MSF + * will force eject all LUNs it operates on (including those + * marked as non-removable or with prevent_medium_removal flag + * set). + */ + int (*thread_exits)(struct fsg_common *common); +}; + /* Data shared by all the FSG instances. */ struct fsg_common { struct usb_gadget *gadget; @@ -274,14 +268,13 @@ struct fsg_common { struct fsg_buffhd *next_buffhd_to_fill; struct fsg_buffhd *next_buffhd_to_drain; struct fsg_buffhd *buffhds; - unsigned int fsg_num_buffers; int cmnd_size; u8 cmnd[MAX_COMMAND_SIZE]; unsigned int nluns; unsigned int lun; - struct fsg_lun **luns; + struct fsg_lun *luns; struct fsg_lun *curlun; unsigned int bulk_out_maxpacket; @@ -301,7 +294,6 @@ struct fsg_common { unsigned int short_packet_received:1; unsigned int bad_lun_okay:1; unsigned int running:1; - unsigned int sysfs:1; int thread_wakeup_needed; struct completion thread_notifier; @@ -321,6 +313,27 @@ struct fsg_common { struct kref ref; }; +struct fsg_config { + unsigned nluns; + struct fsg_lun_config { + const char *filename; + char ro; + char removable; + char cdrom; + char nofua; + } luns[FSG_MAX_LUNS]; + + /* Callback functions. */ + const struct fsg_operations *ops; + /* Gadget's private data. */ + void *private_data; + + const char *vendor_name; /* 8 characters or less */ + const char *product_name; /* 16 characters or less */ + + char can_stall; +}; + struct fsg_dev { struct usb_function function; struct usb_gadget *gadget; /* Copy of cdev->gadget */ @@ -523,7 +536,7 @@ static int fsg_setup(struct usb_function *f, */ DBG(fsg, "bulk reset request\n"); raise_exception(fsg->common, FSG_STATE_RESET); - return USB_GADGET_DELAYED_STATUS; + return DELAYED_STATUS; case US_BULK_GET_MAX_LUN: if (ctrl->bRequestType != @@ -602,14 +615,13 @@ static bool start_out_transfer(struct fsg_common *common, struct fsg_buffhd *bh) return true; } -static int sleep_thread(struct fsg_common *common, bool can_freeze) +static int sleep_thread(struct fsg_common *common) { int rc = 0; /* Wait until a signal arrives or we are woken up */ for (;;) { - if (can_freeze) - try_to_freeze(); + try_to_freeze(); set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) { rc = -EINTR; @@ -683,7 +695,7 @@ static int do_read(struct fsg_common *common) /* Wait for the next buffer to become available */ bh = common->next_buffhd_to_fill; while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common, false); + rc = sleep_thread(common); if (rc) return rc; } @@ -938,7 +950,7 @@ static int do_write(struct fsg_common *common) } /* Wait for something to happen */ - rc = sleep_thread(common, false); + rc = sleep_thread(common); if (rc) return rc; } @@ -1505,7 +1517,7 @@ static int throw_away_data(struct fsg_common *common) } /* Otherwise wait for something to happen */ - rc = sleep_thread(common, true); + rc = sleep_thread(common); if (rc) return rc; } @@ -1626,7 +1638,7 @@ static int send_status(struct fsg_common *common) /* Wait for the next buffer to become available */ bh = common->next_buffhd_to_fill; while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common, true); + rc = sleep_thread(common); if (rc) return rc; } @@ -1829,7 +1841,7 @@ static int do_scsi_command(struct fsg_common *common) bh = common->next_buffhd_to_fill; common->next_buffhd_to_drain = bh; while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common, true); + rc = sleep_thread(common); if (rc) return rc; } @@ -2160,7 +2172,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) common->data_dir = DATA_DIR_NONE; common->lun = cbw->Lun; if (common->lun < common->nluns) - common->curlun = common->luns[common->lun]; + common->curlun = &common->luns[common->lun]; else common->curlun = NULL; common->tag = cbw->Tag; @@ -2175,7 +2187,7 @@ static int get_next_command(struct fsg_common *common) /* Wait for the next buffer to become available */ bh = common->next_buffhd_to_fill; while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common, true); + rc = sleep_thread(common); if (rc) return rc; } @@ -2194,7 +2206,7 @@ static int get_next_command(struct fsg_common *common) /* Wait for the CBW to arrive */ while (bh->state != BUF_STATE_FULL) { - rc = sleep_thread(common, true); + rc = sleep_thread(common); if (rc) return rc; } @@ -2232,7 +2244,7 @@ reset: if (common->fsg) { fsg = common->fsg; - for (i = 0; i < common->fsg_num_buffers; ++i) { + for (i = 0; i < fsg_num_buffers; ++i) { struct fsg_buffhd *bh = &common->buffhds[i]; if (bh->inreq) { @@ -2291,7 +2303,7 @@ reset: clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); /* Allocate the requests */ - for (i = 0; i < common->fsg_num_buffers; ++i) { + for (i = 0; i < fsg_num_buffers; ++i) { struct fsg_buffhd *bh = &common->buffhds[i]; rc = alloc_request(common, fsg->bulk_in, &bh->inreq); @@ -2308,9 +2320,7 @@ reset: common->running = 1; for (i = 0; i < common->nluns; ++i) - if (common->luns[i]) - common->luns[i]->unit_attention_data = - SS_RESET_OCCURRED; + common->luns[i].unit_attention_data = SS_RESET_OCCURRED; return rc; } @@ -2362,7 +2372,7 @@ static void handle_exception(struct fsg_common *common) /* Cancel all the pending transfers */ if (likely(common->fsg)) { - for (i = 0; i < common->fsg_num_buffers; ++i) { + for (i = 0; i < fsg_num_buffers; ++i) { bh = &common->buffhds[i]; if (bh->inreq_busy) usb_ep_dequeue(common->fsg->bulk_in, bh->inreq); @@ -2374,13 +2384,13 @@ static void handle_exception(struct fsg_common *common) /* Wait until everything is idle */ for (;;) { int num_active = 0; - for (i = 0; i < common->fsg_num_buffers; ++i) { + for (i = 0; i < fsg_num_buffers; ++i) { bh = &common->buffhds[i]; num_active += bh->inreq_busy + bh->outreq_busy; } if (num_active == 0) break; - if (sleep_thread(common, true)) + if (sleep_thread(common)) return; } @@ -2397,7 +2407,7 @@ static void handle_exception(struct fsg_common *common) */ spin_lock_irq(&common->lock); - for (i = 0; i < common->fsg_num_buffers; ++i) { + for (i = 0; i < fsg_num_buffers; ++i) { bh = &common->buffhds[i]; bh->state = BUF_STATE_EMPTY; } @@ -2410,9 +2420,7 @@ static void handle_exception(struct fsg_common *common) common->state = FSG_STATE_STATUS_PHASE; else { for (i = 0; i < common->nluns; ++i) { - curlun = common->luns[i]; - if (!curlun) - continue; + curlun = &common->luns[i]; curlun->prevent_medium_removal = 0; curlun->sense_data = SS_NO_SENSE; curlun->unit_attention_data = SS_NO_SENSE; @@ -2454,9 +2462,8 @@ static void handle_exception(struct fsg_common *common) * CONFIG_CHANGE cases. */ /* for (i = 0; i < common->nluns; ++i) */ - /* if (common->luns[i]) */ - /* common->luns[i]->unit_attention_data = */ - /* SS_RESET_OCCURRED; */ + /* common->luns[i].unit_attention_data = */ + /* SS_RESET_OCCURRED; */ break; case FSG_STATE_CONFIG_CHANGE: @@ -2517,7 +2524,7 @@ static int fsg_main_thread(void *common_) } if (!common->running) { - sleep_thread(common, true); + sleep_thread(common); continue; } @@ -2552,13 +2559,12 @@ static int fsg_main_thread(void *common_) if (!common->ops || !common->ops->thread_exits || common->ops->thread_exits(common) < 0) { - struct fsg_lun **curlun_it = common->luns; + struct fsg_lun *curlun = common->luns; unsigned i = common->nluns; down_write(&common->filesem); - for (; i--; ++curlun_it) { - struct fsg_lun *curlun = *curlun_it; - if (!curlun || !fsg_lun_is_open(curlun)) + for (; i--; ++curlun) { + if (!fsg_lun_is_open(curlun)) continue; fsg_lun_close(curlun); @@ -2574,56 +2580,6 @@ static int fsg_main_thread(void *common_) /*************************** DEVICE ATTRIBUTES ***************************/ -static ssize_t ro_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct fsg_lun *curlun = fsg_lun_from_dev(dev); - - return fsg_show_ro(curlun, buf); -} - -static ssize_t nofua_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct fsg_lun *curlun = fsg_lun_from_dev(dev); - - return fsg_show_nofua(curlun, buf); -} - -static ssize_t file_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct fsg_lun *curlun = fsg_lun_from_dev(dev); - struct rw_semaphore *filesem = dev_get_drvdata(dev); - - return fsg_show_file(curlun, filesem, buf); -} - -static ssize_t ro_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct fsg_lun *curlun = fsg_lun_from_dev(dev); - struct rw_semaphore *filesem = dev_get_drvdata(dev); - - return fsg_store_ro(curlun, filesem, buf, count); -} - -static ssize_t nofua_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct fsg_lun *curlun = fsg_lun_from_dev(dev); - - return fsg_store_nofua(curlun, buf, count); -} - -static ssize_t file_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct fsg_lun *curlun = fsg_lun_from_dev(dev); - struct rw_semaphore *filesem = dev_get_drvdata(dev); - - return fsg_store_file(curlun, filesem, buf, count); -} - static DEVICE_ATTR_RW(ro); static DEVICE_ATTR_RW(nofua); static DEVICE_ATTR_RW(file); @@ -2641,422 +2597,221 @@ static void fsg_lun_release(struct device *dev) /* Nothing needs to be done */ } -void fsg_common_get(struct fsg_common *common) +static inline void fsg_common_get(struct fsg_common *common) { kref_get(&common->ref); } -EXPORT_SYMBOL_GPL(fsg_common_get); -void fsg_common_put(struct fsg_common *common) +static inline void fsg_common_put(struct fsg_common *common) { kref_put(&common->ref, fsg_common_release); } -EXPORT_SYMBOL_GPL(fsg_common_put); -/* check if fsg_num_buffers is within a valid range */ -static inline int fsg_num_buffers_validate(unsigned int fsg_num_buffers) +static struct fsg_common *fsg_common_init(struct fsg_common *common, + struct usb_composite_dev *cdev, + struct fsg_config *cfg) { - if (fsg_num_buffers >= 2 && fsg_num_buffers <= 4) - return 0; - pr_err("fsg_num_buffers %u is out of range (%d to %d)\n", - fsg_num_buffers, 2, 4); - return -EINVAL; -} + struct usb_gadget *gadget = cdev->gadget; + struct fsg_buffhd *bh; + struct fsg_lun *curlun; + struct fsg_lun_config *lcfg; + int nluns, i, rc; + char *pathbuf; -static struct fsg_common *fsg_common_setup(struct fsg_common *common) -{ + rc = fsg_num_buffers_validate(); + if (rc != 0) + return ERR_PTR(rc); + + /* Find out how many LUNs there should be */ + nluns = cfg->nluns; + if (nluns < 1 || nluns > FSG_MAX_LUNS) { + dev_err(&gadget->dev, "invalid number of LUNs: %u\n", nluns); + return ERR_PTR(-EINVAL); + } + + /* Allocate? */ if (!common) { - common = kzalloc(sizeof(*common), GFP_KERNEL); + common = kzalloc(sizeof *common, GFP_KERNEL); if (!common) return ERR_PTR(-ENOMEM); common->free_storage_on_release = 1; } else { + memset(common, 0, sizeof *common); common->free_storage_on_release = 0; } - init_rwsem(&common->filesem); - spin_lock_init(&common->lock); - kref_init(&common->ref); - init_completion(&common->thread_notifier); - init_waitqueue_head(&common->fsg_wait); - common->state = FSG_STATE_TERMINATED; - return common; -} - -void fsg_common_set_sysfs(struct fsg_common *common, bool sysfs) -{ - common->sysfs = sysfs; -} -EXPORT_SYMBOL_GPL(fsg_common_set_sysfs); - -static void _fsg_common_free_buffers(struct fsg_buffhd *buffhds, unsigned n) -{ - if (buffhds) { - struct fsg_buffhd *bh = buffhds; - while (n--) { - kfree(bh->buf); - ++bh; - } - kfree(buffhds); + common->buffhds = kcalloc(fsg_num_buffers, + sizeof *(common->buffhds), GFP_KERNEL); + if (!common->buffhds) { + if (common->free_storage_on_release) + kfree(common); + return ERR_PTR(-ENOMEM); } -} -int fsg_common_set_num_buffers(struct fsg_common *common, unsigned int n) -{ - struct fsg_buffhd *bh, *buffhds; - int i, rc; - - rc = fsg_num_buffers_validate(n); - if (rc != 0) - return rc; + common->ops = cfg->ops; + common->private_data = cfg->private_data; - buffhds = kcalloc(n, sizeof(*buffhds), GFP_KERNEL); - if (!buffhds) - return -ENOMEM; + common->gadget = gadget; + common->ep0 = gadget->ep0; + common->ep0req = cdev->req; + common->cdev = cdev; - /* Data buffers cyclic list */ - bh = buffhds; - i = n; - goto buffhds_first_it; - do { - bh->next = bh + 1; - ++bh; -buffhds_first_it: - bh->buf = kmalloc(FSG_BUFLEN, GFP_KERNEL); - if (unlikely(!bh->buf)) + /* Maybe allocate device-global string IDs, and patch descriptors */ + if (fsg_strings[FSG_STRING_INTERFACE].id == 0) { + rc = usb_string_id(cdev); + if (unlikely(rc < 0)) goto error_release; - } while (--i); - bh->next = buffhds; - - _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers); - common->fsg_num_buffers = n; - common->buffhds = buffhds; - - return 0; - -error_release: - /* - * "buf"s pointed to by heads after n - i are NULL - * so releasing them won't hurt - */ - _fsg_common_free_buffers(buffhds, n); - - return -ENOMEM; -} -EXPORT_SYMBOL_GPL(fsg_common_set_num_buffers); + fsg_strings[FSG_STRING_INTERFACE].id = rc; + fsg_intf_desc.iInterface = rc; + } -static inline void fsg_common_remove_sysfs(struct fsg_lun *lun) -{ - device_remove_file(&lun->dev, &dev_attr_nofua); /* - * device_remove_file() => - * - * here the attr (e.g. dev_attr_ro) is only used to be passed to: - * - * sysfs_remove_file() => - * - * here e.g. both dev_attr_ro_cdrom and dev_attr_ro are in - * the same namespace and - * from here only attr->name is passed to: - * - * sysfs_hash_and_remove() - * - * attr->name is the same for dev_attr_ro_cdrom and - * dev_attr_ro - * attr->name is the same for dev_attr_file and - * dev_attr_file_nonremovable - * - * so we don't differentiate between removing e.g. dev_attr_ro_cdrom - * and dev_attr_ro + * Create the LUNs, open their backing files, and register the + * LUN devices in sysfs. */ - device_remove_file(&lun->dev, &dev_attr_ro); - device_remove_file(&lun->dev, &dev_attr_file); -} - -void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs) -{ - if (sysfs) { - fsg_common_remove_sysfs(lun); - device_unregister(&lun->dev); + curlun = kcalloc(nluns, sizeof(*curlun), GFP_KERNEL); + if (unlikely(!curlun)) { + rc = -ENOMEM; + goto error_release; } - fsg_lun_close(lun); - kfree(lun); -} -EXPORT_SYMBOL_GPL(fsg_common_remove_lun); + common->luns = curlun; -static void _fsg_common_remove_luns(struct fsg_common *common, int n) -{ - int i; + init_rwsem(&common->filesem); - for (i = 0; i < n; ++i) - if (common->luns[i]) { - fsg_common_remove_lun(common->luns[i], common->sysfs); - common->luns[i] = NULL; + for (i = 0, lcfg = cfg->luns; i < nluns; ++i, ++curlun, ++lcfg) { + curlun->cdrom = !!lcfg->cdrom; + curlun->ro = lcfg->cdrom || lcfg->ro; + curlun->initially_ro = curlun->ro; + curlun->removable = lcfg->removable; + curlun->dev.release = fsg_lun_release; + curlun->dev.parent = &gadget->dev; + /* curlun->dev.driver = &fsg_driver.driver; XXX */ + dev_set_drvdata(&curlun->dev, &common->filesem); + dev_set_name(&curlun->dev, "lun%d", i); + + rc = device_register(&curlun->dev); + if (rc) { + INFO(common, "failed to register LUN%d: %d\n", i, rc); + common->nluns = i; + put_device(&curlun->dev); + goto error_release; } -} -EXPORT_SYMBOL_GPL(fsg_common_remove_luns); - -void fsg_common_remove_luns(struct fsg_common *common) -{ - _fsg_common_remove_luns(common, common->nluns); -} - -void fsg_common_free_luns(struct fsg_common *common) -{ - fsg_common_remove_luns(common); - kfree(common->luns); - common->luns = NULL; -} -EXPORT_SYMBOL_GPL(fsg_common_free_luns); -int fsg_common_set_nluns(struct fsg_common *common, int nluns) -{ - struct fsg_lun **curlun; + rc = device_create_file(&curlun->dev, + curlun->cdrom + ? &dev_attr_ro_cdrom + : &dev_attr_ro); + if (rc) + goto error_luns; + rc = device_create_file(&curlun->dev, + curlun->removable + ? &dev_attr_file + : &dev_attr_file_nonremovable); + if (rc) + goto error_luns; + rc = device_create_file(&curlun->dev, &dev_attr_nofua); + if (rc) + goto error_luns; - /* Find out how many LUNs there should be */ - if (nluns < 1 || nluns > FSG_MAX_LUNS) { - pr_err("invalid number of LUNs: %u\n", nluns); - return -EINVAL; + if (lcfg->filename) { + rc = fsg_lun_open(curlun, lcfg->filename); + if (rc) + goto error_luns; + } else if (!curlun->removable) { + ERROR(common, "no file given for LUN%d\n", i); + rc = -EINVAL; + goto error_luns; + } } - - curlun = kcalloc(nluns, sizeof(*curlun), GFP_KERNEL); - if (unlikely(!curlun)) - return -ENOMEM; - - if (common->luns) - fsg_common_free_luns(common); - - common->luns = curlun; common->nluns = nluns; - pr_info("Number of LUNs=%d\n", common->nluns); - - return 0; -} -EXPORT_SYMBOL_GPL(fsg_common_set_nluns); - -void fsg_common_set_ops(struct fsg_common *common, - const struct fsg_operations *ops) -{ - common->ops = ops; -} -EXPORT_SYMBOL_GPL(fsg_common_set_ops); - -void fsg_common_free_buffers(struct fsg_common *common) -{ - _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers); - common->buffhds = NULL; -} -EXPORT_SYMBOL_GPL(fsg_common_free_buffers); - -int fsg_common_set_cdev(struct fsg_common *common, - struct usb_composite_dev *cdev, bool can_stall) -{ - struct usb_string *us; - - common->gadget = cdev->gadget; - common->ep0 = cdev->gadget->ep0; - common->ep0req = cdev->req; - common->cdev = cdev; - - us = usb_gstrings_attach(cdev, fsg_strings_array, - ARRAY_SIZE(fsg_strings)); - if (IS_ERR(us)) - return PTR_ERR(us); + /* Data buffers cyclic list */ + bh = common->buffhds; + i = fsg_num_buffers; + goto buffhds_first_it; + do { + bh->next = bh + 1; + ++bh; +buffhds_first_it: + bh->buf = kmalloc(FSG_BUFLEN, GFP_KERNEL); + if (unlikely(!bh->buf)) { + rc = -ENOMEM; + goto error_release; + } + } while (--i); + bh->next = common->buffhds; - fsg_intf_desc.iInterface = us[FSG_STRING_INTERFACE].id; + /* Prepare inquiryString */ + i = get_default_bcdDevice(); + snprintf(common->inquiry_string, sizeof common->inquiry_string, + "%-8s%-16s%04x", cfg->vendor_name ?: "Linux", + /* Assume product name dependent on the first LUN */ + cfg->product_name ?: (common->luns->cdrom + ? "File-CD Gadget" + : "File-Stor Gadget"), + i); /* * Some peripheral controllers are known not to be able to * halt bulk endpoints correctly. If one of them is present, * disable stalls. */ - common->can_stall = can_stall && !(gadget_is_at91(common->gadget)); - - return 0; -} -EXPORT_SYMBOL_GPL(fsg_common_set_cdev); - -static inline int fsg_common_add_sysfs(struct fsg_common *common, - struct fsg_lun *lun) -{ - int rc; + common->can_stall = cfg->can_stall && + !(gadget_is_at91(common->gadget)); - rc = device_register(&lun->dev); - if (rc) { - put_device(&lun->dev); - return rc; - } - - rc = device_create_file(&lun->dev, - lun->cdrom - ? &dev_attr_ro_cdrom - : &dev_attr_ro); - if (rc) - goto error; - rc = device_create_file(&lun->dev, - lun->removable - ? &dev_attr_file - : &dev_attr_file_nonremovable); - if (rc) - goto error; - rc = device_create_file(&lun->dev, &dev_attr_nofua); - if (rc) - goto error; - - return 0; - -error: - /* removing nonexistent files is a no-op */ - fsg_common_remove_sysfs(lun); - device_unregister(&lun->dev); - return rc; -} - -int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, - unsigned int id, const char *name, - const char **name_pfx) -{ - struct fsg_lun *lun; - char *pathbuf, *p; - int rc = -ENOMEM; - - if (!common->nluns || !common->luns) - return -ENODEV; - - if (common->luns[id]) - return -EBUSY; - - if (!cfg->filename && !cfg->removable) { - pr_err("no file given for LUN%d\n", id); - return -EINVAL; - } - - lun = kzalloc(sizeof(*lun), GFP_KERNEL); - if (!lun) - return -ENOMEM; - - lun->name_pfx = name_pfx; - - lun->cdrom = !!cfg->cdrom; - lun->ro = cfg->cdrom || cfg->ro; - lun->initially_ro = lun->ro; - lun->removable = !!cfg->removable; - - if (!common->sysfs) { - /* we DON'T own the name!*/ - lun->name = name; - } else { - lun->dev.release = fsg_lun_release; - lun->dev.parent = &common->gadget->dev; - dev_set_drvdata(&lun->dev, &common->filesem); - dev_set_name(&lun->dev, "%s", name); - lun->name = dev_name(&lun->dev); + spin_lock_init(&common->lock); + kref_init(&common->ref); - rc = fsg_common_add_sysfs(common, lun); - if (rc) { - pr_info("failed to register LUN%d: %d\n", id, rc); - goto error_sysfs; - } + /* Tell the thread to start working */ + common->thread_task = + kthread_create(fsg_main_thread, common, "file-storage"); + if (IS_ERR(common->thread_task)) { + rc = PTR_ERR(common->thread_task); + goto error_release; } + init_completion(&common->thread_notifier); + init_waitqueue_head(&common->fsg_wait); - common->luns[id] = lun; - - if (cfg->filename) { - rc = fsg_lun_open(lun, cfg->filename); - if (rc) - goto error_lun; - } + /* Information */ + INFO(common, FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n"); + INFO(common, "Number of LUNs=%d\n", common->nluns); pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); - p = "(no medium)"; - if (fsg_lun_is_open(lun)) { - p = "(error)"; - if (pathbuf) { - p = d_path(&lun->filp->f_path, pathbuf, PATH_MAX); - if (IS_ERR(p)) - p = "(error)"; + for (i = 0, nluns = common->nluns, curlun = common->luns; + i < nluns; + ++curlun, ++i) { + char *p = "(no medium)"; + if (fsg_lun_is_open(curlun)) { + p = "(error)"; + if (pathbuf) { + p = d_path(&curlun->filp->f_path, + pathbuf, PATH_MAX); + if (IS_ERR(p)) + p = "(error)"; + } } + LINFO(curlun, "LUN: %s%s%sfile: %s\n", + curlun->removable ? "removable " : "", + curlun->ro ? "read only " : "", + curlun->cdrom ? "CD-ROM " : "", + p); } - pr_info("LUN: %s%s%sfile: %s\n", - lun->removable ? "removable " : "", - lun->ro ? "read only " : "", - lun->cdrom ? "CD-ROM " : "", - p); kfree(pathbuf); - return 0; - -error_lun: - if (common->sysfs) { - fsg_common_remove_sysfs(lun); - device_unregister(&lun->dev); - } - fsg_lun_close(lun); - common->luns[id] = NULL; -error_sysfs: - kfree(lun); - return rc; -} -EXPORT_SYMBOL_GPL(fsg_common_create_lun); - -int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg) -{ - char buf[8]; /* enough for 100000000 different numbers, decimal */ - int i, rc; - - for (i = 0; i < common->nluns; ++i) { - snprintf(buf, sizeof(buf), "lun%d", i); - rc = fsg_common_create_lun(common, &cfg->luns[i], i, buf, NULL); - if (rc) - goto fail; - } - - pr_info("Number of LUNs=%d\n", common->nluns); - - return 0; - -fail: - _fsg_common_remove_luns(common, i); - return rc; -} -EXPORT_SYMBOL_GPL(fsg_common_create_luns); - -void fsg_common_set_inquiry_string(struct fsg_common *common, const char *vn, - const char *pn) -{ - int i; - - /* Prepare inquiryString */ - i = get_default_bcdDevice(); - snprintf(common->inquiry_string, sizeof(common->inquiry_string), - "%-8s%-16s%04x", vn ?: "Linux", - /* Assume product name dependent on the first LUN */ - pn ?: ((*common->luns)->cdrom - ? "File-CD Gadget" - : "File-Stor Gadget"), - i); -} -EXPORT_SYMBOL_GPL(fsg_common_set_inquiry_string); - -int fsg_common_run_thread(struct fsg_common *common) -{ - common->state = FSG_STATE_IDLE; - /* Tell the thread to start working */ - common->thread_task = - kthread_create(fsg_main_thread, common, "file-storage"); - if (IS_ERR(common->thread_task)) { - common->state = FSG_STATE_TERMINATED; - return PTR_ERR(common->thread_task); - } - DBG(common, "I/O thread pid: %d\n", task_pid_nr(common->thread_task)); wake_up_process(common->thread_task); - return 0; + return common; + +error_luns: + common->nluns = i + 1; +error_release: + common->state = FSG_STATE_TERMINATED; /* The thread is dead */ + /* Call fsg_common_release() directly, ref might be not initialised. */ + fsg_common_release(&common->ref); + return ERR_PTR(rc); } -EXPORT_SYMBOL_GPL(fsg_common_run_thread); static void fsg_common_release(struct kref *ref) { @@ -3069,26 +2824,36 @@ static void fsg_common_release(struct kref *ref) } if (likely(common->luns)) { - struct fsg_lun **lun_it = common->luns; + struct fsg_lun *lun = common->luns; unsigned i = common->nluns; /* In error recovery common->nluns may be zero. */ - for (; i; --i, ++lun_it) { - struct fsg_lun *lun = *lun_it; - if (!lun) - continue; - if (common->sysfs) - fsg_common_remove_sysfs(lun); + for (; i; --i, ++lun) { + device_remove_file(&lun->dev, &dev_attr_nofua); + device_remove_file(&lun->dev, + lun->cdrom + ? &dev_attr_ro_cdrom + : &dev_attr_ro); + device_remove_file(&lun->dev, + lun->removable + ? &dev_attr_file + : &dev_attr_file_nonremovable); fsg_lun_close(lun); - if (common->sysfs) - device_unregister(&lun->dev); - kfree(lun); + device_unregister(&lun->dev); } kfree(common->luns); } - _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers); + { + struct fsg_buffhd *bh = common->buffhds; + unsigned i = fsg_num_buffers; + do { + kfree(bh->buf); + } while (++bh, --i); + } + + kfree(common->buffhds); if (common->free_storage_on_release) kfree(common); } @@ -3096,6 +2861,24 @@ static void fsg_common_release(struct kref *ref) /*-------------------------------------------------------------------------*/ +static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) +{ + struct fsg_dev *fsg = fsg_from_func(f); + struct fsg_common *common = fsg->common; + + DBG(fsg, "unbind\n"); + if (fsg->common->fsg == fsg) { + fsg->common->new_fsg = NULL; + raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); + /* FIXME: make interruptible or killable somehow? */ + wait_event(common->fsg_wait, common->fsg != fsg); + } + + fsg_common_put(common); + usb_free_all_descriptors(&fsg->function); + kfree(fsg); +} + static int fsg_bind(struct usb_configuration *c, struct usb_function *f) { struct fsg_dev *fsg = fsg_from_func(f); @@ -3104,19 +2887,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) struct usb_ep *ep; unsigned max_burst; int ret; - struct fsg_opts *opts; - - opts = fsg_opts_from_func_inst(f->fi); - if (!opts->no_configfs) { - ret = fsg_common_set_cdev(fsg->common, c->cdev, - fsg->common->can_stall); - if (ret) - return ret; - fsg_common_set_inquiry_string(fsg->common, NULL, NULL); - ret = fsg_common_run_thread(fsg->common); - if (ret) - return ret; - } fsg->gadget = gadget; @@ -3169,472 +2939,95 @@ autoconf_fail: return -ENOTSUPP; } -/****************************** ALLOCATE FUNCTION *************************/ +/****************************** ADD FUNCTION ******************************/ -static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) -{ - struct fsg_dev *fsg = fsg_from_func(f); - struct fsg_common *common = fsg->common; - - DBG(fsg, "unbind\n"); - if (fsg->common->fsg == fsg) { - fsg->common->new_fsg = NULL; - raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); - /* FIXME: make interruptible or killable somehow? */ - wait_event(common->fsg_wait, common->fsg != fsg); - } - - usb_free_all_descriptors(&fsg->function); -} - -static inline struct fsg_lun_opts *to_fsg_lun_opts(struct config_item *item) -{ - return container_of(to_config_group(item), struct fsg_lun_opts, group); -} - -static inline struct fsg_opts *to_fsg_opts(struct config_item *item) -{ - return container_of(to_config_group(item), struct fsg_opts, - func_inst.group); -} - -CONFIGFS_ATTR_STRUCT(fsg_lun_opts); -CONFIGFS_ATTR_OPS(fsg_lun_opts); - -static void fsg_lun_attr_release(struct config_item *item) -{ - struct fsg_lun_opts *lun_opts; - - lun_opts = to_fsg_lun_opts(item); - kfree(lun_opts); -} - -static struct configfs_item_operations fsg_lun_item_ops = { - .release = fsg_lun_attr_release, - .show_attribute = fsg_lun_opts_attr_show, - .store_attribute = fsg_lun_opts_attr_store, -}; - -static ssize_t fsg_lun_opts_file_show(struct fsg_lun_opts *opts, char *page) -{ - struct fsg_opts *fsg_opts; - - fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent); - - return fsg_show_file(opts->lun, &fsg_opts->common->filesem, page); -} - -static ssize_t fsg_lun_opts_file_store(struct fsg_lun_opts *opts, - const char *page, size_t len) -{ - struct fsg_opts *fsg_opts; - - fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent); - - return fsg_store_file(opts->lun, &fsg_opts->common->filesem, page, len); -} - -static struct fsg_lun_opts_attribute fsg_lun_opts_file = - __CONFIGFS_ATTR(file, S_IRUGO | S_IWUSR, fsg_lun_opts_file_show, - fsg_lun_opts_file_store); - -static ssize_t fsg_lun_opts_ro_show(struct fsg_lun_opts *opts, char *page) -{ - return fsg_show_ro(opts->lun, page); -} - -static ssize_t fsg_lun_opts_ro_store(struct fsg_lun_opts *opts, - const char *page, size_t len) -{ - struct fsg_opts *fsg_opts; - - fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent); - - return fsg_store_ro(opts->lun, &fsg_opts->common->filesem, page, len); -} - -static struct fsg_lun_opts_attribute fsg_lun_opts_ro = - __CONFIGFS_ATTR(ro, S_IRUGO | S_IWUSR, fsg_lun_opts_ro_show, - fsg_lun_opts_ro_store); - -static ssize_t fsg_lun_opts_removable_show(struct fsg_lun_opts *opts, - char *page) -{ - return fsg_show_removable(opts->lun, page); -} - -static ssize_t fsg_lun_opts_removable_store(struct fsg_lun_opts *opts, - const char *page, size_t len) -{ - return fsg_store_removable(opts->lun, page, len); -} - -static struct fsg_lun_opts_attribute fsg_lun_opts_removable = - __CONFIGFS_ATTR(removable, S_IRUGO | S_IWUSR, - fsg_lun_opts_removable_show, - fsg_lun_opts_removable_store); - -static ssize_t fsg_lun_opts_cdrom_show(struct fsg_lun_opts *opts, char *page) -{ - return fsg_show_cdrom(opts->lun, page); -} - -static ssize_t fsg_lun_opts_cdrom_store(struct fsg_lun_opts *opts, - const char *page, size_t len) -{ - struct fsg_opts *fsg_opts; - - fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent); - - return fsg_store_cdrom(opts->lun, &fsg_opts->common->filesem, page, - len); -} - -static struct fsg_lun_opts_attribute fsg_lun_opts_cdrom = - __CONFIGFS_ATTR(cdrom, S_IRUGO | S_IWUSR, fsg_lun_opts_cdrom_show, - fsg_lun_opts_cdrom_store); - -static ssize_t fsg_lun_opts_nofua_show(struct fsg_lun_opts *opts, char *page) -{ - return fsg_show_nofua(opts->lun, page); -} - -static ssize_t fsg_lun_opts_nofua_store(struct fsg_lun_opts *opts, - const char *page, size_t len) -{ - return fsg_store_nofua(opts->lun, page, len); -} - -static struct fsg_lun_opts_attribute fsg_lun_opts_nofua = - __CONFIGFS_ATTR(nofua, S_IRUGO | S_IWUSR, fsg_lun_opts_nofua_show, - fsg_lun_opts_nofua_store); - -static struct configfs_attribute *fsg_lun_attrs[] = { - &fsg_lun_opts_file.attr, - &fsg_lun_opts_ro.attr, - &fsg_lun_opts_removable.attr, - &fsg_lun_opts_cdrom.attr, - &fsg_lun_opts_nofua.attr, - NULL, -}; - -static struct config_item_type fsg_lun_type = { - .ct_item_ops = &fsg_lun_item_ops, - .ct_attrs = fsg_lun_attrs, - .ct_owner = THIS_MODULE, -}; - -static struct config_group *fsg_lun_make(struct config_group *group, - const char *name) -{ - struct fsg_lun_opts *opts; - struct fsg_opts *fsg_opts; - struct fsg_lun_config config; - char *num_str; - u8 num; - int ret; - - num_str = strchr(name, '.'); - if (!num_str) { - pr_err("Unable to locate . in LUN.NUMBER\n"); - return ERR_PTR(-EINVAL); - } - num_str++; - - ret = kstrtou8(num_str, 0, &num); - if (ret) - return ERR_PTR(ret); - - fsg_opts = to_fsg_opts(&group->cg_item); - if (num >= FSG_MAX_LUNS) - return ERR_PTR(-ERANGE); - - mutex_lock(&fsg_opts->lock); - if (fsg_opts->refcnt || fsg_opts->common->luns[num]) { - ret = -EBUSY; - goto out; - } - - opts = kzalloc(sizeof(*opts), GFP_KERNEL); - if (!opts) { - ret = -ENOMEM; - goto out; - } - - memset(&config, 0, sizeof(config)); - config.removable = true; - - ret = fsg_common_create_lun(fsg_opts->common, &config, num, name, - (const char **)&group->cg_item.ci_name); - if (ret) { - kfree(opts); - goto out; - } - opts->lun = fsg_opts->common->luns[num]; - opts->lun_id = num; - mutex_unlock(&fsg_opts->lock); - - config_group_init_type_name(&opts->group, name, &fsg_lun_type); - - return &opts->group; -out: - mutex_unlock(&fsg_opts->lock); - return ERR_PTR(ret); -} - -static void fsg_lun_drop(struct config_group *group, struct config_item *item) -{ - struct fsg_lun_opts *lun_opts; - struct fsg_opts *fsg_opts; - - lun_opts = to_fsg_lun_opts(item); - fsg_opts = to_fsg_opts(&group->cg_item); - - mutex_lock(&fsg_opts->lock); - if (fsg_opts->refcnt) { - struct config_item *gadget; - - gadget = group->cg_item.ci_parent->ci_parent; - unregister_gadget_item(gadget); - } - - fsg_common_remove_lun(lun_opts->lun, fsg_opts->common->sysfs); - fsg_opts->common->luns[lun_opts->lun_id] = NULL; - lun_opts->lun_id = 0; - mutex_unlock(&fsg_opts->lock); - - config_item_put(item); -} - -CONFIGFS_ATTR_STRUCT(fsg_opts); -CONFIGFS_ATTR_OPS(fsg_opts); - -static void fsg_attr_release(struct config_item *item) -{ - struct fsg_opts *opts = to_fsg_opts(item); - - usb_put_function_instance(&opts->func_inst); -} - -static struct configfs_item_operations fsg_item_ops = { - .release = fsg_attr_release, - .show_attribute = fsg_opts_attr_show, - .store_attribute = fsg_opts_attr_store, -}; - -static ssize_t fsg_opts_stall_show(struct fsg_opts *opts, char *page) -{ - int result; - - mutex_lock(&opts->lock); - result = sprintf(page, "%d", opts->common->can_stall); - mutex_unlock(&opts->lock); - - return result; -} - -static ssize_t fsg_opts_stall_store(struct fsg_opts *opts, const char *page, - size_t len) -{ - int ret; - bool stall; - - mutex_lock(&opts->lock); - - if (opts->refcnt) { - mutex_unlock(&opts->lock); - return -EBUSY; - } - - ret = strtobool(page, &stall); - if (!ret) { - opts->common->can_stall = stall; - ret = len; - } - - mutex_unlock(&opts->lock); - - return ret; -} - -static struct fsg_opts_attribute fsg_opts_stall = - __CONFIGFS_ATTR(stall, S_IRUGO | S_IWUSR, fsg_opts_stall_show, - fsg_opts_stall_store); - -#ifdef CONFIG_USB_GADGET_DEBUG_FILES -static ssize_t fsg_opts_num_buffers_show(struct fsg_opts *opts, char *page) -{ - int result; - - mutex_lock(&opts->lock); - result = sprintf(page, "%d", opts->common->fsg_num_buffers); - mutex_unlock(&opts->lock); - - return result; -} - -static ssize_t fsg_opts_num_buffers_store(struct fsg_opts *opts, - const char *page, size_t len) -{ - int ret; - u8 num; - - mutex_lock(&opts->lock); - if (opts->refcnt) { - ret = -EBUSY; - goto end; - } - ret = kstrtou8(page, 0, &num); - if (ret) - goto end; - - ret = fsg_num_buffers_validate(num); - if (ret) - goto end; - - fsg_common_set_num_buffers(opts->common, num); - ret = len; - -end: - mutex_unlock(&opts->lock); - return ret; -} - -static struct fsg_opts_attribute fsg_opts_num_buffers = - __CONFIGFS_ATTR(num_buffers, S_IRUGO | S_IWUSR, - fsg_opts_num_buffers_show, - fsg_opts_num_buffers_store); - -#endif - -static struct configfs_attribute *fsg_attrs[] = { - &fsg_opts_stall.attr, -#ifdef CONFIG_USB_GADGET_DEBUG_FILES - &fsg_opts_num_buffers.attr, -#endif +static struct usb_gadget_strings *fsg_strings_array[] = { + &fsg_stringtab, NULL, }; -static struct configfs_group_operations fsg_group_ops = { - .make_group = fsg_lun_make, - .drop_item = fsg_lun_drop, -}; - -static struct config_item_type fsg_func_type = { - .ct_item_ops = &fsg_item_ops, - .ct_group_ops = &fsg_group_ops, - .ct_attrs = fsg_attrs, - .ct_owner = THIS_MODULE, -}; - -static void fsg_free_inst(struct usb_function_instance *fi) -{ - struct fsg_opts *opts; - - opts = fsg_opts_from_func_inst(fi); - fsg_common_put(opts->common); - kfree(opts); -} - -static struct usb_function_instance *fsg_alloc_inst(void) +static int fsg_bind_config(struct usb_composite_dev *cdev, + struct usb_configuration *c, + struct fsg_common *common) { - struct fsg_opts *opts; - struct fsg_lun_config config; - int rc; - - opts = kzalloc(sizeof(*opts), GFP_KERNEL); - if (!opts) - return ERR_PTR(-ENOMEM); - mutex_init(&opts->lock); - opts->func_inst.free_func_inst = fsg_free_inst; - opts->common = fsg_common_setup(opts->common); - if (IS_ERR(opts->common)) { - rc = PTR_ERR(opts->common); - goto release_opts; - } - rc = fsg_common_set_nluns(opts->common, FSG_MAX_LUNS); - if (rc) - goto release_opts; - - rc = fsg_common_set_num_buffers(opts->common, - CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS); - if (rc) - goto release_luns; - - pr_info(FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n"); - - memset(&config, 0, sizeof(config)); - config.removable = true; - rc = fsg_common_create_lun(opts->common, &config, 0, "lun.0", - (const char **)&opts->func_inst.group.cg_item.ci_name); - opts->lun0.lun = opts->common->luns[0]; - opts->lun0.lun_id = 0; - config_group_init_type_name(&opts->lun0.group, "lun.0", &fsg_lun_type); - opts->default_groups[0] = &opts->lun0.group; - opts->func_inst.group.default_groups = opts->default_groups; - - config_group_init_type_name(&opts->func_inst.group, "", &fsg_func_type); - - return &opts->func_inst; - -release_luns: - kfree(opts->common->luns); -release_opts: - kfree(opts); - return ERR_PTR(rc); -} - -static void fsg_free(struct usb_function *f) -{ - struct fsg_dev *fsg; - struct fsg_opts *opts; - - fsg = container_of(f, struct fsg_dev, function); - opts = container_of(f->fi, struct fsg_opts, func_inst); - - mutex_lock(&opts->lock); - opts->refcnt--; - mutex_unlock(&opts->lock); - - kfree(fsg); -} - -static struct usb_function *fsg_alloc(struct usb_function_instance *fi) -{ - struct fsg_opts *opts = fsg_opts_from_func_inst(fi); - struct fsg_common *common = opts->common; struct fsg_dev *fsg; + int rc; - fsg = kzalloc(sizeof(*fsg), GFP_KERNEL); + fsg = kzalloc(sizeof *fsg, GFP_KERNEL); if (unlikely(!fsg)) - return ERR_PTR(-ENOMEM); + return -ENOMEM; - mutex_lock(&opts->lock); - opts->refcnt++; - mutex_unlock(&opts->lock); - fsg->function.name = FSG_DRIVER_DESC; - fsg->function.bind = fsg_bind; - fsg->function.unbind = fsg_unbind; - fsg->function.setup = fsg_setup; - fsg->function.set_alt = fsg_set_alt; - fsg->function.disable = fsg_disable; - fsg->function.free_func = fsg_free; + fsg->function.name = FSG_DRIVER_DESC; + fsg->function.strings = fsg_strings_array; + fsg->function.bind = fsg_bind; + fsg->function.unbind = fsg_unbind; + fsg->function.setup = fsg_setup; + fsg->function.set_alt = fsg_set_alt; + fsg->function.disable = fsg_disable; fsg->common = common; + /* + * Our caller holds a reference to common structure so we + * don't have to be worry about it being freed until we return + * from this function. So instead of incrementing counter now + * and decrement in error recovery we increment it only when + * call to usb_add_function() was successful. + */ - return &fsg->function; + rc = usb_add_function(c, &fsg->function); + if (unlikely(rc)) + kfree(fsg); + else + fsg_common_get(fsg->common); + return rc; } -DECLARE_USB_FUNCTION_INIT(mass_storage, fsg_alloc_inst, fsg_alloc); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Michal Nazarewicz"); /************************* Module parameters *************************/ +struct fsg_module_parameters { + char *file[FSG_MAX_LUNS]; + bool ro[FSG_MAX_LUNS]; + bool removable[FSG_MAX_LUNS]; + bool cdrom[FSG_MAX_LUNS]; + bool nofua[FSG_MAX_LUNS]; + + unsigned int file_count, ro_count, removable_count, cdrom_count; + unsigned int nofua_count; + unsigned int luns; /* nluns */ + bool stall; /* can_stall */ +}; -void fsg_config_from_params(struct fsg_config *cfg, - const struct fsg_module_parameters *params, - unsigned int fsg_num_buffers) +#define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc) \ + module_param_array_named(prefix ## name, params.name, type, \ + &prefix ## params.name ## _count, \ + S_IRUGO); \ + MODULE_PARM_DESC(prefix ## name, desc) + +#define _FSG_MODULE_PARAM(prefix, params, name, type, desc) \ + module_param_named(prefix ## name, params.name, type, \ + S_IRUGO); \ + MODULE_PARM_DESC(prefix ## name, desc) + +#define FSG_MODULE_PARAMETERS(prefix, params) \ + _FSG_MODULE_PARAM_ARRAY(prefix, params, file, charp, \ + "names of backing files or devices"); \ + _FSG_MODULE_PARAM_ARRAY(prefix, params, ro, bool, \ + "true to force read-only"); \ + _FSG_MODULE_PARAM_ARRAY(prefix, params, removable, bool, \ + "true to simulate removable media"); \ + _FSG_MODULE_PARAM_ARRAY(prefix, params, cdrom, bool, \ + "true to simulate CD-ROM instead of disk"); \ + _FSG_MODULE_PARAM_ARRAY(prefix, params, nofua, bool, \ + "true to ignore SCSI WRITE(10,12) FUA bit"); \ + _FSG_MODULE_PARAM(prefix, params, luns, uint, \ + "number of LUNs"); \ + _FSG_MODULE_PARAM(prefix, params, stall, bool, \ + "false to prevent bulk stalls") + +static void +fsg_config_from_params(struct fsg_config *cfg, + const struct fsg_module_parameters *params) { struct fsg_lun_config *lun; unsigned i; @@ -3662,7 +3055,19 @@ void fsg_config_from_params(struct fsg_config *cfg, /* Finalise */ cfg->can_stall = params->stall; - cfg->fsg_num_buffers = fsg_num_buffers; } -EXPORT_SYMBOL_GPL(fsg_config_from_params); +static inline struct fsg_common * +fsg_common_from_params(struct fsg_common *common, + struct usb_composite_dev *cdev, + const struct fsg_module_parameters *params) + __attribute__((unused)); +static inline struct fsg_common * +fsg_common_from_params(struct fsg_common *common, + struct usb_composite_dev *cdev, + const struct fsg_module_parameters *params) +{ + struct fsg_config cfg; + fsg_config_from_params(&cfg, params); + return fsg_common_init(common, cdev, &cfg); +} diff --git a/drivers/usb/gadget/f_mass_storage.h b/drivers/usb/gadget/f_mass_storage.h deleted file mode 100644 index b4866fc..0000000 --- a/drivers/usb/gadget/f_mass_storage.h +++ /dev/null @@ -1,166 +0,0 @@ -#ifndef USB_F_MASS_STORAGE_H -#define USB_F_MASS_STORAGE_H - -#include <linux/usb/composite.h> -#include "storage_common.h" - -struct fsg_module_parameters { - char *file[FSG_MAX_LUNS]; - bool ro[FSG_MAX_LUNS]; - bool removable[FSG_MAX_LUNS]; - bool cdrom[FSG_MAX_LUNS]; - bool nofua[FSG_MAX_LUNS]; - - unsigned int file_count, ro_count, removable_count, cdrom_count; - unsigned int nofua_count; - unsigned int luns; /* nluns */ - bool stall; /* can_stall */ -}; - -#define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc) \ - module_param_array_named(prefix ## name, params.name, type, \ - &prefix ## params.name ## _count, \ - S_IRUGO); \ - MODULE_PARM_DESC(prefix ## name, desc) - -#define _FSG_MODULE_PARAM(prefix, params, name, type, desc) \ - module_param_named(prefix ## name, params.name, type, \ - S_IRUGO); \ - MODULE_PARM_DESC(prefix ## name, desc) - -#define __FSG_MODULE_PARAMETERS(prefix, params) \ - _FSG_MODULE_PARAM_ARRAY(prefix, params, file, charp, \ - "names of backing files or devices"); \ - _FSG_MODULE_PARAM_ARRAY(prefix, params, ro, bool, \ - "true to force read-only"); \ - _FSG_MODULE_PARAM_ARRAY(prefix, params, removable, bool, \ - "true to simulate removable media"); \ - _FSG_MODULE_PARAM_ARRAY(prefix, params, cdrom, bool, \ - "true to simulate CD-ROM instead of disk"); \ - _FSG_MODULE_PARAM_ARRAY(prefix, params, nofua, bool, \ - "true to ignore SCSI WRITE(10,12) FUA bit"); \ - _FSG_MODULE_PARAM(prefix, params, luns, uint, \ - "number of LUNs"); \ - _FSG_MODULE_PARAM(prefix, params, stall, bool, \ - "false to prevent bulk stalls") - -#ifdef CONFIG_USB_GADGET_DEBUG_FILES - -#define FSG_MODULE_PARAMETERS(prefix, params) \ - __FSG_MODULE_PARAMETERS(prefix, params); \ - module_param_named(num_buffers, fsg_num_buffers, uint, S_IRUGO);\ - MODULE_PARM_DESC(num_buffers, "Number of pipeline buffers") -#else - -#define FSG_MODULE_PARAMETERS(prefix, params) \ - __FSG_MODULE_PARAMETERS(prefix, params) - -#endif - -struct fsg_common; - -/* FSF callback functions */ -struct fsg_operations { - /* - * Callback function to call when thread exits. If no - * callback is set or it returns value lower then zero MSF - * will force eject all LUNs it operates on (including those - * marked as non-removable or with prevent_medium_removal flag - * set). - */ - int (*thread_exits)(struct fsg_common *common); -}; - -struct fsg_lun_opts { - struct config_group group; - struct fsg_lun *lun; - int lun_id; -}; - -struct fsg_opts { - struct fsg_common *common; - struct usb_function_instance func_inst; - struct fsg_lun_opts lun0; - struct config_group *default_groups[2]; - bool no_configfs; /* for legacy gadgets */ - - /* - * Read/write access to configfs attributes is handled by configfs. - * - * This is to protect the data from concurrent access by read/write - * and create symlink/remove symlink. - */ - struct mutex lock; - int refcnt; -}; - -struct fsg_lun_config { - const char *filename; - char ro; - char removable; - char cdrom; - char nofua; -}; - -struct fsg_config { - unsigned nluns; - struct fsg_lun_config luns[FSG_MAX_LUNS]; - - /* Callback functions. */ - const struct fsg_operations *ops; - /* Gadget's private data. */ - void *private_data; - - const char *vendor_name; /* 8 characters or less */ - const char *product_name; /* 16 characters or less */ - - char can_stall; - unsigned int fsg_num_buffers; -}; - -static inline struct fsg_opts * -fsg_opts_from_func_inst(const struct usb_function_instance *fi) -{ - return container_of(fi, struct fsg_opts, func_inst); -} - -void fsg_common_get(struct fsg_common *common); - -void fsg_common_put(struct fsg_common *common); - -void fsg_common_set_sysfs(struct fsg_common *common, bool sysfs); - -int fsg_common_set_num_buffers(struct fsg_common *common, unsigned int n); - -void fsg_common_free_buffers(struct fsg_common *common); - -int fsg_common_set_cdev(struct fsg_common *common, - struct usb_composite_dev *cdev, bool can_stall); - -void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs); - -void fsg_common_remove_luns(struct fsg_common *common); - -void fsg_common_free_luns(struct fsg_common *common); - -int fsg_common_set_nluns(struct fsg_common *common, int nluns); - -void fsg_common_set_ops(struct fsg_common *common, - const struct fsg_operations *ops); - -int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, - unsigned int id, const char *name, - const char **name_pfx); - -int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg); - -void fsg_common_set_inquiry_string(struct fsg_common *common, const char *vn, - const char *pn); - -int fsg_common_run_thread(struct fsg_common *common); - -void fsg_config_from_params(struct fsg_config *cfg, - const struct fsg_module_parameters *params, - unsigned int fsg_num_buffers); - -#endif /* USB_F_MASS_STORAGE_H */ diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 807127d..f3bb363 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -33,7 +33,6 @@ #include <linux/io.h> #include <linux/moduleparam.h> #include <linux/of_address.h> -#include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/dma-mapping.h> #include <linux/usb/ch9.h> diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 2344efe..5327c82 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -76,9 +76,7 @@ struct gfs_ffs_obj { USB_GADGET_COMPOSITE_OPTIONS(); -#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS USB_ETHERNET_MODULE_PARAMETERS(); -#endif static struct usb_device_descriptor gfs_dev_desc = { .bLength = sizeof gfs_dev_desc, diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index f827680..c64deb9 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -1165,7 +1165,7 @@ static int udc_proc_read(struct seq_file *m, void *v) s = "invalid"; break; default: s = "?"; break; - } s; }), + }; s; }), (tmp & EPxSTATUS_TOGGLE) ? "data1" : "data0", (tmp & EPxSTATUS_SUSPEND) ? " suspend" : "", (tmp & EPxSTATUS_FIFO_DISABLE) ? " disable" : "", @@ -1701,6 +1701,7 @@ static void goku_remove(struct pci_dev *pdev) if (dev->enabled) pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); dev->regs = NULL; INFO(dev, "unbind\n"); diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c index 6a2a65a..67128be 100644 --- a/drivers/usb/gadget/lpc32xx_udc.c +++ b/drivers/usb/gadget/lpc32xx_udc.c @@ -3078,9 +3078,7 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev) udc->isp1301_i2c_client->addr); pdev->dev.dma_mask = &lpc32xx_usbd_dmamask; - retval = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (retval) - goto resource_fail; + pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); udc->board = &lpc32xx_usbddata; diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index 8e27a8c..080e577 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -37,16 +37,16 @@ #define DRIVER_DESC "Mass Storage Gadget" #define DRIVER_VERSION "2009/09/11" +/*-------------------------------------------------------------------------*/ + /* - * Thanks to NetChip Technologies for donating this product ID. - * - * DO NOT REUSE THESE IDs with any other driver!! Ever!! - * Instead: allocate your own, using normal USB-IF procedures. + * kbuild is not very cooperative with respect to linking separately + * compiled library objects into one module. So for now we won't use + * separate compilation ... ensuring init/exit sections work to shrink + * the runtime footprint, and giving us at least some parts of what + * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ -#define FSG_VENDOR_ID 0x0525 /* NetChip */ -#define FSG_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */ - -#include "f_mass_storage.h" +#include "f_mass_storage.c" /*-------------------------------------------------------------------------*/ USB_GADGET_COMPOSITE_OPTIONS(); @@ -97,28 +97,11 @@ static struct usb_gadget_strings *dev_strings[] = { NULL, }; -static struct usb_function_instance *fi_msg; -static struct usb_function *f_msg; - /****************************** Configurations ******************************/ static struct fsg_module_parameters mod_data = { .stall = 1 }; -#ifdef CONFIG_USB_GADGET_DEBUG_FILES - -static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS; - -#else - -/* - * Number of buffers we will use. - * 2 is usually enough for good buffering pipeline - */ -#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS - -#endif /* CONFIG_USB_GADGET_DEBUG_FILES */ - FSG_MODULE_PARAMETERS(/* no prefix */, mod_data); static unsigned long msg_registered; @@ -132,7 +115,13 @@ static int msg_thread_exits(struct fsg_common *common) static int __init msg_do_config(struct usb_configuration *c) { - struct fsg_opts *opts; + static const struct fsg_operations ops = { + .thread_exits = msg_thread_exits, + }; + static struct fsg_common common; + + struct fsg_common *retp; + struct fsg_config config; int ret; if (gadget_is_otg(c->cdev->gadget)) { @@ -140,24 +129,15 @@ static int __init msg_do_config(struct usb_configuration *c) c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - opts = fsg_opts_from_func_inst(fi_msg); - - f_msg = usb_get_function(fi_msg); - if (IS_ERR(f_msg)) - return PTR_ERR(f_msg); - - ret = fsg_common_run_thread(opts->common); - if (ret) - goto put_func; - - ret = usb_add_function(c, f_msg); - if (ret) - goto put_func; + fsg_config_from_params(&config, &mod_data); + config.ops = &ops; - return 0; + retp = fsg_common_init(&common, c->cdev, &config); + if (IS_ERR(retp)) + return PTR_ERR(retp); -put_func: - usb_put_function(f_msg); + ret = fsg_bind_config(c->cdev, c, &common); + fsg_common_put(&common); return ret; } @@ -172,79 +152,23 @@ static struct usb_configuration msg_config_driver = { static int __init msg_bind(struct usb_composite_dev *cdev) { - static const struct fsg_operations ops = { - .thread_exits = msg_thread_exits, - }; - struct fsg_opts *opts; - struct fsg_config config; int status; - fi_msg = usb_get_function_instance("mass_storage"); - if (IS_ERR(fi_msg)) - return PTR_ERR(fi_msg); - - fsg_config_from_params(&config, &mod_data, fsg_num_buffers); - opts = fsg_opts_from_func_inst(fi_msg); - - opts->no_configfs = true; - status = fsg_common_set_num_buffers(opts->common, fsg_num_buffers); - if (status) - goto fail; - - status = fsg_common_set_nluns(opts->common, config.nluns); - if (status) - goto fail_set_nluns; - - fsg_common_set_ops(opts->common, &ops); - - status = fsg_common_set_cdev(opts->common, cdev, config.can_stall); - if (status) - goto fail_set_cdev; - - fsg_common_set_sysfs(opts->common, true); - status = fsg_common_create_luns(opts->common, &config); - if (status) - goto fail_set_cdev; - - fsg_common_set_inquiry_string(opts->common, config.vendor_name, - config.product_name); - status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) - goto fail_string_ids; + return status; msg_device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; status = usb_add_config(cdev, &msg_config_driver, msg_do_config); if (status < 0) - goto fail_string_ids; - + return status; usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&cdev->gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); set_bit(0, &msg_registered); return 0; - -fail_string_ids: - fsg_common_remove_luns(opts->common); -fail_set_cdev: - fsg_common_free_luns(opts->common); -fail_set_nluns: - fsg_common_free_buffers(opts->common); -fail: - usb_put_function_instance(fi_msg); - return status; } -static int msg_unbind(struct usb_composite_dev *cdev) -{ - if (!IS_ERR(f_msg)) - usb_put_function(f_msg); - - if (!IS_ERR(fi_msg)) - usb_put_function_instance(fi_msg); - - return 0; -} /****************************** Some noise ******************************/ @@ -255,7 +179,6 @@ static __refdata struct usb_composite_driver msg_driver = { .needs_serial = 1, .strings = dev_strings, .bind = msg_bind, - .unbind = msg_unbind, }; MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 4fdaa54..2339325 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -15,7 +15,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/netdevice.h> #include "u_serial.h" #if defined USB_ETH_RNDIS @@ -33,11 +32,22 @@ MODULE_AUTHOR("Michal Nazarewicz"); MODULE_LICENSE("GPL"); -#include "f_mass_storage.h" +/***************************** All the files... *****************************/ -#include "u_ecm.h" +/* + * kbuild is not very cooperative with respect to linking separately + * compiled library objects into one module. So for now we won't use + * separate compilation ... ensuring init/exit sections work to shrink + * the runtime footprint, and giving us at least some parts of what + * a "gcc --combine ... part1.c part2.c part3.c ... " build would. + */ +#include "f_mass_storage.c" + +#define USBF_ECM_INCLUDED +#include "f_ecm.c" #ifdef USB_ETH_RNDIS -# include "u_rndis.h" +# define USB_FRNDIS_INCLUDED +# include "f_rndis.c" # include "rndis.h" #endif #include "u_ether.h" @@ -122,36 +132,22 @@ static struct usb_gadget_strings *dev_strings[] = { /****************************** Configurations ******************************/ static struct fsg_module_parameters fsg_mod_data = { .stall = 1 }; -#ifdef CONFIG_USB_GADGET_DEBUG_FILES - -static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS; - -#else - -/* - * Number of buffers we will use. - * 2 is usually enough for good buffering pipeline - */ -#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS +FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); -#endif /* CONFIG_USB_DEBUG */ +static struct fsg_common fsg_common; -FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); +static u8 host_mac[ETH_ALEN]; static struct usb_function_instance *fi_acm; -static struct usb_function_instance *fi_msg; +static struct eth_dev *the_dev; /********** RNDIS **********/ #ifdef USB_ETH_RNDIS -static struct usb_function_instance *fi_rndis; static struct usb_function *f_acm_rndis; -static struct usb_function *f_rndis; -static struct usb_function *f_msg_rndis; static __init int rndis_do_config(struct usb_configuration *c) { - struct fsg_opts *fsg_opts; int ret; if (gadget_is_otg(c->cdev->gadget)) { @@ -159,50 +155,27 @@ static __init int rndis_do_config(struct usb_configuration *c) c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - f_rndis = usb_get_function(fi_rndis); - if (IS_ERR(f_rndis)) - return PTR_ERR(f_rndis); - - ret = usb_add_function(c, f_rndis); + ret = rndis_bind_config(c, host_mac, the_dev); if (ret < 0) - goto err_func_rndis; + return ret; f_acm_rndis = usb_get_function(fi_acm); - if (IS_ERR(f_acm_rndis)) { - ret = PTR_ERR(f_acm_rndis); - goto err_func_acm; - } + if (IS_ERR(f_acm_rndis)) + return PTR_ERR(f_acm_rndis); ret = usb_add_function(c, f_acm_rndis); if (ret) goto err_conf; - f_msg_rndis = usb_get_function(fi_msg); - if (IS_ERR(f_msg_rndis)) { - ret = PTR_ERR(f_msg_rndis); + ret = fsg_bind_config(c->cdev, c, &fsg_common); + if (ret < 0) goto err_fsg; - } - - fsg_opts = fsg_opts_from_func_inst(fi_msg); - ret = fsg_common_run_thread(fsg_opts->common); - if (ret) - goto err_run; - - ret = usb_add_function(c, f_msg_rndis); - if (ret) - goto err_run; return 0; -err_run: - usb_put_function(f_msg_rndis); err_fsg: usb_remove_function(c, f_acm_rndis); err_conf: usb_put_function(f_acm_rndis); -err_func_acm: - usb_remove_function(c, f_rndis); -err_func_rndis: - usb_put_function(f_rndis); return ret; } @@ -232,14 +205,10 @@ static __ref int rndis_config_register(struct usb_composite_dev *cdev) /********** CDC ECM **********/ #ifdef CONFIG_USB_G_MULTI_CDC -static struct usb_function_instance *fi_ecm; static struct usb_function *f_acm_multi; -static struct usb_function *f_ecm; -static struct usb_function *f_msg_multi; static __init int cdc_do_config(struct usb_configuration *c) { - struct fsg_opts *fsg_opts; int ret; if (gadget_is_otg(c->cdev->gadget)) { @@ -247,51 +216,28 @@ static __init int cdc_do_config(struct usb_configuration *c) c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - f_ecm = usb_get_function(fi_ecm); - if (IS_ERR(f_ecm)) - return PTR_ERR(f_ecm); - - ret = usb_add_function(c, f_ecm); + ret = ecm_bind_config(c, host_mac, the_dev); if (ret < 0) - goto err_func_ecm; + return ret; /* implicit port_num is zero */ f_acm_multi = usb_get_function(fi_acm); - if (IS_ERR(f_acm_multi)) { - ret = PTR_ERR(f_acm_multi); - goto err_func_acm; - } + if (IS_ERR(f_acm_multi)) + return PTR_ERR(f_acm_multi); ret = usb_add_function(c, f_acm_multi); if (ret) goto err_conf; - f_msg_multi = usb_get_function(fi_msg); - if (IS_ERR(f_msg_multi)) { - ret = PTR_ERR(f_msg_multi); + ret = fsg_bind_config(c->cdev, c, &fsg_common); + if (ret < 0) goto err_fsg; - } - - fsg_opts = fsg_opts_from_func_inst(fi_msg); - ret = fsg_common_run_thread(fsg_opts->common); - if (ret) - goto err_run; - - ret = usb_add_function(c, f_msg_multi); - if (ret) - goto err_run; return 0; -err_run: - usb_put_function(f_msg_multi); err_fsg: usb_remove_function(c, f_acm_multi); err_conf: usb_put_function(f_acm_multi); -err_func_acm: - usb_remove_function(c, f_ecm); -err_func_ecm: - usb_put_function(f_ecm); return ret; } @@ -324,67 +270,19 @@ static __ref int cdc_config_register(struct usb_composite_dev *cdev) static int __ref multi_bind(struct usb_composite_dev *cdev) { struct usb_gadget *gadget = cdev->gadget; -#ifdef CONFIG_USB_G_MULTI_CDC - struct f_ecm_opts *ecm_opts; -#endif -#ifdef USB_ETH_RNDIS - struct f_rndis_opts *rndis_opts; -#endif - struct fsg_opts *fsg_opts; - struct fsg_config config; int status; if (!can_support_ecm(cdev->gadget)) { dev_err(&gadget->dev, "controller '%s' not usable\n", - gadget->name); + gadget->name); return -EINVAL; } -#ifdef CONFIG_USB_G_MULTI_CDC - fi_ecm = usb_get_function_instance("ecm"); - if (IS_ERR(fi_ecm)) - return PTR_ERR(fi_ecm); - - ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst); - - gether_set_qmult(ecm_opts->net, qmult); - if (!gether_set_host_addr(ecm_opts->net, host_addr)) - pr_info("using host ethernet address: %s", host_addr); - if (!gether_set_dev_addr(ecm_opts->net, dev_addr)) - pr_info("using self ethernet address: %s", dev_addr); -#endif - -#ifdef USB_ETH_RNDIS - fi_rndis = usb_get_function_instance("rndis"); - if (IS_ERR(fi_rndis)) { - status = PTR_ERR(fi_rndis); - goto fail; - } - - rndis_opts = container_of(fi_rndis, struct f_rndis_opts, func_inst); - - gether_set_qmult(rndis_opts->net, qmult); - if (!gether_set_host_addr(rndis_opts->net, host_addr)) - pr_info("using host ethernet address: %s", host_addr); - if (!gether_set_dev_addr(rndis_opts->net, dev_addr)) - pr_info("using self ethernet address: %s", dev_addr); -#endif - -#if (defined CONFIG_USB_G_MULTI_CDC && defined USB_ETH_RNDIS) - /* - * If both ecm and rndis are selected then: - * 1) rndis borrows the net interface from ecm - * 2) since the interface is shared it must not be bound - * twice - in ecm's _and_ rndis' binds, so do it here. - */ - gether_set_gadget(ecm_opts->net, cdev->gadget); - status = gether_register_netdev(ecm_opts->net); - if (status) - goto fail0; - - rndis_borrow_net(fi_rndis, ecm_opts->net); - ecm_opts->bound = true; -#endif + /* set up network link layer */ + the_dev = gether_setup(cdev->gadget, dev_addr, host_addr, host_mac, + qmult); + if (IS_ERR(the_dev)) + return PTR_ERR(the_dev); /* set up serial link layer */ fi_acm = usb_get_function_instance("acm"); @@ -394,102 +292,57 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) } /* set up mass storage function */ - fi_msg = usb_get_function_instance("mass_storage"); - if (IS_ERR(fi_msg)) { - status = PTR_ERR(fi_msg); - goto fail1; + { + void *retp; + retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data); + if (IS_ERR(retp)) { + status = PTR_ERR(retp); + goto fail1; + } } - fsg_config_from_params(&config, &fsg_mod_data, fsg_num_buffers); - fsg_opts = fsg_opts_from_func_inst(fi_msg); - - fsg_opts->no_configfs = true; - status = fsg_common_set_num_buffers(fsg_opts->common, fsg_num_buffers); - if (status) - goto fail2; - - status = fsg_common_set_nluns(fsg_opts->common, config.nluns); - if (status) - goto fail_set_nluns; - - status = fsg_common_set_cdev(fsg_opts->common, cdev, config.can_stall); - if (status) - goto fail_set_cdev; - - fsg_common_set_sysfs(fsg_opts->common, true); - status = fsg_common_create_luns(fsg_opts->common, &config); - if (status) - goto fail_set_cdev; - - fsg_common_set_inquiry_string(fsg_opts->common, config.vendor_name, - config.product_name); /* allocate string IDs */ status = usb_string_ids_tab(cdev, strings_dev); if (unlikely(status < 0)) - goto fail_string_ids; + goto fail2; device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; /* register configurations */ status = rndis_config_register(cdev); if (unlikely(status < 0)) - goto fail_string_ids; + goto fail2; status = cdc_config_register(cdev); if (unlikely(status < 0)) - goto fail_string_ids; + goto fail2; usb_composite_overwrite_options(cdev, &coverwrite); /* we're done */ dev_info(&gadget->dev, DRIVER_DESC "\n"); + fsg_common_put(&fsg_common); return 0; /* error recovery */ -fail_string_ids: - fsg_common_remove_luns(fsg_opts->common); -fail_set_cdev: - fsg_common_free_luns(fsg_opts->common); -fail_set_nluns: - fsg_common_free_buffers(fsg_opts->common); fail2: - usb_put_function_instance(fi_msg); + fsg_common_put(&fsg_common); fail1: usb_put_function_instance(fi_acm); fail0: -#ifdef USB_ETH_RNDIS - usb_put_function_instance(fi_rndis); -fail: -#endif -#ifdef CONFIG_USB_G_MULTI_CDC - usb_put_function_instance(fi_ecm); -#endif + gether_cleanup(the_dev); return status; } static int __exit multi_unbind(struct usb_composite_dev *cdev) { #ifdef CONFIG_USB_G_MULTI_CDC - usb_put_function(f_msg_multi); -#endif -#ifdef USB_ETH_RNDIS - usb_put_function(f_msg_rndis); -#endif - usb_put_function_instance(fi_msg); -#ifdef CONFIG_USB_G_MULTI_CDC usb_put_function(f_acm_multi); #endif #ifdef USB_ETH_RNDIS usb_put_function(f_acm_rndis); #endif usb_put_function_instance(fi_acm); -#ifdef USB_ETH_RNDIS - usb_put_function(f_rndis); - usb_put_function_instance(fi_rndis); -#endif -#ifdef CONFIG_USB_G_MULTI_CDC - usb_put_function(f_ecm); - usb_put_function_instance(fi_ecm); -#endif + gether_cleanup(the_dev); return 0; } diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c index 234711e..561b30e 100644 --- a/drivers/usb/gadget/mv_u3d_core.c +++ b/drivers/usb/gadget/mv_u3d_core.c @@ -310,7 +310,6 @@ static struct mv_u3d_trb *mv_u3d_build_trb_one(struct mv_u3d_req *req, */ trb_hw = dma_pool_alloc(u3d->trb_pool, GFP_ATOMIC, dma); if (!trb_hw) { - kfree(trb); dev_err(u3d->dev, "%s, dma_pool_alloc fail\n", __func__); return NULL; @@ -455,7 +454,6 @@ static int mv_u3d_req_to_trb(struct mv_u3d_req *req) trb_hw = kcalloc(trb_num, sizeof(*trb_hw), GFP_ATOMIC); if (!trb_hw) { - kfree(trb); dev_err(u3d->dev, "%s, trb_hw alloc fail\n", __func__); return -ENOMEM; @@ -1938,7 +1936,7 @@ static int mv_u3d_probe(struct platform_device *dev) } u3d->irq = r->start; if (request_irq(u3d->irq, mv_u3d_irq, - IRQF_SHARED, driver_name, u3d)) { + IRQF_DISABLED | IRQF_SHARED, driver_name, u3d)) { u3d->irq = 0; dev_err(&dev->dev, "Request irq %d for u3d failed\n", u3d->irq); diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index fc85217..0781bff 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -129,7 +129,7 @@ static char *type_string (u8 bmAttributes) case USB_ENDPOINT_XFER_BULK: return "bulk"; case USB_ENDPOINT_XFER_ISOC: return "iso"; case USB_ENDPOINT_XFER_INT: return "intr"; - } + }; return "control"; } #endif @@ -1630,7 +1630,7 @@ static ssize_t queues_show(struct device *_dev, struct device_attribute *attr, val = "intr"; break; default: val = "iso"; break; - } val; }), + }; val; }), usb_endpoint_maxp (d) & 0x1fff, ep->dma ? "dma" : "pio", ep->fifo_size ); @@ -2680,6 +2680,7 @@ static void net2280_remove (struct pci_dev *pdev) if (dev->enabled) pci_disable_device (pdev); device_remove_file (&pdev->dev, &dev_attr_registers); + pci_set_drvdata (pdev, NULL); INFO (dev, "unbind\n"); } diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 32d5e92..24174e1 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -3080,6 +3080,7 @@ static void pch_udc_remove(struct pci_dev *pdev) if (dev->active) pci_disable_device(pdev); kfree(dev); + pci_set_drvdata(pdev, NULL); } #ifdef CONFIG_PM diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 409a3c4..0ac6064 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -54,7 +54,6 @@ */ #ifdef CONFIG_ARCH_PXA #include <mach/pxa25x-udc.h> -#include <mach/hardware.h> #endif #ifdef CONFIG_ARCH_LUBBOCK diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index a3ad732..9575085 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -1068,7 +1068,7 @@ static int rndis_proc_show(struct seq_file *m, void *v) s = "RNDIS_INITIALIZED"; break; case RNDIS_DATA_INITIALIZED: s = "RNDIS_DATA_INITIALIZED"; break; - } s; }), + }; s; }), param->medium, (param->media_state) ? 0 : param->speed*100, (param->media_state) ? "disconnected" : "connected", diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index e20bc10..a8a99e4 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -83,12 +83,9 @@ struct s3c_hsotg_req; * @dir_in: Set to true if this endpoint is of the IN direction, which * means that it is sending data to the Host. * @index: The index for the endpoint registers. - * @mc: Multi Count - number of transactions per microframe - * @interval - Interval for periodic endpoints * @name: The name array passed to the USB core. * @halted: Set if the endpoint has been halted. * @periodic: Set if this is a periodic ep, such as Interrupt - * @isochronous: Set if this is a isochronous ep * @sent_zlp: Set if we've sent a zero-length packet. * @total_data: The total number of data bytes done. * @fifo_size: The size of the FIFO (for periodic IN endpoints) @@ -124,12 +121,9 @@ struct s3c_hsotg_ep { unsigned char dir_in; unsigned char index; - unsigned char mc; - unsigned char interval; unsigned int halted:1; unsigned int periodic:1; - unsigned int isochronous:1; unsigned int sent_zlp:1; char name[10]; @@ -474,7 +468,6 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, void *data; int can_write; int pkt_round; - int max_transfer; to_write -= (buf_pos - hs_ep->last_load); @@ -542,10 +535,8 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, can_write *= 4; /* fifo size is in 32bit quantities. */ } - max_transfer = hs_ep->ep.maxpacket * hs_ep->mc; - - dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, max_transfer %d\n", - __func__, gnptxsts, can_write, to_write, max_transfer); + dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, mps %d\n", + __func__, gnptxsts, can_write, to_write, hs_ep->ep.maxpacket); /* * limit to 512 bytes of data, it seems at least on the non-periodic @@ -560,21 +551,19 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, * the transfer to return that it did not run out of fifo space * doing it. */ - if (to_write > max_transfer) { - to_write = max_transfer; + if (to_write > hs_ep->ep.maxpacket) { + to_write = hs_ep->ep.maxpacket; - /* it's needed only when we do not use dedicated fifos */ - if (!hsotg->dedicated_fifos) - s3c_hsotg_en_gsint(hsotg, - periodic ? GINTSTS_PTxFEmp : - GINTSTS_NPTxFEmp); + s3c_hsotg_en_gsint(hsotg, + periodic ? GINTSTS_PTxFEmp : + GINTSTS_NPTxFEmp); } /* see if we can write data */ if (to_write > can_write) { to_write = can_write; - pkt_round = to_write % max_transfer; + pkt_round = to_write % hs_ep->ep.maxpacket; /* * Round the write down to an @@ -592,11 +581,9 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, * is more room left. */ - /* it's needed only when we do not use dedicated fifos */ - if (!hsotg->dedicated_fifos) - s3c_hsotg_en_gsint(hsotg, - periodic ? GINTSTS_PTxFEmp : - GINTSTS_NPTxFEmp); + s3c_hsotg_en_gsint(hsotg, + periodic ? GINTSTS_PTxFEmp : + GINTSTS_NPTxFEmp); } dev_dbg(hsotg->dev, "write %d/%d, can_write %d, done %d\n", @@ -740,16 +727,8 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, else packets = 1; /* send one packet if length is zero. */ - if (hs_ep->isochronous && length > (hs_ep->mc * hs_ep->ep.maxpacket)) { - dev_err(hsotg->dev, "req length > maxpacket*mc\n"); - return; - } - if (dir_in && index != 0) - if (hs_ep->isochronous) - epsize = DxEPTSIZ_MC(packets); - else - epsize = DxEPTSIZ_MC(1); + epsize = DxEPTSIZ_MC(1); else epsize = 0; @@ -841,9 +820,6 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, readl(hsotg->regs + epctrl_reg)); - - /* enable ep interrupts */ - s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 1); } /** @@ -1115,7 +1091,6 @@ static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg, bool set = (ctrl->bRequest == USB_REQ_SET_FEATURE); struct s3c_hsotg_ep *ep; int ret; - bool halted; dev_dbg(hsotg->dev, "%s: %s_FEATURE\n", __func__, set ? "SET" : "CLEAR"); @@ -1130,8 +1105,6 @@ static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg, switch (le16_to_cpu(ctrl->wValue)) { case USB_ENDPOINT_HALT: - halted = ep->halted; - s3c_hsotg_ep_sethalt(&ep->ep, set); ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0); @@ -1141,12 +1114,7 @@ static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg, return ret; } - /* - * we have to complete all requests for ep if it was - * halted, and the halt was cleared by CLEAR_FEATURE - */ - - if (!set && halted) { + if (!set) { /* * If we have request in progress, * then complete it @@ -1179,9 +1147,6 @@ static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg, return 1; } -static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg); -static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg); - /** * s3c_hsotg_process_control - process a control request * @hsotg: The device state @@ -1222,7 +1187,6 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { switch (ctrl->bRequest) { case USB_REQ_SET_ADDRESS: - s3c_hsotg_disconnect(hsotg); dcfg = readl(hsotg->regs + DCFG); dcfg &= ~DCFG_DevAddr_MASK; dcfg |= ctrl->wValue << DCFG_DevAddr_SHIFT; @@ -1247,9 +1211,7 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, /* as a fallback, try delivering it to the driver to deal with */ if (ret == 0 && hsotg->driver) { - spin_unlock(&hsotg->lock); ret = hsotg->driver->setup(&hsotg->gadget, ctrl); - spin_lock(&hsotg->lock); if (ret < 0) dev_dbg(hsotg->dev, "driver->setup() ret %d\n", ret); } @@ -1284,15 +1246,11 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, * don't believe we need to anything more to get the EP * to reply with a STALL packet */ - - /* - * complete won't be called, so we enqueue - * setup request here - */ - s3c_hsotg_enqueue_setup(hsotg); } } +static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg); + /** * s3c_hsotg_complete_setup - completion of a setup transfer * @ep: The endpoint the request was on. @@ -1312,12 +1270,10 @@ static void s3c_hsotg_complete_setup(struct usb_ep *ep, return; } - spin_lock(&hsotg->lock); if (req->actual == 0) s3c_hsotg_enqueue_setup(hsotg); else s3c_hsotg_process_control(hsotg, req->buf); - spin_unlock(&hsotg->lock); } /** @@ -1742,7 +1698,6 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg, struct s3c_hsotg_ep *hs_ep = &hsotg->eps[ep]; void __iomem *regs = hsotg->regs; u32 mpsval; - u32 mcval; u32 reg; if (ep == 0) { @@ -1750,19 +1705,15 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg, mpsval = s3c_hsotg_ep0_mps(mps); if (mpsval > 3) goto bad_mps; - hs_ep->ep.maxpacket = mps; - hs_ep->mc = 1; } else { - mpsval = mps & DxEPCTL_MPS_MASK; - if (mpsval > 1024) + if (mps >= DxEPCTL_MPS_LIMIT+1) goto bad_mps; - mcval = ((mps >> 11) & 0x3) + 1; - hs_ep->mc = mcval; - if (mcval > 3) - goto bad_mps; - hs_ep->ep.maxpacket = mpsval; + + mpsval = mps; } + hs_ep->ep.maxpacket = mps; + /* * update both the in and out endpoint controldir_ registers, even * if one of the directions may not be in use. @@ -1831,16 +1782,8 @@ static int s3c_hsotg_trytx(struct s3c_hsotg *hsotg, { struct s3c_hsotg_req *hs_req = hs_ep->req; - if (!hs_ep->dir_in || !hs_req) { - /** - * if request is not enqueued, we disable interrupts - * for endpoints, excepting ep0 - */ - if (hs_ep->index != 0) - s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, - hs_ep->dir_in, 0); + if (!hs_ep->dir_in || !hs_req) return 0; - } if (hs_req->req.actual < hs_req->req.length) { dev_dbg(hsotg->dev, "trying to write more for ep%d\n", @@ -1944,10 +1887,8 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, u32 epctl_reg = dir_in ? DIEPCTL(idx) : DOEPCTL(idx); u32 epsiz_reg = dir_in ? DIEPTSIZ(idx) : DOEPTSIZ(idx); u32 ints; - u32 ctrl; ints = readl(hsotg->regs + epint_reg); - ctrl = readl(hsotg->regs + epctl_reg); /* Clear endpoint interrupts */ writel(ints, hsotg->regs + epint_reg); @@ -1956,14 +1897,6 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, __func__, idx, dir_in ? "in" : "out", ints); if (ints & DxEPINT_XferCompl) { - if (hs_ep->isochronous && hs_ep->interval == 1) { - if (ctrl & DxEPCTL_EOFrNum) - ctrl |= DxEPCTL_SetEvenFr; - else - ctrl |= DxEPCTL_SetOddFr; - writel(ctrl, hsotg->regs + epctl_reg); - } - dev_dbg(hsotg->dev, "%s: XferCompl: DxEPCTL=0x%08x, DxEPTSIZ=%08x\n", __func__, readl(hsotg->regs + epctl_reg), @@ -2030,7 +1963,7 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, if (ints & DxEPINT_Back2BackSetup) dev_dbg(hsotg->dev, "%s: B2BSetup/INEPNakEff\n", __func__); - if (dir_in && !hs_ep->isochronous) { + if (dir_in) { /* not sure if this is important, but we'll clear it anyway */ if (ints & DIEPMSK_INTknTXFEmpMsk) { dev_dbg(hsotg->dev, "%s: ep%d: INTknTXFEmpMsk\n", @@ -2159,14 +2092,12 @@ static void kill_all_requests(struct s3c_hsotg *hsotg, } #define call_gadget(_hs, _entry) \ -do { \ if ((_hs)->gadget.speed != USB_SPEED_UNKNOWN && \ (_hs)->driver && (_hs)->driver->_entry) { \ spin_unlock(&_hs->lock); \ (_hs)->driver->_entry(&(_hs)->gadget); \ spin_lock(&_hs->lock); \ - } \ -} while (0) + } /** * s3c_hsotg_disconnect - disconnect service @@ -2310,19 +2241,15 @@ static void s3c_hsotg_core_init(struct s3c_hsotg *hsotg) GAHBCFG_HBstLen_Incr4, hsotg->regs + GAHBCFG); else - writel(((hsotg->dedicated_fifos) ? (GAHBCFG_NPTxFEmpLvl | - GAHBCFG_PTxFEmpLvl) : 0) | - GAHBCFG_GlblIntrEn, - hsotg->regs + GAHBCFG); + writel(GAHBCFG_GlblIntrEn, hsotg->regs + GAHBCFG); /* - * If INTknTXFEmpMsk is enabled, it's important to disable ep interrupts - * when we have no data to transfer. Otherwise we get being flooded by - * interrupts. + * Enabling INTknTXFEmpMsk here seems to be a big mistake, we end + * up being flooded with interrupts if the host is polling the + * endpoint to try and read data. */ - writel(((hsotg->dedicated_fifos) ? DIEPMSK_TxFIFOEmpty | - DIEPMSK_INTknTXFEmpMsk : 0) | + writel(((hsotg->dedicated_fifos) ? DIEPMSK_TxFIFOEmpty : 0) | DIEPMSK_EPDisbldMsk | DIEPMSK_XferComplMsk | DIEPMSK_TimeOUTMsk | DIEPMSK_AHBErrMsk | DIEPMSK_INTknEPMisMsk, @@ -2451,14 +2378,10 @@ irq_retry: if (gintsts & (GINTSTS_OEPInt | GINTSTS_IEPInt)) { u32 daint = readl(hsotg->regs + DAINT); - u32 daintmsk = readl(hsotg->regs + DAINTMSK); - u32 daint_out, daint_in; + u32 daint_out = daint >> DAINT_OutEP_SHIFT; + u32 daint_in = daint & ~(daint_out << DAINT_OutEP_SHIFT); int ep; - daint &= daintmsk; - daint_out = daint >> DAINT_OutEP_SHIFT; - daint_in = daint & ~(daint_out << DAINT_OutEP_SHIFT); - dev_dbg(hsotg->dev, "%s: daint=%08x\n", __func__, daint); for (ep = 0; ep < 15 && daint_out; ep++, daint_out >>= 1) { @@ -2539,6 +2462,7 @@ irq_retry: writel(GINTSTS_USBSusp, hsotg->regs + GINTSTS); call_gadget(hsotg, suspend); + s3c_hsotg_disconnect(hsotg); } if (gintsts & GINTSTS_WkUpInt) { @@ -2653,25 +2577,16 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, epctrl |= DxEPCTL_SNAK; /* update the endpoint state */ - s3c_hsotg_set_ep_maxpacket(hsotg, hs_ep->index, mps); + hs_ep->ep.maxpacket = mps; /* default, set to non-periodic */ - hs_ep->isochronous = 0; hs_ep->periodic = 0; - hs_ep->halted = 0; - hs_ep->interval = desc->bInterval; - - if (hs_ep->interval > 1 && hs_ep->mc > 1) - dev_err(hsotg->dev, "MC > 1 when interval is not 1\n"); switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { case USB_ENDPOINT_XFER_ISOC: - epctrl |= DxEPCTL_EPType_Iso; - epctrl |= DxEPCTL_SetEvenFr; - hs_ep->isochronous = 1; - if (dir_in) - hs_ep->periodic = 1; - break; + dev_err(hsotg->dev, "no current ISOC support\n"); + ret = -EINVAL; + goto out; case USB_ENDPOINT_XFER_BULK: epctrl |= DxEPCTL_EPType_Bulk; @@ -2719,6 +2634,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, /* enable the endpoint interrupt */ s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1); +out: spin_unlock_irqrestore(&hsotg->lock, flags); return ret; } @@ -2860,8 +2776,6 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) writel(epctl, hs->regs + epreg); - hs_ep->halted = value; - return 0; } @@ -2989,7 +2903,7 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget, int ret; if (!hsotg) { - pr_err("%s: called with no device\n", __func__); + printk(KERN_ERR "%s: called with no device\n", __func__); return -ENODEV; } @@ -3152,7 +3066,7 @@ static void s3c_hsotg_initep(struct s3c_hsotg *hsotg, hs_ep->parent = hsotg; hs_ep->ep.name = hs_ep->name; - hs_ep->ep.maxpacket = epnum ? 1024 : EP0_MPS_LIMIT; + hs_ep->ep.maxpacket = epnum ? 512 : EP0_MPS_LIMIT; hs_ep->ep.ops = &s3c_hsotg_ep_ops; /* @@ -3286,7 +3200,7 @@ static int state_show(struct seq_file *seq, void *v) readl(regs + GNPTXSTS), readl(regs + GRXSTSR)); - seq_puts(seq, "\nEndpoint status:\n"); + seq_printf(seq, "\nEndpoint status:\n"); for (idx = 0; idx < 15; idx++) { u32 in, out; @@ -3303,7 +3217,7 @@ static int state_show(struct seq_file *seq, void *v) seq_printf(seq, ", DIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x", in, out); - seq_puts(seq, "\n"); + seq_printf(seq, "\n"); } return 0; @@ -3337,7 +3251,7 @@ static int fifo_show(struct seq_file *seq, void *v) u32 val; int idx; - seq_puts(seq, "Non-periodic FIFOs:\n"); + seq_printf(seq, "Non-periodic FIFOs:\n"); seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + GRXFSIZ)); val = readl(regs + GNPTXFSIZ); @@ -3345,7 +3259,7 @@ static int fifo_show(struct seq_file *seq, void *v) val >> GNPTXFSIZ_NPTxFDep_SHIFT, val & GNPTXFSIZ_NPTxFStAddr_MASK); - seq_puts(seq, "\nPeriodic TXFIFOs:\n"); + seq_printf(seq, "\nPeriodic TXFIFOs:\n"); for (idx = 1; idx <= 15; idx++) { val = readl(regs + DPTXFSIZn(idx)); @@ -3416,7 +3330,7 @@ static int ep_show(struct seq_file *seq, void *v) readl(regs + DIEPTSIZ(index)), readl(regs + DOEPTSIZ(index))); - seq_puts(seq, "\n"); + seq_printf(seq, "\n"); seq_printf(seq, "mps %d\n", ep->ep.maxpacket); seq_printf(seq, "total_data=%ld\n", ep->total_data); @@ -3427,7 +3341,7 @@ static int ep_show(struct seq_file *seq, void *v) list_for_each_entry(req, &ep->queue, queue) { if (--show_limit < 0) { - seq_puts(seq, "not showing more requests...\n"); + seq_printf(seq, "not showing more requests...\n"); break; } diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index ec20a1f..08a1a32 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -23,17 +23,242 @@ * The valid range of num_buffers is: num >= 2 && num <= 4. */ -#include <linux/module.h> -#include <linux/blkdev.h> -#include <linux/file.h> -#include <linux/fs.h> -#include <linux/usb/composite.h> -#include "storage_common.h" +#include <linux/usb/storage.h> +#include <scsi/scsi.h> +#include <asm/unaligned.h> + + +/* + * Thanks to NetChip Technologies for donating this product ID. + * + * DO NOT REUSE THESE IDs with any other driver!! Ever!! + * Instead: allocate your own, using normal USB-IF procedures. + */ +#define FSG_VENDOR_ID 0x0525 /* NetChip */ +#define FSG_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */ + + +/*-------------------------------------------------------------------------*/ + + +#ifndef DEBUG +#undef VERBOSE_DEBUG +#undef DUMP_MSGS +#endif /* !DEBUG */ + +#ifdef VERBOSE_DEBUG +#define VLDBG LDBG +#else +#define VLDBG(lun, fmt, args...) do { } while (0) +#endif /* VERBOSE_DEBUG */ + +#define LDBG(lun, fmt, args...) dev_dbg (&(lun)->dev, fmt, ## args) +#define LERROR(lun, fmt, args...) dev_err (&(lun)->dev, fmt, ## args) +#define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args) +#define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args) + + +#ifdef DUMP_MSGS + +# define dump_msg(fsg, /* const char * */ label, \ + /* const u8 * */ buf, /* unsigned */ length) do { \ + if (length < 512) { \ + DBG(fsg, "%s, length %u:\n", label, length); \ + print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, \ + 16, 1, buf, length, 0); \ + } \ +} while (0) + +# define dump_cdb(fsg) do { } while (0) + +#else + +# define dump_msg(fsg, /* const char * */ label, \ + /* const u8 * */ buf, /* unsigned */ length) do { } while (0) + +# ifdef VERBOSE_DEBUG + +# define dump_cdb(fsg) \ + print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE, \ + 16, 1, (fsg)->cmnd, (fsg)->cmnd_size, 0) \ + +# else + +# define dump_cdb(fsg) do { } while (0) + +# endif /* VERBOSE_DEBUG */ + +#endif /* DUMP_MSGS */ + +/*-------------------------------------------------------------------------*/ + +/* Length of a SCSI Command Data Block */ +#define MAX_COMMAND_SIZE 16 + +/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */ +#define SS_NO_SENSE 0 +#define SS_COMMUNICATION_FAILURE 0x040800 +#define SS_INVALID_COMMAND 0x052000 +#define SS_INVALID_FIELD_IN_CDB 0x052400 +#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x052100 +#define SS_LOGICAL_UNIT_NOT_SUPPORTED 0x052500 +#define SS_MEDIUM_NOT_PRESENT 0x023a00 +#define SS_MEDIUM_REMOVAL_PREVENTED 0x055302 +#define SS_NOT_READY_TO_READY_TRANSITION 0x062800 +#define SS_RESET_OCCURRED 0x062900 +#define SS_SAVING_PARAMETERS_NOT_SUPPORTED 0x053900 +#define SS_UNRECOVERED_READ_ERROR 0x031100 +#define SS_WRITE_ERROR 0x030c02 +#define SS_WRITE_PROTECTED 0x072700 + +#define SK(x) ((u8) ((x) >> 16)) /* Sense Key byte, etc. */ +#define ASC(x) ((u8) ((x) >> 8)) +#define ASCQ(x) ((u8) (x)) + + +/*-------------------------------------------------------------------------*/ + + +struct fsg_lun { + struct file *filp; + loff_t file_length; + loff_t num_sectors; + + unsigned int initially_ro:1; + unsigned int ro:1; + unsigned int removable:1; + unsigned int cdrom:1; + unsigned int prevent_medium_removal:1; + unsigned int registered:1; + unsigned int info_valid:1; + unsigned int nofua:1; + + u32 sense_data; + u32 sense_data_info; + u32 unit_attention_data; + + unsigned int blkbits; /* Bits of logical block size of bound block device */ + unsigned int blksize; /* logical block size of bound block device */ + struct device dev; +}; + +static inline bool fsg_lun_is_open(struct fsg_lun *curlun) +{ + return curlun->filp != NULL; +} + +static inline struct fsg_lun *fsg_lun_from_dev(struct device *dev) +{ + return container_of(dev, struct fsg_lun, dev); +} + + +/* Big enough to hold our biggest descriptor */ +#define EP0_BUFSIZE 256 +#define DELAYED_STATUS (EP0_BUFSIZE + 999) /* An impossibly large value */ + +#ifdef CONFIG_USB_GADGET_DEBUG_FILES + +static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS; +module_param_named(num_buffers, fsg_num_buffers, uint, S_IRUGO); +MODULE_PARM_DESC(num_buffers, "Number of pipeline buffers"); + +#else + +/* + * Number of buffers we will use. + * 2 is usually enough for good buffering pipeline + */ +#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS + +#endif /* CONFIG_USB_GADGET_DEBUG_FILES */ + +/* check if fsg_num_buffers is within a valid range */ +static inline int fsg_num_buffers_validate(void) +{ + if (fsg_num_buffers >= 2 && fsg_num_buffers <= 4) + return 0; + pr_err("fsg_num_buffers %u is out of range (%d to %d)\n", + fsg_num_buffers, 2 ,4); + return -EINVAL; +} + +/* Default size of buffer length. */ +#define FSG_BUFLEN ((u32)16384) + +/* Maximal number of LUNs supported in mass storage function */ +#define FSG_MAX_LUNS 8 + +enum fsg_buffer_state { + BUF_STATE_EMPTY = 0, + BUF_STATE_FULL, + BUF_STATE_BUSY +}; + +struct fsg_buffhd { + void *buf; + enum fsg_buffer_state state; + struct fsg_buffhd *next; + + /* + * The NetChip 2280 is faster, and handles some protocol faults + * better, if we don't submit any short bulk-out read requests. + * So we will record the intended request length here. + */ + unsigned int bulk_out_intended_length; + + struct usb_request *inreq; + int inreq_busy; + struct usb_request *outreq; + int outreq_busy; +}; + +enum fsg_state { + /* This one isn't used anywhere */ + FSG_STATE_COMMAND_PHASE = -10, + FSG_STATE_DATA_PHASE, + FSG_STATE_STATUS_PHASE, + + FSG_STATE_IDLE = 0, + FSG_STATE_ABORT_BULK_OUT, + FSG_STATE_RESET, + FSG_STATE_INTERFACE_CHANGE, + FSG_STATE_CONFIG_CHANGE, + FSG_STATE_DISCONNECT, + FSG_STATE_EXIT, + FSG_STATE_TERMINATED +}; + +enum data_direction { + DATA_DIR_UNKNOWN = 0, + DATA_DIR_FROM_HOST, + DATA_DIR_TO_HOST, + DATA_DIR_NONE +}; + + +/*-------------------------------------------------------------------------*/ + + +static inline u32 get_unaligned_be24(u8 *buf) +{ + return 0xffffff & (u32) get_unaligned_be32(buf - 1); +} + + +/*-------------------------------------------------------------------------*/ + + +enum { + FSG_STRING_INTERFACE +}; + /* There is only one interface. */ -struct usb_interface_descriptor fsg_intf_desc = { +static struct usb_interface_descriptor +fsg_intf_desc = { .bLength = sizeof fsg_intf_desc, .bDescriptorType = USB_DT_INTERFACE, @@ -43,14 +268,14 @@ struct usb_interface_descriptor fsg_intf_desc = { .bInterfaceProtocol = USB_PR_BULK, /* Adjusted during fsg_bind() */ .iInterface = FSG_STRING_INTERFACE, }; -EXPORT_SYMBOL(fsg_intf_desc); /* * Three full-speed endpoint descriptors: bulk-in, bulk-out, and * interrupt-in. */ -struct usb_endpoint_descriptor fsg_fs_bulk_in_desc = { +static struct usb_endpoint_descriptor +fsg_fs_bulk_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -58,9 +283,9 @@ struct usb_endpoint_descriptor fsg_fs_bulk_in_desc = { .bmAttributes = USB_ENDPOINT_XFER_BULK, /* wMaxPacketSize set by autoconfiguration */ }; -EXPORT_SYMBOL(fsg_fs_bulk_in_desc); -struct usb_endpoint_descriptor fsg_fs_bulk_out_desc = { +static struct usb_endpoint_descriptor +fsg_fs_bulk_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -68,15 +293,13 @@ struct usb_endpoint_descriptor fsg_fs_bulk_out_desc = { .bmAttributes = USB_ENDPOINT_XFER_BULK, /* wMaxPacketSize set by autoconfiguration */ }; -EXPORT_SYMBOL(fsg_fs_bulk_out_desc); -struct usb_descriptor_header *fsg_fs_function[] = { +static struct usb_descriptor_header *fsg_fs_function[] = { (struct usb_descriptor_header *) &fsg_intf_desc, (struct usb_descriptor_header *) &fsg_fs_bulk_in_desc, (struct usb_descriptor_header *) &fsg_fs_bulk_out_desc, NULL, }; -EXPORT_SYMBOL(fsg_fs_function); /* @@ -87,7 +310,8 @@ EXPORT_SYMBOL(fsg_fs_function); * and a "device qualifier" ... plus more construction options * for the configuration descriptor. */ -struct usb_endpoint_descriptor fsg_hs_bulk_in_desc = { +static struct usb_endpoint_descriptor +fsg_hs_bulk_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -95,9 +319,9 @@ struct usb_endpoint_descriptor fsg_hs_bulk_in_desc = { .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(512), }; -EXPORT_SYMBOL(fsg_hs_bulk_in_desc); -struct usb_endpoint_descriptor fsg_hs_bulk_out_desc = { +static struct usb_endpoint_descriptor +fsg_hs_bulk_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -106,18 +330,17 @@ struct usb_endpoint_descriptor fsg_hs_bulk_out_desc = { .wMaxPacketSize = cpu_to_le16(512), .bInterval = 1, /* NAK every 1 uframe */ }; -EXPORT_SYMBOL(fsg_hs_bulk_out_desc); -struct usb_descriptor_header *fsg_hs_function[] = { +static struct usb_descriptor_header *fsg_hs_function[] = { (struct usb_descriptor_header *) &fsg_intf_desc, (struct usb_descriptor_header *) &fsg_hs_bulk_in_desc, (struct usb_descriptor_header *) &fsg_hs_bulk_out_desc, NULL, }; -EXPORT_SYMBOL(fsg_hs_function); -struct usb_endpoint_descriptor fsg_ss_bulk_in_desc = { +static struct usb_endpoint_descriptor +fsg_ss_bulk_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -125,17 +348,16 @@ struct usb_endpoint_descriptor fsg_ss_bulk_in_desc = { .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(1024), }; -EXPORT_SYMBOL(fsg_ss_bulk_in_desc); -struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = { +static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = { .bLength = sizeof(fsg_ss_bulk_in_comp_desc), .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, /*.bMaxBurst = DYNAMIC, */ }; -EXPORT_SYMBOL(fsg_ss_bulk_in_comp_desc); -struct usb_endpoint_descriptor fsg_ss_bulk_out_desc = { +static struct usb_endpoint_descriptor +fsg_ss_bulk_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -143,17 +365,15 @@ struct usb_endpoint_descriptor fsg_ss_bulk_out_desc = { .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(1024), }; -EXPORT_SYMBOL(fsg_ss_bulk_out_desc); -struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = { +static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = { .bLength = sizeof(fsg_ss_bulk_in_comp_desc), .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, /*.bMaxBurst = DYNAMIC, */ }; -EXPORT_SYMBOL(fsg_ss_bulk_out_comp_desc); -struct usb_descriptor_header *fsg_ss_function[] = { +static struct usb_descriptor_header *fsg_ss_function[] = { (struct usb_descriptor_header *) &fsg_intf_desc, (struct usb_descriptor_header *) &fsg_ss_bulk_in_desc, (struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc, @@ -161,7 +381,17 @@ struct usb_descriptor_header *fsg_ss_function[] = { (struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc, NULL, }; -EXPORT_SYMBOL(fsg_ss_function); + +/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */ +static struct usb_string fsg_strings[] = { + {FSG_STRING_INTERFACE, fsg_string_interface}, + {} +}; + +static struct usb_gadget_strings fsg_stringtab = { + .language = 0x0409, /* en-us */ + .strings = fsg_strings, +}; /*-------------------------------------------------------------------------*/ @@ -171,7 +401,7 @@ EXPORT_SYMBOL(fsg_ss_function); * the caller must own fsg->filesem for writing. */ -void fsg_lun_close(struct fsg_lun *curlun) +static void fsg_lun_close(struct fsg_lun *curlun) { if (curlun->filp) { LDBG(curlun, "close backing file\n"); @@ -179,9 +409,9 @@ void fsg_lun_close(struct fsg_lun *curlun) curlun->filp = NULL; } } -EXPORT_SYMBOL(fsg_lun_close); -int fsg_lun_open(struct fsg_lun *curlun, const char *filename) + +static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) { int ro; struct file *filp = NULL; @@ -278,7 +508,6 @@ out: fput(filp); return rc; } -EXPORT_SYMBOL(fsg_lun_open); /*-------------------------------------------------------------------------*/ @@ -287,7 +516,7 @@ EXPORT_SYMBOL(fsg_lun_open); * Sync the file data, don't bother with the metadata. * This code was copied from fs/buffer.c:sys_fdatasync(). */ -int fsg_lun_fsync_sub(struct fsg_lun *curlun) +static int fsg_lun_fsync_sub(struct fsg_lun *curlun) { struct file *filp = curlun->filp; @@ -295,9 +524,8 @@ int fsg_lun_fsync_sub(struct fsg_lun *curlun) return 0; return vfs_fsync(filp, 1); } -EXPORT_SYMBOL(fsg_lun_fsync_sub); -void store_cdrom_address(u8 *dest, int msf, u32 addr) +static void store_cdrom_address(u8 *dest, int msf, u32 addr) { if (msf) { /* Convert to Minutes-Seconds-Frames */ @@ -314,28 +542,34 @@ void store_cdrom_address(u8 *dest, int msf, u32 addr) put_unaligned_be32(addr, dest); } } -EXPORT_SYMBOL(store_cdrom_address); + /*-------------------------------------------------------------------------*/ -ssize_t fsg_show_ro(struct fsg_lun *curlun, char *buf) +static ssize_t ro_show(struct device *dev, struct device_attribute *attr, + char *buf) { + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + return sprintf(buf, "%d\n", fsg_lun_is_open(curlun) ? curlun->ro : curlun->initially_ro); } -EXPORT_SYMBOL(fsg_show_ro); -ssize_t fsg_show_nofua(struct fsg_lun *curlun, char *buf) +static ssize_t nofua_show(struct device *dev, struct device_attribute *attr, + char *buf) { + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + return sprintf(buf, "%u\n", curlun->nofua); } -EXPORT_SYMBOL(fsg_show_nofua); -ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, - char *buf) +static ssize_t file_show(struct device *dev, struct device_attribute *attr, + char *buf) { + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + struct rw_semaphore *filesem = dev_get_drvdata(dev); char *p; ssize_t rc; @@ -357,44 +591,17 @@ ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, up_read(filesem); return rc; } -EXPORT_SYMBOL(fsg_show_file); - -ssize_t fsg_show_cdrom(struct fsg_lun *curlun, char *buf) -{ - return sprintf(buf, "%u\n", curlun->cdrom); -} -EXPORT_SYMBOL(fsg_show_cdrom); - -ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf) -{ - return sprintf(buf, "%u\n", curlun->removable); -} -EXPORT_SYMBOL(fsg_show_removable); -/* - * The caller must hold fsg->filesem for reading when calling this function. - */ -static ssize_t _fsg_store_ro(struct fsg_lun *curlun, bool ro) -{ - if (fsg_lun_is_open(curlun)) { - LDBG(curlun, "read-only status change prevented\n"); - return -EBUSY; - } - - curlun->ro = ro; - curlun->initially_ro = ro; - LDBG(curlun, "read-only status set to %d\n", curlun->ro); - return 0; -} - -ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem, - const char *buf, size_t count) +static ssize_t ro_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { ssize_t rc; - bool ro; + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + struct rw_semaphore *filesem = dev_get_drvdata(dev); + unsigned ro; - rc = strtobool(buf, &ro); + rc = kstrtouint(buf, 2, &ro); if (rc) return rc; @@ -403,21 +610,27 @@ ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem, * backing file is closed. */ down_read(filesem); - rc = _fsg_store_ro(curlun, ro); - if (!rc) + if (fsg_lun_is_open(curlun)) { + LDBG(curlun, "read-only status change prevented\n"); + rc = -EBUSY; + } else { + curlun->ro = ro; + curlun->initially_ro = ro; + LDBG(curlun, "read-only status set to %d\n", curlun->ro); rc = count; + } up_read(filesem); - return rc; } -EXPORT_SYMBOL(fsg_store_ro); -ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count) +static ssize_t nofua_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { - bool nofua; + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + unsigned nofua; int ret; - ret = strtobool(buf, &nofua); + ret = kstrtouint(buf, 2, &nofua); if (ret) return ret; @@ -429,11 +642,12 @@ ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count) return count; } -EXPORT_SYMBOL(fsg_store_nofua); -ssize_t fsg_store_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, - const char *buf, size_t count) +static ssize_t file_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + struct rw_semaphore *filesem = dev_get_drvdata(dev); int rc = 0; if (curlun->prevent_medium_removal && fsg_lun_is_open(curlun)) { @@ -460,45 +674,3 @@ ssize_t fsg_store_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, up_write(filesem); return (rc < 0 ? rc : count); } -EXPORT_SYMBOL(fsg_store_file); - -ssize_t fsg_store_cdrom(struct fsg_lun *curlun, struct rw_semaphore *filesem, - const char *buf, size_t count) -{ - bool cdrom; - int ret; - - ret = strtobool(buf, &cdrom); - if (ret) - return ret; - - down_read(filesem); - ret = cdrom ? _fsg_store_ro(curlun, true) : 0; - - if (!ret) { - curlun->cdrom = cdrom; - ret = count; - } - up_read(filesem); - - return ret; -} -EXPORT_SYMBOL(fsg_store_cdrom); - -ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf, - size_t count) -{ - bool removable; - int ret; - - ret = strtobool(buf, &removable); - if (ret) - return ret; - - curlun->removable = removable; - - return count; -} -EXPORT_SYMBOL(fsg_store_removable); - -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/storage_common.h b/drivers/usb/gadget/storage_common.h deleted file mode 100644 index 70c8914..0000000 --- a/drivers/usb/gadget/storage_common.h +++ /dev/null @@ -1,225 +0,0 @@ -#ifndef USB_STORAGE_COMMON_H -#define USB_STORAGE_COMMON_H - -#include <linux/device.h> -#include <linux/usb/storage.h> -#include <scsi/scsi.h> -#include <asm/unaligned.h> - -#ifndef DEBUG -#undef VERBOSE_DEBUG -#undef DUMP_MSGS -#endif /* !DEBUG */ - -#ifdef VERBOSE_DEBUG -#define VLDBG LDBG -#else -#define VLDBG(lun, fmt, args...) do { } while (0) -#endif /* VERBOSE_DEBUG */ - -#define _LMSG(func, lun, fmt, args...) \ - do { \ - if ((lun)->name_pfx && *(lun)->name_pfx) \ - func("%s/%s: " fmt, *(lun)->name_pfx, \ - (lun)->name, ## args); \ - else \ - func("%s: " fmt, (lun)->name, ## args); \ - } while (0) - -#define LDBG(lun, fmt, args...) _LMSG(pr_debug, lun, fmt, ## args) -#define LERROR(lun, fmt, args...) _LMSG(pr_err, lun, fmt, ## args) -#define LWARN(lun, fmt, args...) _LMSG(pr_warn, lun, fmt, ## args) -#define LINFO(lun, fmt, args...) _LMSG(pr_info, lun, fmt, ## args) - - -#ifdef DUMP_MSGS - -# define dump_msg(fsg, /* const char * */ label, \ - /* const u8 * */ buf, /* unsigned */ length) \ -do { \ - if (length < 512) { \ - DBG(fsg, "%s, length %u:\n", label, length); \ - print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, \ - 16, 1, buf, length, 0); \ - } \ -} while (0) - -# define dump_cdb(fsg) do { } while (0) - -#else - -# define dump_msg(fsg, /* const char * */ label, \ - /* const u8 * */ buf, /* unsigned */ length) do { } while (0) - -# ifdef VERBOSE_DEBUG - -# define dump_cdb(fsg) \ - print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE, \ - 16, 1, (fsg)->cmnd, (fsg)->cmnd_size, 0) \ - -# else - -# define dump_cdb(fsg) do { } while (0) - -# endif /* VERBOSE_DEBUG */ - -#endif /* DUMP_MSGS */ - -/* Length of a SCSI Command Data Block */ -#define MAX_COMMAND_SIZE 16 - -/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */ -#define SS_NO_SENSE 0 -#define SS_COMMUNICATION_FAILURE 0x040800 -#define SS_INVALID_COMMAND 0x052000 -#define SS_INVALID_FIELD_IN_CDB 0x052400 -#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x052100 -#define SS_LOGICAL_UNIT_NOT_SUPPORTED 0x052500 -#define SS_MEDIUM_NOT_PRESENT 0x023a00 -#define SS_MEDIUM_REMOVAL_PREVENTED 0x055302 -#define SS_NOT_READY_TO_READY_TRANSITION 0x062800 -#define SS_RESET_OCCURRED 0x062900 -#define SS_SAVING_PARAMETERS_NOT_SUPPORTED 0x053900 -#define SS_UNRECOVERED_READ_ERROR 0x031100 -#define SS_WRITE_ERROR 0x030c02 -#define SS_WRITE_PROTECTED 0x072700 - -#define SK(x) ((u8) ((x) >> 16)) /* Sense Key byte, etc. */ -#define ASC(x) ((u8) ((x) >> 8)) -#define ASCQ(x) ((u8) (x)) - -struct fsg_lun { - struct file *filp; - loff_t file_length; - loff_t num_sectors; - - unsigned int initially_ro:1; - unsigned int ro:1; - unsigned int removable:1; - unsigned int cdrom:1; - unsigned int prevent_medium_removal:1; - unsigned int registered:1; - unsigned int info_valid:1; - unsigned int nofua:1; - - u32 sense_data; - u32 sense_data_info; - u32 unit_attention_data; - - unsigned int blkbits; /* Bits of logical block size - of bound block device */ - unsigned int blksize; /* logical block size of bound block device */ - struct device dev; - const char *name; /* "lun.name" */ - const char **name_pfx; /* "function.name" */ -}; - -static inline bool fsg_lun_is_open(struct fsg_lun *curlun) -{ - return curlun->filp != NULL; -} - -/* Default size of buffer length. */ -#define FSG_BUFLEN ((u32)16384) - -/* Maximal number of LUNs supported in mass storage function */ -#define FSG_MAX_LUNS 8 - -enum fsg_buffer_state { - BUF_STATE_EMPTY = 0, - BUF_STATE_FULL, - BUF_STATE_BUSY -}; - -struct fsg_buffhd { - void *buf; - enum fsg_buffer_state state; - struct fsg_buffhd *next; - - /* - * The NetChip 2280 is faster, and handles some protocol faults - * better, if we don't submit any short bulk-out read requests. - * So we will record the intended request length here. - */ - unsigned int bulk_out_intended_length; - - struct usb_request *inreq; - int inreq_busy; - struct usb_request *outreq; - int outreq_busy; -}; - -enum fsg_state { - /* This one isn't used anywhere */ - FSG_STATE_COMMAND_PHASE = -10, - FSG_STATE_DATA_PHASE, - FSG_STATE_STATUS_PHASE, - - FSG_STATE_IDLE = 0, - FSG_STATE_ABORT_BULK_OUT, - FSG_STATE_RESET, - FSG_STATE_INTERFACE_CHANGE, - FSG_STATE_CONFIG_CHANGE, - FSG_STATE_DISCONNECT, - FSG_STATE_EXIT, - FSG_STATE_TERMINATED -}; - -enum data_direction { - DATA_DIR_UNKNOWN = 0, - DATA_DIR_FROM_HOST, - DATA_DIR_TO_HOST, - DATA_DIR_NONE -}; - -static inline u32 get_unaligned_be24(u8 *buf) -{ - return 0xffffff & (u32) get_unaligned_be32(buf - 1); -} - -static inline struct fsg_lun *fsg_lun_from_dev(struct device *dev) -{ - return container_of(dev, struct fsg_lun, dev); -} - -enum { - FSG_STRING_INTERFACE -}; - -extern struct usb_interface_descriptor fsg_intf_desc; - -extern struct usb_endpoint_descriptor fsg_fs_bulk_in_desc; -extern struct usb_endpoint_descriptor fsg_fs_bulk_out_desc; -extern struct usb_descriptor_header *fsg_fs_function[]; - -extern struct usb_endpoint_descriptor fsg_hs_bulk_in_desc; -extern struct usb_endpoint_descriptor fsg_hs_bulk_out_desc; -extern struct usb_descriptor_header *fsg_hs_function[]; - -extern struct usb_endpoint_descriptor fsg_ss_bulk_in_desc; -extern struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc; -extern struct usb_endpoint_descriptor fsg_ss_bulk_out_desc; -extern struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc; -extern struct usb_descriptor_header *fsg_ss_function[]; - -void fsg_lun_close(struct fsg_lun *curlun); -int fsg_lun_open(struct fsg_lun *curlun, const char *filename); -int fsg_lun_fsync_sub(struct fsg_lun *curlun); -void store_cdrom_address(u8 *dest, int msf, u32 addr); -ssize_t fsg_show_ro(struct fsg_lun *curlun, char *buf); -ssize_t fsg_show_nofua(struct fsg_lun *curlun, char *buf); -ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, - char *buf); -ssize_t fsg_show_cdrom(struct fsg_lun *curlun, char *buf); -ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf); -ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem, - const char *buf, size_t count); -ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count); -ssize_t fsg_store_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, - const char *buf, size_t count); -ssize_t fsg_store_cdrom(struct fsg_lun *curlun, struct rw_semaphore *filesem, - const char *buf, size_t count); -ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf, - size_t count); - -#endif /* USB_STORAGE_COMMON_H */ diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index 0f8aad7..0ff3339 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c @@ -370,7 +370,7 @@ err: return -ENOMEM; } -static void bot_cleanup_old_alt(struct f_uas *fu) +void bot_cleanup_old_alt(struct f_uas *fu) { if (!(fu->flags & USBG_ENABLED)) return; @@ -472,7 +472,7 @@ static int usbg_bot_setup(struct usb_function *f, bot_enqueue_cmd_cbw(fu); return 0; break; - } + }; return -ENOTSUPP; } @@ -617,7 +617,7 @@ static void uasp_status_data_cmpl(struct usb_ep *ep, struct usb_request *req) default: BUG(); - } + }; return; cleanup: @@ -1923,15 +1923,15 @@ static int usbg_register_configfs(void) } fabric->tf_ops = usbg_ops; - fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = usbg_wwn_attrs; - fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = usbg_base_attrs; - fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL; - fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL; - fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL; - fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL; - fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL; - fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL; - fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL; + TF_CIT_TMPL(fabric)->tfc_wwn_cit.ct_attrs = usbg_wwn_attrs; + TF_CIT_TMPL(fabric)->tfc_tpg_base_cit.ct_attrs = usbg_base_attrs; + TF_CIT_TMPL(fabric)->tfc_tpg_attrib_cit.ct_attrs = NULL; + TF_CIT_TMPL(fabric)->tfc_tpg_param_cit.ct_attrs = NULL; + TF_CIT_TMPL(fabric)->tfc_tpg_np_base_cit.ct_attrs = NULL; + TF_CIT_TMPL(fabric)->tfc_tpg_nacl_base_cit.ct_attrs = NULL; + TF_CIT_TMPL(fabric)->tfc_tpg_nacl_attrib_cit.ct_attrs = NULL; + TF_CIT_TMPL(fabric)->tfc_tpg_nacl_auth_cit.ct_attrs = NULL; + TF_CIT_TMPL(fabric)->tfc_tpg_nacl_param_cit.ct_attrs = NULL; ret = target_fabric_configfs_register(fabric); if (ret < 0) { printk(KERN_ERR "target_fabric_configfs_register() failed" diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 27768a7..59891b1 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -356,8 +356,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); return 0; err1: - if (ret != -EISNAM) - dev_err(&udc->dev, "failed to start %s: %d\n", + dev_err(&udc->dev, "failed to start %s: %d\n", udc->driver->function, ret); udc->driver = NULL; udc->dev.driver = NULL; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index f49b0b6..0deb9d6 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -91,22 +91,10 @@ static struct usb_zero_options gzero_options = { * functional coverage for the "USBCV" test harness from USB-IF. * It's always set if OTG mode is enabled. */ -static unsigned autoresume = DEFAULT_AUTORESUME; +unsigned autoresume = DEFAULT_AUTORESUME; module_param(autoresume, uint, S_IRUGO); MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup"); -/* Maximum Autoresume time */ -static unsigned max_autoresume; -module_param(max_autoresume, uint, S_IRUGO); -MODULE_PARM_DESC(max_autoresume, "maximum seconds before remote wakeup"); - -/* Interval between two remote wakeups */ -static unsigned autoresume_interval_ms; -module_param(autoresume_interval_ms, uint, S_IRUGO); -MODULE_PARM_DESC(autoresume_interval_ms, - "milliseconds to increase successive wakeup delays"); - -static unsigned autoresume_step_ms; /*-------------------------------------------------------------------------*/ static struct usb_device_descriptor device_desc = { @@ -195,16 +183,8 @@ static void zero_suspend(struct usb_composite_dev *cdev) return; if (autoresume) { - if (max_autoresume && - (autoresume_step_ms > max_autoresume * 1000)) - autoresume_step_ms = autoresume * 1000; - - mod_timer(&autoresume_timer, jiffies + - msecs_to_jiffies(autoresume_step_ms)); - DBG(cdev, "suspend, wakeup in %d milliseconds\n", - autoresume_step_ms); - - autoresume_step_ms += autoresume_interval_ms; + mod_timer(&autoresume_timer, jiffies + (HZ * autoresume)); + DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume); } else DBG(cdev, "%s\n", __func__); } @@ -336,7 +316,6 @@ static int __init zero_bind(struct usb_composite_dev *cdev) if (autoresume) { sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; - autoresume_step_ms = autoresume * 1000; } /* support OTG systems */ |