Merge tag 'usb-4.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 29 Oct 2016 17:07:59 +0000 (10:07 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 29 Oct 2016 17:07:59 +0000 (10:07 -0700)
Pull USB fixes from Greg KH:
 "Here are a number of small USB driver fixes for 4.9-rc3.

  There is the usual number of gadget and xhci patches in here to
  resolved reported issues, as well as some usb-serial driver fixes and
  new device ids.

  All have been in linux-next with no reported issues"

* tag 'usb-4.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (26 commits)
  usb: chipidea: host: fix NULL ptr dereference during shutdown
  usb: renesas_usbhs: add wait after initialization for R-Car Gen3
  usb: increase ohci watchdog delay to 275 msec
  usb: musb: Call pm_runtime from musb_gadget_queue
  usb: musb: Fix hardirq-safe hardirq-unsafe lock order error
  usb: ehci-platform: increase EHCI_MAX_RSTS to 4
  usb: ohci-at91: Set RemoteWakeupConnected bit explicitly.
  USB: serial: fix potential NULL-dereference at probe
  xhci: use default USB_RESUME_TIMEOUT when resuming ports.
  xhci: workaround for hosts missing CAS bit
  xhci: add restart quirk for Intel Wildcatpoint PCH
  USB: serial: cp210x: fix tiocmget error handling
  wusb: fix error return code in wusb_prf()
  Revert "Documentation: devicetree: dwc2: Deprecate g-tx-fifo-size"
  Revert "usb: dwc2: gadget: fix TX FIFO size and address initialization"
  Revert "usb: dwc2: gadget: change variable name to more meaningful"
  USB: serial: ftdi_sio: add support for Infineon TriBoard TC2X7
  wusb: Stop using the stack for sg crypto scratch space
  usb: dwc3: Fix size used in dma_free_coherent()
  usb: gadget: f_fs: stop sleeping in ffs_func_eps_disable
  ...

23 files changed:
Documentation/devicetree/bindings/usb/dwc2.txt
drivers/usb/chipidea/host.c
drivers/usb/dwc2/core.c
drivers/usb/dwc2/core.h
drivers/usb/dwc2/gadget.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/u_ether.c
drivers/usb/gadget/udc/atmel_usba_udc.c
drivers/usb/host/ehci-platform.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci.h
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/omap2430.c
drivers/usb/renesas_usbhs/rcar3.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/usb-serial.c
drivers/usb/wusbcore/crypto.c

index 455f2c3..2c30a54 100644 (file)
@@ -28,10 +28,7 @@ Refer to phy/phy-bindings.txt for generic phy consumer properties
 - g-use-dma: enable dma usage in gadget driver.
 - g-rx-fifo-size: size of rx fifo size in gadget mode.
 - g-np-tx-fifo-size: size of non-periodic tx fifo size in gadget mode.
-
-Deprecated properties:
-- g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0)
-  in gadget mode.
+- g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0) in gadget mode.
 
 Example:
 
index 96ae695..111b0e0 100644 (file)
@@ -188,6 +188,8 @@ static void host_stop(struct ci_hdrc *ci)
 
        if (hcd) {
                usb_remove_hcd(hcd);
+               ci->role = CI_ROLE_END;
+               synchronize_irq(ci->irq);
                usb_put_hcd(hcd);
                if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci) &&
                        (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON))
index fa9b26b..4c0fa0b 100644 (file)
@@ -463,9 +463,18 @@ static void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg)
  */
 void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg)
 {
+       bool ret;
+
        switch (hsotg->dr_mode) {
        case USB_DR_MODE_HOST:
-               dwc2_force_mode(hsotg, true);
+               ret = dwc2_force_mode(hsotg, true);
+               /*
+                * NOTE: This is required for some rockchip soc based
+                * platforms on their host-only dwc2.
+                */
+               if (!ret)
+                       msleep(50);
+
                break;
        case USB_DR_MODE_PERIPHERAL:
                dwc2_force_mode(hsotg, false);
index aad4107..2a21a04 100644 (file)
@@ -259,6 +259,13 @@ enum dwc2_lx_state {
        DWC2_L3,        /* Off state */
 };
 
+/*
+ * Gadget periodic tx fifo sizes as used by legacy driver
+ * EP0 is not included
+ */
+#define DWC2_G_P_LEGACY_TX_FIFO_SIZE {256, 256, 256, 256, 768, 768, 768, \
+                                          768, 0, 0, 0, 0, 0, 0, 0}
+
 /* Gadget ep0 states */
 enum dwc2_ep0_state {
        DWC2_EP0_SETUP,
index 4cd6403..24fbebc 100644 (file)
@@ -186,10 +186,9 @@ static void dwc2_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg,
  */
 static void dwc2_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
 {
-       unsigned int fifo;
+       unsigned int ep;
        unsigned int addr;
        int timeout;
-       u32 dptxfsizn;
        u32 val;
 
        /* Reset fifo map if not correctly cleared during previous session */
@@ -217,16 +216,16 @@ static void dwc2_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
         * them to endpoints dynamically according to maxpacket size value of
         * given endpoint.
         */
-       for (fifo = 1; fifo < MAX_EPS_CHANNELS; fifo++) {
-               dptxfsizn = dwc2_readl(hsotg->regs + DPTXFSIZN(fifo));
-
-               val = (dptxfsizn & FIFOSIZE_DEPTH_MASK) | addr;
-               addr += dptxfsizn >> FIFOSIZE_DEPTH_SHIFT;
-
-               if (addr > hsotg->fifo_mem)
-                       break;
+       for (ep = 1; ep < MAX_EPS_CHANNELS; ep++) {
+               if (!hsotg->g_tx_fifo_sz[ep])
+                       continue;
+               val = addr;
+               val |= hsotg->g_tx_fifo_sz[ep] << FIFOSIZE_DEPTH_SHIFT;
+               WARN_ONCE(addr + hsotg->g_tx_fifo_sz[ep] > hsotg->fifo_mem,
+                         "insufficient fifo memory");
+               addr += hsotg->g_tx_fifo_sz[ep];
 
-               dwc2_writel(val, hsotg->regs + DPTXFSIZN(fifo));
+               dwc2_writel(val, hsotg->regs + DPTXFSIZN(ep));
        }
 
        /*
@@ -3807,10 +3806,36 @@ static void dwc2_hsotg_dump(struct dwc2_hsotg *hsotg)
 static void dwc2_hsotg_of_probe(struct dwc2_hsotg *hsotg)
 {
        struct device_node *np = hsotg->dev->of_node;
+       u32 len = 0;
+       u32 i = 0;
 
        /* Enable dma if requested in device tree */
        hsotg->g_using_dma = of_property_read_bool(np, "g-use-dma");
 
+       /*
+       * Register TX periodic fifo size per endpoint.
+       * EP0 is excluded since it has no fifo configuration.
+       */
+       if (!of_find_property(np, "g-tx-fifo-size", &len))
+               goto rx_fifo;
+
+       len /= sizeof(u32);
+
+       /* Read tx fifo sizes other than ep0 */
+       if (of_property_read_u32_array(np, "g-tx-fifo-size",
+                                               &hsotg->g_tx_fifo_sz[1], len))
+               goto rx_fifo;
+
+       /* Add ep0 */
+       len++;
+
+       /* Make remaining TX fifos unavailable */
+       if (len < MAX_EPS_CHANNELS) {
+               for (i = len; i < MAX_EPS_CHANNELS; i++)
+                       hsotg->g_tx_fifo_sz[i] = 0;
+       }
+
+rx_fifo:
        /* Register RX fifo size */
        of_property_read_u32(np, "g-rx-fifo-size", &hsotg->g_rx_fifo_sz);
 
@@ -3832,10 +3857,13 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
        struct device *dev = hsotg->dev;
        int epnum;
        int ret;
+       int i;
+       u32 p_tx_fifo[] = DWC2_G_P_LEGACY_TX_FIFO_SIZE;
 
        /* Initialize to legacy fifo configuration values */
        hsotg->g_rx_fifo_sz = 2048;
        hsotg->g_np_g_tx_fifo_sz = 1024;
+       memcpy(&hsotg->g_tx_fifo_sz[1], p_tx_fifo, sizeof(p_tx_fifo));
        /* Device tree specific probe */
        dwc2_hsotg_of_probe(hsotg);
 
@@ -3853,6 +3881,9 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
        dev_dbg(dev, "NonPeriodic TXFIFO size: %d\n",
                                                hsotg->g_np_g_tx_fifo_sz);
        dev_dbg(dev, "RXFIFO size: %d\n", hsotg->g_rx_fifo_sz);
+       for (i = 0; i < MAX_EPS_CHANNELS; i++)
+               dev_dbg(dev, "Periodic TXFIFO%2d size: %d\n", i,
+                                               hsotg->g_tx_fifo_sz[i]);
 
        hsotg->gadget.max_speed = USB_SPEED_HIGH;
        hsotg->gadget.ops = &dwc2_hsotg_gadget_ops;
index 07cc892..1dfa56a 100644 (file)
@@ -783,6 +783,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
                req->trb = trb;
                req->trb_dma = dwc3_trb_dma_offset(dep, trb);
                req->first_trb_index = dep->trb_enqueue;
+               dep->queued_requests++;
        }
 
        dwc3_ep_inc_enq(dep);
@@ -833,8 +834,6 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
 
        trb->ctrl |= DWC3_TRB_CTRL_HWO;
 
-       dep->queued_requests++;
-
        trace_dwc3_prepare_trb(dep, trb);
 }
 
@@ -1074,9 +1073,17 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 
        list_add_tail(&req->list, &dep->pending_list);
 
-       if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
-                       dep->flags & DWC3_EP_PENDING_REQUEST) {
-               if (list_empty(&dep->started_list)) {
+       /*
+        * NOTICE: Isochronous endpoints should NEVER be prestarted. We must
+        * wait for a XferNotReady event so we will know what's the current
+        * (micro-)frame number.
+        *
+        * Without this trick, we are very, very likely gonna get Bus Expiry
+        * errors which will force us issue EndTransfer command.
+        */
+       if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
+               if ((dep->flags & DWC3_EP_PENDING_REQUEST) &&
+                               list_empty(&dep->started_list)) {
                        dwc3_stop_active_transfer(dwc, dep->number, true);
                        dep->flags = DWC3_EP_ENABLED;
                }
@@ -1861,8 +1868,11 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
        unsigned int            s_pkt = 0;
        unsigned int            trb_status;
 
-       dep->queued_requests--;
        dwc3_ep_inc_deq(dep);
+
+       if (req->trb == trb)
+               dep->queued_requests--;
+
        trace_dwc3_complete_trb(dep, trb);
 
        /*
@@ -2980,7 +2990,7 @@ err3:
        kfree(dwc->setup_buf);
 
 err2:
-       dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
+       dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb) * 2,
                        dwc->ep0_trb, dwc->ep0_trb_addr);
 
 err1:
@@ -3005,7 +3015,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
        kfree(dwc->setup_buf);
        kfree(dwc->zlp_buf);
 
-       dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
+       dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb) * 2,
                        dwc->ep0_trb, dwc->ep0_trb_addr);
 
        dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
index 54ad100..e40d47d 100644 (file)
@@ -136,8 +136,60 @@ struct ffs_epfile {
        /*
         * Buffer for holding data from partial reads which may happen since
         * we’re rounding user read requests to a multiple of a max packet size.
+        *
+        * The pointer is initialised with NULL value and may be set by
+        * __ffs_epfile_read_data function to point to a temporary buffer.
+        *
+        * In normal operation, calls to __ffs_epfile_read_buffered will consume
+        * data from said buffer and eventually free it.  Importantly, while the
+        * function is using the buffer, it sets the pointer to NULL.  This is
+        * all right since __ffs_epfile_read_data and __ffs_epfile_read_buffered
+        * can never run concurrently (they are synchronised by epfile->mutex)
+        * so the latter will not assign a new value to the pointer.
+        *
+        * Meanwhile ffs_func_eps_disable frees the buffer (if the pointer is
+        * valid) and sets the pointer to READ_BUFFER_DROP value.  This special
+        * value is crux of the synchronisation between ffs_func_eps_disable and
+        * __ffs_epfile_read_data.
+        *
+        * Once __ffs_epfile_read_data is about to finish it will try to set the
+        * pointer back to its old value (as described above), but seeing as the
+        * pointer is not-NULL (namely READ_BUFFER_DROP) it will instead free
+        * the buffer.
+        *
+        * == State transitions ==
+        *
+        * â€¢ ptr == NULL:  (initial state)
+        *   â—¦ __ffs_epfile_read_buffer_free: go to ptr == DROP
+        *   â—¦ __ffs_epfile_read_buffered:    nop
+        *   â—¦ __ffs_epfile_read_data allocates temp buffer: go to ptr == buf
+        *   â—¦ reading finishes:              n/a, not in â€˜and reading’ state
+        * â€¢ ptr == DROP:
+        *   â—¦ __ffs_epfile_read_buffer_free: nop
+        *   â—¦ __ffs_epfile_read_buffered:    go to ptr == NULL
+        *   â—¦ __ffs_epfile_read_data allocates temp buffer: free buf, nop
+        *   â—¦ reading finishes:              n/a, not in â€˜and reading’ state
+        * â€¢ ptr == buf:
+        *   â—¦ __ffs_epfile_read_buffer_free: free buf, go to ptr == DROP
+        *   â—¦ __ffs_epfile_read_buffered:    go to ptr == NULL and reading
+        *   â—¦ __ffs_epfile_read_data:        n/a, __ffs_epfile_read_buffered
+        *                                    is always called first
+        *   â—¦ reading finishes:              n/a, not in â€˜and reading’ state
+        * â€¢ ptr == NULL and reading:
+        *   â—¦ __ffs_epfile_read_buffer_free: go to ptr == DROP and reading
+        *   â—¦ __ffs_epfile_read_buffered:    n/a, mutex is held
+        *   â—¦ __ffs_epfile_read_data:        n/a, mutex is held
+        *   â—¦ reading finishes and â€¦
+        *     â€¦ all data read:               free buf, go to ptr == NULL
+        *     â€¦ otherwise:                   go to ptr == buf and reading
+        * â€¢ ptr == DROP and reading:
+        *   â—¦ __ffs_epfile_read_buffer_free: nop
+        *   â—¦ __ffs_epfile_read_buffered:    n/a, mutex is held
+        *   â—¦ __ffs_epfile_read_data:        n/a, mutex is held
+        *   â—¦ reading finishes:              free buf, go to ptr == DROP
         */
-       struct ffs_buffer               *read_buffer;   /* P: epfile->mutex */
+       struct ffs_buffer               *read_buffer;
+#define READ_BUFFER_DROP ((struct ffs_buffer *)ERR_PTR(-ESHUTDOWN))
 
        char                            name[5];
 
@@ -736,25 +788,47 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
        schedule_work(&io_data->work);
 }
 
+static void __ffs_epfile_read_buffer_free(struct ffs_epfile *epfile)
+{
+       /*
+        * See comment in struct ffs_epfile for full read_buffer pointer
+        * synchronisation story.
+        */
+       struct ffs_buffer *buf = xchg(&epfile->read_buffer, READ_BUFFER_DROP);
+       if (buf && buf != READ_BUFFER_DROP)
+               kfree(buf);
+}
+
 /* Assumes epfile->mutex is held. */
 static ssize_t __ffs_epfile_read_buffered(struct ffs_epfile *epfile,
                                          struct iov_iter *iter)
 {
-       struct ffs_buffer *buf = epfile->read_buffer;
+       /*
+        * Null out epfile->read_buffer so ffs_func_eps_disable does not free
+        * the buffer while we are using it.  See comment in struct ffs_epfile
+        * for full read_buffer pointer synchronisation story.
+        */
+       struct ffs_buffer *buf = xchg(&epfile->read_buffer, NULL);
        ssize_t ret;
-       if (!buf)
+       if (!buf || buf == READ_BUFFER_DROP)
                return 0;
 
        ret = copy_to_iter(buf->data, buf->length, iter);
        if (buf->length == ret) {
                kfree(buf);
-               epfile->read_buffer = NULL;
-       } else if (unlikely(iov_iter_count(iter))) {
+               return ret;
+       }
+
+       if (unlikely(iov_iter_count(iter))) {
                ret = -EFAULT;
        } else {
                buf->length -= ret;
                buf->data += ret;
        }
+
+       if (cmpxchg(&epfile->read_buffer, NULL, buf))
+               kfree(buf);
+
        return ret;
 }
 
@@ -783,7 +857,15 @@ static ssize_t __ffs_epfile_read_data(struct ffs_epfile *epfile,
        buf->length = data_len;
        buf->data = buf->storage;
        memcpy(buf->storage, data + ret, data_len);
-       epfile->read_buffer = buf;
+
+       /*
+        * At this point read_buffer is NULL or READ_BUFFER_DROP (if
+        * ffs_func_eps_disable has been called in the meanwhile).  See comment
+        * in struct ffs_epfile for full read_buffer pointer synchronisation
+        * story.
+        */
+       if (unlikely(cmpxchg(&epfile->read_buffer, NULL, buf)))
+               kfree(buf);
 
        return ret;
 }
@@ -1097,8 +1179,7 @@ ffs_epfile_release(struct inode *inode, struct file *file)
 
        ENTER();
 
-       kfree(epfile->read_buffer);
-       epfile->read_buffer = NULL;
+       __ffs_epfile_read_buffer_free(epfile);
        ffs_data_closed(epfile->ffs);
 
        return 0;
@@ -1724,24 +1805,20 @@ static void ffs_func_eps_disable(struct ffs_function *func)
        unsigned count            = func->ffs->eps_count;
        unsigned long flags;
 
+       spin_lock_irqsave(&func->ffs->eps_lock, flags);
        do {
-               if (epfile)
-                       mutex_lock(&epfile->mutex);
-               spin_lock_irqsave(&func->ffs->eps_lock, flags);
                /* pending requests get nuked */
                if (likely(ep->ep))
                        usb_ep_disable(ep->ep);
                ++ep;
-               spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
 
                if (epfile) {
                        epfile->ep = NULL;
-                       kfree(epfile->read_buffer);
-                       epfile->read_buffer = NULL;
-                       mutex_unlock(&epfile->mutex);
+                       __ffs_epfile_read_buffer_free(epfile);
                        ++epfile;
                }
        } while (--count);
+       spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
 }
 
 static int ffs_func_eps_enable(struct ffs_function *func)
index 9c8c9ed..fe18116 100644 (file)
@@ -590,8 +590,9 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
 
        /* throttle high/super speed IRQ rate back slightly */
        if (gadget_is_dualspeed(dev->gadget))
-               req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH ||
-                                    dev->gadget->speed == USB_SPEED_SUPER)
+               req->no_interrupt = (((dev->gadget->speed == USB_SPEED_HIGH ||
+                                      dev->gadget->speed == USB_SPEED_SUPER)) &&
+                                       !list_empty(&dev->tx_reqs))
                        ? ((atomic_read(&dev->tx_qlen) % dev->qmult) != 0)
                        : 0;
 
index bb1f6c8..45bc997 100644 (file)
@@ -1978,7 +1978,7 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
                        dev_err(&pdev->dev, "of_probe: name error(%d)\n", ret);
                        goto err;
                }
-               ep->ep.name = name;
+               ep->ep.name = kasprintf(GFP_KERNEL, "ep%d", ep->index);
 
                ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
                ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
index 876dca4..a268d9e 100644 (file)
@@ -39,7 +39,7 @@
 
 #define DRIVER_DESC "EHCI generic platform driver"
 #define EHCI_MAX_CLKS 4
-#define EHCI_MAX_RSTS 3
+#define EHCI_MAX_RSTS 4
 #define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv)
 
 struct ehci_platform_priv {
index 5b5880c..b38a228 100644 (file)
@@ -221,6 +221,12 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
        ohci->num_ports = board->ports;
        at91_start_hc(pdev);
 
+       /*
+        * The RemoteWakeupConnected bit has to be set explicitly
+        * before calling ohci_run. The reset value of this bit is 0.
+        */
+       ohci->hc_control = OHCI_CTRL_RWC;
+
        retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (retval == 0) {
                device_wakeup_enable(hcd->self.controller);
@@ -677,9 +683,6 @@ ohci_hcd_at91_drv_suspend(struct device *dev)
         * REVISIT: some boards will be able to turn VBUS off...
         */
        if (!ohci_at91->wakeup) {
-               ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
-               ohci->hc_control &= OHCI_CTRL_RWC;
-               ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
                ohci->rh_state = OHCI_RH_HALTED;
 
                /* flush the writes */
index 1700908..86612ac 100644 (file)
@@ -72,7 +72,7 @@
 static const char      hcd_name [] = "ohci_hcd";
 
 #define        STATECHANGE_DELAY       msecs_to_jiffies(300)
-#define        IO_WATCHDOG_DELAY       msecs_to_jiffies(250)
+#define        IO_WATCHDOG_DELAY       msecs_to_jiffies(275)
 
 #include "ohci.h"
 #include "pci-quirks.h"
index 730b9fd..0ef1690 100644 (file)
@@ -1166,7 +1166,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                                xhci_set_link_state(xhci, port_array, wIndex,
                                                        XDEV_RESUME);
                                spin_unlock_irqrestore(&xhci->lock, flags);
-                               msleep(20);
+                               msleep(USB_RESUME_TIMEOUT);
                                spin_lock_irqsave(&xhci->lock, flags);
                                xhci_set_link_state(xhci, port_array, wIndex,
                                                        XDEV_U0);
@@ -1355,6 +1355,35 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
        return 0;
 }
 
+/*
+ * Workaround for missing Cold Attach Status (CAS) if device re-plugged in S3.
+ * warm reset a USB3 device stuck in polling or compliance mode after resume.
+ * See Intel 100/c230 series PCH specification update Doc #332692-006 Errata #8
+ */
+static bool xhci_port_missing_cas_quirk(int port_index,
+                                            __le32 __iomem **port_array)
+{
+       u32 portsc;
+
+       portsc = readl(port_array[port_index]);
+
+       /* if any of these are set we are not stuck */
+       if (portsc & (PORT_CONNECT | PORT_CAS))
+               return false;
+
+       if (((portsc & PORT_PLS_MASK) != XDEV_POLLING) &&
+           ((portsc & PORT_PLS_MASK) != XDEV_COMP_MODE))
+               return false;
+
+       /* clear wakeup/change bits, and do a warm port reset */
+       portsc &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS);
+       portsc |= PORT_WR;
+       writel(portsc, port_array[port_index]);
+       /* flush write */
+       readl(port_array[port_index]);
+       return true;
+}
+
 int xhci_bus_resume(struct usb_hcd *hcd)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
@@ -1392,6 +1421,14 @@ int xhci_bus_resume(struct usb_hcd *hcd)
                u32 temp;
 
                temp = readl(port_array[port_index]);
+
+               /* warm reset CAS limited ports stuck in polling/compliance */
+               if ((xhci->quirks & XHCI_MISSING_CAS) &&
+                   (hcd->speed >= HCD_USB3) &&
+                   xhci_port_missing_cas_quirk(port_index, port_array)) {
+                       xhci_dbg(xhci, "reset stuck port %d\n", port_index);
+                       continue;
+               }
                if (DEV_SUPERSPEED_ANY(temp))
                        temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS);
                else
@@ -1410,7 +1447,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
 
        if (need_usb2_u3_exit) {
                spin_unlock_irqrestore(&xhci->lock, flags);
-               msleep(20);
+               msleep(USB_RESUME_TIMEOUT);
                spin_lock_irqsave(&xhci->lock, flags);
        }
 
index d7b0f97..e96ae80 100644 (file)
 
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI     0x8c31
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI  0x9c31
+#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_XHCI       0x9cb1
 #define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI            0x22b5
 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI                0xa12f
 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI       0x9d2f
 #define PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI             0x0aa8
 #define PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI             0x1aa8
+#define PCI_DEVICE_ID_INTEL_APL_XHCI                   0x5aa8
 
 static const char hcd_name[] = "xhci_hcd";
 
@@ -153,7 +155,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                xhci->quirks |= XHCI_SPURIOUS_REBOOT;
        }
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
-               pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) {
+               (pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI ||
+                pdev->device == PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_XHCI)) {
                xhci->quirks |= XHCI_SPURIOUS_REBOOT;
                xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
        }
@@ -169,6 +172,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                 pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
                xhci->quirks |= XHCI_SSIC_PORT_UNUSED;
        }
+       if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+           (pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
+            pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI))
+               xhci->quirks |= XHCI_MISSING_CAS;
+
        if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
                        pdev->device == PCI_DEVICE_ID_EJ168) {
                xhci->quirks |= XHCI_RESET_ON_RESUME;
index b2c1dc5..f945380 100644 (file)
@@ -314,6 +314,8 @@ struct xhci_op_regs {
 #define XDEV_U2                (0x2 << 5)
 #define XDEV_U3                (0x3 << 5)
 #define XDEV_INACTIVE  (0x6 << 5)
+#define XDEV_POLLING   (0x7 << 5)
+#define XDEV_COMP_MODE  (0xa << 5)
 #define XDEV_RESUME    (0xf << 5)
 /* true: port has power (see HCC_PPC) */
 #define PORT_POWER     (1 << 9)
@@ -1653,6 +1655,7 @@ struct xhci_hcd {
 #define XHCI_MTK_HOST          (1 << 21)
 #define XHCI_SSIC_PORT_UNUSED  (1 << 22)
 #define XHCI_NO_64BIT_SUPPORT  (1 << 23)
+#define XHCI_MISSING_CAS       (1 << 24)
        unsigned int            num_active_eps;
        unsigned int            limit_active_eps;
        /* There are two roothubs to keep track of bus suspend info for */
index bff4869..4042ea0 100644 (file)
@@ -1255,6 +1255,7 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
 
        map_dma_buffer(request, musb, musb_ep);
 
+       pm_runtime_get_sync(musb->controller);
        spin_lock_irqsave(&musb->lock, lockflags);
 
        /* don't queue if the ep is down */
@@ -1275,6 +1276,9 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
 
 unlock:
        spin_unlock_irqrestore(&musb->lock, lockflags);
+       pm_runtime_mark_last_busy(musb->controller);
+       pm_runtime_put_autosuspend(musb->controller);
+
        return status;
 }
 
index 1ab6973..cc12254 100644 (file)
@@ -287,6 +287,7 @@ static int omap2430_musb_init(struct musb *musb)
        }
        musb->isr = omap2430_musb_interrupt;
        phy_init(musb->phy);
+       phy_power_on(musb->phy);
 
        l = musb_readl(musb->mregs, OTG_INTERFSEL);
 
@@ -323,8 +324,6 @@ static void omap2430_musb_enable(struct musb *musb)
        struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev);
        struct omap_musb_board_data *data = pdata->board_data;
 
-       if (!WARN_ON(!musb->phy))
-               phy_power_on(musb->phy);
 
        switch (glue->status) {
 
@@ -361,9 +360,6 @@ static void omap2430_musb_disable(struct musb *musb)
        struct device *dev = musb->controller;
        struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 
-       if (!WARN_ON(!musb->phy))
-               phy_power_off(musb->phy);
-
        if (glue->status != MUSB_UNKNOWN)
                omap_control_usb_set_mode(glue->control_otghs,
                        USB_MODE_DISCONNECT);
@@ -375,6 +371,7 @@ static int omap2430_musb_exit(struct musb *musb)
        struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 
        omap2430_low_level_exit(musb);
+       phy_power_off(musb->phy);
        phy_exit(musb->phy);
        musb->phy = NULL;
        cancel_work_sync(&glue->omap_musb_mailbox_work);
index 1d70add..d544b33 100644 (file)
@@ -9,6 +9,7 @@
  *
  */
 
+#include <linux/delay.h>
 #include <linux/io.h>
 #include "common.h"
 #include "rcar3.h"
@@ -35,10 +36,13 @@ static int usbhs_rcar3_power_ctrl(struct platform_device *pdev,
 
        usbhs_write32(priv, UGCTRL2, UGCTRL2_RESERVED_3 | UGCTRL2_USB0SEL_OTG);
 
-       if (enable)
+       if (enable) {
                usbhs_bset(priv, LPSTS, LPSTS_SUSPM, LPSTS_SUSPM);
-       else
+               /* The controller on R-Car Gen3 needs to wait up to 45 usec */
+               udelay(45);
+       } else {
                usbhs_bset(priv, LPSTS, LPSTS_SUSPM, 0);
+       }
 
        return 0;
 }
index 54a4de0..f61477b 100644 (file)
@@ -1077,7 +1077,9 @@ static int cp210x_tiocmget(struct tty_struct *tty)
        u8 control;
        int result;
 
-       cp210x_read_u8_reg(port, CP210X_GET_MDMSTS, &control);
+       result = cp210x_read_u8_reg(port, CP210X_GET_MDMSTS, &control);
+       if (result)
+               return result;
 
        result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0)
                |((control & CONTROL_RTS) ? TIOCM_RTS : 0)
index b2d767e..0ff7f38 100644 (file)
@@ -986,7 +986,8 @@ static const struct usb_device_id id_table_combined[] = {
        /* ekey Devices */
        { USB_DEVICE(FTDI_VID, FTDI_EKEY_CONV_USB_PID) },
        /* Infineon Devices */
-       { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) },
+       { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_TC1798_PID, 1) },
+       { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_TC2X7_PID, 1) },
        /* GE Healthcare devices */
        { USB_DEVICE(GE_HEALTHCARE_VID, GE_HEALTHCARE_NEMO_TRACKER_PID) },
        /* Active Research (Actisense) devices */
index f87a938..21011c0 100644 (file)
 /*
  * Infineon Technologies
  */
-#define INFINEON_VID           0x058b
-#define INFINEON_TRIBOARD_PID  0x0028 /* DAS JTAG TriBoard TC1798 V1.0 */
+#define INFINEON_VID                   0x058b
+#define INFINEON_TRIBOARD_TC1798_PID   0x0028 /* DAS JTAG TriBoard TC1798 V1.0 */
+#define INFINEON_TRIBOARD_TC2X7_PID    0x0043 /* DAS JTAG TriBoard TC2X7 V1.0 */
 
 /*
  * Acton Research Corp.
index d213cf4..4a037b4 100644 (file)
@@ -1078,7 +1078,8 @@ static int usb_serial_probe(struct usb_interface *interface,
 
        serial->disconnected = 0;
 
-       usb_serial_console_init(serial->port[0]->minor);
+       if (num_ports > 0)
+               usb_serial_console_init(serial->port[0]->minor);
 exit:
        module_put(type->driver.owner);
        return 0;
index 79b2b62..79451f7 100644 (file)
@@ -133,6 +133,13 @@ static void bytewise_xor(void *_bo, const void *_bi1, const void *_bi2,
                bo[itr] = bi1[itr] ^ bi2[itr];
 }
 
+/* Scratch space for MAC calculations. */
+struct wusb_mac_scratch {
+       struct aes_ccm_b0 b0;
+       struct aes_ccm_b1 b1;
+       struct aes_ccm_a ax;
+};
+
 /*
  * CC-MAC function WUSB1.0[6.5]
  *
@@ -197,16 +204,15 @@ static void bytewise_xor(void *_bo, const void *_bi1, const void *_bi2,
  *       what sg[4] is for. Maybe there is a smarter way to do this.
  */
 static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
-                       struct crypto_cipher *tfm_aes, void *mic,
+                       struct crypto_cipher *tfm_aes,
+                       struct wusb_mac_scratch *scratch,
+                       void *mic,
                        const struct aes_ccm_nonce *n,
                        const struct aes_ccm_label *a, const void *b,
                        size_t blen)
 {
        int result = 0;
        SKCIPHER_REQUEST_ON_STACK(req, tfm_cbc);
-       struct aes_ccm_b0 b0;
-       struct aes_ccm_b1 b1;
-       struct aes_ccm_a ax;
        struct scatterlist sg[4], sg_dst;
        void *dst_buf;
        size_t dst_size;
@@ -218,16 +224,17 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
         * These checks should be compile time optimized out
         * ensure @a fills b1's mac_header and following fields
         */
-       WARN_ON(sizeof(*a) != sizeof(b1) - sizeof(b1.la));
-       WARN_ON(sizeof(b0) != sizeof(struct aes_ccm_block));
-       WARN_ON(sizeof(b1) != sizeof(struct aes_ccm_block));
-       WARN_ON(sizeof(ax) != sizeof(struct aes_ccm_block));
+       WARN_ON(sizeof(*a) != sizeof(scratch->b1) - sizeof(scratch->b1.la));
+       WARN_ON(sizeof(scratch->b0) != sizeof(struct aes_ccm_block));
+       WARN_ON(sizeof(scratch->b1) != sizeof(struct aes_ccm_block));
+       WARN_ON(sizeof(scratch->ax) != sizeof(struct aes_ccm_block));
 
        result = -ENOMEM;
        zero_padding = blen % sizeof(struct aes_ccm_block);
        if (zero_padding)
                zero_padding = sizeof(struct aes_ccm_block) - zero_padding;
-       dst_size = blen + sizeof(b0) + sizeof(b1) + zero_padding;
+       dst_size = blen + sizeof(scratch->b0) + sizeof(scratch->b1) +
+               zero_padding;
        dst_buf = kzalloc(dst_size, GFP_KERNEL);
        if (!dst_buf)
                goto error_dst_buf;
@@ -235,9 +242,9 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
        memset(iv, 0, sizeof(iv));
 
        /* Setup B0 */
-       b0.flags = 0x59;        /* Format B0 */
-       b0.ccm_nonce = *n;
-       b0.lm = cpu_to_be16(0); /* WUSB1.0[6.5] sez l(m) is 0 */
+       scratch->b0.flags = 0x59;       /* Format B0 */
+       scratch->b0.ccm_nonce = *n;
+       scratch->b0.lm = cpu_to_be16(0);        /* WUSB1.0[6.5] sez l(m) is 0 */
 
        /* Setup B1
         *
@@ -246,12 +253,12 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
         * 14'--after clarification, it means to use A's contents
         * for MAC Header, EO, sec reserved and padding.
         */
-       b1.la = cpu_to_be16(blen + 14);
-       memcpy(&b1.mac_header, a, sizeof(*a));
+       scratch->b1.la = cpu_to_be16(blen + 14);
+       memcpy(&scratch->b1.mac_header, a, sizeof(*a));
 
        sg_init_table(sg, ARRAY_SIZE(sg));
-       sg_set_buf(&sg[0], &b0, sizeof(b0));
-       sg_set_buf(&sg[1], &b1, sizeof(b1));
+       sg_set_buf(&sg[0], &scratch->b0, sizeof(scratch->b0));
+       sg_set_buf(&sg[1], &scratch->b1, sizeof(scratch->b1));
        sg_set_buf(&sg[2], b, blen);
        /* 0 if well behaved :) */
        sg_set_buf(&sg[3], bzero, zero_padding);
@@ -276,11 +283,12 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
         * POS Crypto API: size is assumed to be AES's block size.
         * Thanks for documenting it -- tip taken from airo.c
         */
-       ax.flags = 0x01;                /* as per WUSB 1.0 spec */
-       ax.ccm_nonce = *n;
-       ax.counter = 0;
-       crypto_cipher_encrypt_one(tfm_aes, (void *)&ax, (void *)&ax);
-       bytewise_xor(mic, &ax, iv, 8);
+       scratch->ax.flags = 0x01;               /* as per WUSB 1.0 spec */
+       scratch->ax.ccm_nonce = *n;
+       scratch->ax.counter = 0;
+       crypto_cipher_encrypt_one(tfm_aes, (void *)&scratch->ax,
+                                 (void *)&scratch->ax);
+       bytewise_xor(mic, &scratch->ax, iv, 8);
        result = 8;
 error_cbc_crypt:
        kfree(dst_buf);
@@ -303,6 +311,7 @@ ssize_t wusb_prf(void *out, size_t out_size,
        struct aes_ccm_nonce n = *_n;
        struct crypto_skcipher *tfm_cbc;
        struct crypto_cipher *tfm_aes;
+       struct wusb_mac_scratch *scratch;
        u64 sfn = 0;
        __le64 sfn_le;
 
@@ -329,17 +338,25 @@ ssize_t wusb_prf(void *out, size_t out_size,
                printk(KERN_ERR "E: can't set AES key: %d\n", (int)result);
                goto error_setkey_aes;
        }
+       scratch = kmalloc(sizeof(*scratch), GFP_KERNEL);
+       if (!scratch) {
+               result = -ENOMEM;
+               goto error_alloc_scratch;
+       }
 
        for (bitr = 0; bitr < (len + 63) / 64; bitr++) {
                sfn_le = cpu_to_le64(sfn++);
                memcpy(&n.sfn, &sfn_le, sizeof(n.sfn)); /* n.sfn++... */
-               result = wusb_ccm_mac(tfm_cbc, tfm_aes, out + bytes,
+               result = wusb_ccm_mac(tfm_cbc, tfm_aes, scratch, out + bytes,
                                      &n, a, b, blen);
                if (result < 0)
                        goto error_ccm_mac;
                bytes += result;
        }
        result = bytes;
+
+       kfree(scratch);
+error_alloc_scratch:
 error_ccm_mac:
 error_setkey_aes:
        crypto_free_cipher(tfm_aes);