diff options
Diffstat (limited to 'drivers/usb')
| -rw-r--r-- | drivers/usb/class/cdc-acm.c | 3 | ||||
| -rw-r--r-- | drivers/usb/core/driver.c | 6 | ||||
| -rw-r--r-- | drivers/usb/core/hub.c | 24 | ||||
| -rw-r--r-- | drivers/usb/dwc3/dwc3-msm.c | 28 | ||||
| -rw-r--r-- | drivers/usb/gadget/configfs.c | 3 | ||||
| -rw-r--r-- | drivers/usb/gadget/function/f_cdev.c | 10 | ||||
| -rw-r--r-- | drivers/usb/gadget/function/f_fs.c | 385 | ||||
| -rw-r--r-- | drivers/usb/gadget/function/f_gsi.c | 199 | ||||
| -rw-r--r-- | drivers/usb/misc/iowarrior.c | 6 | ||||
| -rw-r--r-- | drivers/usb/phy/phy-msm-qusb-v2.c | 70 | ||||
| -rw-r--r-- | drivers/usb/phy/phy-msm-qusb.c | 68 | ||||
| -rw-r--r-- | drivers/usb/renesas_usbhs/fifo.c | 4 | ||||
| -rw-r--r-- | drivers/usb/renesas_usbhs/mod_gadget.c | 6 | ||||
| -rw-r--r-- | drivers/usb/serial/cp210x.c | 1 | ||||
| -rw-r--r-- | drivers/usb/serial/cypress_m8.c | 11 | ||||
| -rw-r--r-- | drivers/usb/serial/digi_acceleport.c | 19 | ||||
| -rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 4 | ||||
| -rw-r--r-- | drivers/usb/serial/ftdi_sio_ids.h | 8 | ||||
| -rw-r--r-- | drivers/usb/serial/mct_u232.c | 9 | ||||
| -rw-r--r-- | drivers/usb/serial/option.c | 2 | ||||
| -rw-r--r-- | drivers/usb/storage/uas.c | 23 | ||||
| -rw-r--r-- | drivers/usb/storage/unusual_uas.h | 7 | ||||
| -rw-r--r-- | drivers/usb/storage/usb.c | 5 |
23 files changed, 662 insertions, 239 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index fa4e23930614..d37fdcc3143c 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1114,6 +1114,9 @@ static int acm_probe(struct usb_interface *intf, if (quirks == NO_UNION_NORMAL) { data_interface = usb_ifnum_to_if(usb_dev, 1); control_interface = usb_ifnum_to_if(usb_dev, 0); + /* we would crash */ + if (!data_interface || !control_interface) + return -ENODEV; goto skip_normal_probe; } diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 56593a9a8726..2057d91d8336 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -502,11 +502,15 @@ static int usb_unbind_interface(struct device *dev) int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void *priv) { - struct device *dev = &iface->dev; + struct device *dev; struct usb_device *udev; int retval = 0; int lpm_disable_error; + if (!iface) + return -ENODEV; + + dev = &iface->dev; if (dev->driver) return -EBUSY; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 1560f3f3e756..84df093639ac 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -4277,7 +4277,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, { struct usb_device *hdev = hub->hdev; struct usb_hcd *hcd = bus_to_hcd(hdev->bus); - int i, j, retval; + int retries, operations, retval, i; unsigned delay = HUB_SHORT_RESET_TIME; enum usb_device_speed oldspeed = udev->speed; const char *speed; @@ -4379,7 +4379,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, * first 8 bytes of the device descriptor to get the ep0 maxpacket * value. */ - for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) { + for (retries = 0; retries < GET_DESCRIPTOR_TRIES; (++retries, msleep(100))) { bool did_new_scheme = false; if (use_new_scheme(udev, retry_counter)) { @@ -4406,7 +4406,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, * 255 is for WUSB devices, we actually need to use * 512 (WUSB1.0[4.8.1]). */ - for (j = 0; j < 3; ++j) { + for (operations = 0; operations < 3; ++operations) { buf->bMaxPacketSize0 = 0; r = usb_control_msg(udev, usb_rcvaddr0pipe(), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, @@ -4426,7 +4426,13 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, r = -EPROTO; break; } - if (r == 0) + /* + * Some devices time out if they are powered on + * when already connected. They need a second + * reset. But only on the first attempt, + * lest we get into a time out/reset loop + */ + if (r == 0 || (r == -ETIMEDOUT && retries == 0)) break; } udev->descriptor.bMaxPacketSize0 = @@ -4458,7 +4464,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, * authorization will assign the final address. */ if (udev->wusb == 0) { - for (j = 0; j < SET_ADDRESS_TRIES; ++j) { + for (operations = 0; operations < SET_ADDRESS_TRIES; ++operations) { retval = hub_set_address(udev, devnum); if (retval >= 0) break; @@ -5386,6 +5392,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) } bos = udev->bos; + udev->bos = NULL; for (i = 0; i < SET_CONFIG_TRIES; ++i) { @@ -5478,11 +5485,8 @@ done: usb_set_usb2_hardware_lpm(udev, 1); usb_unlocked_enable_lpm(udev); usb_enable_ltm(udev); - /* release the new BOS descriptor allocated by hub_port_init() */ - if (udev->bos != bos) { - usb_release_bos_descriptor(udev); - udev->bos = bos; - } + usb_release_bos_descriptor(udev); + udev->bos = bos; return 0; re_enumerate: diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 4635edf0189b..4d35de1c14c5 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -92,6 +92,13 @@ MODULE_PARM_DESC(cpu_to_affin, "affin usb irq to this cpu"); #define PIPE3_PHYSTATUS_SW BIT(3) #define PIPE_UTMI_CLK_DIS BIT(8) +#define HS_PHY_CTRL_REG (QSCRATCH_REG_OFFSET + 0x10) +#define UTMI_OTG_VBUS_VALID BIT(20) +#define SW_SESSVLD_SEL BIT(28) + +#define SS_PHY_CTRL_REG (QSCRATCH_REG_OFFSET + 0x30) +#define LANE0_PWR_PRESENT BIT(24) + /* GSI related registers */ #define GSI_TRB_ADDR_BIT_53_MASK (1 << 21) #define GSI_TRB_ADDR_BIT_55_MASK (1 << 23) @@ -3090,6 +3097,25 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on) return 0; } +static void dwc3_override_vbus_status(struct dwc3_msm *mdwc, bool vbus_present) +{ + struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); + + /* Update OTG VBUS Valid from HSPHY to controller */ + dwc3_msm_write_readback(mdwc->base, HS_PHY_CTRL_REG, + vbus_present ? UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL : + UTMI_OTG_VBUS_VALID, + vbus_present ? UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL : 0); + + /* Update only if Super Speed is supported */ + if (dwc->maximum_speed == USB_SPEED_SUPER) { + /* Update VBUS Valid from SSPHY to controller */ + dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, + LANE0_PWR_PRESENT, + vbus_present ? LANE0_PWR_PRESENT : 0); + } +} + /** * dwc3_otg_start_peripheral - bind/unbind the peripheral controller. * @@ -3110,6 +3136,7 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on) dev_dbg(mdwc->dev, "%s: turn on gadget %s\n", __func__, dwc->gadget.name); + dwc3_override_vbus_status(mdwc, true); usb_phy_notify_connect(mdwc->hs_phy, USB_SPEED_HIGH); usb_phy_notify_connect(mdwc->ss_phy, USB_SPEED_SUPER); @@ -3125,6 +3152,7 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on) usb_gadget_vbus_disconnect(&dwc->gadget); usb_phy_notify_disconnect(mdwc->hs_phy, USB_SPEED_HIGH); usb_phy_notify_disconnect(mdwc->ss_phy, USB_SPEED_SUPER); + dwc3_override_vbus_status(mdwc, false); dwc3_usb3_phy_suspend(dwc, false); } diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 3639890c0dc7..5db4fe9e3cdf 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -1738,7 +1738,10 @@ void unregister_gadget_item(struct config_item *item) { struct gadget_info *gi = to_gadget_info(item); + /* to protect race with gadget_dev_desc_UDC_store*/ + mutex_lock(&gi->lock); unregister_gadget(gi); + mutex_unlock(&gi->lock); } EXPORT_SYMBOL_GPL(unregister_gadget_item); diff --git a/drivers/usb/gadget/function/f_cdev.c b/drivers/usb/gadget/function/f_cdev.c index 0a9a3afd72dd..b22ea656367e 100644 --- a/drivers/usb/gadget/function/f_cdev.c +++ b/drivers/usb/gadget/function/f_cdev.c @@ -529,6 +529,14 @@ static int usb_cser_notify(struct f_cdev *port, u8 type, u16 value, const unsigned len = sizeof(*notify) + length; void *buf; int status; + unsigned long flags; + + spin_lock_irqsave(&port->port_lock, flags); + if (!port->is_connected) { + spin_unlock_irqrestore(&port->port_lock, flags); + pr_debug("%s: port disconnected\n", __func__); + return -ENODEV; + } req = port->port_usb.notify_req; port->port_usb.notify_req = NULL; @@ -544,7 +552,9 @@ static int usb_cser_notify(struct f_cdev *port, u8 type, u16 value, notify->wValue = cpu_to_le16(value); notify->wIndex = cpu_to_le16(port->port_usb.data_id); notify->wLength = cpu_to_le16(length); + /* 2 byte data copy */ memcpy(buf, data, length); + spin_unlock_irqrestore(&port->port_lock, flags); status = usb_ep_queue(ep, req, GFP_ATOMIC); if (status < 0) { diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 48f987d77e91..c5fd3ce3ed9a 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -24,6 +24,7 @@ #include <linux/hid.h> #include <linux/module.h> #include <linux/uio.h> +#include <linux/ipc_logging.h> #include <asm/unaligned.h> #include <linux/usb/composite.h> @@ -41,6 +42,15 @@ #define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */ +#define NUM_PAGES 10 /* # of pages for ipc logging */ + +static void *ffs_ipc_log; +#define ffs_log(fmt, ...) do { \ + ipc_log_string(ffs_ipc_log, "%s: " fmt, __func__, \ + ##__VA_ARGS__); \ + pr_debug(fmt, ##__VA_ARGS__); \ +} while (0) + /* Reference counter handling */ static void ffs_data_get(struct ffs_data *ffs); static void ffs_data_put(struct ffs_data *ffs); @@ -214,6 +224,9 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len) spin_unlock_irq(&ffs->ev.waitq.lock); + ffs_log("enter: state %d setup_state %d flags %lu", ffs->state, + ffs->setup_state, ffs->flags); + req->buf = data; req->length = len; @@ -238,11 +251,18 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len) } ffs->setup_state = FFS_NO_SETUP; + + ffs_log("exit: state %d setup_state %d flags %lu", ffs->state, + ffs->setup_state, ffs->flags); + return req->status ? req->status : req->actual; } static int __ffs_ep0_stall(struct ffs_data *ffs) { + ffs_log("state %d setup_state %d flags %lu can_stall %d", ffs->state, + ffs->setup_state, ffs->flags, ffs->ev.can_stall); + if (ffs->ev.can_stall) { pr_vdebug("ep0 stall\n"); usb_ep_set_halt(ffs->gadget->ep0); @@ -263,6 +283,9 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf, ENTER(); + ffs_log("enter:len %zu state %d setup_state %d flags %lu", len, + ffs->state, ffs->setup_state, ffs->flags); + /* Fast check if setup was canceled */ if (ffs_setup_state_clear_cancelled(ffs) == FFS_SETUP_CANCELLED) return -EIDRM; @@ -391,6 +414,9 @@ done_spin: break; } + ffs_log("exit:ret %zu state %d setup_state %d flags %lu", ret, + ffs->state, ffs->setup_state, ffs->flags); + mutex_unlock(&ffs->mutex); return ret; } @@ -424,6 +450,10 @@ static ssize_t __ffs_ep0_read_events(struct ffs_data *ffs, char __user *buf, ffs->ev.count * sizeof *ffs->ev.types); spin_unlock_irq(&ffs->ev.waitq.lock); + + ffs_log("state %d setup_state %d flags %lu #evt %zu", ffs->state, + ffs->setup_state, ffs->flags, n); + mutex_unlock(&ffs->mutex); return unlikely(copy_to_user(buf, events, size)) ? -EFAULT : size; @@ -439,6 +469,9 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf, ENTER(); + ffs_log("enter:len %zu state %d setup_state %d flags %lu", len, + ffs->state, ffs->setup_state, ffs->flags); + /* Fast check if setup was canceled */ if (ffs_setup_state_clear_cancelled(ffs) == FFS_SETUP_CANCELLED) return -EIDRM; @@ -527,8 +560,12 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf, spin_unlock_irq(&ffs->ev.waitq.lock); done_mutex: + ffs_log("exit:ret %d state %d setup_state %d flags %lu", ret, + ffs->state, ffs->setup_state, ffs->flags); + mutex_unlock(&ffs->mutex); kfree(data); + return ret; } @@ -538,6 +575,9 @@ static int ffs_ep0_open(struct inode *inode, struct file *file) ENTER(); + ffs_log("state %d setup_state %d flags %lu opened %d", ffs->state, + ffs->setup_state, ffs->flags, atomic_read(&ffs->opened)); + if (unlikely(ffs->state == FFS_CLOSING)) return -EBUSY; @@ -557,6 +597,9 @@ static int ffs_ep0_release(struct inode *inode, struct file *file) ENTER(); + ffs_log("state %d setup_state %d flags %lu opened %d", ffs->state, + ffs->setup_state, ffs->flags, atomic_read(&ffs->opened)); + ffs_data_closed(ffs); return 0; @@ -570,6 +613,9 @@ static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value) ENTER(); + ffs_log("state %d setup_state %d flags %lu opened %d", ffs->state, + ffs->setup_state, ffs->flags, atomic_read(&ffs->opened)); + if (code == FUNCTIONFS_INTERFACE_REVMAP) { struct ffs_function *func = ffs->func; ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV; @@ -588,6 +634,9 @@ static unsigned int ffs_ep0_poll(struct file *file, poll_table *wait) unsigned int mask = POLLWRNORM; int ret; + ffs_log("enter:state %d setup_state %d flags %lu opened %d", ffs->state, + ffs->setup_state, ffs->flags, atomic_read(&ffs->opened)); + poll_wait(file, &ffs->ev.waitq, wait); ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK); @@ -618,6 +667,8 @@ static unsigned int ffs_ep0_poll(struct file *file, poll_table *wait) break; } + ffs_log("exit: mask %u", mask); + mutex_unlock(&ffs->mutex); return mask; @@ -648,6 +699,7 @@ static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req) ep->status = req->status ? req->status : req->actual; /* Set is_busy false to indicate completion of last request */ ep->is_busy = false; + ffs_log("ep status %d for req %p", ep->status, req); complete(req->context); } } @@ -659,6 +711,8 @@ static void ffs_user_copy_worker(struct work_struct *work) int ret = io_data->req->status ? io_data->req->status : io_data->req->actual; + ffs_log("enter: ret %d", ret); + if (io_data->read && ret > 0) { use_mm(io_data->mm); ret = copy_to_iter(io_data->buf, ret, &io_data->data); @@ -680,6 +734,8 @@ static void ffs_user_copy_worker(struct work_struct *work) kfree(io_data->to_free); kfree(io_data->buf); kfree(io_data); + + ffs_log("exit"); } static void ffs_epfile_async_io_complete(struct usb_ep *_ep, @@ -689,8 +745,12 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep, ENTER(); + ffs_log("enter"); + INIT_WORK(&io_data->work, ffs_user_copy_worker); schedule_work(&io_data->work); + + ffs_log("exit"); } static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) @@ -701,6 +761,9 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) ssize_t ret, data_len = -EINVAL; int halt; + ffs_log("enter: epfile name %s epfile err %d", epfile->name, + atomic_read(&epfile->error)); + smp_mb__before_atomic(); if (atomic_read(&epfile->error)) return -ENODEV; @@ -927,6 +990,9 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) } mutex_unlock(&epfile->mutex); + + ffs_log("exit:ret %zu", ret); + return ret; error_lock: @@ -934,6 +1000,9 @@ error_lock: mutex_unlock(&epfile->mutex); error: kfree(data); + + ffs_log("exit: ret %zu", ret); + return ret; } @@ -944,6 +1013,9 @@ ffs_epfile_open(struct inode *inode, struct file *file) ENTER(); + ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state, + epfile->ffs->setup_state, epfile->ffs->flags); + if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) return -ENODEV; @@ -962,6 +1034,9 @@ ffs_epfile_open(struct inode *inode, struct file *file) smp_mb__before_atomic(); atomic_set(&epfile->error, 0); + ffs_log("exit:state %d setup_state %d flag %lu", epfile->ffs->state, + epfile->ffs->setup_state, epfile->ffs->flags); + return 0; } @@ -973,6 +1048,9 @@ static int ffs_aio_cancel(struct kiocb *kiocb) ENTER(); + ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state, + epfile->ffs->setup_state, epfile->ffs->flags); + spin_lock_irq(&epfile->ffs->eps_lock); if (likely(io_data && io_data->ep && io_data->req)) @@ -982,6 +1060,8 @@ static int ffs_aio_cancel(struct kiocb *kiocb) spin_unlock_irq(&epfile->ffs->eps_lock); + ffs_log("exit: value %d", value); + return value; } @@ -992,6 +1072,8 @@ static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from) ENTER(); + ffs_log("enter"); + if (!is_sync_kiocb(kiocb)) { p = kmalloc(sizeof(io_data), GFP_KERNEL); if (unlikely(!p)) @@ -1018,6 +1100,9 @@ static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from) kfree(p); else *from = p->data; + + ffs_log("exit"); + return res; } @@ -1028,6 +1113,8 @@ static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to) ENTER(); + ffs_log("enter"); + if (!is_sync_kiocb(kiocb)) { p = kmalloc(sizeof(io_data), GFP_KERNEL); if (unlikely(!p)) @@ -1066,6 +1153,9 @@ static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to) } else { *to = p->data; } + + ffs_log("enter"); + return res; } @@ -1076,12 +1166,17 @@ ffs_epfile_release(struct inode *inode, struct file *file) ENTER(); + ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state, + epfile->ffs->setup_state, epfile->ffs->flags); + smp_mb__before_atomic(); atomic_set(&epfile->opened, 0); atomic_set(&epfile->error, 1); ffs_data_closed(epfile->ffs); file->private_data = NULL; + ffs_log("exit"); + return 0; } @@ -1093,6 +1188,9 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code, ENTER(); + ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state, + epfile->ffs->setup_state, epfile->ffs->flags); + if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) return -ENODEV; @@ -1143,6 +1241,8 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code, } spin_unlock_irq(&epfile->ffs->eps_lock); + ffs_log("exit:ret %d", ret); + return ret; } @@ -1174,6 +1274,8 @@ ffs_sb_make_inode(struct super_block *sb, void *data, ENTER(); + ffs_log("enter"); + inode = new_inode(sb); if (likely(inode)) { @@ -1193,6 +1295,8 @@ ffs_sb_make_inode(struct super_block *sb, void *data, inode->i_op = iops; } + ffs_log("exit"); + return inode; } @@ -1207,6 +1311,8 @@ static struct dentry *ffs_sb_create_file(struct super_block *sb, ENTER(); + ffs_log("enter"); + dentry = d_alloc_name(sb->s_root, name); if (unlikely(!dentry)) return NULL; @@ -1218,6 +1324,9 @@ static struct dentry *ffs_sb_create_file(struct super_block *sb, } d_add(dentry, inode); + + ffs_log("exit"); + return dentry; } @@ -1243,6 +1352,8 @@ static int ffs_sb_fill(struct super_block *sb, void *_data, int silent) ENTER(); + ffs_log("enter"); + ffs->sb = sb; data->ffs_data = NULL; sb->s_fs_info = ffs; @@ -1267,6 +1378,8 @@ static int ffs_sb_fill(struct super_block *sb, void *_data, int silent) &ffs_ep0_operations))) return -ENOMEM; + ffs_log("exit"); + return 0; } @@ -1274,6 +1387,8 @@ static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts) { ENTER(); + ffs_log("enter"); + if (!opts || !*opts) return 0; @@ -1356,6 +1471,8 @@ invalid: opts = comma + 1; } + ffs_log("exit"); + return 0; } @@ -1381,6 +1498,8 @@ ffs_fs_mount(struct file_system_type *t, int flags, ENTER(); + ffs_log("enter"); + ret = ffs_fs_parse_opts(&data, opts); if (unlikely(ret < 0)) return ERR_PTR(ret); @@ -1410,6 +1529,9 @@ ffs_fs_mount(struct file_system_type *t, int flags, ffs_release_dev(data.ffs_data); ffs_data_put(data.ffs_data); } + + ffs_log("exit"); + return rv; } @@ -1418,12 +1540,16 @@ ffs_fs_kill_sb(struct super_block *sb) { ENTER(); + ffs_log("enter"); + kill_litter_super(sb); if (sb->s_fs_info) { ffs_release_dev(sb->s_fs_info); ffs_data_closed(sb->s_fs_info); ffs_data_put(sb->s_fs_info); } + + ffs_log("exit"); } static struct file_system_type ffs_fs_type = { @@ -1449,6 +1575,8 @@ static int functionfs_init(void) else pr_err("failed registering file system (%d)\n", ret); + ffs_ipc_log = ipc_log_context_create(NUM_PAGES, "f_fs", 0); + return ret; } @@ -1470,14 +1598,21 @@ static void ffs_data_get(struct ffs_data *ffs) { ENTER(); + ffs_log("enter"); + smp_mb__before_atomic(); atomic_inc(&ffs->ref); + + ffs_log("exit"); } static void ffs_data_opened(struct ffs_data *ffs) { ENTER(); + ffs_log("enter: state %d setup_state %d flag %lu opened %d", ffs->state, + ffs->setup_state, ffs->flags, atomic_read(&ffs->opened)); + smp_mb__before_atomic(); atomic_inc(&ffs->ref); if (atomic_add_return(1, &ffs->opened) == 1 && @@ -1485,12 +1620,17 @@ static void ffs_data_opened(struct ffs_data *ffs) ffs->state = FFS_CLOSING; ffs_data_reset(ffs); } + + ffs_log("exit: state %d setup_state %d flag %lu", ffs->state, + ffs->setup_state, ffs->flags); } static void ffs_data_put(struct ffs_data *ffs) { ENTER(); + ffs_log("enter"); + smp_mb__before_atomic(); if (unlikely(atomic_dec_and_test(&ffs->ref))) { pr_info("%s(): freeing\n", __func__); @@ -1500,12 +1640,17 @@ static void ffs_data_put(struct ffs_data *ffs) kfree(ffs->dev_name); kfree(ffs); } + + ffs_log("exit"); } static void ffs_data_closed(struct ffs_data *ffs) { ENTER(); + ffs_log("enter: state %d setup_state %d flag %lu opened %d", ffs->state, + ffs->setup_state, ffs->flags, atomic_read(&ffs->opened)); + smp_mb__before_atomic(); if (atomic_dec_and_test(&ffs->opened)) { if (ffs->no_disconnect) { @@ -1529,6 +1674,9 @@ static void ffs_data_closed(struct ffs_data *ffs) ffs_data_reset(ffs); } + ffs_log("exit: state %d setup_state %d flag %lu", ffs->state, + ffs->setup_state, ffs->flags); + ffs_data_put(ffs); } @@ -1540,6 +1688,8 @@ static struct ffs_data *ffs_data_new(void) ENTER(); + ffs_log("enter"); + atomic_set(&ffs->ref, 1); atomic_set(&ffs->opened, 0); ffs->state = FFS_READ_DESCRIPTORS; @@ -1553,6 +1703,8 @@ static struct ffs_data *ffs_data_new(void) /* XXX REVISIT need to update it in some places, or do we? */ ffs->ev.can_stall = 1; + ffs_log("exit"); + return ffs; } @@ -1560,6 +1712,9 @@ static void ffs_data_clear(struct ffs_data *ffs) { ENTER(); + ffs_log("enter: state %d setup_state %d flag %lu", ffs->state, + ffs->setup_state, ffs->flags); + pr_debug("%s: ffs->gadget= %p, ffs->flags= %lu\n", __func__, ffs->gadget, ffs->flags); ffs_closed(ffs); @@ -1578,12 +1733,18 @@ static void ffs_data_clear(struct ffs_data *ffs) kfree(ffs->raw_descs_data); kfree(ffs->raw_strings); kfree(ffs->stringtabs); + + ffs_log("exit: state %d setup_state %d flag %lu", ffs->state, + ffs->setup_state, ffs->flags); } static void ffs_data_reset(struct ffs_data *ffs) { ENTER(); + ffs_log("enter: state %d setup_state %d flag %lu", ffs->state, + ffs->setup_state, ffs->flags); + ffs_data_clear(ffs); ffs->epfiles = NULL; @@ -1606,6 +1767,9 @@ static void ffs_data_reset(struct ffs_data *ffs) ffs->state = FFS_READ_DESCRIPTORS; ffs->setup_state = FFS_NO_SETUP; ffs->flags = 0; + + ffs_log("exit: state %d setup_state %d flag %lu", ffs->state, + ffs->setup_state, ffs->flags); } @@ -1616,6 +1780,9 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) ENTER(); + ffs_log("enter: state %d setup_state %d flag %lu", ffs->state, + ffs->setup_state, ffs->flags); + if (WARN_ON(ffs->state != FFS_ACTIVE || test_and_set_bit(FFS_FL_BOUND, &ffs->flags))) return -EBADFD; @@ -1641,6 +1808,10 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) } ffs->gadget = cdev->gadget; + + ffs_log("exit: state %d setup_state %d flag %lu gadget %p\n", + ffs->state, ffs->setup_state, ffs->flags, ffs->gadget); + ffs_data_get(ffs); return 0; } @@ -1654,6 +1825,8 @@ static void functionfs_unbind(struct ffs_data *ffs) ffs->ep0req = NULL; ffs->gadget = NULL; clear_bit(FFS_FL_BOUND, &ffs->flags); + ffs_log("state %d setup_state %d flag %lu gadget %p\n", + ffs->state, ffs->setup_state, ffs->flags, ffs->gadget); ffs_data_put(ffs); } } @@ -1665,6 +1838,9 @@ static int ffs_epfiles_create(struct ffs_data *ffs) ENTER(); + ffs_log("enter: state %d setup_state %d flag %lu", ffs->state, + ffs->setup_state, ffs->flags); + count = ffs->eps_count; epfiles = kcalloc(count, sizeof(*epfiles), GFP_KERNEL); if (!epfiles) @@ -1690,6 +1866,10 @@ static int ffs_epfiles_create(struct ffs_data *ffs) } ffs->epfiles = epfiles; + + ffs_log("exit: epfile name %s state %d setup_state %d flag %lu", + epfile->name, ffs->state, ffs->setup_state, ffs->flags); + return 0; } @@ -1699,6 +1879,8 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count) ENTER(); + ffs_log("enter: epfilename %s", epfile->name); + for (; count; --count, ++epfile) { BUG_ON(mutex_is_locked(&epfile->mutex) || waitqueue_active(&epfile->wait)); @@ -1710,6 +1892,8 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count) } kfree(epfiles); + + ffs_log("exit"); } static void ffs_func_eps_disable(struct ffs_function *func) @@ -1719,6 +1903,9 @@ static void ffs_func_eps_disable(struct ffs_function *func) unsigned count = func->ffs->eps_count; unsigned long flags; + ffs_log("enter: state %d setup_state %d flag %lu", func->ffs->state, + func->ffs->setup_state, func->ffs->flags); + spin_lock_irqsave(&func->ffs->eps_lock, flags); do { @@ -1738,6 +1925,8 @@ static void ffs_func_eps_disable(struct ffs_function *func) } } while (--count); spin_unlock_irqrestore(&func->ffs->eps_lock, flags); + + ffs_log("exit"); } static int ffs_func_eps_enable(struct ffs_function *func) @@ -1749,6 +1938,9 @@ static int ffs_func_eps_enable(struct ffs_function *func) unsigned long flags; int ret = 0; + ffs_log("enter: state %d setup_state %d flag %lu", func->ffs->state, + func->ffs->setup_state, func->ffs->flags); + spin_lock_irqsave(&func->ffs->eps_lock, flags); do { struct usb_endpoint_descriptor *ds; @@ -1786,6 +1978,7 @@ static int ffs_func_eps_enable(struct ffs_function *func) epfile->ep = ep; epfile->in = usb_endpoint_dir_in(ds); epfile->isoc = usb_endpoint_xfer_isoc(ds); + ffs_log("usb_ep_enable %s", ep->ep->name); } else { break; } @@ -1797,6 +1990,8 @@ static int ffs_func_eps_enable(struct ffs_function *func) } while (--count); spin_unlock_irqrestore(&func->ffs->eps_lock, flags); + ffs_log("exit: ret %d", ret); + return ret; } @@ -1837,6 +2032,8 @@ static int __must_check ffs_do_single_desc(char *data, unsigned len, ENTER(); + ffs_log("enter: len %u", len); + /* At least two bytes are required: length and type */ if (len < 2) { pr_vdebug("descriptor too short\n"); @@ -1953,6 +2150,8 @@ inv_length: #undef __entity_check_STRING #undef __entity_check_ENDPOINT + ffs_log("exit: desc type %d length %d", _ds->bDescriptorType, length); + return length; } @@ -1964,6 +2163,8 @@ static int __must_check ffs_do_descs(unsigned count, char *data, unsigned len, ENTER(); + ffs_log("enter: len %u", len); + for (;;) { int ret; @@ -1991,6 +2192,8 @@ static int __must_check ffs_do_descs(unsigned count, char *data, unsigned len, data += ret; ++num; } + + ffs_log("exit: len %u", len); } static int __ffs_data_do_entity(enum ffs_entity_type type, @@ -2002,6 +2205,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type, ENTER(); + ffs_log("enter: type %u", type); + switch (type) { case FFS_DESCRIPTOR: break; @@ -2040,6 +2245,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type, break; } + ffs_log("exit"); + return 0; } @@ -2049,6 +2256,8 @@ static int __ffs_do_os_desc_header(enum ffs_os_desc_type *next_type, u16 bcd_version = le16_to_cpu(desc->bcdVersion); u16 w_index = le16_to_cpu(desc->wIndex); + ffs_log("enter"); + if (bcd_version != 1) { pr_vdebug("unsupported os descriptors version: %d", bcd_version); @@ -2066,6 +2275,8 @@ static int __ffs_do_os_desc_header(enum ffs_os_desc_type *next_type, return -EINVAL; } + ffs_log("exit: size of desc %lu", sizeof(*desc)); + return sizeof(*desc); } @@ -2085,6 +2296,8 @@ static int __must_check ffs_do_single_os_desc(char *data, unsigned len, ENTER(); + ffs_log("enter: len %u os desc type %d", len, type); + /* loop over all ext compat/ext prop descriptors */ while (feature_count--) { ret = entity(type, h, data, len, priv); @@ -2095,6 +2308,9 @@ static int __must_check ffs_do_single_os_desc(char *data, unsigned len, data += ret; len -= ret; } + + ffs_log("exit"); + return _len - len; } @@ -2108,6 +2324,8 @@ static int __must_check ffs_do_os_descs(unsigned count, ENTER(); + ffs_log("enter: len %u", len); + for (num = 0; num < count; ++num) { int ret; enum ffs_os_desc_type type; @@ -2157,6 +2375,9 @@ static int __must_check ffs_do_os_descs(unsigned count, len -= ret; data += ret; } + + ffs_log("exit"); + return _len - len; } @@ -2172,6 +2393,8 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type, ENTER(); + ffs_log("enter: len %u", len); + switch (type) { case FFS_OS_DESC_EXT_COMPAT: { struct usb_ext_compat_desc *d = data; @@ -2226,6 +2449,9 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type, pr_vdebug("unknown descriptor: %d\n", type); return -EINVAL; } + + ffs_log("exit"); + return length; } @@ -2239,6 +2465,8 @@ static int __ffs_data_got_descs(struct ffs_data *ffs, ENTER(); + ffs_log("enter: len %zu", len); + if (get_unaligned_le32(data + 4) != len) goto error; @@ -2349,10 +2577,13 @@ static int __ffs_data_got_descs(struct ffs_data *ffs, ffs->ss_descs_count = counts[2]; ffs->ms_os_descs_count = os_descs_count; + ffs_log("exit"); + return 0; error: kfree(_data); + ffs_log("exit: ret %d", ret); return ret; } @@ -2366,6 +2597,8 @@ static int __ffs_data_got_strings(struct ffs_data *ffs, ENTER(); + ffs_log("enter: len %zu", len); + if (unlikely(get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC || get_unaligned_le32(data + 4) != len)) goto error; @@ -2480,12 +2713,14 @@ static int __ffs_data_got_strings(struct ffs_data *ffs, ffs->stringtabs = stringtabs; ffs->raw_strings = _data; + ffs_log("exit"); return 0; error_free: kfree(stringtabs); error: kfree(_data); + ffs_log("exit: -EINVAL"); return -EINVAL; } @@ -2498,6 +2733,9 @@ static void __ffs_event_add(struct ffs_data *ffs, enum usb_functionfs_event_type rem_type1, rem_type2 = type; int neg = 0; + ffs_log("enter: type %d state %d setup_state %d flag %lu", type, + ffs->state, ffs->setup_state, ffs->flags); + /* * Abort any unhandled setup * @@ -2557,6 +2795,9 @@ static void __ffs_event_add(struct ffs_data *ffs, wake_up_locked(&ffs->ev.waitq); if (ffs->ffs_eventfd) eventfd_signal(ffs->ffs_eventfd, 1); + + ffs_log("exit: state %d setup_state %d flag %lu", ffs->state, + ffs->setup_state, ffs->flags); } static void ffs_event_add(struct ffs_data *ffs, @@ -2591,6 +2832,8 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep, int idx; static const char *speed_names[] = { "full", "high", "super" }; + ffs_log("enter"); + if (type != FFS_DESCRIPTOR) return 0; @@ -2666,6 +2909,8 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep, } ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength); + ffs_log("exit"); + return 0; } @@ -2677,6 +2922,8 @@ static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep, unsigned idx; u8 newValue; + ffs_log("enter: type %d", type); + switch (type) { default: case FFS_DESCRIPTOR: @@ -2721,6 +2968,9 @@ static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep, pr_vdebug("%02x -> %02x\n", *valuep, newValue); *valuep = newValue; + + ffs_log("exit: newValue %d", newValue); + return 0; } @@ -2731,6 +2981,8 @@ static int __ffs_func_bind_do_os_desc(enum ffs_os_desc_type type, struct ffs_function *func = priv; u8 length = 0; + ffs_log("enter: type %d", type); + switch (type) { case FFS_OS_DESC_EXT_COMPAT: { struct usb_ext_compat_desc *desc = data; @@ -2800,6 +3052,8 @@ static int __ffs_func_bind_do_os_desc(enum ffs_os_desc_type type, pr_vdebug("unknown descriptor: %d\n", type); } + ffs_log("exit"); + return length; } @@ -2813,6 +3067,8 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f, ENTER(); + ffs_log("enter"); + /* * Legacy gadget triggers binding in functionfs_ready_callback, * which already uses locking; taking the same lock here would @@ -2847,6 +3103,8 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f, ffs_opts->refcnt++; func->function.strings = func->ffs->stringtabs; + ffs_log("exit"); + return ffs_opts; } @@ -2889,6 +3147,9 @@ static int _ffs_func_bind(struct usb_configuration *c, ENTER(); + ffs_log("enter: state %d setup_state %d flag %lu", ffs->state, + ffs->setup_state, ffs->flags); + /* Has descriptors only for speeds gadget does not support */ if (unlikely(!(full | high | super))) return -ENOTSUPP; @@ -3006,10 +3267,15 @@ static int _ffs_func_bind(struct usb_configuration *c, /* And we're done */ ffs_event_add(ffs, FUNCTIONFS_BIND); + + ffs_log("exit: state %d setup_state %d flag %lu", ffs->state, + ffs->setup_state, ffs->flags); + return 0; error: /* XXX Do we need to release all claimed endpoints here? */ + ffs_log("exit: ret %d", ret); return ret; } @@ -3020,6 +3286,8 @@ static int ffs_func_bind(struct usb_configuration *c, struct ffs_function *func = ffs_func_from_usb(f); int ret; + ffs_log("enter"); + if (IS_ERR(ffs_opts)) return PTR_ERR(ffs_opts); @@ -3027,6 +3295,8 @@ static int ffs_func_bind(struct usb_configuration *c, if (ret && !--ffs_opts->refcnt) functionfs_unbind(func->ffs); + ffs_log("exit: ret %d", ret); + return ret; } @@ -3037,7 +3307,12 @@ static void ffs_reset_work(struct work_struct *work) { struct ffs_data *ffs = container_of(work, struct ffs_data, reset_work); + + ffs_log("enter"); + ffs_data_reset(ffs); + + ffs_log("exit"); } static int ffs_func_set_alt(struct usb_function *f, @@ -3047,6 +3322,8 @@ static int ffs_func_set_alt(struct usb_function *f, struct ffs_data *ffs = func->ffs; int ret = 0, intf; + ffs_log("enter"); + if (alt != (unsigned)-1) { intf = ffs_func_revmap_intf(func, interface); if (unlikely(intf < 0)) @@ -3082,6 +3359,8 @@ static int ffs_func_set_alt(struct usb_function *f, usb_gadget_autopm_get_async(ffs->gadget); } + ffs_log("exit: ret %d", ret); + return ret; } @@ -3090,9 +3369,13 @@ static void ffs_func_disable(struct usb_function *f) struct ffs_function *func = ffs_func_from_usb(f); struct ffs_data *ffs = func->ffs; + ffs_log("enter"); + ffs_func_set_alt(f, 0, (unsigned)-1); /* matching put to allow LPM on disconnect */ usb_gadget_autopm_put_async(ffs->gadget); + + ffs_log("exit"); } static int ffs_func_setup(struct usb_function *f, @@ -3105,6 +3388,8 @@ static int ffs_func_setup(struct usb_function *f, ENTER(); + ffs_log("enter"); + pr_vdebug("creq->bRequestType = %02x\n", creq->bRequestType); pr_vdebug("creq->bRequest = %02x\n", creq->bRequest); pr_vdebug("creq->wValue = %04x\n", le16_to_cpu(creq->wValue)); @@ -3148,19 +3433,31 @@ static int ffs_func_setup(struct usb_function *f, __ffs_event_add(ffs, FUNCTIONFS_SETUP); spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags); + ffs_log("exit"); + return 0; } static void ffs_func_suspend(struct usb_function *f) { ENTER(); + + ffs_log("enter"); + ffs_event_add(ffs_func_from_usb(f)->ffs, FUNCTIONFS_SUSPEND); + + ffs_log("exit"); } static void ffs_func_resume(struct usb_function *f) { ENTER(); + + ffs_log("enter"); + ffs_event_add(ffs_func_from_usb(f)->ffs, FUNCTIONFS_RESUME); + + ffs_log("exit"); } @@ -3177,11 +3474,15 @@ static int ffs_func_revmap_intf(struct ffs_function *func, u8 intf) short *nums = func->interfaces_nums; unsigned count = func->ffs->interfaces_count; + ffs_log("enter"); + for (; count; --count, ++nums) { if (*nums >= 0 && *nums == intf) return nums - func->interfaces_nums; } + ffs_log("exit"); + return -EDOM; } @@ -3194,6 +3495,8 @@ static struct ffs_dev *_ffs_do_find_dev(const char *name) { struct ffs_dev *dev; + ffs_log("enter"); + list_for_each_entry(dev, &ffs_devices, entry) { if (!dev->name || !name) continue; @@ -3201,6 +3504,8 @@ static struct ffs_dev *_ffs_do_find_dev(const char *name) return dev; } + ffs_log("exit"); + return NULL; } @@ -3211,12 +3516,16 @@ static struct ffs_dev *_ffs_get_single_dev(void) { struct ffs_dev *dev; + ffs_log("enter"); + if (list_is_singular(&ffs_devices)) { dev = list_first_entry(&ffs_devices, struct ffs_dev, entry); if (dev->single) return dev; } + ffs_log("exit"); + return NULL; } @@ -3227,11 +3536,17 @@ static struct ffs_dev *_ffs_find_dev(const char *name) { struct ffs_dev *dev; + ffs_log("enter"); + dev = _ffs_get_single_dev(); if (dev) return dev; - return _ffs_do_find_dev(name); + dev = _ffs_do_find_dev(name); + + ffs_log("exit"); + + return dev; } /* Configfs support *********************************************************/ @@ -3353,6 +3668,10 @@ static void ffs_func_unbind(struct usb_configuration *c, unsigned long flags; ENTER(); + + ffs_log("enter: state %d setup_state %d flag %lu", ffs->state, + ffs->setup_state, ffs->flags); + if (ffs->func == func) { ffs_func_eps_disable(func); ffs->func = NULL; @@ -3383,6 +3702,9 @@ static void ffs_func_unbind(struct usb_configuration *c, func->interfaces_nums = NULL; ffs_event_add(ffs, FUNCTIONFS_UNBIND); + + ffs_log("exit: state %d setup_state %d flag %lu", ffs->state, + ffs->setup_state, ffs->flags); } static struct usb_function *ffs_alloc(struct usb_function_instance *fi) @@ -3445,12 +3767,16 @@ static int _ffs_name_dev(struct ffs_dev *dev, const char *name) { struct ffs_dev *existing; + ffs_log("enter"); + existing = _ffs_do_find_dev(name); if (existing) return -EBUSY; dev->name = name; + ffs_log("exit"); + return 0; } @@ -3461,10 +3787,14 @@ int ffs_name_dev(struct ffs_dev *dev, const char *name) { int ret; + ffs_log("enter"); + ffs_dev_lock(); ret = _ffs_name_dev(dev, name); ffs_dev_unlock(); + ffs_log("exit"); + return ret; } EXPORT_SYMBOL_GPL(ffs_name_dev); @@ -3473,6 +3803,8 @@ int ffs_single_dev(struct ffs_dev *dev) { int ret; + ffs_log("enter"); + ret = 0; ffs_dev_lock(); @@ -3482,6 +3814,9 @@ int ffs_single_dev(struct ffs_dev *dev) dev->single = true; ffs_dev_unlock(); + + ffs_log("exit"); + return ret; } EXPORT_SYMBOL_GPL(ffs_single_dev); @@ -3491,12 +3826,17 @@ EXPORT_SYMBOL_GPL(ffs_single_dev); */ static void _ffs_free_dev(struct ffs_dev *dev) { + + ffs_log("enter"); + list_del(&dev->entry); if (dev->name_allocated) kfree(dev->name); kfree(dev); if (list_empty(&ffs_devices)) functionfs_cleanup(); + + ffs_log("exit"); } static void *ffs_acquire_dev(const char *dev_name) @@ -3504,6 +3844,9 @@ static void *ffs_acquire_dev(const char *dev_name) struct ffs_dev *ffs_dev; ENTER(); + + ffs_log("enter"); + ffs_dev_lock(); ffs_dev = _ffs_find_dev(dev_name); @@ -3518,6 +3861,9 @@ static void *ffs_acquire_dev(const char *dev_name) ffs_dev->mounted = true; ffs_dev_unlock(); + + ffs_log("exit"); + return ffs_dev; } @@ -3526,6 +3872,9 @@ static void ffs_release_dev(struct ffs_data *ffs_data) struct ffs_dev *ffs_dev; ENTER(); + + ffs_log("enter"); + ffs_dev_lock(); ffs_dev = ffs_data->private_data; @@ -3537,6 +3886,8 @@ static void ffs_release_dev(struct ffs_data *ffs_data) } ffs_dev_unlock(); + + ffs_log("exit"); } static int ffs_ready(struct ffs_data *ffs) @@ -3545,6 +3896,9 @@ static int ffs_ready(struct ffs_data *ffs) int ret = 0; ENTER(); + + ffs_log("enter"); + ffs_dev_lock(); ffs_obj = ffs->private_data; @@ -3569,6 +3923,9 @@ static int ffs_ready(struct ffs_data *ffs) set_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags); done: ffs_dev_unlock(); + + ffs_log("exit"); + return ret; } @@ -3578,11 +3935,16 @@ static void ffs_closed(struct ffs_data *ffs) struct f_fs_opts *opts; ENTER(); + + ffs_log("enter"); + ffs_dev_lock(); ffs_obj = ffs->private_data; - if (!ffs_obj) + if (!ffs_obj) { + ffs_dev_unlock(); goto done; + } ffs_obj->desc_ready = false; @@ -3590,20 +3952,29 @@ static void ffs_closed(struct ffs_data *ffs) ffs_obj->ffs_closed_callback) ffs_obj->ffs_closed_callback(ffs); - if (ffs_obj->opts) + if (ffs_obj->opts) { opts = ffs_obj->opts; - else + } else { + ffs_dev_unlock(); goto done; + } smp_mb__before_atomic(); if (opts->no_configfs || !opts->func_inst.group.cg_item.ci_parent - || !atomic_read(&opts->func_inst.group.cg_item.ci_kref.refcount)) + || !atomic_read(&opts->func_inst.group.cg_item.ci_kref.refcount)) { + ffs_dev_unlock(); goto done; + } + + ffs_dev_unlock(); - unregister_gadget_item(ffs_obj->opts-> + if (test_bit(FFS_FL_BOUND, &ffs->flags)) { + unregister_gadget_item(opts-> func_inst.group.cg_item.ci_parent->ci_parent); + ffs_log("unreg gadget done"); + } done: - ffs_dev_unlock(); + ffs_log("exit"); } /* Misc helper functions ****************************************************/ diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index 5612645d7237..a629723d19cb 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -39,6 +39,8 @@ static struct workqueue_struct *ipa_usb_wq; static void ipa_disconnect_handler(struct gsi_data_port *d_port); static int gsi_ctrl_send_notification(struct f_gsi *gsi, enum gsi_ctrl_notify_state); +static int gsi_alloc_trb_buffer(struct f_gsi *gsi); +static void gsi_free_trb_buffer(struct f_gsi *gsi); void post_event(struct gsi_data_port *port, u8 event) { @@ -474,6 +476,9 @@ static void ipa_disconnect_work_handler(struct gsi_data_port *d_port) if (gsi->d_port.out_ep) usb_gsi_ep_op(gsi->d_port.out_ep, NULL, GSI_EP_OP_FREE_TRBS); + + /* free buffers allocated with each TRB */ + gsi_free_trb_buffer(gsi); } static int ipa_suspend_work_handler(struct gsi_data_port *d_port) @@ -547,6 +552,7 @@ static void ipa_work_handler(struct work_struct *w) struct usb_gadget *gadget = d_port->gadget; struct device *dev; struct device *gad_dev; + struct f_gsi *gsi; event = read_event(d_port); @@ -566,31 +572,27 @@ static void ipa_work_handler(struct work_struct *w) return; } + gsi = d_port_to_gsi(d_port); + switch (d_port->sm_state) { case STATE_UNINITIALIZED: break; case STATE_INITIALIZED: if (event == EVT_CONNECT_IN_PROGRESS) { + usb_gadget_autopm_get(d_port->gadget); + log_event_dbg("%s: get = %d", __func__, + atomic_read(&gad_dev->power.usage_count)); + /* allocate buffers used with each TRB */ + ret = gsi_alloc_trb_buffer(gsi); + if (ret) { + log_event_err("%s: gsi_alloc_trb_failed\n", + __func__); + break; + } ipa_connect_channels(d_port); d_port->sm_state = STATE_CONNECT_IN_PROGRESS; log_event_dbg("%s: ST_INIT_EVT_CONN_IN_PROG", __func__); - } else if (event == EVT_HOST_READY) { - /* - * When in a composition such as RNDIS + ADB, - * RNDIS host sends a GEN_CURRENT_PACKET_FILTER msg - * to enable/disable flow control eg. during RNDIS - * adaptor disable/enable from device manager. - * In the case of the msg to disable flow control, - * connect IPA channels and enable data path. - * EVT_HOST_READY is posted to the state machine - * in the handler for this msg. - */ - ipa_connect_channels(d_port); - ipa_data_path_enable(d_port); - d_port->sm_state = STATE_CONNECTED; - log_event_dbg("%s: ST_INIT_EVT_HOST_READY", - __func__); } break; case STATE_CONNECT_IN_PROGRESS: @@ -648,6 +650,7 @@ static void ipa_work_handler(struct work_struct *w) &gad_dev->power.usage_count)); } else if (event == EVT_SUSPEND) { if (peek_event(d_port) == EVT_DISCONNECTED) { + read_event(d_port); ipa_disconnect_work_handler(d_port); d_port->sm_state = STATE_INITIALIZED; usb_gadget_autopm_put_async(d_port->gadget); @@ -718,19 +721,12 @@ static void ipa_work_handler(struct work_struct *w) case STATE_SUSPENDED: if (event == EVT_RESUMED) { + usb_gadget_autopm_get(d_port->gadget); + log_event_dbg("%s: ST_SUS_EVT_RES", __func__); + log_event_dbg("%s: get = %d", __func__, + atomic_read(&gad_dev->power.usage_count)); ipa_resume_work_handler(d_port); d_port->sm_state = STATE_CONNECTED; - /* - * Increment usage count here to disallow gadget - * parent suspend. This counter will decrement - * after IPA handshake is done in disconnect work - * (due to cable disconnect) or in suspended state. - */ - usb_gadget_autopm_get_noresume(d_port->gadget); - log_event_dbg("%s: ST_SUS_EVT_RES", __func__); - log_event_dbg("%s: get_nores2 = %d", __func__, - atomic_read( - &gad_dev->power.usage_count)); } else if (event == EVT_DISCONNECTED) { ipa_disconnect_work_handler(d_port); d_port->sm_state = STATE_INITIALIZED; @@ -1714,6 +1710,92 @@ static int gsi_get_alt(struct usb_function *f, unsigned intf) return -EINVAL; } +static int gsi_alloc_trb_buffer(struct f_gsi *gsi) +{ + u32 len_in = 0, len_out = 0; + int ret = 0; + + log_event_dbg("allocate trb's buffer\n"); + + if (gsi->d_port.in_ep && !gsi->d_port.in_request.buf_base_addr) { + log_event_dbg("IN: num_bufs:=%zu, buf_len=%zu\n", + gsi->d_port.in_request.num_bufs, + gsi->d_port.in_request.buf_len); + + len_in = gsi->d_port.in_request.buf_len * + gsi->d_port.in_request.num_bufs; + gsi->d_port.in_request.buf_base_addr = + dma_zalloc_coherent(gsi->d_port.gadget->dev.parent, + len_in, &gsi->d_port.in_request.dma, GFP_KERNEL); + if (!gsi->d_port.in_request.buf_base_addr) { + dev_err(&gsi->d_port.gadget->dev, + "IN buf_base_addr allocate failed %s\n", + gsi->function.name); + ret = -ENOMEM; + goto fail1; + } + } + + if (gsi->d_port.out_ep && !gsi->d_port.out_request.buf_base_addr) { + log_event_dbg("OUT: num_bufs:=%zu, buf_len=%zu\n", + gsi->d_port.out_request.num_bufs, + gsi->d_port.out_request.buf_len); + + len_out = gsi->d_port.out_request.buf_len * + gsi->d_port.out_request.num_bufs; + gsi->d_port.out_request.buf_base_addr = + dma_zalloc_coherent(gsi->d_port.gadget->dev.parent, + len_out, &gsi->d_port.out_request.dma, GFP_KERNEL); + if (!gsi->d_port.out_request.buf_base_addr) { + dev_err(&gsi->d_port.gadget->dev, + "OUT buf_base_addr allocate failed %s\n", + gsi->function.name); + ret = -ENOMEM; + goto fail; + } + } + + log_event_dbg("finished allocating trb's buffer\n"); + return ret; + +fail: + if (len_in && gsi->d_port.in_request.buf_base_addr) { + dma_free_coherent(gsi->d_port.gadget->dev.parent, len_in, + gsi->d_port.in_request.buf_base_addr, + gsi->d_port.in_request.dma); + gsi->d_port.in_request.buf_base_addr = NULL; + } +fail1: + return ret; +} + +static void gsi_free_trb_buffer(struct f_gsi *gsi) +{ + u32 len; + + log_event_dbg("freeing trb's buffer\n"); + + if (gsi->d_port.out_ep && + gsi->d_port.out_request.buf_base_addr) { + len = gsi->d_port.out_request.buf_len * + gsi->d_port.out_request.num_bufs; + dma_free_coherent(gsi->d_port.gadget->dev.parent, len, + gsi->d_port.out_request.buf_base_addr, + gsi->d_port.out_request.dma); + gsi->d_port.out_request.buf_base_addr = NULL; + } + + if (gsi->d_port.in_ep && + gsi->d_port.in_request.buf_base_addr) { + len = gsi->d_port.in_request.buf_len * + gsi->d_port.in_request.num_bufs; + dma_free_coherent(gsi->d_port.gadget->dev.parent, len, + gsi->d_port.in_request.buf_base_addr, + gsi->d_port.in_request.dma); + gsi->d_port.in_request.buf_base_addr = NULL; + } +} + static int gsi_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { struct f_gsi *gsi = func_to_gsi(f); @@ -1827,14 +1909,14 @@ static int gsi_set_alt(struct usb_function *f, unsigned intf, unsigned alt) if (gsi->prot_id == IPA_USB_ECM) gsi->d_port.cdc_filter = DEFAULT_FILTER; + post_event(&gsi->d_port, EVT_CONNECT_IN_PROGRESS); /* - * Increment usage count upon cable connect. Decrement - * after IPA disconnect is done in disconnect work - * (due to cable disconnect) or in suspend work. + * For RNDIS the event is posted from the flow control + * handler which is invoked when the host sends the + * GEN_CURRENT_PACKET_FILTER message. */ - usb_gadget_autopm_get_noresume(gsi->d_port.gadget); - - post_event(&gsi->d_port, EVT_CONNECT_IN_PROGRESS); + if (gsi->prot_id != IPA_USB_RNDIS) + post_event(&gsi->d_port, EVT_HOST_READY); queue_work(gsi->d_port.ipa_usb_wq, &gsi->d_port.usb_ipa_w); } @@ -2042,7 +2124,6 @@ static int gsi_update_function_bind_params(struct f_gsi *gsi, struct usb_ep *ep; struct usb_cdc_notification *event; struct usb_function *f = &gsi->function; - u32 len = 0; int status; /* maybe allocate device-global string IDs */ @@ -2162,37 +2243,9 @@ skip_string_id_alloc: gsi->d_port.in_request.buf_len = info->in_req_buf_len; gsi->d_port.in_request.num_bufs = info->in_req_num_buf; - len = gsi->d_port.in_request.buf_len * gsi->d_port.in_request.num_bufs; - dev_dbg(&cdev->gadget->dev, "%zu %zu\n", gsi->d_port.in_request.buf_len, - gsi->d_port.in_request.num_bufs); - gsi->d_port.in_request.buf_base_addr = - dma_zalloc_coherent(cdev->gadget->dev.parent, len, - &gsi->d_port.in_request.dma, GFP_KERNEL); - if (!gsi->d_port.in_request.buf_base_addr) { - dev_err(&cdev->gadget->dev, - "IN buf_base_addr allocate failed %s\n", - gsi->function.name); - goto fail; - } - if (gsi->d_port.out_ep) { gsi->d_port.out_request.buf_len = info->out_req_buf_len; gsi->d_port.out_request.num_bufs = info->out_req_num_buf; - len = - gsi->d_port.out_request.buf_len * - gsi->d_port.out_request.num_bufs; - dev_dbg(&cdev->gadget->dev, "%zu %zu\n", - gsi->d_port.out_request.buf_len, - gsi->d_port.out_request.num_bufs); - gsi->d_port.out_request.buf_base_addr = - dma_zalloc_coherent(cdev->gadget->dev.parent, len, - &gsi->d_port.out_request.dma, GFP_KERNEL); - if (!gsi->d_port.out_request.buf_base_addr) { - dev_err(&cdev->gadget->dev, - "OUT buf_base_addr allocate failed %s\n", - gsi->function.name); - goto fail; - } } /* Initialize event queue */ @@ -2263,14 +2316,6 @@ fail: gsi->d_port.out_ep->driver_data = NULL; if (gsi->d_port.in_ep && gsi->d_port.in_ep->desc) gsi->d_port.in_ep->driver_data = NULL; - if (len && gsi->d_port.in_request.buf_base_addr) - dma_free_coherent(cdev->gadget->dev.parent, len, - gsi->d_port.in_request.buf_base_addr, - gsi->d_port.in_request.dma); - if (len && gsi->d_port.out_request.buf_base_addr) - dma_free_coherent(cdev->gadget->dev.parent, len, - gsi->d_port.out_request.buf_base_addr, - gsi->d_port.out_request.dma); log_event_err("%s: bind failed for %s", __func__, f->name); return -ENOMEM; } @@ -2564,8 +2609,6 @@ fail: static void gsi_unbind(struct usb_configuration *c, struct usb_function *f) { struct f_gsi *gsi = func_to_gsi(f); - struct usb_composite_dev *cdev = c->cdev; - u32 len; /* * Use drain_workqueue to accomplish below conditions: @@ -2600,19 +2643,7 @@ static void gsi_unbind(struct usb_configuration *c, struct usb_function *f) if (gsi->c_port.notify) { kfree(gsi->c_port.notify_req->buf); usb_ep_free_request(gsi->c_port.notify, gsi->c_port.notify_req); - - len = - gsi->d_port.out_request.buf_len * - gsi->d_port.out_request.num_bufs; - dma_free_coherent(&cdev->gadget->dev, len, - gsi->d_port.out_request.buf_base_addr, - gsi->d_port.out_request.dma); } - - len = gsi->d_port.in_request.buf_len * gsi->d_port.in_request.num_bufs; - dma_free_coherent(&cdev->gadget->dev, len, - gsi->d_port.in_request.buf_base_addr, - gsi->d_port.in_request.dma); } diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index c6bfd13f6c92..1950e87b4219 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -787,6 +787,12 @@ static int iowarrior_probe(struct usb_interface *interface, iface_desc = interface->cur_altsetting; dev->product_id = le16_to_cpu(udev->descriptor.idProduct); + if (iface_desc->desc.bNumEndpoints < 1) { + dev_err(&interface->dev, "Invalid number of endpoints\n"); + retval = -EINVAL; + goto error; + } + /* set up the endpoint information */ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; diff --git a/drivers/usb/phy/phy-msm-qusb-v2.c b/drivers/usb/phy/phy-msm-qusb-v2.c index 5a29fc96f940..f8121eb4f63a 100644 --- a/drivers/usb/phy/phy-msm-qusb-v2.c +++ b/drivers/usb/phy/phy-msm-qusb-v2.c @@ -54,10 +54,6 @@ #define QUSB2PHY_PORT_TUNE2 0x240 -#define HS_PHY_CTRL_REG 0x10 -#define UTMI_OTG_VBUS_VALID BIT(20) -#define SW_SESSVLD_SEL BIT(28) - #define QUSB2PHY_1P8_VOL_MIN 1800000 /* uV */ #define QUSB2PHY_1P8_VOL_MAX 1800000 /* uV */ #define QUSB2PHY_1P8_HPM_LOAD 30000 /* uA */ @@ -76,7 +72,6 @@ MODULE_PARM_DESC(phy_tune2, "QUSB PHY v2 TUNE2"); struct qusb_phy { struct usb_phy phy; void __iomem *base; - void __iomem *qscratch_base; void __iomem *tune2_efuse_reg; struct clk *ref_clk_src; @@ -625,25 +620,6 @@ static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend) return 0; } -static void qusb_write_readback(void *base, u32 offset, - const u32 mask, u32 val) -{ - u32 write_val, tmp = readl_relaxed(base + offset); - - tmp &= ~mask; /* retain other bits */ - write_val = tmp | val; - - writel_relaxed(write_val, base + offset); - - /* Read back to see if val was written */ - tmp = readl_relaxed(base + offset); - tmp &= mask; /* clear other bits */ - - if (tmp != val) - pr_err("%s: write: %x to QSCRATCH: %x FAILED\n", - __func__, val, offset); -} - static int qusb_phy_notify_connect(struct usb_phy *phy, enum usb_device_speed speed) { @@ -651,21 +627,11 @@ static int qusb_phy_notify_connect(struct usb_phy *phy, qphy->cable_connected = true; - dev_dbg(phy->dev, " cable_connected=%d\n", qphy->cable_connected); - if (qphy->qusb_phy_host_init_seq && qphy->phy.flags & PHY_HOST_MODE) qusb_phy_host_init(phy); - /* Set OTG VBUS Valid from HSPHY to controller */ - qusb_write_readback(qphy->qscratch_base, HS_PHY_CTRL_REG, - UTMI_OTG_VBUS_VALID, - UTMI_OTG_VBUS_VALID); - - /* Indicate value is driven by UTMI_OTG_VBUS_VALID bit */ - qusb_write_readback(qphy->qscratch_base, HS_PHY_CTRL_REG, - SW_SESSVLD_SEL, SW_SESSVLD_SEL); - - dev_dbg(phy->dev, "QUSB2 phy connect notification\n"); + dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n", + qphy->cable_connected); return 0; } @@ -676,17 +642,8 @@ static int qusb_phy_notify_disconnect(struct usb_phy *phy, qphy->cable_connected = false; - dev_dbg(phy->dev, " cable_connected=%d\n", qphy->cable_connected); - - /* Set OTG VBUS Valid from HSPHY to controller */ - qusb_write_readback(qphy->qscratch_base, HS_PHY_CTRL_REG, - UTMI_OTG_VBUS_VALID, 0); - - /* Indicate value is driven by UTMI_OTG_VBUS_VALID bit */ - qusb_write_readback(qphy->qscratch_base, HS_PHY_CTRL_REG, - SW_SESSVLD_SEL, 0); - - dev_dbg(phy->dev, "QUSB2 phy disconnect notification\n"); + dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n", + qphy->cable_connected); return 0; } @@ -768,16 +725,6 @@ static int qusb_phy_probe(struct platform_device *pdev) return PTR_ERR(qphy->base); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "qscratch_base"); - if (res) { - qphy->qscratch_base = devm_ioremap_resource(dev, res); - if (IS_ERR(qphy->qscratch_base)) { - dev_dbg(dev, "couldn't ioremap qscratch_base\n"); - qphy->qscratch_base = NULL; - } - } - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "emu_phy_base"); if (res) { qphy->emu_phy_base = devm_ioremap_resource(dev, res); @@ -852,7 +799,7 @@ static int qusb_phy_probe(struct platform_device *pdev) } of_property_read_u32_array(dev->of_node, - "qcom,qemu-init-seq", + "qcom,emu-init-seq", qphy->emu_init_seq, qphy->emu_init_seq_len); } else { @@ -977,11 +924,8 @@ static int qusb_phy_probe(struct platform_device *pdev) qphy->phy.set_suspend = qusb_phy_set_suspend; qphy->phy.shutdown = qusb_phy_shutdown; qphy->phy.type = USB_PHY_TYPE_USB2; - - if (qphy->qscratch_base) { - qphy->phy.notify_connect = qusb_phy_notify_connect; - qphy->phy.notify_disconnect = qusb_phy_notify_disconnect; - } + qphy->phy.notify_connect = qusb_phy_notify_connect; + qphy->phy.notify_disconnect = qusb_phy_notify_disconnect; ret = usb_add_phy_dev(&qphy->phy); if (ret) diff --git a/drivers/usb/phy/phy-msm-qusb.c b/drivers/usb/phy/phy-msm-qusb.c index 1eb0c8d6b62f..5ec08098d197 100644 --- a/drivers/usb/phy/phy-msm-qusb.c +++ b/drivers/usb/phy/phy-msm-qusb.c @@ -88,9 +88,6 @@ #define LINESTATE_DP BIT(0) #define LINESTATE_DM BIT(1) -#define HS_PHY_CTRL_REG 0x10 -#define UTMI_OTG_VBUS_VALID BIT(20) -#define SW_SESSVLD_SEL BIT(28) #define QUSB2PHY_1P8_VOL_MIN 1800000 /* uV */ #define QUSB2PHY_1P8_VOL_MAX 1800000 /* uV */ @@ -109,7 +106,6 @@ MODULE_PARM_DESC(tune2, "QUSB PHY TUNE2"); struct qusb_phy { struct usb_phy phy; void __iomem *base; - void __iomem *qscratch_base; void __iomem *tune2_efuse_reg; void __iomem *ref_clk_base; @@ -686,24 +682,6 @@ static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend) return 0; } -static void qusb_write_readback(void *base, u32 offset, - const u32 mask, u32 val) -{ - u32 write_val, tmp = readl_relaxed(base + offset); - tmp &= ~mask; /* retain other bits */ - write_val = tmp | val; - - writel_relaxed(write_val, base + offset); - - /* Read back to see if val was written */ - tmp = readl_relaxed(base + offset); - tmp &= mask; /* clear other bits */ - - if (tmp != val) - pr_err("%s: write: %x to QSCRATCH: %x FAILED\n", - __func__, val, offset); -} - static int qusb_phy_notify_connect(struct usb_phy *phy, enum usb_device_speed speed) { @@ -711,18 +689,8 @@ static int qusb_phy_notify_connect(struct usb_phy *phy, qphy->cable_connected = true; - dev_dbg(phy->dev, " cable_connected=%d\n", qphy->cable_connected); - - /* Set OTG VBUS Valid from HSPHY to controller */ - qusb_write_readback(qphy->qscratch_base, HS_PHY_CTRL_REG, - UTMI_OTG_VBUS_VALID, - UTMI_OTG_VBUS_VALID); - - /* Indicate value is driven by UTMI_OTG_VBUS_VALID bit */ - qusb_write_readback(qphy->qscratch_base, HS_PHY_CTRL_REG, - SW_SESSVLD_SEL, SW_SESSVLD_SEL); - - dev_dbg(phy->dev, "QUSB2 phy connect notification\n"); + dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n", + qphy->cable_connected); return 0; } @@ -733,17 +701,8 @@ static int qusb_phy_notify_disconnect(struct usb_phy *phy, qphy->cable_connected = false; - dev_dbg(phy->dev, " cable_connected=%d\n", qphy->cable_connected); - - /* Set OTG VBUS Valid from HSPHY to controller */ - qusb_write_readback(qphy->qscratch_base, HS_PHY_CTRL_REG, - UTMI_OTG_VBUS_VALID, 0); - - /* Indicate value is driven by UTMI_OTG_VBUS_VALID bit */ - qusb_write_readback(qphy->qscratch_base, HS_PHY_CTRL_REG, - SW_SESSVLD_SEL, 0); - - dev_dbg(phy->dev, "QUSB2 phy disconnect notification\n"); + dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n", + qphy->cable_connected); return 0; } @@ -827,16 +786,6 @@ static int qusb_phy_probe(struct platform_device *pdev) return PTR_ERR(qphy->base); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "qscratch_base"); - if (res) { - qphy->qscratch_base = devm_ioremap_resource(dev, res); - if (IS_ERR(qphy->qscratch_base)) { - dev_dbg(dev, "couldn't ioremap qscratch_base\n"); - qphy->qscratch_base = NULL; - } - } - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "emu_phy_base"); if (res) { qphy->emu_phy_base = devm_ioremap_resource(dev, res); @@ -929,7 +878,7 @@ static int qusb_phy_probe(struct platform_device *pdev) } of_property_read_u32_array(dev->of_node, - "qcom,qemu-init-seq", + "qcom,emu-init-seq", qphy->emu_init_seq, qphy->emu_init_seq_len); } else { @@ -1051,11 +1000,8 @@ static int qusb_phy_probe(struct platform_device *pdev) qphy->phy.set_suspend = qusb_phy_set_suspend; qphy->phy.shutdown = qusb_phy_shutdown; qphy->phy.type = USB_PHY_TYPE_USB2; - - if (qphy->qscratch_base) { - qphy->phy.notify_connect = qusb_phy_notify_connect; - qphy->phy.notify_disconnect = qusb_phy_notify_disconnect; - } + qphy->phy.notify_connect = qusb_phy_notify_connect; + qphy->phy.notify_disconnect = qusb_phy_notify_disconnect; /* * On some platforms multiple QUSB PHYs are available. If QUSB PHY is diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index c0f5c652d272..f1893e08e51a 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -190,7 +190,8 @@ static int usbhsf_pkt_handler(struct usbhs_pipe *pipe, int type) goto __usbhs_pkt_handler_end; } - ret = func(pkt, &is_done); + if (likely(func)) + ret = func(pkt, &is_done); if (is_done) __usbhsf_pkt_del(pkt); @@ -889,6 +890,7 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) pkt->trans = len; + usbhsf_tx_irq_ctrl(pipe, 0); INIT_WORK(&pkt->work, xfer_work); schedule_work(&pkt->work); diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 8f7a78e70975..fa14198daf77 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -158,10 +158,14 @@ static void usbhsg_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt) struct usbhs_pipe *pipe = pkt->pipe; struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe); struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt); + unsigned long flags; ureq->req.actual = pkt->actual; - usbhsg_queue_pop(uep, ureq, 0); + usbhs_lock(priv, flags); + if (uep) + __usbhsg_queue_pop(uep, ureq, 0); + usbhs_unlock(priv, flags); } static void usbhsg_queue_push(struct usbhsg_uep *uep, diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 7a76fe4c2f9e..bdc0f2f24f19 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -164,6 +164,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x18EF, 0xE025) }, /* ELV Marble Sound Board 1 */ { USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */ { USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */ + { USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */ { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */ { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 01bf53392819..244acb1299a9 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -447,6 +447,11 @@ static int cypress_generic_port_probe(struct usb_serial_port *port) struct usb_serial *serial = port->serial; struct cypress_private *priv; + if (!port->interrupt_out_urb || !port->interrupt_in_urb) { + dev_err(&port->dev, "required endpoint is missing\n"); + return -ENODEV; + } + priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -606,12 +611,6 @@ static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port) cypress_set_termios(tty, port, &priv->tmp_termios); /* setup the port and start reading from the device */ - if (!port->interrupt_in_urb) { - dev_err(&port->dev, "%s - interrupt_in_urb is empty!\n", - __func__); - return -1; - } - usb_fill_int_urb(port->interrupt_in_urb, serial->dev, usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress), port->interrupt_in_urb->transfer_buffer, diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 12b0e67473ba..3df7b7ec178e 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -1251,8 +1251,27 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num) static int digi_startup(struct usb_serial *serial) { + struct device *dev = &serial->interface->dev; struct digi_serial *serial_priv; int ret; + int i; + + /* check whether the device has the expected number of endpoints */ + if (serial->num_port_pointers < serial->type->num_ports + 1) { + dev_err(dev, "OOB endpoints missing\n"); + return -ENODEV; + } + + for (i = 0; i < serial->type->num_ports + 1 ; i++) { + if (!serial->port[i]->read_urb) { + dev_err(dev, "bulk-in endpoint missing\n"); + return -ENODEV; + } + if (!serial->port[i]->write_urb) { + dev_err(dev, "bulk-out endpoint missing\n"); + return -ENODEV; + } + } serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL); if (!serial_priv) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 8c660ae401d8..b61f12160d37 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1004,6 +1004,10 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_DISPLAY_PID) }, { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_LITE_PID) }, { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ANALOG_PID) }, + /* ICP DAS I-756xU devices */ + { USB_DEVICE(ICPDAS_VID, ICPDAS_I7560U_PID) }, + { USB_DEVICE(ICPDAS_VID, ICPDAS_I7561U_PID) }, + { USB_DEVICE(ICPDAS_VID, ICPDAS_I7563U_PID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index a84df2513994..c5d6c1e73e8e 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -872,6 +872,14 @@ #define NOVITUS_BONO_E_PID 0x6010 /* + * ICPDAS I-756*U devices + */ +#define ICPDAS_VID 0x1b5c +#define ICPDAS_I7560U_PID 0x0103 +#define ICPDAS_I7561U_PID 0x0104 +#define ICPDAS_I7563U_PID 0x0105 + +/* * RT Systems programming cables for various ham radios */ #define RTSYSTEMS_VID 0x2100 /* Vendor ID */ diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index fd707d6a10e2..89726f702202 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -376,14 +376,21 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port, static int mct_u232_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct mct_u232_private *priv; + /* check first to simplify error handling */ + if (!serial->port[1] || !serial->port[1]->interrupt_in_urb) { + dev_err(&port->dev, "expected endpoint missing\n"); + return -ENODEV; + } + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; /* Use second interrupt-in endpoint for reading. */ - priv->read_urb = port->serial->port[1]->interrupt_in_urb; + priv->read_urb = serial->port[1]->interrupt_in_urb; priv->read_urb->context = port; spin_lock_init(&priv->lock); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 348e19834b83..c6f497f16526 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1818,6 +1818,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x00, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) }, { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) }, + { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e19, 0xff), /* D-Link DWM-221 B1 */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */ { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x4000, 0xff) }, /* OLICARD300 - MT6225 */ diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 5c66d3f7a6d0..9baf081174ce 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -2,7 +2,7 @@ * USB Attached SCSI * Note that this is not the same as the USB Mass Storage driver * - * Copyright Hans de Goede <hdegoede@redhat.com> for Red Hat, Inc. 2013 - 2014 + * Copyright Hans de Goede <hdegoede@redhat.com> for Red Hat, Inc. 2013 - 2016 * Copyright Matthew Wilcox for Intel Corp, 2010 * Copyright Sarah Sharp for Intel Corp, 2010 * @@ -757,6 +757,17 @@ static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd) return SUCCESS; } +static int uas_target_alloc(struct scsi_target *starget) +{ + struct uas_dev_info *devinfo = (struct uas_dev_info *) + dev_to_shost(starget->dev.parent)->hostdata; + + if (devinfo->flags & US_FL_NO_REPORT_LUNS) + starget->no_report_luns = 1; + + return 0; +} + static int uas_slave_alloc(struct scsi_device *sdev) { struct uas_dev_info *devinfo = @@ -800,7 +811,6 @@ static int uas_slave_configure(struct scsi_device *sdev) if (devinfo->flags & US_FL_BROKEN_FUA) sdev->broken_fua = 1; - scsi_change_queue_depth(sdev, devinfo->qdepth - 2); return 0; } @@ -808,11 +818,12 @@ static struct scsi_host_template uas_host_template = { .module = THIS_MODULE, .name = "uas", .queuecommand = uas_queuecommand, + .target_alloc = uas_target_alloc, .slave_alloc = uas_slave_alloc, .slave_configure = uas_slave_configure, .eh_abort_handler = uas_eh_abort_handler, .eh_bus_reset_handler = uas_eh_bus_reset_handler, - .can_queue = 65536, /* Is there a limit on the _host_ ? */ + .can_queue = MAX_CMNDS, .this_id = -1, .sg_tablesize = SG_NONE, .skip_settle_delay = 1, @@ -932,6 +943,12 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) if (result) goto set_alt0; + /* + * 1 tag is reserved for untagged commands + + * 1 tag to avoid off by one errors in some bridge firmwares + */ + shost->can_queue = devinfo->qdepth - 2; + usb_set_intfdata(intf, shost); result = scsi_add_host(shost, &intf->dev); if (result) diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h index ccc113e83d88..53341a77d89f 100644 --- a/drivers/usb/storage/unusual_uas.h +++ b/drivers/usb/storage/unusual_uas.h @@ -64,6 +64,13 @@ UNUSUAL_DEV(0x0bc2, 0x3312, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_ATA_1X), +/* Reported-by: David Webb <djw@noc.ac.uk> */ +UNUSUAL_DEV(0x0bc2, 0x331a, 0x0000, 0x9999, + "Seagate", + "Expansion Desk", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_NO_REPORT_LUNS), + /* Reported-by: Hans de Goede <hdegoede@redhat.com> */ UNUSUAL_DEV(0x0bc2, 0x3320, 0x0000, 0x9999, "Seagate", diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 43576ed31ccd..9de988a0f856 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -482,7 +482,7 @@ void usb_stor_adjust_quirks(struct usb_device *udev, unsigned long *fflags) US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16 | US_FL_INITIAL_READ10 | US_FL_WRITE_CACHE | US_FL_NO_ATA_1X | US_FL_NO_REPORT_OPCODES | - US_FL_MAX_SECTORS_240); + US_FL_MAX_SECTORS_240 | US_FL_NO_REPORT_LUNS); p = quirks; while (*p) { @@ -532,6 +532,9 @@ void usb_stor_adjust_quirks(struct usb_device *udev, unsigned long *fflags) case 'i': f |= US_FL_IGNORE_DEVICE; break; + case 'j': + f |= US_FL_NO_REPORT_LUNS; + break; case 'l': f |= US_FL_NOT_LOCKABLE; break; |
