Merge remote-tracking branch 'usb-gadget/next'
authorStephen Rothwell <sfr@canb.auug.org.au>
Tue, 13 Sep 2016 02:42:48 +0000 (12:42 +1000)
committerStephen Rothwell <sfr@canb.auug.org.au>
Tue, 13 Sep 2016 02:42:48 +0000 (12:42 +1000)
1  2 
drivers/usb/common/ulpi.c
drivers/usb/dwc2/core.h
drivers/usb/dwc3/core.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/udc/core.c
drivers/usb/phy/phy-generic.c
drivers/usb/renesas_usbhs/mod_gadget.c
include/linux/ulpi/driver.h

index e04a34e7a341d64af2262cf0dd436875794ac09a,d4ff6df859eb3956fd8840541619d6b87157c173..8b317702d7610d3dae663df4f1fc0feff87c36f6
  
  int ulpi_read(struct ulpi *ulpi, u8 addr)
  {
-       return ulpi->ops->read(ulpi->ops, addr);
+       return ulpi->ops->read(ulpi->dev.parent, addr);
  }
  EXPORT_SYMBOL_GPL(ulpi_read);
  
  int ulpi_write(struct ulpi *ulpi, u8 addr, u8 val)
  {
-       return ulpi->ops->write(ulpi->ops, addr, val);
+       return ulpi->ops->write(ulpi->dev.parent, addr, val);
  }
  EXPORT_SYMBOL_GPL(ulpi_write);
  
@@@ -127,17 -127,16 +127,17 @@@ static struct device_type ulpi_dev_typ
   *
   * Registers a driver with the ULPI bus.
   */
 -int ulpi_register_driver(struct ulpi_driver *drv)
 +int __ulpi_register_driver(struct ulpi_driver *drv, struct module *module)
  {
        if (!drv->probe)
                return -EINVAL;
  
 +      drv->driver.owner = module;
        drv->driver.bus = &ulpi_bus;
  
        return driver_register(&drv->driver);
  }
 -EXPORT_SYMBOL_GPL(ulpi_register_driver);
 +EXPORT_SYMBOL_GPL(__ulpi_register_driver);
  
  /**
   * ulpi_unregister_driver - unregister a driver with the ULPI bus
@@@ -157,6 -156,8 +157,8 @@@ static int ulpi_register(struct device 
  {
        int ret;
  
+       ulpi->dev.parent = dev; /* needed early for ops */
        /* Test the interface */
        ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa);
        if (ret < 0)
        ulpi->id.product = ulpi_read(ulpi, ULPI_PRODUCT_ID_LOW);
        ulpi->id.product |= ulpi_read(ulpi, ULPI_PRODUCT_ID_HIGH) << 8;
  
-       ulpi->dev.parent = dev;
        ulpi->dev.bus = &ulpi_bus;
        ulpi->dev.type = &ulpi_dev_type;
        dev_set_name(&ulpi->dev, "%s.ulpi", dev_name(dev));
   * Allocates and registers a ULPI device and an interface for it. Called from
   * the USB controller that provides the ULPI interface.
   */
- struct ulpi *ulpi_register_interface(struct device *dev, struct ulpi_ops *ops)
+ struct ulpi *ulpi_register_interface(struct device *dev,
+                                    const struct ulpi_ops *ops)
  {
        struct ulpi *ulpi;
        int ret;
                return ERR_PTR(-ENOMEM);
  
        ulpi->ops = ops;
-       ops->dev = dev;
  
        ret = ulpi_register(dev, ulpi);
        if (ret) {
diff --combined drivers/usb/dwc2/core.h
index d64551243789a2a1cd2ea045df62d8407a8fbde1,466c220914d4d063d3347db4188686db2b919c43..aad4107ef927e26388f302ebbbd7907ad9a295c0
@@@ -259,13 -259,6 +259,6 @@@ 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,
@@@ -868,7 -861,6 +861,7 @@@ struct dwc2_hsotg 
        void *priv;
        int     irq;
        struct clk *clk;
 +      struct reset_control *reset;
  
        unsigned int queuing_high_bandwidth:1;
        unsigned int srp_success:1;
  #define DWC2_CORE_REV_2_92a   0x4f54292a
  #define DWC2_CORE_REV_2_94a   0x4f54294a
  #define DWC2_CORE_REV_3_00a   0x4f54300a
+ #define DWC2_CORE_REV_3_10a   0x4f54310a
  
  #if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
        union dwc2_hcd_internal_flags {
diff --combined drivers/usb/dwc3/core.c
index 35d092456bec1da828ea41476e421d47809380a5,dcacc7056271985c454d03f32ba6a153254d7280..7287a763cd0cc4ca5a114ed687e6c34b0bdd643d
  
  #define DWC3_DEFAULT_AUTOSUSPEND_DELAY        5000 /* ms */
  
+ /**
+  * dwc3_get_dr_mode - Validates and sets dr_mode
+  * @dwc: pointer to our context structure
+  */
+ static int dwc3_get_dr_mode(struct dwc3 *dwc)
+ {
+       enum usb_dr_mode mode;
+       struct device *dev = dwc->dev;
+       unsigned int hw_mode;
+       if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
+               dwc->dr_mode = USB_DR_MODE_OTG;
+       mode = dwc->dr_mode;
+       hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
+       switch (hw_mode) {
+       case DWC3_GHWPARAMS0_MODE_GADGET:
+               if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) {
+                       dev_err(dev,
+                               "Controller does not support host mode.\n");
+                       return -EINVAL;
+               }
+               mode = USB_DR_MODE_PERIPHERAL;
+               break;
+       case DWC3_GHWPARAMS0_MODE_HOST:
+               if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) {
+                       dev_err(dev,
+                               "Controller does not support device mode.\n");
+                       return -EINVAL;
+               }
+               mode = USB_DR_MODE_HOST;
+               break;
+       default:
+               if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
+                       mode = USB_DR_MODE_HOST;
+               else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
+                       mode = USB_DR_MODE_PERIPHERAL;
+       }
+       if (mode != dwc->dr_mode) {
+               dev_warn(dev,
+                        "Configuration mismatch. dr_mode forced to %s\n",
+                        mode == USB_DR_MODE_HOST ? "host" : "gadget");
+               dwc->dr_mode = mode;
+       }
+       return 0;
+ }
  void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
  {
        u32 reg;
@@@ -448,6 -499,9 +499,9 @@@ static int dwc3_phy_setup(struct dwc3 *
        if (dwc->dis_u3_susphy_quirk)
                reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
  
+       if (dwc->dis_del_phy_power_chg_quirk)
+               reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE;
        dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
  
        reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
                break;
        }
  
+       switch (dwc->hsphy_mode) {
+       case USBPHY_INTERFACE_MODE_UTMI:
+               reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
+                      DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
+               reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) |
+                      DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT);
+               break;
+       case USBPHY_INTERFACE_MODE_UTMIW:
+               reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
+                      DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
+               reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT) |
+                      DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT);
+               break;
+       default:
+               break;
+       }
        /*
         * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to
         * '0' during coreConsultant configuration. So default value will
        if (dwc->dis_enblslpm_quirk)
                reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
  
+       if (dwc->dis_u2_freeclk_exists_quirk)
+               reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS;
        dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
  
        return 0;
@@@ -666,6 -740,32 +740,32 @@@ static int dwc3_core_init(struct dwc3 *
                goto err4;
        }
  
+       switch (dwc->dr_mode) {
+       case USB_DR_MODE_PERIPHERAL:
+               dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
+               break;
+       case USB_DR_MODE_HOST:
+               dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
+               break;
+       case USB_DR_MODE_OTG:
+               dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
+               break;
+       default:
+               dev_warn(dwc->dev, "Unsupported mode %d\n", dwc->dr_mode);
+               break;
+       }
+       /*
+        * ENDXFER polling is available on version 3.10a and later of
+        * the DWC_usb3 controller. It is NOT available in the
+        * DWC_usb31 controller.
+        */
+       if (!dwc3_is_usb31(dwc) && dwc->revision >= DWC3_REVISION_310A) {
+               reg = dwc3_readl(dwc->regs, DWC3_GUCTL2);
+               reg |= DWC3_GUCTL2_RST_ACTBITLATER;
+               dwc3_writel(dwc->regs, DWC3_GUCTL2, reg);
+       }
        return 0;
  
  err4:
@@@ -763,7 -863,6 +863,6 @@@ static int dwc3_core_init_mode(struct d
  
        switch (dwc->dr_mode) {
        case USB_DR_MODE_PERIPHERAL:
-               dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
                ret = dwc3_gadget_init(dwc);
                if (ret) {
                        if (ret != -EPROBE_DEFER)
                }
                break;
        case USB_DR_MODE_HOST:
-               dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
                ret = dwc3_host_init(dwc);
                if (ret) {
                        if (ret != -EPROBE_DEFER)
                }
                break;
        case USB_DR_MODE_OTG:
-               dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
                ret = dwc3_host_init(dwc);
                if (ret) {
                        if (ret != -EPROBE_DEFER)
@@@ -888,6 -985,7 +985,7 @@@ static int dwc3_probe(struct platform_d
  
        dwc->maximum_speed = usb_get_maximum_speed(dev);
        dwc->dr_mode = usb_get_dr_mode(dev);
+       dwc->hsphy_mode = of_usb_get_phy_mode(dev->of_node);
  
        dwc->has_lpm_erratum = device_property_read_bool(dev,
                                "snps,has-lpm-erratum");
                                "snps,dis_enblslpm_quirk");
        dwc->dis_rxdet_inp3_quirk = device_property_read_bool(dev,
                                "snps,dis_rxdet_inp3_quirk");
+       dwc->dis_u2_freeclk_exists_quirk = device_property_read_bool(dev,
+                               "snps,dis-u2-freeclk-exists-quirk");
+       dwc->dis_del_phy_power_chg_quirk = device_property_read_bool(dev,
+                               "snps,dis-del-phy-power-chg-quirk");
  
        dwc->tx_de_emphasis_quirk = device_property_read_bool(dev,
                                "snps,tx_de_emphasis_quirk");
                goto err2;
        }
  
-       if (IS_ENABLED(CONFIG_USB_DWC3_HOST) &&
-                       (dwc->dr_mode == USB_DR_MODE_OTG ||
-                                       dwc->dr_mode == USB_DR_MODE_UNKNOWN))
-               dwc->dr_mode = USB_DR_MODE_HOST;
-       else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET) &&
-                       (dwc->dr_mode == USB_DR_MODE_OTG ||
-                                       dwc->dr_mode == USB_DR_MODE_UNKNOWN))
-               dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
-       if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
-               dwc->dr_mode = USB_DR_MODE_OTG;
+       ret = dwc3_get_dr_mode(dwc);
+       if (ret)
+               goto err3;
  
        ret = dwc3_alloc_scratch_buffers(dwc);
        if (ret)
@@@ -1192,7 -1286,6 +1286,7 @@@ static int dwc3_runtime_resume(struct d
        }
  
        pm_runtime_mark_last_busy(dev);
 +      pm_runtime_put(dev);
  
        return 0;
  }
index 122e64df2f4dc173123ddbfe7ef934d8630851a2,e49082f9edeb94358bd23153a4cdb2c3ff248659..07cc8929f27134e40b1084389fb3efb3c29c58f6
@@@ -174,15 -174,8 +174,8 @@@ void dwc3_gadget_giveback(struct dwc3_e
                int status)
  {
        struct dwc3                     *dwc = dep->dwc;
-       int                             i;
  
-       if (req->started) {
-               i = 0;
-               do {
-                       dwc3_ep_inc_deq(dep);
-               } while(++i < req->request.num_mapped_sgs);
-               req->started = false;
-       }
+       req->started = false;
        list_del(&req->list);
        req->trb = NULL;
  
@@@ -348,7 -341,8 +341,8 @@@ static int dwc3_send_clear_stall_ep_cmd
         * IN transfers due to a mishandled error condition. Synopsys
         * STAR 9000614252.
         */
-       if (dep->direction && (dwc->revision >= DWC3_REVISION_260A))
+       if (dep->direction && (dwc->revision >= DWC3_REVISION_260A) &&
+           (dwc->gadget.speed >= USB_SPEED_SUPER))
                cmd |= DWC3_DEPCMD_CLEARPENDIN;
  
        memset(&params, 0, sizeof(params));
@@@ -490,7 -484,8 +484,8 @@@ static int dwc3_gadget_set_ep_config(st
                params.param0 |= DWC3_DEPCFG_ACTION_INIT;
        }
  
-       params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN;
+       if (usb_endpoint_xfer_control(desc))
+               params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN;
  
        if (dep->number <= 1 || usb_endpoint_xfer_isoc(desc))
                params.param1 |= DWC3_DEPCFG_XFER_NOT_READY_EN;
@@@ -764,6 -759,8 +759,8 @@@ static void dwc3_gadget_ep_free_request
        kfree(req);
  }
  
+ static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep);
  /**
   * dwc3_prepare_one_trb - setup one TRB from one request
   * @dep: endpoint for which this request is prepared
   */
  static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
                struct dwc3_request *req, dma_addr_t dma,
-               unsigned length, unsigned last, unsigned chain, unsigned node)
+               unsigned length, unsigned chain, unsigned node)
  {
        struct dwc3_trb         *trb;
  
-       dwc3_trace(trace_dwc3_gadget, "%s: req %p dma %08llx length %d%s%s",
+       dwc3_trace(trace_dwc3_gadget, "%s: req %p dma %08llx length %d%s",
                        dep->name, req, (unsigned long long) dma,
-                       length, last ? " last" : "",
-                       chain ? " chain" : "");
+                       length, chain ? " chain" : "");
  
        trb = &dep->trb_pool[dep->trb_enqueue];
  
        /* always enable Continue on Short Packet */
        trb->ctrl |= DWC3_TRB_CTRL_CSP;
  
-       if (!req->request.no_interrupt && !chain)
+       if ((!req->request.no_interrupt && !chain) ||
+                       (dwc3_calc_trbs_left(dep) == 0))
                trb->ctrl |= DWC3_TRB_CTRL_IOC | DWC3_TRB_CTRL_ISP_IMI;
  
-       if (last && !usb_endpoint_xfer_isoc(dep->endpoint.desc))
-               trb->ctrl |= DWC3_TRB_CTRL_LST;
        if (chain)
                trb->ctrl |= DWC3_TRB_CTRL_CHN;
  
   */
  static struct dwc3_trb *dwc3_ep_prev_trb(struct dwc3_ep *dep, u8 index)
  {
-       if (!index)
-               index = DWC3_TRB_NUM - 2;
-       else
-               index = dep->trb_enqueue - 1;
+       u8 tmp = index;
  
-       return &dep->trb_pool[index];
+       if (!tmp)
+               tmp = DWC3_TRB_NUM - 1;
+       return &dep->trb_pool[tmp - 1];
  }
  
  static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep)
  }
  
  static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
-               struct dwc3_request *req, unsigned int trbs_left,
-               unsigned int more_coming)
+               struct dwc3_request *req)
  {
-       struct usb_request *request = &req->request;
-       struct scatterlist *sg = request->sg;
+       struct scatterlist *sg = req->sg;
        struct scatterlist *s;
-       unsigned int    last = false;
        unsigned int    length;
        dma_addr_t      dma;
        int             i;
  
-       for_each_sg(sg, s, request->num_mapped_sgs, i) {
+       for_each_sg(sg, s, req->num_pending_sgs, i) {
                unsigned chain = true;
  
                length = sg_dma_len(s);
                dma = sg_dma_address(s);
  
-               if (sg_is_last(s)) {
-                       if (usb_endpoint_xfer_int(dep->endpoint.desc) ||
-                               !more_coming)
-                               last = true;
-                       chain = false;
-               }
-               if (!trbs_left--)
-                       last = true;
-               if (last)
+               if (sg_is_last(s))
                        chain = false;
  
                dwc3_prepare_one_trb(dep, req, dma, length,
-                               last, chain, i);
+                               chain, i);
  
-               if (last)
+               if (!dwc3_calc_trbs_left(dep))
                        break;
        }
  }
  
  static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
-               struct dwc3_request *req, unsigned int trbs_left,
-               unsigned int more_coming)
+               struct dwc3_request *req)
  {
-       unsigned int    last = false;
        unsigned int    length;
        dma_addr_t      dma;
  
        dma = req->request.dma;
        length = req->request.length;
  
-       if (!trbs_left)
-               last = true;
-       /* Is this the last request? */
-       if (usb_endpoint_xfer_int(dep->endpoint.desc) || !more_coming)
-               last = true;
        dwc3_prepare_one_trb(dep, req, dma, length,
-                       last, false, 0);
+                       false, 0);
  }
  
  /*
  static void dwc3_prepare_trbs(struct dwc3_ep *dep)
  {
        struct dwc3_request     *req, *n;
-       unsigned int            more_coming;
-       u32                     trbs_left;
  
        BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM);
  
-       trbs_left = dwc3_calc_trbs_left(dep);
-       if (!trbs_left)
+       if (!dwc3_calc_trbs_left(dep))
                return;
  
-       more_coming = dep->allocated_requests - dep->queued_requests;
        list_for_each_entry_safe(req, n, &dep->pending_list, list) {
-               if (req->request.num_mapped_sgs > 0)
-                       dwc3_prepare_one_trb_sg(dep, req, trbs_left--,
-                                       more_coming);
+               if (req->num_pending_sgs > 0)
+                       dwc3_prepare_one_trb_sg(dep, req);
                else
-                       dwc3_prepare_one_trb_linear(dep, req, trbs_left--,
-                                       more_coming);
+                       dwc3_prepare_one_trb_linear(dep, req);
  
-               if (!trbs_left)
+               if (!dwc3_calc_trbs_left(dep))
                        return;
        }
  }
@@@ -1101,93 -1064,29 +1064,29 @@@ static int __dwc3_gadget_ep_queue(struc
  
        trace_dwc3_ep_queue(req);
  
-       /*
-        * We only add to our list of requests now and
-        * start consuming the list once we get XferNotReady
-        * IRQ.
-        *
-        * That way, we avoid doing anything that we don't need
-        * to do now and defer it until the point we receive a
-        * particular token from the Host side.
-        *
-        * This will also avoid Host cancelling URBs due to too
-        * many NAKs.
-        */
        ret = usb_gadget_map_request(&dwc->gadget, &req->request,
                        dep->direction);
        if (ret)
                return ret;
  
-       list_add_tail(&req->list, &dep->pending_list);
-       /*
-        * If there are no pending requests and the endpoint isn't already
-        * busy, we will just start the request straight away.
-        *
-        * This will save one IRQ (XFER_NOT_READY) and possibly make it a
-        * little bit faster.
-        */
-       if (!usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
-                       !usb_endpoint_xfer_int(dep->endpoint.desc)) {
-               ret = __dwc3_gadget_kick_transfer(dep, 0);
-               goto out;
-       }
-       /*
-        * There are a few special cases:
-        *
-        * 1. XferNotReady with empty list of requests. We need to kick the
-        *    transfer here in that situation, otherwise we will be NAKing
-        *    forever. If we get XferNotReady before gadget driver has a
-        *    chance to queue a request, we will ACK the IRQ but won't be
-        *    able to receive the data until the next request is queued.
-        *    The following code is handling exactly that.
-        *
-        */
-       if (dep->flags & DWC3_EP_PENDING_REQUEST) {
-               /*
-                * If xfernotready is already elapsed and it is a case
-                * of isoc transfer, then issue END TRANSFER, so that
-                * you can receive xfernotready again and can have
-                * notion of current microframe.
-                */
-               if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
-                       if (list_empty(&dep->started_list)) {
-                               dwc3_stop_active_transfer(dwc, dep->number, true);
-                               dep->flags = DWC3_EP_ENABLED;
-                       }
-                       return 0;
-               }
-               ret = __dwc3_gadget_kick_transfer(dep, 0);
-               if (!ret)
-                       dep->flags &= ~DWC3_EP_PENDING_REQUEST;
+       req->sg                 = req->request.sg;
+       req->num_pending_sgs    = req->request.num_mapped_sgs;
  
-               goto out;
-       }
+       list_add_tail(&req->list, &dep->pending_list);
  
-       /*
-        * 2. XferInProgress on Isoc EP with an active transfer. We need to
-        *    kick the transfer here after queuing a request, otherwise the
-        *    core may not see the modified TRB(s).
-        */
        if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
-                       (dep->flags & DWC3_EP_BUSY) &&
-                       !(dep->flags & DWC3_EP_MISSED_ISOC)) {
-               WARN_ON_ONCE(!dep->resource_index);
-               ret = __dwc3_gadget_kick_transfer(dep, dep->resource_index);
-               goto out;
+                       dep->flags & DWC3_EP_PENDING_REQUEST) {
+               if (list_empty(&dep->started_list)) {
+                       dwc3_stop_active_transfer(dwc, dep->number, true);
+                       dep->flags = DWC3_EP_ENABLED;
+               }
+               return 0;
        }
  
-       /*
-        * 4. Stream Capable Bulk Endpoints. We need to start the transfer
-        * right away, otherwise host will not know we have streams to be
-        * handled.
-        */
-       if (dep->stream_capable)
-               ret = __dwc3_gadget_kick_transfer(dep, 0);
+       if (!dwc3_calc_trbs_left(dep))
+               return 0;
  
- out:
+       ret = __dwc3_gadget_kick_transfer(dep, 0);
        if (ret && ret != -EBUSY)
                dwc3_trace(trace_dwc3_gadget,
                                "%s: failed to kick transfers",
@@@ -1433,7 -1332,7 +1332,7 @@@ static int dwc3_gadget_get_frame(struc
  
  static int __dwc3_gadget_wakeup(struct dwc3 *dwc)
  {
 -      unsigned long           timeout;
 +      int                     retries;
  
        int                     ret;
        u32                     reg;
        }
  
        /* poll until Link State changes to ON */
 -      timeout = jiffies + msecs_to_jiffies(100);
 +      retries = 20000;
  
 -      while (!time_after(jiffies, timeout)) {
 +      while (retries--) {
                reg = dwc3_readl(dwc->regs, DWC3_DSTS);
  
                /* in HS, means ON */
@@@ -1963,6 -1862,7 +1862,7 @@@ static int __dwc3_cleanup_done_trbs(str
        unsigned int            trb_status;
  
        dep->queued_requests--;
+       dwc3_ep_inc_deq(dep);
        trace_dwc3_complete_trb(dep, trb);
  
        /*
                return 1;
  
        count = trb->size & DWC3_TRB_SIZE_MASK;
+       req->request.actual += count;
  
        if (dep->direction) {
                if (count) {
  
        if (s_pkt && !chain)
                return 1;
-       if ((event->status & DEPEVT_STATUS_LST) &&
-                       (trb->ctrl & (DWC3_TRB_CTRL_LST |
-                               DWC3_TRB_CTRL_HWO)))
-               return 1;
        if ((event->status & DEPEVT_STATUS_IOC) &&
                        (trb->ctrl & DWC3_TRB_CTRL_IOC))
                return 1;
        return 0;
  }
  
  static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
                const struct dwc3_event_depevt *event, int status)
  {
-       struct dwc3_request     *req;
+       struct dwc3_request     *req, *n;
        struct dwc3_trb         *trb;
-       unsigned int            slot;
-       unsigned int            i;
-       int                     count = 0;
+       bool                    ioc = false;
        int                     ret;
  
-       do {
+       list_for_each_entry_safe(req, n, &dep->started_list, list) {
+               unsigned length;
+               unsigned actual;
                int chain;
  
-               req = next_request(&dep->started_list);
-               if (WARN_ON_ONCE(!req))
-                       return 1;
-               chain = req->request.num_mapped_sgs > 0;
-               i = 0;
-               do {
-                       slot = req->first_trb_index + i;
-                       if (slot == DWC3_TRB_NUM - 1)
-                               slot++;
-                       slot %= DWC3_TRB_NUM;
-                       trb = &dep->trb_pool[slot];
-                       count += trb->size & DWC3_TRB_SIZE_MASK;
+               length = req->request.length;
+               chain = req->num_pending_sgs > 0;
+               if (chain) {
+                       struct scatterlist *sg = req->sg;
+                       struct scatterlist *s;
+                       unsigned int pending = req->num_pending_sgs;
+                       unsigned int i;
  
+                       for_each_sg(sg, s, pending, i) {
+                               trb = &dep->trb_pool[dep->trb_dequeue];
+                               req->sg = sg_next(s);
+                               req->num_pending_sgs--;
+                               ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
+                                               event, status, chain);
+                               if (ret)
+                                       break;
+                       }
+               } else {
+                       trb = &dep->trb_pool[dep->trb_dequeue];
                        ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
                                        event, status, chain);
-                       if (ret)
-                               break;
-               } while (++i < req->request.num_mapped_sgs);
+               }
  
                /*
                 * We assume here we will always receive the entire data block
                 * should receive and we simply bounce the request back to the
                 * gadget driver for further processing.
                 */
-               req->request.actual += req->request.length - count;
+               actual = length - req->request.actual;
+               req->request.actual = actual;
+               if (ret && chain && (actual < length) && req->num_pending_sgs)
+                       return __dwc3_gadget_kick_transfer(dep, 0);
                dwc3_gadget_giveback(dep, req, status);
  
-               if (ret)
+               if (ret) {
+                       if ((event->status & DEPEVT_STATUS_IOC) &&
+                           (trb->ctrl & DWC3_TRB_CTRL_IOC))
+                               ioc = true;
                        break;
-       } while (1);
+               }
+       }
  
        /*
         * Our endpoint might get disabled by another thread during
                return 1;
        }
  
-       if (usb_endpoint_xfer_isoc(dep->endpoint.desc))
-               if ((event->status & DEPEVT_STATUS_IOC) &&
-                               (trb->ctrl & DWC3_TRB_CTRL_IOC))
-                       return 0;
+       if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && ioc)
+               return 0;
        return 1;
  }
  
@@@ -2322,6 -2234,18 +2234,18 @@@ static void dwc3_stop_active_transfer(s
         *
         * - Issue EndTransfer WITH CMDIOC bit set
         * - Wait 100us
+        *
+        * As of IP version 3.10a of the DWC_usb3 IP, the controller
+        * supports a mode to work around the above limitation. The
+        * software can poll the CMDACT bit in the DEPCMD register
+        * after issuing a EndTransfer command. This mode is enabled
+        * by writing GUCTL2[14]. This polling is already done in the
+        * dwc3_send_gadget_ep_cmd() function so if the mode is
+        * enabled, the EndTransfer command will have completed upon
+        * returning from this function and we don't need to delay for
+        * 100us.
+        *
+        * This mode is NOT available on the DWC_usb31 IP.
         */
  
        cmd = DWC3_DEPCMD_ENDTRANSFER;
        WARN_ON_ONCE(ret);
        dep->resource_index = 0;
        dep->flags &= ~DWC3_EP_BUSY;
-       udelay(100);
+       if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A)
+               udelay(100);
  }
  
  static void dwc3_stop_active_transfers(struct dwc3 *dwc)
index 40c04bb25f2f9f2eee7c4b326e8585e6de3e4fb9,d8e6686a84b72b0958525e564f95665810799e6f..9483489080f66230370db44a2326a152a3f3eb47
@@@ -107,10 -107,8 +107,8 @@@ int usb_ep_enable(struct usb_ep *ep
                goto out;
  
        ret = ep->ops->enable(ep, ep->desc);
-       if (ret) {
-               ret = ret;
+       if (ret)
                goto out;
-       }
  
        ep->enabled = true;
  
@@@ -827,7 -825,7 +825,7 @@@ void usb_gadget_unmap_request_by_dev(st
                return;
  
        if (req->num_mapped_sgs) {
 -              dma_unmap_sg(dev, req->sg, req->num_mapped_sgs,
 +              dma_unmap_sg(dev, req->sg, req->num_sgs,
                                is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
  
                req->num_mapped_sgs = 0;
index 427efb5eebae9b386c2437d0da82477462cd184f,c14e767a3fbf074f573380592760c8e038c49b87..8311ba2968cd1e14f21b6c497b463d4ec4cf9abe
@@@ -118,8 -118,6 +118,6 @@@ static irqreturn_t nop_gpio_vbus_thread
                status = USB_EVENT_VBUS;
                otg->state = OTG_STATE_B_PERIPHERAL;
                nop->phy.last_event = status;
-               if (otg->gadget)
-                       usb_gadget_vbus_connect(otg->gadget);
  
                /* drawing a "unit load" is *always* OK, except for OTG */
                nop_set_vbus_draw(nop, 100);
        } else {
                nop_set_vbus_draw(nop, 0);
  
-               if (otg->gadget)
-                       usb_gadget_vbus_disconnect(otg->gadget);
                status = USB_EVENT_NONE;
                otg->state = OTG_STATE_B_IDLE;
                nop->phy.last_event = status;
  int usb_gen_phy_init(struct usb_phy *phy)
  {
        struct usb_phy_generic *nop = dev_get_drvdata(phy->dev);
 +      int ret;
  
        if (!IS_ERR(nop->vcc)) {
                if (regulator_enable(nop->vcc))
                        dev_err(phy->dev, "Failed to enable power\n");
        }
  
 -      if (!IS_ERR(nop->clk))
 -              clk_prepare_enable(nop->clk);
 +      if (!IS_ERR(nop->clk)) {
 +              ret = clk_prepare_enable(nop->clk);
 +              if (ret)
 +                      return ret;
 +      }
  
        nop_reset(nop);
  
@@@ -191,7 -183,8 +187,8 @@@ static int nop_set_peripheral(struct us
  
        otg->gadget = gadget;
        if (otg->state == OTG_STATE_B_PERIPHERAL)
-               usb_gadget_vbus_connect(gadget);
+               atomic_notifier_call_chain(&otg->usb_phy->notifier,
+                                          USB_EVENT_VBUS, otg->gadget);
        else
                otg->state = OTG_STATE_B_IDLE;
        return 0;
@@@ -326,6 -319,8 +323,8 @@@ static int usb_phy_generic_probe(struc
                                gpiod_to_irq(nop->gpiod_vbus), err);
                        return err;
                }
+               nop->phy.otg->state = gpiod_get_value(nop->gpiod_vbus) ?
+                       OTG_STATE_B_PERIPHERAL : OTG_STATE_B_IDLE;
        }
  
        nop->phy.init           = usb_gen_phy_init;
index 86b37a8eedd445d9559c35bec1bead959bb22f1f,5732998de92afb1379f558653c1e9b52a03a1edc..5bc7a6138855ec7ecf69046ceb71a3c992ccb9fa
@@@ -1072,7 -1072,7 +1072,7 @@@ int usbhs_mod_gadget_probe(struct usbhs
  
        gpriv->transceiver = usb_get_phy(USB_PHY_TYPE_UNDEFINED);
        dev_info(dev, "%stransceiver found\n",
 -               gpriv->transceiver ? "" : "no ");
 +               !IS_ERR(gpriv->transceiver) ? "" : "no ");
  
        /*
         * CAUTION
        gpriv->gadget.name              = "renesas_usbhs_udc";
        gpriv->gadget.ops               = &usbhsg_gadget_ops;
        gpriv->gadget.max_speed         = USB_SPEED_HIGH;
+       gpriv->gadget.quirk_avoids_skb_reserve = usbhs_get_dparam(priv,
+                                                               has_usb_dmac);
  
        INIT_LIST_HEAD(&gpriv->gadget.ep_list);
  
index 80b36ca12e80ec9aec1cff524475e7195526c1a1,a44408f6d53225a9d497e29804d1d0163f4d59c1..a7af21a5524805b47718ef8001eea20e83860647
@@@ -15,7 -15,7 +15,7 @@@ struct ulpi_ops
   */
  struct ulpi {
        struct ulpi_device_id id;
-       struct ulpi_ops *ops;
+       const struct ulpi_ops *ops;
        struct device dev;
  };
  
@@@ -47,11 -47,7 +47,11 @@@ struct ulpi_driver 
  
  #define to_ulpi_driver(d) container_of(d, struct ulpi_driver, driver)
  
 -int ulpi_register_driver(struct ulpi_driver *drv);
 +/*
 + * use a macro to avoid include chaining to get THIS_MODULE
 + */
 +#define ulpi_register_driver(drv) __ulpi_register_driver(drv, THIS_MODULE)
 +int __ulpi_register_driver(struct ulpi_driver *drv, struct module *module);
  void ulpi_unregister_driver(struct ulpi_driver *drv);
  
  #define module_ulpi_driver(__ulpi_driver) \
This page took 0.044007 seconds and 5 git commands to generate.