summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
committerScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
commit62b8c978ee6b8d135d9e7953221de58000dba986 (patch)
tree683b04b2e627f6710c22c151b23c8cc9a165315e /drivers/usb/gadget
parent78fd82238d0e5716578c326404184a27ba67fd6e (diff)
downloadlinux-fsl-qoriq-62b8c978ee6b8d135d9e7953221de58000dba986.tar.xz
Rewind v3.13-rc3+ (78fd82238d0e5716) to v3.12
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/Kconfig35
-rw-r--r--drivers/usb/gadget/Makefile5
-rw-r--r--drivers/usb/gadget/acm_ms.c125
-rw-r--r--drivers/usb/gadget/amd5536udc.c2
-rw-r--r--drivers/usb/gadget/composite.c3
-rw-r--r--drivers/usb/gadget/configfs.c10
-rw-r--r--drivers/usb/gadget/configfs.h6
-rw-r--r--drivers/usb/gadget/dummy_hcd.c6
-rw-r--r--drivers/usb/gadget/f_fs.c4
-rw-r--r--drivers/usb/gadget/f_mass_storage.c1279
-rw-r--r--drivers/usb/gadget/f_mass_storage.h166
-rw-r--r--drivers/usb/gadget/fsl_qe_udc.c1
-rw-r--r--drivers/usb/gadget/g_ffs.c2
-rw-r--r--drivers/usb/gadget/goku_udc.c3
-rw-r--r--drivers/usb/gadget/lpc32xx_udc.c4
-rw-r--r--drivers/usb/gadget/mass_storage.c125
-rw-r--r--drivers/usb/gadget/multi.c247
-rw-r--r--drivers/usb/gadget/mv_u3d_core.c4
-rw-r--r--drivers/usb/gadget/net2280.c5
-rw-r--r--drivers/usb/gadget/pch_udc.c1
-rw-r--r--drivers/usb/gadget/pxa25x_udc.c1
-rw-r--r--drivers/usb/gadget/rndis.c2
-rw-r--r--drivers/usb/gadget/s3c-hsotg.c174
-rw-r--r--drivers/usb/gadget/storage_common.c430
-rw-r--r--drivers/usb/gadget/storage_common.h225
-rw-r--r--drivers/usb/gadget/tcm_usb_gadget.c24
-rw-r--r--drivers/usb/gadget/udc-core.c3
-rw-r--r--drivers/usb/gadget/zero.c27
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 */