diff options
Diffstat (limited to 'drivers')
27 files changed, 686 insertions, 210 deletions
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 813d4d3a51c6..1173f9cbc137 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -270,6 +270,7 @@ static ssize_t cxacru_sysfs_showattr_dB(s16 value, char *buf) static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf) { static char *str[] = { "no", "yes" }; + if (unlikely(value >= ARRAY_SIZE(str))) return snprintf(buf, PAGE_SIZE, "%u\n", value); return snprintf(buf, PAGE_SIZE, "%s\n", str[value]); @@ -278,6 +279,7 @@ static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf) static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf) { static char *str[] = { NULL, "not connected", "connected", "lost" }; + if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL)) return snprintf(buf, PAGE_SIZE, "%u\n", value); return snprintf(buf, PAGE_SIZE, "%s\n", str[value]); @@ -702,6 +704,7 @@ static int cxacru_cm_get_array(struct cxacru_data *instance, enum cxacru_cm_requ len = ret / 4; for (offb = 0; offb < len; ) { int l = le32_to_cpu(buf[offb++]); + if (l < 0 || l > stride || l > (len - offb) / 2) { if (printk_ratelimit()) usb_err(instance->usbatm, "invalid data length from cm %#x: %d\n", @@ -732,6 +735,7 @@ cleanup: static int cxacru_card_status(struct cxacru_data *instance) { int ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0); + if (ret < 0) { /* firmware not loaded */ usb_dbg(instance->usbatm, "cxacru_adsl_start: CARD_GET_STATUS returned %d\n", ret); return ret; @@ -945,6 +949,7 @@ static int cxacru_fw(struct usb_device *usb_dev, enum cxacru_fw_request fw, offb = offd = 0; do { int l = min_t(int, stride, size - offd); + buf[offb++] = fw; buf[offb++] = l; buf[offb++] = code1; @@ -1091,8 +1096,8 @@ static int cxacru_heavy_init(struct usbatm_data *usbatm_instance, { const struct firmware *fw, *bp; struct cxacru_data *instance = usbatm_instance->driver_data; - int ret = cxacru_find_firmware(instance, "fw", &fw); + if (ret) { usb_warn(usbatm_instance, "firmware (cxacru-fw.bin) unavailable (system misconfigured?)\n"); return ret; diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index f38e875a3fb1..433bbc34a8a4 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -57,6 +57,7 @@ #include <linux/mutex.h> #undef DEBUG #include <linux/usb.h> +#include <linux/usb/ch9.h> #include <linux/ratelimit.h> /* @@ -79,12 +80,20 @@ #define IOCNR_SOFT_RESET 7 /* Get device_id string: */ #define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len) -/* The following ioctls were added for http://hpoj.sourceforge.net: */ -/* Get two-int array: - * [0]=current protocol (1=7/1/1, 2=7/1/2, 3=7/1/3), - * [1]=supported protocol mask (mask&(1<<n)!=0 means 7/1/n supported): */ +/* The following ioctls were added for http://hpoj.sourceforge.net: + * Get two-int array: + * [0]=current protocol + * (1=USB_CLASS_PRINTER/1/1, 2=USB_CLASS_PRINTER/1/2, + * 3=USB_CLASS_PRINTER/1/3), + * [1]=supported protocol mask (mask&(1<<n)!=0 means + * USB_CLASS_PRINTER/1/n supported): + */ #define LPIOC_GET_PROTOCOLS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_PROTOCOLS, len) -/* Set protocol (arg: 1=7/1/1, 2=7/1/2, 3=7/1/3): */ +/* + * Set protocol + * (arg: 1=USB_CLASS_PRINTER/1/1, 2=USB_CLASS_PRINTER/1/2, + * 3=USB_CLASS_PRINTER/1/3): + */ #define LPIOC_SET_PROTOCOL _IOC(_IOC_WRITE, 'P', IOCNR_SET_PROTOCOL, 0) /* Set channel number (HP Vendor-specific command): */ #define LPIOC_HP_SET_CHANNEL _IOC(_IOC_WRITE, 'P', IOCNR_HP_SET_CHANNEL, 0) @@ -146,8 +155,10 @@ struct usblp { int readcount; /* Counter for reads */ int ifnum; /* Interface number */ struct usb_interface *intf; /* The interface */ - /* Alternate-setting numbers and endpoints for each protocol - * (7/1/{index=1,2,3}) that the device supports: */ + /* + * Alternate-setting numbers and endpoints for each protocol + * (USB_CLASS_PRINTER/1/{index=1,2,3}) that the device supports: + */ struct { int alt_setting; struct usb_endpoint_descriptor *epwrite; @@ -1206,19 +1217,23 @@ abort_ret: * but our requirements are too intricate for simple match to handle. * * The "proto_bias" option may be used to specify the preferred protocol - * for all USB printers (1=7/1/1, 2=7/1/2, 3=7/1/3). If the device - * supports the preferred protocol, then we bind to it. + * for all USB printers (1=USB_CLASS_PRINTER/1/1, 2=USB_CLASS_PRINTER/1/2, + * 3=USB_CLASS_PRINTER/1/3). If the device supports the preferred protocol, + * then we bind to it. * - * The best interface for us is 7/1/2, because it is compatible - * with a stream of characters. If we find it, we bind to it. + * The best interface for us is USB_CLASS_PRINTER/1/2, because it + * is compatible with a stream of characters. If we find it, we bind to it. * * Note that the people from hpoj.sourceforge.net need to be able to - * bind to 7/1/3 (MLC/1284.4), so we provide them ioctls for this purpose. + * bind to USB_CLASS_PRINTER/1/3 (MLC/1284.4), so we provide them ioctls + * for this purpose. * - * Failing 7/1/2, we look for 7/1/3, even though it's probably not - * stream-compatible, because this matches the behaviour of the old code. + * Failing USB_CLASS_PRINTER/1/2, we look for USB_CLASS_PRINTER/1/3, + * even though it's probably not stream-compatible, because this matches + * the behaviour of the old code. * - * If nothing else, we bind to 7/1/1 - the unidirectional interface. + * If nothing else, we bind to USB_CLASS_PRINTER/1/1 + * - the unidirectional interface. */ static int usblp_select_alts(struct usblp *usblp) { @@ -1236,7 +1251,8 @@ static int usblp_select_alts(struct usblp *usblp) for (i = 0; i < if_alt->num_altsetting; i++) { ifd = &if_alt->altsetting[i]; - if (ifd->desc.bInterfaceClass != 7 || ifd->desc.bInterfaceSubClass != 1) + if (ifd->desc.bInterfaceClass != USB_CLASS_PRINTER || + ifd->desc.bInterfaceSubClass != 1) if (!(usblp->quirks & USBLP_QUIRK_BAD_CLASS)) continue; @@ -1262,8 +1278,10 @@ static int usblp_select_alts(struct usblp *usblp) if (!epwrite || (ifd->desc.bInterfaceProtocol > 1 && !epread)) continue; - /* Turn off reads for 7/1/1 (unidirectional) interfaces - * and buggy bidirectional printers. */ + /* + * Turn off reads for USB_CLASS_PRINTER/1/1 (unidirectional) + * interfaces and buggy bidirectional printers. + */ if (ifd->desc.bInterfaceProtocol == 1) { epread = NULL; } else if (usblp->quirks & USBLP_QUIRK_BIDIR) { @@ -1406,12 +1424,12 @@ static int usblp_resume(struct usb_interface *intf) } static const struct usb_device_id usblp_ids[] = { - { USB_DEVICE_INFO(7, 1, 1) }, - { USB_DEVICE_INFO(7, 1, 2) }, - { USB_DEVICE_INFO(7, 1, 3) }, - { USB_INTERFACE_INFO(7, 1, 1) }, - { USB_INTERFACE_INFO(7, 1, 2) }, - { USB_INTERFACE_INFO(7, 1, 3) }, + { USB_DEVICE_INFO(USB_CLASS_PRINTER, 1, 1) }, + { USB_DEVICE_INFO(USB_CLASS_PRINTER, 1, 2) }, + { USB_DEVICE_INFO(USB_CLASS_PRINTER, 1, 3) }, + { USB_INTERFACE_INFO(USB_CLASS_PRINTER, 1, 1) }, + { USB_INTERFACE_INFO(USB_CLASS_PRINTER, 1, 2) }, + { USB_INTERFACE_INFO(USB_CLASS_PRINTER, 1, 3) }, { USB_DEVICE(0x04b8, 0x0202) }, /* Seiko Epson Receipt Printer M129C */ { } /* Terminating entry */ }; diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 986abde07683..38ae877c46e3 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -103,7 +103,7 @@ MODULE_PARM_DESC(usbfs_snoop, "true to log all usbfs traffic"); #define snoop(dev, format, arg...) \ do { \ if (usbfs_snoop) \ - dev_info(dev , format , ## arg); \ + dev_info(dev, format, ## arg); \ } while (0) enum snoop_when { @@ -1082,7 +1082,8 @@ static int proc_bulk(struct usb_dev_state *ps, void __user *arg) ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb)); if (ret) return ret; - if (!(tbuf = kmalloc(len1, GFP_KERNEL))) { + tbuf = kmalloc(len1, GFP_KERNEL); + if (!tbuf) { ret = -ENOMEM; goto done; } @@ -1224,7 +1225,8 @@ static int proc_setintf(struct usb_dev_state *ps, void __user *arg) if (copy_from_user(&setintf, arg, sizeof(setintf))) return -EFAULT; - if ((ret = checkintf(ps, setintf.interface))) + ret = checkintf(ps, setintf.interface); + if (ret) return ret; destroy_async_on_interface(ps, setintf.interface); @@ -1319,7 +1321,7 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb is_in = (uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0; u = 0; - switch(uurb->type) { + switch (uurb->type) { case USBDEVFS_URB_TYPE_CONTROL: if (!usb_endpoint_xfer_control(&ep->desc)) return -EINVAL; @@ -1393,7 +1395,8 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb number_of_packets = uurb->number_of_packets; isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * number_of_packets; - if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL))) + isopkt = kmalloc(isofrmlen, GFP_KERNEL); + if (!isopkt) return -ENOMEM; if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) { ret = -EFAULT; @@ -1904,7 +1907,8 @@ static int proc_releaseinterface(struct usb_dev_state *ps, void __user *arg) if (get_user(ifnum, (unsigned int __user *)arg)) return -EFAULT; - if ((ret = releaseintf(ps, ifnum)) < 0) + ret = releaseintf(ps, ifnum); + if (ret < 0) return ret; destroy_async_on_interface (ps, ifnum); return 0; @@ -1919,7 +1923,8 @@ static int proc_ioctl(struct usb_dev_state *ps, struct usbdevfs_ioctl *ctl) struct usb_driver *driver = NULL; /* alloc buffer */ - if ((size = _IOC_SIZE(ctl->ioctl_code)) > 0) { + size = _IOC_SIZE(ctl->ioctl_code); + if (size > 0) { buf = kmalloc(size, GFP_KERNEL); if (buf == NULL) return -ENOMEM; diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 818369afff63..6b5063e7943f 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -160,6 +160,7 @@ static ssize_t remove_id_store(struct device_driver *driver, const char *buf, spin_lock(&usb_driver->dynids.lock); list_for_each_entry_safe(dynid, n, &usb_driver->dynids.list, node) { struct usb_device_id *id = &dynid->id; + if ((id->idVendor == idVendor) && (id->idProduct == idProduct)) { list_del(&dynid->node); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index cbcd0920fb51..4d64e5c499e1 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2686,12 +2686,14 @@ int usb_add_hcd(struct usb_hcd *hcd, * bottom up so that hcds can customize the root hubs before hub_wq * starts talking to them. (Note, bus id is assigned early too.) */ - if ((retval = hcd_buffer_create(hcd)) != 0) { + retval = hcd_buffer_create(hcd); + if (retval != 0) { dev_dbg(hcd->self.controller, "pool alloc failed\n"); goto err_create_buf; } - if ((retval = usb_register_bus(&hcd->self)) < 0) + retval = usb_register_bus(&hcd->self); + if (retval < 0) goto err_register_bus; rhdev = usb_alloc_dev(NULL, &hcd->self, 0); @@ -2737,9 +2739,13 @@ int usb_add_hcd(struct usb_hcd *hcd, /* "reset" is misnamed; its role is now one-time init. the controller * should already have been reset (and boot firmware kicked off etc). */ - if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) { - dev_err(hcd->self.controller, "can't setup: %d\n", retval); - goto err_hcd_driver_setup; + if (hcd->driver->reset) { + retval = hcd->driver->reset(hcd); + if (retval < 0) { + dev_err(hcd->self.controller, "can't setup: %d\n", + retval); + goto err_hcd_driver_setup; + } } hcd->rh_pollable = 1; @@ -2769,7 +2775,8 @@ int usb_add_hcd(struct usb_hcd *hcd, } /* starting here, usbcore will pay attention to this root hub */ - if ((retval = register_root_hub(hcd)) != 0) + retval = register_root_hub(hcd); + if (retval != 0) goto err_register_root_hub; retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 73dfa194160b..a0b22be1509d 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -50,8 +50,8 @@ DEFINE_MUTEX(usb_port_peer_mutex); /* cycle leds on hubs that aren't blinking for attention */ static bool blinkenlights = 0; -module_param (blinkenlights, bool, S_IRUGO); -MODULE_PARM_DESC (blinkenlights, "true to cycle leds on hubs"); +module_param(blinkenlights, bool, S_IRUGO); +MODULE_PARM_DESC(blinkenlights, "true to cycle leds on hubs"); /* * Device SATA8000 FW1.0 from DATAST0R Technology Corp requires about @@ -439,7 +439,7 @@ static void set_port_led(struct usb_hub *hub, int port1, int selector) #define LED_CYCLE_PERIOD ((2*HZ)/3) -static void led_work (struct work_struct *work) +static void led_work(struct work_struct *work) { struct usb_hub *hub = container_of(work, struct usb_hub, leds.work); @@ -646,7 +646,7 @@ static void hub_irq(struct urb *urb) default: /* presumably an error */ /* Cause a hub reset after 10 consecutive errors */ - dev_dbg (hub->intfdev, "transfer --> %d\n", status); + dev_dbg(hub->intfdev, "transfer --> %d\n", status); if ((++hub->nerrors < 10) || hub->error) goto resubmit; hub->error = status; @@ -671,14 +671,14 @@ resubmit: if (hub->quiescing) return; - if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0 + if ((status = usb_submit_urb(hub->urb, GFP_ATOMIC)) != 0 && status != -ENODEV && status != -EPERM) - dev_err (hub->intfdev, "resubmit --> %d\n", status); + dev_err(hub->intfdev, "resubmit --> %d\n", status); } /* USB 2.0 spec Section 11.24.2.3 */ static inline int -hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt) +hub_clear_tt_buffer(struct usb_device *hdev, u16 devinfo, u16 tt) { /* Need to clear both directions for control ep */ if (((devinfo >> 11) & USB_ENDPOINT_XFERTYPE_MASK) == @@ -706,7 +706,7 @@ static void hub_tt_work(struct work_struct *work) container_of(work, struct usb_hub, tt.clear_work); unsigned long flags; - spin_lock_irqsave (&hub->tt.lock, flags); + spin_lock_irqsave(&hub->tt.lock, flags); while (!list_empty(&hub->tt.clear_list)) { struct list_head *next; struct usb_tt_clear *clear; @@ -715,14 +715,14 @@ static void hub_tt_work(struct work_struct *work) int status; next = hub->tt.clear_list.next; - clear = list_entry (next, struct usb_tt_clear, clear_list); - list_del (&clear->clear_list); + clear = list_entry(next, struct usb_tt_clear, clear_list); + list_del(&clear->clear_list); /* drop lock so HCD can concurrently report other TT errors */ - spin_unlock_irqrestore (&hub->tt.lock, flags); - status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt); + spin_unlock_irqrestore(&hub->tt.lock, flags); + status = hub_clear_tt_buffer(hdev, clear->devinfo, clear->tt); if (status && status != -ENODEV) - dev_err (&hdev->dev, + dev_err(&hdev->dev, "clear tt %d (%04x) error %d\n", clear->tt, clear->devinfo, status); @@ -734,7 +734,7 @@ static void hub_tt_work(struct work_struct *work) kfree(clear); spin_lock_irqsave(&hub->tt.lock, flags); } - spin_unlock_irqrestore (&hub->tt.lock, flags); + spin_unlock_irqrestore(&hub->tt.lock, flags); } /** @@ -797,7 +797,7 @@ int usb_hub_clear_tt_buffer(struct urb *urb) */ clear = kmalloc(sizeof *clear, GFP_ATOMIC); if (clear == NULL) { - dev_err (&udev->dev, "can't save CLEAR_TT_BUFFER state\n"); + dev_err(&udev->dev, "can't save CLEAR_TT_BUFFER state\n"); /* FIXME recover somehow ... RESET_TT? */ return -ENOMEM; } @@ -806,10 +806,10 @@ int usb_hub_clear_tt_buffer(struct urb *urb) clear->tt = tt->multi ? udev->ttport : 1; clear->devinfo = usb_pipeendpoint (pipe); clear->devinfo |= udev->devnum << 4; - clear->devinfo |= usb_pipecontrol (pipe) + clear->devinfo |= usb_pipecontrol(pipe) ? (USB_ENDPOINT_XFER_CONTROL << 11) : (USB_ENDPOINT_XFER_BULK << 11); - if (usb_pipein (pipe)) + if (usb_pipein(pipe)) clear->devinfo |= 1 << 15; /* info for completion callback */ @@ -817,10 +817,10 @@ int usb_hub_clear_tt_buffer(struct urb *urb) clear->ep = urb->ep; /* tell keventd to clear state for this TT */ - spin_lock_irqsave (&tt->lock, flags); - list_add_tail (&clear->clear_list, &tt->clear_list); + spin_lock_irqsave(&tt->lock, flags); + list_add_tail(&clear->clear_list, &tt->clear_list); schedule_work(&tt->clear_work); - spin_unlock_irqrestore (&tt->lock, flags); + spin_unlock_irqrestore(&tt->lock, flags); return 0; } EXPORT_SYMBOL_GPL(usb_hub_clear_tt_buffer); @@ -3950,6 +3950,8 @@ int usb_disable_lpm(struct usb_device *udev) if (usb_disable_link_state(hcd, udev, USB3_LPM_U2)) goto enable_lpm; + udev->usb3_lpm_enabled = 0; + return 0; enable_lpm: @@ -4007,6 +4009,8 @@ void usb_enable_lpm(struct usb_device *udev) usb_enable_link_state(hcd, udev, USB3_LPM_U1); usb_enable_link_state(hcd, udev, USB3_LPM_U2); + + udev->usb3_lpm_enabled = 1; } EXPORT_SYMBOL_GPL(usb_enable_lpm); diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index d26973844a4d..cfc68c11c3f5 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -531,6 +531,25 @@ static ssize_t usb2_lpm_besl_store(struct device *dev, } static DEVICE_ATTR_RW(usb2_lpm_besl); +static ssize_t usb3_hardware_lpm_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_device *udev = to_usb_device(dev); + const char *p; + + usb_lock_device(udev); + + if (udev->usb3_lpm_enabled) + p = "enabled"; + else + p = "disabled"; + + usb_unlock_device(udev); + + return sprintf(buf, "%s\n", p); +} +static DEVICE_ATTR_RO(usb3_hardware_lpm); + static struct attribute *usb2_hardware_lpm_attr[] = { &dev_attr_usb2_hardware_lpm.attr, &dev_attr_usb2_lpm_l1_timeout.attr, @@ -542,6 +561,15 @@ static struct attribute_group usb2_hardware_lpm_attr_group = { .attrs = usb2_hardware_lpm_attr, }; +static struct attribute *usb3_hardware_lpm_attr[] = { + &dev_attr_usb3_hardware_lpm.attr, + NULL, +}; +static struct attribute_group usb3_hardware_lpm_attr_group = { + .name = power_group_name, + .attrs = usb3_hardware_lpm_attr, +}; + static struct attribute *power_attrs[] = { &dev_attr_autosuspend.attr, &dev_attr_level.attr, @@ -564,6 +592,9 @@ static int add_power_attributes(struct device *dev) if (udev->usb2_hw_lpm_capable == 1) rc = sysfs_merge_group(&dev->kobj, &usb2_hardware_lpm_attr_group); + if (udev->lpm_capable == 1) + rc = sysfs_merge_group(&dev->kobj, + &usb3_hardware_lpm_attr_group); } return rc; diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 8afc3c1efdab..5f0567927f1f 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -32,7 +32,14 @@ config USB_XHCI_PCI default y config USB_XHCI_PLATFORM - tristate + tristate "Generic xHCI driver for a platform device" + ---help--- + Adds an xHCI host driver for a generic platform device, which + provides a memory space and an irq. + It is also a prerequisite for platform specific drivers that + implement some extra quirks. + + If unsure, say N. config USB_XHCI_MVEBU tristate "xHCI support for Marvell Armada 375/38x" diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c index 526cfab41d5f..5398e3d42822 100644 --- a/drivers/usb/host/bcma-hcd.c +++ b/drivers/usb/host/bcma-hcd.c @@ -2,7 +2,8 @@ * Broadcom specific Advanced Microcontroller Bus * Broadcom USB-core driver (BCMA bus glue) * - * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de> + * Copyright 2011-2015 Hauke Mehrtens <hauke@hauke-m.de> + * Copyright 2015 Felix Fietkau <nbd@openwrt.org> * * Based on ssb-ohci driver * Copyright 2007 Michael Buesch <m@bues.ch> @@ -23,6 +24,8 @@ #include <linux/platform_device.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/of.h> +#include <linux/of_gpio.h> #include <linux/usb/ehci_pdriver.h> #include <linux/usb/ohci_pdriver.h> @@ -88,7 +91,7 @@ static void bcma_hcd_4716wa(struct bcma_device *dev) } /* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */ -static void bcma_hcd_init_chip(struct bcma_device *dev) +static void bcma_hcd_init_chip_mips(struct bcma_device *dev) { u32 tmp; @@ -159,6 +162,87 @@ static void bcma_hcd_init_chip(struct bcma_device *dev) } } +static void bcma_hcd_init_chip_arm_phy(struct bcma_device *dev) +{ + struct bcma_device *arm_core; + void __iomem *dmu; + + arm_core = bcma_find_core(dev->bus, BCMA_CORE_ARMCA9); + if (!arm_core) { + dev_err(&dev->dev, "can not find ARM Cortex A9 ihost core\n"); + return; + } + + dmu = ioremap_nocache(arm_core->addr_s[0], 0x1000); + if (!dmu) { + dev_err(&dev->dev, "can not map ARM Cortex A9 ihost core\n"); + return; + } + + /* Unlock DMU PLL settings */ + iowrite32(0x0000ea68, dmu + 0x180); + + /* Write USB 2.0 PLL control setting */ + iowrite32(0x00dd10c3, dmu + 0x164); + + /* Lock DMU PLL settings */ + iowrite32(0x00000000, dmu + 0x180); + + iounmap(dmu); +} + +static void bcma_hcd_init_chip_arm_hc(struct bcma_device *dev) +{ + u32 val; + + /* + * Delay after PHY initialized to ensure HC is ready to be configured + */ + usleep_range(1000, 2000); + + /* Set packet buffer OUT threshold */ + val = bcma_read32(dev, 0x94); + val &= 0xffff; + val |= 0x80 << 16; + bcma_write32(dev, 0x94, val); + + /* Enable break memory transfer */ + val = bcma_read32(dev, 0x9c); + val |= 1; + bcma_write32(dev, 0x9c, val); +} + +static void bcma_hcd_init_chip_arm(struct bcma_device *dev) +{ + bcma_core_enable(dev, 0); + + if (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4707 || + dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM53018) { + if (dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4707 || + dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4708) + bcma_hcd_init_chip_arm_phy(dev); + + bcma_hcd_init_chip_arm_hc(dev); + } +} + +static void bcma_hci_platform_power_gpio(struct bcma_device *dev, bool val) +{ + int gpio; + + gpio = of_get_named_gpio(dev->dev.of_node, "vcc-gpio", 0); + if (!gpio_is_valid(gpio)) + return; + + if (val) { + gpio_request(gpio, "bcma-hcd-gpio"); + gpio_set_value(gpio, 1); + } else { + gpio_set_value(gpio, 0); + gpio_free(gpio); + } +} + static const struct usb_ehci_pdata ehci_pdata = { }; @@ -169,7 +253,7 @@ static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, boo { struct platform_device *hci_dev; struct resource hci_res[2]; - int ret = -ENOMEM; + int ret; memset(hci_res, 0, sizeof(hci_res)); @@ -183,7 +267,7 @@ static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, boo hci_dev = platform_device_alloc(ohci ? "ohci-platform" : "ehci-platform" , 0); if (!hci_dev) - return NULL; + return ERR_PTR(-ENOMEM); hci_dev->dev.parent = &dev->dev; hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask; @@ -214,39 +298,45 @@ err_alloc: static int bcma_hcd_probe(struct bcma_device *dev) { int err; - u16 chipid_top; u32 ohci_addr; struct bcma_hcd_device *usb_dev; struct bcma_chipinfo *chipinfo; chipinfo = &dev->bus->chipinfo; - /* USBcores are only connected on embedded devices. */ - chipid_top = (chipinfo->id & 0xFF00); - if (chipid_top != 0x4700 && chipid_top != 0x5300) - return -ENODEV; /* TODO: Probably need checks here; is the core connected? */ if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32))) return -EOPNOTSUPP; - usb_dev = kzalloc(sizeof(struct bcma_hcd_device), GFP_KERNEL); + usb_dev = devm_kzalloc(&dev->dev, sizeof(struct bcma_hcd_device), + GFP_KERNEL); if (!usb_dev) return -ENOMEM; - bcma_hcd_init_chip(dev); + bcma_hci_platform_power_gpio(dev, true); + + switch (dev->id.id) { + case BCMA_CORE_NS_USB20: + bcma_hcd_init_chip_arm(dev); + break; + case BCMA_CORE_USB20_HOST: + bcma_hcd_init_chip_mips(dev); + break; + default: + return -ENODEV; + } /* In AI chips EHCI is addrspace 0, OHCI is 1 */ ohci_addr = dev->addr_s[0]; - if ((chipinfo->id == 0x5357 || chipinfo->id == 0x4749) + if ((chipinfo->id == BCMA_CHIP_ID_BCM5357 || + chipinfo->id == BCMA_CHIP_ID_BCM4749) && chipinfo->rev == 0) ohci_addr = 0x18009000; usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, true, ohci_addr); - if (IS_ERR(usb_dev->ohci_dev)) { - err = PTR_ERR(usb_dev->ohci_dev); - goto err_free_usb_dev; - } + if (IS_ERR(usb_dev->ohci_dev)) + return PTR_ERR(usb_dev->ohci_dev); usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, false, dev->addr); if (IS_ERR(usb_dev->ehci_dev)) { @@ -259,8 +349,6 @@ static int bcma_hcd_probe(struct bcma_device *dev) err_unregister_ohci_dev: platform_device_unregister(usb_dev->ohci_dev); -err_free_usb_dev: - kfree(usb_dev); return err; } @@ -280,6 +368,7 @@ static void bcma_hcd_remove(struct bcma_device *dev) static void bcma_hcd_shutdown(struct bcma_device *dev) { + bcma_hci_platform_power_gpio(dev, false); bcma_core_disable(dev, 0); } @@ -287,6 +376,7 @@ static void bcma_hcd_shutdown(struct bcma_device *dev) static int bcma_hcd_suspend(struct bcma_device *dev) { + bcma_hci_platform_power_gpio(dev, false); bcma_core_disable(dev, 0); return 0; @@ -294,6 +384,7 @@ static int bcma_hcd_suspend(struct bcma_device *dev) static int bcma_hcd_resume(struct bcma_device *dev) { + bcma_hci_platform_power_gpio(dev, true); bcma_core_enable(dev, 0); return 0; @@ -306,6 +397,7 @@ static int bcma_hcd_resume(struct bcma_device *dev) static const struct bcma_device_id bcma_hcd_table[] = { BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS), + BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB20, BCMA_ANY_REV, BCMA_ANY_CLASS), {}, }; MODULE_DEVICE_TABLE(bcma, bcma_hcd_table); diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 5352e74b92e2..202dafb7d0cb 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -127,7 +127,18 @@ static int fsl_ehci_drv_probe(struct platform_device *pdev) /* Enable USB controller, 83xx or 8536 */ if (pdata->have_sysif_regs && pdata->controller_ver < FSL_USB_VER_1_6) - setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4); + clrsetbits_be32(hcd->regs + FSL_SOC_USB_CTRL, + CONTROL_REGISTER_W1C_MASK, 0x4); + + /* + * Enable UTMI phy and program PTS field in UTMI mode before asserting + * controller reset for USB Controller version 2.5 + */ + if (pdata->has_fsl_erratum_a007792) { + clrsetbits_be32(hcd->regs + FSL_SOC_USB_CTRL, + CONTROL_REGISTER_W1C_MASK, CTRL_UTMI_PHY_EN); + writel(PORT_PTS_UTMI, hcd->regs + FSL_SOC_USB_PORTSC1); + } /* Don't need to set host mode here. It will be done by tdi_reset() */ @@ -191,9 +202,11 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, case FSL_USB2_PHY_ULPI: if (pdata->have_sysif_regs && pdata->controller_ver) { /* controller version 1.6 or above */ - clrbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN); - setbits32(non_ehci + FSL_SOC_USB_CTRL, - ULPI_PHY_CLK_SEL | USB_CTRL_USB_EN); + clrbits32(non_ehci + FSL_SOC_USB_CTRL, + CONTROL_REGISTER_W1C_MASK | UTMI_PHY_EN); + clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL, + CONTROL_REGISTER_W1C_MASK, + ULPI_PHY_CLK_SEL | USB_CTRL_USB_EN); } portsc |= PORT_PTS_ULPI; break; @@ -204,30 +217,33 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, portsc |= PORT_PTS_PTW; /* fall through */ case FSL_USB2_PHY_UTMI: + case FSL_USB2_PHY_UTMI_DUAL: if (pdata->have_sysif_regs && pdata->controller_ver) { /* controller version 1.6 or above */ - setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN); + clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL, + CONTROL_REGISTER_W1C_MASK, UTMI_PHY_EN); mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to become stable - 10ms*/ } /* enable UTMI PHY */ if (pdata->have_sysif_regs) - setbits32(non_ehci + FSL_SOC_USB_CTRL, - CTRL_UTMI_PHY_EN); + clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL, + CONTROL_REGISTER_W1C_MASK, + CTRL_UTMI_PHY_EN); portsc |= PORT_PTS_UTMI; break; case FSL_USB2_PHY_NONE: break; } - if (pdata->have_sysif_regs && - pdata->controller_ver > FSL_USB_VER_1_6 && - (phy_mode == FSL_USB2_PHY_ULPI)) { - /* check PHY_CLK_VALID to get phy clk valid */ - if (!(spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) & - PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0) || - in_be32(non_ehci + FSL_SOC_USB_PRICTRL))) { - dev_warn(hcd->self.controller, "USB PHY clock invalid\n"); + /* + * check PHY_CLK_VALID to determine phy clock presence before writing + * to portsc + */ + if (pdata->check_phy_clk_valid) { + if (!(in_be32(non_ehci + FSL_SOC_USB_CTRL) & PHY_CLK_VALID)) { + dev_warn(hcd->self.controller, + "USB PHY clock invalid\n"); return -EINVAL; } } @@ -235,7 +251,8 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); if (phy_mode != FSL_USB2_PHY_ULPI && pdata->have_sysif_regs) - setbits32(non_ehci + FSL_SOC_USB_CTRL, USB_CTRL_USB_EN); + clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL, + CONTROL_REGISTER_W1C_MASK, USB_CTRL_USB_EN); return 0; } diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h index dbd292e9f0a7..1a8a60a57cf2 100644 --- a/drivers/usb/host/ehci-fsl.h +++ b/drivers/usb/host/ehci-fsl.h @@ -52,6 +52,7 @@ #define SNOOP_SIZE_2GB 0x1e /* control Register Bit Masks */ +#define CONTROL_REGISTER_W1C_MASK 0x00020000 /* W1C: PHY_CLK_VALID */ #define ULPI_INT_EN (1<<0) #define WU_INT_EN (1<<1) #define USB_CTRL_USB_EN (1<<2) diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index 2593def13cea..5c3c08598682 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -45,6 +45,7 @@ struct ehci_platform_priv { struct reset_control *rst; struct phy **phys; int num_phys; + bool reset_on_resume; }; static const char hcd_name[] = "ehci-platform"; @@ -56,7 +57,6 @@ static int ehci_platform_reset(struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci(hcd); int retval; - hcd->has_tt = pdata->has_tt; ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug; if (pdata->pre_setup) { @@ -193,11 +193,11 @@ static int ehci_platform_probe(struct platform_device *dev) if (of_property_read_bool(dev->dev.of_node, "needs-reset-on-resume")) - pdata->reset_on_resume = 1; + priv->reset_on_resume = true; if (of_property_read_bool(dev->dev.of_node, "has-transaction-translator")) - pdata->has_tt = 1; + hcd->has_tt = 1; priv->num_phys = of_count_phandle_with_args(dev->dev.of_node, "phys", "#phy-cells"); @@ -247,6 +247,10 @@ static int ehci_platform_probe(struct platform_device *dev) ehci->big_endian_desc = 1; if (pdata->big_endian_mmio) ehci->big_endian_mmio = 1; + if (pdata->has_tt) + hcd->has_tt = 1; + if (pdata->reset_on_resume) + priv->reset_on_resume = true; #ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO if (ehci->big_endian_mmio) { @@ -359,6 +363,7 @@ static int ehci_platform_resume(struct device *dev) struct usb_ehci_pdata *pdata = dev_get_platdata(dev); struct platform_device *pdev = container_of(dev, struct platform_device, dev); + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); if (pdata->power_on) { int err = pdata->power_on(pdev); @@ -366,7 +371,7 @@ static int ehci_platform_resume(struct device *dev) return err; } - ehci_resume(hcd, pdata->reset_on_resume); + ehci_resume(hcd, priv->reset_on_resume); return 0; } #endif /* CONFIG_PM_SLEEP */ diff --git a/drivers/usb/host/ehci-st.c b/drivers/usb/host/ehci-st.c index 7e4bd39cf757..b7c5cfa37a83 100644 --- a/drivers/usb/host/ehci-st.c +++ b/drivers/usb/host/ehci-st.c @@ -54,7 +54,6 @@ static int st_ehci_platform_reset(struct usb_hcd *hcd) struct platform_device *pdev = to_platform_device(hcd->self.controller); struct usb_ehci_pdata *pdata = dev_get_platdata(&pdev->dev); struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; u32 threshold; /* Set EHCI packet buffer IN/OUT threshold to 128 bytes */ @@ -62,11 +61,7 @@ static int st_ehci_platform_reset(struct usb_hcd *hcd) writel(threshold, hcd->regs + AHB2STBUS_INSREG01); ehci->caps = hcd->regs + pdata->caps_offset; - retval = ehci_setup(hcd); - if (retval) - return retval; - - return 0; + return ehci_setup(hcd); } static int st_ehci_platform_power_on(struct platform_device *dev) diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 5e0d60035216..9f731413ab3e 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -69,6 +69,8 @@ static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type) return FSL_USB2_PHY_UTMI; if (!strcasecmp(phy_type, "utmi_wide")) return FSL_USB2_PHY_UTMI_WIDE; + if (!strcasecmp(phy_type, "utmi_dual")) + return FSL_USB2_PHY_UTMI_DUAL; if (!strcasecmp(phy_type, "serial")) return FSL_USB2_PHY_SERIAL; @@ -119,9 +121,9 @@ error: static const struct of_device_id fsl_usb2_mph_dr_of_match[]; -static int usb_get_ver_info(struct device_node *np) +static enum fsl_usb2_controller_ver usb_get_ver_info(struct device_node *np) { - int ver = -1; + enum fsl_usb2_controller_ver ver = FSL_USB_VER_NONE; /* * returns 1 for usb controller version 1.6 @@ -142,7 +144,7 @@ static int usb_get_ver_info(struct device_node *np) else /* for previous controller versions */ ver = FSL_USB_VER_OLD; - if (ver > -1) + if (ver > FSL_USB_VER_NONE) return ver; } @@ -214,8 +216,23 @@ static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev) pdata->phy_mode = determine_usb_phy(prop); pdata->controller_ver = usb_get_ver_info(np); + /* Activate Erratum by reading property in device tree */ + if (of_get_property(np, "fsl,usb-erratum-a007792", NULL)) + pdata->has_fsl_erratum_a007792 = 1; + else + pdata->has_fsl_erratum_a007792 = 0; + + /* + * Determine whether phy_clk_valid needs to be checked + * by reading property in device tree + */ + if (of_get_property(np, "phy-clk-valid", NULL)) + pdata->check_phy_clk_valid = 1; + else + pdata->check_phy_clk_valid = 0; + if (pdata->have_sysif_regs) { - if (pdata->controller_ver < 0) { + if (pdata->controller_ver == FSL_USB_VER_NONE) { dev_warn(&ofdev->dev, "Could not get controller version\n"); return -ENODEV; } diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 6352f54e65a1..fe3bd1cb8b6b 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -2670,7 +2670,6 @@ static int oxu_hcd_init(struct usb_hcd *hcd) static int oxu_reset(struct usb_hcd *hcd) { struct oxu_hcd *oxu = hcd_to_oxu(hcd); - int ret; spin_lock_init(&oxu->mem_lock); INIT_LIST_HEAD(&oxu->urb_list); @@ -2696,11 +2695,7 @@ static int oxu_reset(struct usb_hcd *hcd) oxu->hcs_params = readl(&oxu->caps->hcs_params); oxu->sbrn = 0x20; - ret = oxu_hcd_init(hcd); - if (ret) - return ret; - - return 0; + return oxu_hcd_init(hcd); } static int oxu_run(struct usb_hcd *hcd) diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index d51687780b61..a67bd5090330 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -1542,11 +1542,8 @@ static int u132_periodic_reinit(struct u132 *u132) (fit ^ FIT) | u132->hc_fminterval); if (retval) return retval; - retval = u132_write_pcimem(u132, periodicstart, - ((9 * fi) / 10) & 0x3fff); - if (retval) - return retval; - return 0; + return u132_write_pcimem(u132, periodicstart, + ((9 * fi) / 10) & 0x3fff); } static char *hcfs2string(int state) @@ -2701,28 +2698,18 @@ static int u132_roothub_setportfeature(struct u132 *u132, u16 wValue, if (wIndex == 0 || wIndex > u132->num_ports) { return -EINVAL; } else { - int retval; int port_index = wIndex - 1; struct u132_port *port = &u132->port[port_index]; port->Status &= ~(1 << wValue); switch (wValue) { case USB_PORT_FEAT_SUSPEND: - retval = u132_write_pcimem(u132, - roothub.portstatus[port_index], RH_PS_PSS); - if (retval) - return retval; - return 0; + return u132_write_pcimem(u132, + roothub.portstatus[port_index], RH_PS_PSS); case USB_PORT_FEAT_POWER: - retval = u132_write_pcimem(u132, - roothub.portstatus[port_index], RH_PS_PPS); - if (retval) - return retval; - return 0; + return u132_write_pcimem(u132, + roothub.portstatus[port_index], RH_PS_PPS); case USB_PORT_FEAT_RESET: - retval = u132_roothub_portreset(u132, port_index); - if (retval) - return retval; - return 0; + return u132_roothub_portreset(u132, port_index); default: return -EPIPE; } @@ -2737,7 +2724,6 @@ static int u132_roothub_clearportfeature(struct u132 *u132, u16 wValue, } else { int port_index = wIndex - 1; u32 temp; - int retval; struct u132_port *port = &u132->port[port_index]; port->Status &= ~(1 << wValue); switch (wValue) { @@ -2773,11 +2759,8 @@ static int u132_roothub_clearportfeature(struct u132 *u132, u16 wValue, default: return -EPIPE; } - retval = u132_write_pcimem(u132, roothub.portstatus[port_index], - temp); - if (retval) - return retval; - return 0; + return u132_write_pcimem(u132, roothub.portstatus[port_index], + temp); } } diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index 745717ec9c89..2d16faefb429 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -99,6 +99,10 @@ static void xhci_print_cap_regs(struct xhci_hcd *xhci) xhci_dbg(xhci, "HCC PARAMS 0x%x:\n", (unsigned int) temp); xhci_dbg(xhci, " HC generates %s bit addresses\n", HCC_64BIT_ADDR(temp) ? "64" : "32"); + xhci_dbg(xhci, " HC %s Contiguous Frame ID Capability\n", + HCC_CFC(temp) ? "has" : "hasn't"); + xhci_dbg(xhci, " HC %s generate Stopped - Short Package event\n", + HCC_SPC(temp) ? "can" : "can't"); /* FIXME */ xhci_dbg(xhci, " FIXME: more HCCPARAMS debugging\n"); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 32f4d564494a..a47a1e897086 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1812,7 +1812,9 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td, if (skip) goto td_cleanup; - if (trb_comp_code == COMP_STOP_INVAL || trb_comp_code == COMP_STOP) { + if (trb_comp_code == COMP_STOP_INVAL || + trb_comp_code == COMP_STOP || + trb_comp_code == COMP_STOP_SHORT) { /* The Endpoint Stop Command completion will take care of any * stopped TDs. A stopped TD may be restarted, so don't update * the ring dequeue pointer or take this TD off any lists yet. @@ -1919,8 +1921,22 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, else *status = 0; break; - case COMP_STOP_INVAL: + case COMP_STOP_SHORT: + if (event_trb == ep_ring->dequeue || event_trb == td->last_trb) + xhci_warn(xhci, "WARN: Stopped Short Packet on ctrl setup or status TRB\n"); + else + td->urb->actual_length = + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); + + return finish_td(xhci, td, event_trb, event, ep, status, false); case COMP_STOP: + /* Did we stop at data stage? */ + if (event_trb != ep_ring->dequeue && event_trb != td->last_trb) + td->urb->actual_length = + td->urb->transfer_buffer_length - + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); + /* fall through */ + case COMP_STOP_INVAL: return finish_td(xhci, td, event_trb, event, ep, status, false); default: if (!xhci_requires_manual_halt_cleanup(xhci, @@ -2014,6 +2030,8 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, } if ((xhci->quirks & XHCI_TRUST_TX_LENGTH)) trb_comp_code = COMP_SHORT_TX; + /* fallthrough */ + case COMP_STOP_SHORT: case COMP_SHORT_TX: frame->status = td->urb->transfer_flags & URB_SHORT_NOT_OK ? -EREMOTEIO : 0; @@ -2049,6 +2067,10 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, if (trb_comp_code == COMP_SUCCESS || skip_td) { frame->actual_length = frame->length; td->urb->actual_length += frame->length; + } else if (trb_comp_code == COMP_STOP_SHORT) { + frame->actual_length = + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); + td->urb->actual_length += frame->actual_length; } else { for (cur_trb = ep_ring->dequeue, cur_seg = ep_ring->deq_seg; cur_trb != event_trb; @@ -2129,6 +2151,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, *status = 0; } break; + case COMP_STOP_SHORT: case COMP_SHORT_TX: if (td->urb->transfer_flags & URB_SHORT_NOT_OK) *status = -EREMOTEIO; @@ -2145,8 +2168,20 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, td->urb->ep->desc.bEndpointAddress, td->urb->transfer_buffer_length, EVENT_TRB_LEN(le32_to_cpu(event->transfer_len))); + /* Stopped - short packet completion */ + if (trb_comp_code == COMP_STOP_SHORT) { + td->urb->actual_length = + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); + + if (td->urb->transfer_buffer_length < + td->urb->actual_length) { + xhci_warn(xhci, "HC gave bad length of %d bytes txed\n", + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len))); + td->urb->actual_length = 0; + /* status will be set by usb core for canceled urbs */ + } /* Fast path - was this the last TRB in the TD for this URB? */ - if (event_trb == td->last_trb) { + } else if (event_trb == td->last_trb) { if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { td->urb->actual_length = td->urb->transfer_buffer_length - @@ -2300,6 +2335,9 @@ static int handle_tx_event(struct xhci_hcd *xhci, case COMP_STOP_INVAL: xhci_dbg(xhci, "Stopped on No-op or Link TRB\n"); break; + case COMP_STOP_SHORT: + xhci_dbg(xhci, "Stopped with short packet transfer detected\n"); + break; case COMP_STALL: xhci_dbg(xhci, "Stalled endpoint\n"); ep->ep_state |= EP_HALTED; @@ -3041,9 +3079,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct xhci_td *td; struct scatterlist *sg; int num_sgs; - int trb_buff_len, this_sg_len, running_total; + int trb_buff_len, this_sg_len, running_total, ret; unsigned int total_packet_count; + bool zero_length_needed; bool first_trb; + int last_trb_num; u64 addr; bool more_trbs_coming; @@ -3059,13 +3099,27 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length, usb_endpoint_maxp(&urb->ep->desc)); - trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id], + ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index, urb->stream_id, num_trbs, urb, 0, mem_flags); - if (trb_buff_len < 0) - return trb_buff_len; + if (ret < 0) + return ret; urb_priv = urb->hcpriv; + + /* Deal with URB_ZERO_PACKET - need one more td/trb */ + zero_length_needed = urb->transfer_flags & URB_ZERO_PACKET && + urb_priv->length == 2; + if (zero_length_needed) { + num_trbs++; + xhci_dbg(xhci, "Creating zero length td.\n"); + ret = prepare_transfer(xhci, xhci->devs[slot_id], + ep_index, urb->stream_id, + 1, urb, 1, mem_flags); + if (ret < 0) + return ret; + } + td = urb_priv->td[0]; /* @@ -3095,6 +3149,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, trb_buff_len = urb->transfer_buffer_length; first_trb = true; + last_trb_num = zero_length_needed ? 2 : 1; /* Queue the first TRB, even if it's zero-length */ do { u32 field = 0; @@ -3112,12 +3167,15 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, /* Chain all the TRBs together; clear the chain bit in the last * TRB to indicate it's the last TRB in the chain. */ - if (num_trbs > 1) { + if (num_trbs > last_trb_num) { field |= TRB_CHAIN; - } else { - /* FIXME - add check for ZERO_PACKET flag before this */ + } else if (num_trbs == last_trb_num) { td->last_trb = ep_ring->enqueue; field |= TRB_IOC; + } else if (zero_length_needed && num_trbs == 1) { + trb_buff_len = 0; + urb_priv->td[1]->last_trb = ep_ring->enqueue; + field |= TRB_IOC; } /* Only set interrupt on short packet for IN endpoints */ @@ -3179,7 +3237,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, if (running_total + trb_buff_len > urb->transfer_buffer_length) trb_buff_len = urb->transfer_buffer_length - running_total; - } while (running_total < urb->transfer_buffer_length); + } while (num_trbs > 0); check_trb_math(urb, num_trbs, running_total); giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, @@ -3197,7 +3255,9 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, int num_trbs; struct xhci_generic_trb *start_trb; bool first_trb; + int last_trb_num; bool more_trbs_coming; + bool zero_length_needed; int start_cycle; u32 field, length_field; @@ -3228,7 +3288,6 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, num_trbs++; running_total += TRB_MAX_BUFF_SIZE; } - /* FIXME: this doesn't deal with URB_ZERO_PACKET - need one more */ ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index, urb->stream_id, @@ -3237,6 +3296,20 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, return ret; urb_priv = urb->hcpriv; + + /* Deal with URB_ZERO_PACKET - need one more td/trb */ + zero_length_needed = urb->transfer_flags & URB_ZERO_PACKET && + urb_priv->length == 2; + if (zero_length_needed) { + num_trbs++; + xhci_dbg(xhci, "Creating zero length td.\n"); + ret = prepare_transfer(xhci, xhci->devs[slot_id], + ep_index, urb->stream_id, + 1, urb, 1, mem_flags); + if (ret < 0) + return ret; + } + td = urb_priv->td[0]; /* @@ -3258,7 +3331,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, trb_buff_len = urb->transfer_buffer_length; first_trb = true; - + last_trb_num = zero_length_needed ? 2 : 1; /* Queue the first TRB, even if it's zero-length */ do { u32 remainder = 0; @@ -3275,12 +3348,15 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, /* Chain all the TRBs together; clear the chain bit in the last * TRB to indicate it's the last TRB in the chain. */ - if (num_trbs > 1) { + if (num_trbs > last_trb_num) { field |= TRB_CHAIN; - } else { - /* FIXME - add check for ZERO_PACKET flag before this */ + } else if (num_trbs == last_trb_num) { td->last_trb = ep_ring->enqueue; field |= TRB_IOC; + } else if (zero_length_needed && num_trbs == 1) { + trb_buff_len = 0; + urb_priv->td[1]->last_trb = ep_ring->enqueue; + field |= TRB_IOC; } /* Only set interrupt on short packet for IN endpoints */ @@ -3318,7 +3394,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, trb_buff_len = urb->transfer_buffer_length - running_total; if (trb_buff_len > TRB_MAX_BUFF_SIZE) trb_buff_len = TRB_MAX_BUFF_SIZE; - } while (running_total < urb->transfer_buffer_length); + } while (num_trbs > 0); check_trb_math(urb, num_trbs, running_total); giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, @@ -3517,6 +3593,97 @@ static unsigned int xhci_get_last_burst_packet_count(struct xhci_hcd *xhci, } } +/* + * Calculates Frame ID field of the isochronous TRB identifies the + * target frame that the Interval associated with this Isochronous + * Transfer Descriptor will start on. Refer to 4.11.2.5 in 1.1 spec. + * + * Returns actual frame id on success, negative value on error. + */ +static int xhci_get_isoc_frame_id(struct xhci_hcd *xhci, + struct urb *urb, int index) +{ + int start_frame, ist, ret = 0; + int start_frame_id, end_frame_id, current_frame_id; + + if (urb->dev->speed == USB_SPEED_LOW || + urb->dev->speed == USB_SPEED_FULL) + start_frame = urb->start_frame + index * urb->interval; + else + start_frame = (urb->start_frame + index * urb->interval) >> 3; + + /* Isochronous Scheduling Threshold (IST, bits 0~3 in HCSPARAMS2): + * + * If bit [3] of IST is cleared to '0', software can add a TRB no + * later than IST[2:0] Microframes before that TRB is scheduled to + * be executed. + * If bit [3] of IST is set to '1', software can add a TRB no later + * than IST[2:0] Frames before that TRB is scheduled to be executed. + */ + ist = HCS_IST(xhci->hcs_params2) & 0x7; + if (HCS_IST(xhci->hcs_params2) & (1 << 3)) + ist <<= 3; + + /* Software shall not schedule an Isoch TD with a Frame ID value that + * is less than the Start Frame ID or greater than the End Frame ID, + * where: + * + * End Frame ID = (Current MFINDEX register value + 895 ms.) MOD 2048 + * Start Frame ID = (Current MFINDEX register value + IST + 1) MOD 2048 + * + * Both the End Frame ID and Start Frame ID values are calculated + * in microframes. When software determines the valid Frame ID value; + * The End Frame ID value should be rounded down to the nearest Frame + * boundary, and the Start Frame ID value should be rounded up to the + * nearest Frame boundary. + */ + current_frame_id = readl(&xhci->run_regs->microframe_index); + start_frame_id = roundup(current_frame_id + ist + 1, 8); + end_frame_id = rounddown(current_frame_id + 895 * 8, 8); + + start_frame &= 0x7ff; + start_frame_id = (start_frame_id >> 3) & 0x7ff; + end_frame_id = (end_frame_id >> 3) & 0x7ff; + + xhci_dbg(xhci, "%s: index %d, reg 0x%x start_frame_id 0x%x, end_frame_id 0x%x, start_frame 0x%x\n", + __func__, index, readl(&xhci->run_regs->microframe_index), + start_frame_id, end_frame_id, start_frame); + + if (start_frame_id < end_frame_id) { + if (start_frame > end_frame_id || + start_frame < start_frame_id) + ret = -EINVAL; + } else if (start_frame_id > end_frame_id) { + if ((start_frame > end_frame_id && + start_frame < start_frame_id)) + ret = -EINVAL; + } else { + ret = -EINVAL; + } + + if (index == 0) { + if (ret == -EINVAL || start_frame == start_frame_id) { + start_frame = start_frame_id + 1; + if (urb->dev->speed == USB_SPEED_LOW || + urb->dev->speed == USB_SPEED_FULL) + urb->start_frame = start_frame; + else + urb->start_frame = start_frame << 3; + ret = 0; + } + } + + if (ret) { + xhci_warn(xhci, "Frame ID %d (reg %d, index %d) beyond range (%d, %d)\n", + start_frame, current_frame_id, index, + start_frame_id, end_frame_id); + xhci_warn(xhci, "Ignore frame ID field, use SIA bit instead\n"); + return ret; + } + + return start_frame; +} + /* This is for isoc transfer */ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index) @@ -3533,7 +3700,9 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, u64 start_addr, addr; int i, j; bool more_trbs_coming; + struct xhci_virt_ep *xep; + xep = &xhci->devs[slot_id]->eps[ep_index]; ep_ring = xhci->devs[slot_id]->eps[ep_index].ring; num_tds = urb->number_of_packets; @@ -3581,6 +3750,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, td = urb_priv->td[i]; for (j = 0; j < trbs_per_td; j++) { + int frame_id = 0; u32 remainder = 0; field = 0; @@ -3589,8 +3759,20 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, TRB_TLBPC(residue); /* Queue the isoc TRB */ field |= TRB_TYPE(TRB_ISOC); - /* Assume URB_ISO_ASAP is set */ - field |= TRB_SIA; + + /* Calculate Frame ID and SIA fields */ + if (!(urb->transfer_flags & URB_ISO_ASAP) && + HCC_CFC(xhci->hcc_params)) { + frame_id = xhci_get_isoc_frame_id(xhci, + urb, + i); + if (frame_id >= 0) + field |= TRB_FRAME_ID(frame_id); + else + field |= TRB_SIA; + } else + field |= TRB_SIA; + if (i == 0) { if (start_cycle == 0) field |= 0x1; @@ -3666,6 +3848,10 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, } } + /* store the next frame id */ + if (HCC_CFC(xhci->hcc_params)) + xep->next_frame_id = urb->start_frame + num_tds * urb->interval; + if (xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs == 0) { if (xhci->quirks & XHCI_AMD_PLL_FIX) usb_amd_quirk_pll_disable(); @@ -3699,12 +3885,34 @@ cleanup: return ret; } +static int ep_ring_is_processing(struct xhci_hcd *xhci, + int slot_id, unsigned int ep_index) +{ + struct xhci_virt_device *xdev; + struct xhci_ring *ep_ring; + struct xhci_ep_ctx *ep_ctx; + struct xhci_virt_ep *xep; + dma_addr_t hw_deq; + + xdev = xhci->devs[slot_id]; + xep = &xhci->devs[slot_id]->eps[ep_index]; + ep_ring = xep->ring; + ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); + + if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) != EP_STATE_RUNNING) + return 0; + + hw_deq = le64_to_cpu(ep_ctx->deq) & ~EP_CTX_CYCLE_MASK; + return (hw_deq != + xhci_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue)); +} + /* * Check transfer ring to guarantee there is enough room for the urb. * Update ISO URB start_frame and interval. - * Update interval as xhci_queue_intr_tx does. Just use xhci frame_index to - * update the urb->start_frame by now. - * Always assume URB_ISO_ASAP set, and NEVER use urb->start_frame as input. + * Update interval as xhci_queue_intr_tx does. Use xhci frame_index to + * update urb->start_frame if URB_ISO_ASAP is set in transfer_flags or + * Contiguous Frame ID is not supported by HC. */ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index) @@ -3717,8 +3925,11 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, int ep_interval; int num_tds, num_trbs, i; int ret; + struct xhci_virt_ep *xep; + int ist; xdev = xhci->devs[slot_id]; + xep = &xhci->devs[slot_id]->eps[ep_index]; ep_ring = xdev->eps[ep_index].ring; ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); @@ -3735,14 +3946,10 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, if (ret) return ret; - start_frame = readl(&xhci->run_regs->microframe_index); - start_frame &= 0x3fff; - - urb->start_frame = start_frame; - if (urb->dev->speed == USB_SPEED_LOW || - urb->dev->speed == USB_SPEED_FULL) - urb->start_frame >>= 3; - + /* + * Check interval value. This should be done before we start to + * calculate the start frame value. + */ xhci_interval = EP_INTERVAL_TO_UFRAMES(le32_to_cpu(ep_ctx->ep_info)); ep_interval = urb->interval; /* Convert to microframes */ @@ -3763,6 +3970,40 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, urb->dev->speed == USB_SPEED_FULL) urb->interval /= 8; } + + /* Calculate the start frame and put it in urb->start_frame. */ + if (HCC_CFC(xhci->hcc_params) && + ep_ring_is_processing(xhci, slot_id, ep_index)) { + urb->start_frame = xep->next_frame_id; + goto skip_start_over; + } + + start_frame = readl(&xhci->run_regs->microframe_index); + start_frame &= 0x3fff; + /* + * Round up to the next frame and consider the time before trb really + * gets scheduled by hardare. + */ + ist = HCS_IST(xhci->hcs_params2) & 0x7; + if (HCS_IST(xhci->hcs_params2) & (1 << 3)) + ist <<= 3; + start_frame += ist + XHCI_CFC_DELAY; + start_frame = roundup(start_frame, 8); + + /* + * Round up to the next ESIT (Endpoint Service Interval Time) if ESIT + * is greate than 8 microframes. + */ + if (urb->dev->speed == USB_SPEED_LOW || + urb->dev->speed == USB_SPEED_FULL) { + start_frame = roundup(start_frame, urb->interval << 3); + urb->start_frame = start_frame >> 3; + } else { + start_frame = roundup(start_frame, urb->interval); + urb->start_frame = start_frame; + } + +skip_start_over: ep_ring->num_trbs_free_temp = ep_ring->num_trbs_free; return xhci_queue_isoc_tx(xhci, mem_flags, urb, slot_id, ep_index); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 526ebc0c7e72..6b0f4a47e402 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1340,6 +1340,11 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) if (usb_endpoint_xfer_isoc(&urb->ep->desc)) size = urb->number_of_packets; + else if (usb_endpoint_is_bulk_out(&urb->ep->desc) && + urb->transfer_buffer_length > 0 && + urb->transfer_flags & URB_ZERO_PACKET && + !(urb->transfer_buffer_length % usb_endpoint_maxp(&urb->ep->desc))) + size = 2; else size = 1; @@ -3117,7 +3122,7 @@ static u32 xhci_calculate_no_streams_bitmask(struct xhci_hcd *xhci, } /* - * The USB device drivers use this function (though the HCD interface in USB + * The USB device drivers use this function (through the HCD interface in USB * core) to prepare a set of bulk endpoints to use streams. Streams are used to * coordinate mass storage command queueing across multiple endpoints (basically * a stream ID == a task ID). @@ -4678,7 +4683,6 @@ int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd, { struct xhci_hcd *xhci; u16 mel; - int ret; xhci = hcd_to_xhci(hcd); if (!xhci || !(xhci->quirks & XHCI_LPM_SUPPORT) || @@ -4686,10 +4690,7 @@ int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd, return 0; mel = calculate_max_exit_latency(udev, state, USB3_LPM_DISABLED); - ret = xhci_change_max_exit_latency(xhci, udev, mel); - if (ret) - return ret; - return 0; + return xhci_change_max_exit_latency(xhci, udev, mel); } #else /* CONFIG_PM */ diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index ed2ebf647c38..dbda41e91c84 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -119,6 +119,10 @@ struct xhci_cap_regs { #define HCC_LTC(p) ((p) & (1 << 6)) /* true: no secondary Stream ID Support */ #define HCC_NSS(p) ((p) & (1 << 7)) +/* true: HC supports Stopped - Short Packet */ +#define HCC_SPC(p) ((p) & (1 << 9)) +/* true: HC has Contiguous Frame ID Capability */ +#define HCC_CFC(p) ((p) & (1 << 11)) /* Max size for Primary Stream Arrays - 2^(n+1), where n is bits 12:15 */ #define HCC_MAX_PSA(p) (1 << ((((p) >> 12) & 0xf) + 1)) /* Extended Capabilities pointer from PCI base - section 5.3.6 */ @@ -891,6 +895,8 @@ struct xhci_virt_ep { /* Bandwidth checking storage */ struct xhci_bw_info bw_info; struct list_head bw_endpoint_list; + /* Isoch Frame ID checking storage */ + int next_frame_id; }; enum xhci_overhead_type { @@ -1059,8 +1065,8 @@ struct xhci_transfer_event { #define COMP_STOP 26 /* Same as COMP_EP_STOPPED, but the transferred length in the event is invalid */ #define COMP_STOP_INVAL 27 -/* Control Abort Error - Debug Capability - control pipe aborted */ -#define COMP_DBG_ABORT 28 +/* Same as COMP_EP_STOPPED, but a short packet detected */ +#define COMP_STOP_SHORT 28 /* Max Exit Latency Too Large Error */ #define COMP_MEL_ERR 29 /* TRB type 30 reserved */ @@ -1165,6 +1171,7 @@ enum xhci_setup_dev { /* Isochronous TRB specific fields */ #define TRB_SIA (1<<31) +#define TRB_FRAME_ID(p) (((p) & 0x7ff) << 20) struct xhci_generic_trb { __le32 field[4]; @@ -1601,6 +1608,8 @@ struct xhci_driver_overrides { int (*start)(struct usb_hcd *hcd); }; +#define XHCI_CFC_DELAY 10 + /* convert between an HCD pointer and the corresponding EHCI_HCD */ static inline struct xhci_hcd *hcd_to_xhci(struct usb_hcd *hcd) { diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 8ab1f8f3c26e..52c27cab78c3 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -2568,11 +2568,7 @@ static int ftdi_elan_close_controller(struct usb_ftdi *ftdi, int fn) 0x00); if (UxxxStatus) return UxxxStatus; - UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, - &pcidata); - if (UxxxStatus) - return UxxxStatus; - return 0; + return ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, &pcidata); } static int ftdi_elan_found_controller(struct usb_ftdi *ftdi, int fn, int quirk) @@ -2695,11 +2691,7 @@ static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi) } } if (ftdi->function > 0) { - UxxxStatus = ftdi_elan_setup_controller(ftdi, - ftdi->function - 1); - if (UxxxStatus) - return UxxxStatus; - return 0; + return ftdi_elan_setup_controller(ftdi, ftdi->function - 1); } else if (controllers > 0) { return -ENXIO; } else if (unrecognized > 0) { diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 1334a3de31b8..a0cfead6150f 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -482,11 +482,7 @@ static int dsps_musb_init(struct musb *musb) dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val); } - ret = dsps_musb_dbg_init(musb, glue); - if (ret) - return ret; - - return 0; + return dsps_musb_dbg_init(musb, glue); } static int dsps_musb_exit(struct musb *musb) diff --git a/drivers/usb/phy/phy-keystone.c b/drivers/usb/phy/phy-keystone.c index e0556f7832b5..01d4e4cdbc79 100644 --- a/drivers/usb/phy/phy-keystone.c +++ b/drivers/usb/phy/phy-keystone.c @@ -96,11 +96,7 @@ static int keystone_usbphy_probe(struct platform_device *pdev) platform_set_drvdata(pdev, k_phy); - ret = usb_add_phy_dev(&k_phy->usb_phy_gen.phy); - if (ret) - return ret; - - return 0; + return usb_add_phy_dev(&k_phy->usb_phy_gen.phy); } static int keystone_usbphy_remove(struct platform_device *pdev) diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index 3fcc0483a081..4d863ebc117c 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -506,11 +506,7 @@ static int mxs_phy_probe(struct platform_device *pdev) device_set_wakeup_capable(&pdev->dev, true); - ret = usb_add_phy_dev(&mxs_phy->phy); - if (ret) - return ret; - - return 0; + return usb_add_phy_dev(&mxs_phy->phy); } static int mxs_phy_remove(struct platform_device *pdev) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index dc2aa3261202..54f916fa238d 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -21,6 +21,7 @@ #include <linux/platform_device.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> +#include <linux/usb/otg.h> #include "common.h" /* @@ -50,6 +51,8 @@ struct usbhsg_gpriv { int uep_size; struct usb_gadget_driver *driver; + struct usb_phy *transceiver; + bool vbus_active; u32 status; #define USBHSG_STATUS_STARTED (1 << 0) @@ -873,6 +876,27 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) } /* + * VBUS provided by the PHY + */ +static int usbhsm_phy_get_vbus(struct platform_device *pdev) +{ + struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); + struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); + + return gpriv->vbus_active; +} + +static void usbhs_mod_phy_mode(struct usbhs_priv *priv) +{ + struct usbhs_mod_info *info = &priv->mod_info; + + info->irq_vbus = NULL; + priv->pfunc.get_vbus = usbhsm_phy_get_vbus; + + usbhs_irq_callback_update(priv, NULL); +} + +/* * * linux usb function * @@ -882,12 +906,28 @@ static int usbhsg_gadget_start(struct usb_gadget *gadget, { struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); + struct device *dev = usbhs_priv_to_dev(priv); + int ret; if (!driver || !driver->setup || driver->max_speed < USB_SPEED_FULL) return -EINVAL; + /* connect to bus through transceiver */ + if (!IS_ERR_OR_NULL(gpriv->transceiver)) { + ret = otg_set_peripheral(gpriv->transceiver->otg, + &gpriv->gadget); + if (ret) { + dev_err(dev, "%s: can't bind to transceiver\n", + gpriv->gadget.name); + return ret; + } + + /* get vbus using phy versions */ + usbhs_mod_phy_mode(priv); + } + /* first hook up the driver ... */ gpriv->driver = driver; @@ -900,6 +940,10 @@ static int usbhsg_gadget_stop(struct usb_gadget *gadget) struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); usbhsg_try_stop(priv, USBHSG_STATUS_REGISTERD); + + if (!IS_ERR_OR_NULL(gpriv->transceiver)) + otg_set_peripheral(gpriv->transceiver->otg, NULL); + gpriv->driver = NULL; return 0; @@ -947,12 +991,26 @@ static int usbhsg_set_selfpowered(struct usb_gadget *gadget, int is_self) return 0; } +static int usbhsg_vbus_session(struct usb_gadget *gadget, int is_active) +{ + struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); + struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); + struct platform_device *pdev = usbhs_priv_to_pdev(priv); + + gpriv->vbus_active = !!is_active; + + renesas_usbhs_call_notify_hotplug(pdev); + + return 0; +} + static const struct usb_gadget_ops usbhsg_gadget_ops = { .get_frame = usbhsg_get_frame, .set_selfpowered = usbhsg_set_selfpowered, .udc_start = usbhsg_gadget_start, .udc_stop = usbhsg_gadget_stop, .pullup = usbhsg_pullup, + .vbus_session = usbhsg_vbus_session, }; static int usbhsg_start(struct usbhs_priv *priv) @@ -994,6 +1052,10 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) goto usbhs_mod_gadget_probe_err_gpriv; } + gpriv->transceiver = usb_get_phy(USB_PHY_TYPE_UNDEFINED); + dev_info(dev, "%stransceiver found\n", + gpriv->transceiver ? "" : "no "); + /* * CAUTION * diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c index 460a40669967..31a8b47f1ac6 100644 --- a/drivers/usb/serial/mxuport.c +++ b/drivers/usb/serial/mxuport.c @@ -1137,13 +1137,9 @@ static int mxuport_port_probe(struct usb_serial_port *port) return err; /* Set interface (RS-232) */ - err = mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_INTERFACE, - MX_INT_RS232, - port->port_number); - if (err) - return err; - - return 0; + return mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_INTERFACE, + MX_INT_RS232, + port->port_number); } static int mxuport_alloc_write_urb(struct usb_serial *serial, diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 540add24a12f..5e67f63b2e46 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -1111,7 +1111,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) * command phase and the data phase. Some devices need a little * more than that, probably because of clock rate inaccuracies. */ if (unlikely(us->fflags & US_FL_GO_SLOW)) - udelay(125); + usleep_range(125, 150); if (transfer_length) { unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? |