Merge 5.14-rc6 into usb-next
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Aug 2021 07:04:28 +0000 (09:04 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Aug 2021 07:04:28 +0000 (09:04 +0200)
We need the USB fix in here as well.

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1  2 
drivers/usb/dwc3/gadget.c

@@@ -632,187 -632,6 +632,187 @@@ static void dwc3_stop_active_transfer(s
                bool interrupt);
  
  /**
 + * dwc3_gadget_calc_tx_fifo_size - calculates the txfifo size value
 + * @dwc: pointer to the DWC3 context
 + * @nfifos: number of fifos to calculate for
 + *
 + * Calculates the size value based on the equation below:
 + *
 + * DWC3 revision 280A and prior:
 + * fifo_size = mult * (max_packet / mdwidth) + 1;
 + *
 + * DWC3 revision 290A and onwards:
 + * fifo_size = mult * ((max_packet + mdwidth)/mdwidth + 1) + 1
 + *
 + * The max packet size is set to 1024, as the txfifo requirements mainly apply
 + * to super speed USB use cases.  However, it is safe to overestimate the fifo
 + * allocations for other scenarios, i.e. high speed USB.
 + */
 +static int dwc3_gadget_calc_tx_fifo_size(struct dwc3 *dwc, int mult)
 +{
 +      int max_packet = 1024;
 +      int fifo_size;
 +      int mdwidth;
 +
 +      mdwidth = dwc3_mdwidth(dwc);
 +
 +      /* MDWIDTH is represented in bits, we need it in bytes */
 +      mdwidth >>= 3;
 +
 +      if (DWC3_VER_IS_PRIOR(DWC3, 290A))
 +              fifo_size = mult * (max_packet / mdwidth) + 1;
 +      else
 +              fifo_size = mult * ((max_packet + mdwidth) / mdwidth) + 1;
 +      return fifo_size;
 +}
 +
 +/**
 + * dwc3_gadget_clear_tx_fifo_size - Clears txfifo allocation
 + * @dwc: pointer to the DWC3 context
 + *
 + * Iterates through all the endpoint registers and clears the previous txfifo
 + * allocations.
 + */
 +void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc)
 +{
 +      struct dwc3_ep *dep;
 +      int fifo_depth;
 +      int size;
 +      int num;
 +
 +      if (!dwc->do_fifo_resize)
 +              return;
 +
 +      /* Read ep0IN related TXFIFO size */
 +      dep = dwc->eps[1];
 +      size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0));
 +      if (DWC3_IP_IS(DWC3))
 +              fifo_depth = DWC3_GTXFIFOSIZ_TXFDEP(size);
 +      else
 +              fifo_depth = DWC31_GTXFIFOSIZ_TXFDEP(size);
 +
 +      dwc->last_fifo_depth = fifo_depth;
 +      /* Clear existing TXFIFO for all IN eps except ep0 */
 +      for (num = 3; num < min_t(int, dwc->num_eps, DWC3_ENDPOINTS_NUM);
 +           num += 2) {
 +              dep = dwc->eps[num];
 +              /* Don't change TXFRAMNUM on usb31 version */
 +              size = DWC3_IP_IS(DWC3) ? 0 :
 +                      dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(num >> 1)) &
 +                                 DWC31_GTXFIFOSIZ_TXFRAMNUM;
 +
 +              dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(num >> 1), size);
 +      }
 +      dwc->num_ep_resized = 0;
 +}
 +
 +/*
 + * dwc3_gadget_resize_tx_fifos - reallocate fifo spaces for current use-case
 + * @dwc: pointer to our context structure
 + *
 + * This function will a best effort FIFO allocation in order
 + * to improve FIFO usage and throughput, while still allowing
 + * us to enable as many endpoints as possible.
 + *
 + * Keep in mind that this operation will be highly dependent
 + * on the configured size for RAM1 - which contains TxFifo -,
 + * the amount of endpoints enabled on coreConsultant tool, and
 + * the width of the Master Bus.
 + *
 + * In general, FIFO depths are represented with the following equation:
 + *
 + * fifo_size = mult * ((max_packet + mdwidth)/mdwidth + 1) + 1
 + *
 + * In conjunction with dwc3_gadget_check_config(), this resizing logic will
 + * ensure that all endpoints will have enough internal memory for one max
 + * packet per endpoint.
 + */
 +static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
 +{
 +      struct dwc3 *dwc = dep->dwc;
 +      int fifo_0_start;
 +      int ram1_depth;
 +      int fifo_size;
 +      int min_depth;
 +      int num_in_ep;
 +      int remaining;
 +      int num_fifos = 1;
 +      int fifo;
 +      int tmp;
 +
 +      if (!dwc->do_fifo_resize)
 +              return 0;
 +
 +      /* resize IN endpoints except ep0 */
 +      if (!usb_endpoint_dir_in(dep->endpoint.desc) || dep->number <= 1)
 +              return 0;
 +
 +      ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
 +
 +      if ((dep->endpoint.maxburst > 1 &&
 +           usb_endpoint_xfer_bulk(dep->endpoint.desc)) ||
 +          usb_endpoint_xfer_isoc(dep->endpoint.desc))
 +              num_fifos = 3;
 +
 +      if (dep->endpoint.maxburst > 6 &&
 +          usb_endpoint_xfer_bulk(dep->endpoint.desc) && DWC3_IP_IS(DWC31))
 +              num_fifos = dwc->tx_fifo_resize_max_num;
 +
 +      /* FIFO size for a single buffer */
 +      fifo = dwc3_gadget_calc_tx_fifo_size(dwc, 1);
 +
 +      /* Calculate the number of remaining EPs w/o any FIFO */
 +      num_in_ep = dwc->max_cfg_eps;
 +      num_in_ep -= dwc->num_ep_resized;
 +
 +      /* Reserve at least one FIFO for the number of IN EPs */
 +      min_depth = num_in_ep * (fifo + 1);
 +      remaining = ram1_depth - min_depth - dwc->last_fifo_depth;
 +      remaining = max_t(int, 0, remaining);
 +      /*
 +       * We've already reserved 1 FIFO per EP, so check what we can fit in
 +       * addition to it.  If there is not enough remaining space, allocate
 +       * all the remaining space to the EP.
 +       */
 +      fifo_size = (num_fifos - 1) * fifo;
 +      if (remaining < fifo_size)
 +              fifo_size = remaining;
 +
 +      fifo_size += fifo;
 +      /* Last increment according to the TX FIFO size equation */
 +      fifo_size++;
 +
 +      /* Check if TXFIFOs start at non-zero addr */
 +      tmp = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0));
 +      fifo_0_start = DWC3_GTXFIFOSIZ_TXFSTADDR(tmp);
 +
 +      fifo_size |= (fifo_0_start + (dwc->last_fifo_depth << 16));
 +      if (DWC3_IP_IS(DWC3))
 +              dwc->last_fifo_depth += DWC3_GTXFIFOSIZ_TXFDEP(fifo_size);
 +      else
 +              dwc->last_fifo_depth += DWC31_GTXFIFOSIZ_TXFDEP(fifo_size);
 +
 +      /* Check fifo size allocation doesn't exceed available RAM size. */
 +      if (dwc->last_fifo_depth >= ram1_depth) {
 +              dev_err(dwc->dev, "Fifosize(%d) > RAM size(%d) %s depth:%d\n",
 +                      dwc->last_fifo_depth, ram1_depth,
 +                      dep->endpoint.name, fifo_size);
 +              if (DWC3_IP_IS(DWC3))
 +                      fifo_size = DWC3_GTXFIFOSIZ_TXFDEP(fifo_size);
 +              else
 +                      fifo_size = DWC31_GTXFIFOSIZ_TXFDEP(fifo_size);
 +
 +              dwc->last_fifo_depth -= fifo_size;
 +              return -ENOMEM;
 +      }
 +
 +      dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(dep->number >> 1), fifo_size);
 +      dwc->num_ep_resized++;
 +
 +      return 0;
 +}
 +
 +/**
   * __dwc3_gadget_ep_enable - initializes a hw endpoint
   * @dep: endpoint to be initialized
   * @action: one of INIT, MODIFY or RESTORE
@@@ -829,10 -648,6 +829,10 @@@ static int __dwc3_gadget_ep_enable(stru
        int                     ret;
  
        if (!(dep->flags & DWC3_EP_ENABLED)) {
 +              ret = dwc3_gadget_resize_tx_fifos(dep);
 +              if (ret)
 +                      return ret;
 +
                ret = dwc3_gadget_start_config(dep);
                if (ret)
                        return ret;
@@@ -1926,13 -1741,9 +1926,9 @@@ static void dwc3_gadget_ep_cleanup_canc
  {
        struct dwc3_request             *req;
        struct dwc3_request             *tmp;
-       struct list_head                local;
        struct dwc3                     *dwc = dep->dwc;
  
- restart:
-       list_replace_init(&dep->cancelled_list, &local);
-       list_for_each_entry_safe(req, tmp, &local, list) {
+       list_for_each_entry_safe(req, tmp, &dep->cancelled_list, list) {
                dwc3_gadget_ep_skip_trbs(dep, req);
                switch (req->status) {
                case DWC3_REQUEST_STATUS_DISCONNECTED:
                        break;
                }
        }
-       if (!list_empty(&dep->cancelled_list))
-               goto restart;
  }
  
  static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
@@@ -2701,7 -2509,6 +2694,7 @@@ static int dwc3_gadget_stop(struct usb_
  
        spin_lock_irqsave(&dwc->lock, flags);
        dwc->gadget_driver      = NULL;
 +      dwc->max_cfg_eps = 0;
        spin_unlock_irqrestore(&dwc->lock, flags);
  
        free_irq(dwc->irq_gadget, dwc->ev_buf);
@@@ -2789,51 -2596,6 +2782,51 @@@ static int dwc3_gadget_vbus_draw(struc
        return ret;
  }
  
 +/**
 + * dwc3_gadget_check_config - ensure dwc3 can support the USB configuration
 + * @g: pointer to the USB gadget
 + *
 + * Used to record the maximum number of endpoints being used in a USB composite
 + * device. (across all configurations)  This is to be used in the calculation
 + * of the TXFIFO sizes when resizing internal memory for individual endpoints.
 + * It will help ensured that the resizing logic reserves enough space for at
 + * least one max packet.
 + */
 +static int dwc3_gadget_check_config(struct usb_gadget *g)
 +{
 +      struct dwc3 *dwc = gadget_to_dwc(g);
 +      struct usb_ep *ep;
 +      int fifo_size = 0;
 +      int ram1_depth;
 +      int ep_num = 0;
 +
 +      if (!dwc->do_fifo_resize)
 +              return 0;
 +
 +      list_for_each_entry(ep, &g->ep_list, ep_list) {
 +              /* Only interested in the IN endpoints */
 +              if (ep->claimed && (ep->address & USB_DIR_IN))
 +                      ep_num++;
 +      }
 +
 +      if (ep_num <= dwc->max_cfg_eps)
 +              return 0;
 +
 +      /* Update the max number of eps in the composition */
 +      dwc->max_cfg_eps = ep_num;
 +
 +      fifo_size = dwc3_gadget_calc_tx_fifo_size(dwc, dwc->max_cfg_eps);
 +      /* Based on the equation, increment by one for every ep */
 +      fifo_size += dwc->max_cfg_eps;
 +
 +      /* Check if we can fit a single fifo per endpoint */
 +      ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
 +      if (fifo_size > ram1_depth)
 +              return -ENOMEM;
 +
 +      return 0;
 +}
 +
  static void dwc3_gadget_async_callbacks(struct usb_gadget *g, bool enable)
  {
        struct dwc3             *dwc = gadget_to_dwc(g);
@@@ -2855,7 -2617,6 +2848,7 @@@ static const struct usb_gadget_ops dwc3
        .udc_set_ssp_rate       = dwc3_gadget_set_ssp_rate,
        .get_config_params      = dwc3_gadget_config_params,
        .vbus_draw              = dwc3_gadget_vbus_draw,
 +      .check_config           = dwc3_gadget_check_config,
        .udc_async_callbacks    = dwc3_gadget_async_callbacks,
  };
  
@@@ -3208,12 -2969,8 +3201,8 @@@ static void dwc3_gadget_ep_cleanup_comp
  {
        struct dwc3_request     *req;
        struct dwc3_request     *tmp;
-       struct list_head        local;
  
- restart:
-       list_replace_init(&dep->started_list, &local);
-       list_for_each_entry_safe(req, tmp, &local, list) {
+       list_for_each_entry_safe(req, tmp, &dep->started_list, list) {
                int ret;
  
                ret = dwc3_gadget_ep_cleanup_completed_request(dep, event,
                if (ret)
                        break;
        }
-       if (!list_empty(&dep->started_list))
-               goto restart;
  }
  
  static bool dwc3_gadget_ep_should_continue(struct dwc3_ep *dep)
@@@ -4258,7 -4012,7 +4244,7 @@@ int dwc3_gadget_init(struct dwc3 *dwc
        }
  
  
 -      usb_initialize_gadget(dwc->dev, dwc->gadget, dwc_gadget_release);
 +      usb_initialize_gadget(dwc->sysdev, dwc->gadget, dwc_gadget_release);
        dev                             = &dwc->gadget->dev;
        dev->platform_data              = dwc;
        dwc->gadget->ops                = &dwc3_gadget_ops;