Merge v5.14-rc3 into usb-next
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 26 Jul 2021 09:16:46 +0000 (11:16 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 26 Jul 2021 09:16:46 +0000 (11:16 +0200)
We need the fixes in here, and this resolves a merge issue with
drivers/usb/dwc3/gadget.c

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1  2 
drivers/usb/dwc2/core.h
drivers/usb/dwc2/gadget.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/host/xhci-pci-renesas.c
drivers/usb/host/xhci-pci.c

diff --combined drivers/usb/dwc2/core.h
@@@ -122,7 -122,6 +122,7 @@@ struct dwc2_hsotg_req
   * @periodic: Set if this is a periodic ep, such as Interrupt
   * @isochronous: Set if this is a isochronous ep
   * @send_zlp: Set if we need to send a zero-length packet.
 + * @wedged: Set if ep is wedged.
   * @desc_list_dma: The DMA address of descriptor chain currently in use.
   * @desc_list: Pointer to descriptor DMA chain head currently in use.
   * @desc_count: Count of entries within the DMA descriptor chain of EP.
@@@ -173,7 -172,6 +173,7 @@@ struct dwc2_hsotg_ep 
        unsigned int            periodic:1;
        unsigned int            isochronous:1;
        unsigned int            send_zlp:1;
 +      unsigned int            wedged:1;
        unsigned int            target_frame;
  #define TARGET_FRAME_INITIAL   0xFFFFFFFF
        bool                    frame_overrun;
@@@ -385,6 -383,9 +385,9 @@@ enum dwc2_ep0_state 
   *                    0 - No (default)
   *                    1 - Partial power down
   *                    2 - Hibernation
+  * @no_clock_gating:  Specifies whether to avoid clock gating feature.
+  *                    0 - No (use clock gating)
+  *                    1 - Yes (avoid it)
   * @lpm:              Enable LPM support.
   *                    0 - No
   *                    1 - Yes
@@@ -482,6 -483,7 +485,7 @@@ struct dwc2_core_params 
  #define DWC2_POWER_DOWN_PARAM_NONE            0
  #define DWC2_POWER_DOWN_PARAM_PARTIAL         1
  #define DWC2_POWER_DOWN_PARAM_HIBERNATION     2
+       bool no_clock_gating;
  
        bool lpm;
        bool lpm_clock_gating;
@@@ -1806,8 -1806,7 +1806,8 @@@ static int dwc2_hsotg_process_req_featu
                case USB_ENDPOINT_HALT:
                        halted = ep->halted;
  
 -                      dwc2_hsotg_ep_sethalt(&ep->ep, set, true);
 +                      if (!ep->wedged)
 +                              dwc2_hsotg_ep_sethalt(&ep->ep, set, true);
  
                        ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
                        if (ret) {
@@@ -2750,12 -2749,14 +2750,14 @@@ static void dwc2_hsotg_complete_in(stru
                return;
        }
  
-       /* Zlp for all endpoints, for ep0 only in DATA IN stage */
+       /* Zlp for all endpoints in non DDMA, for ep0 only in DATA IN stage */
        if (hs_ep->send_zlp) {
-               dwc2_hsotg_program_zlp(hsotg, hs_ep);
                hs_ep->send_zlp = 0;
-               /* transfer will be completed on next complete interrupt */
-               return;
+               if (!using_desc_dma(hsotg)) {
+                       dwc2_hsotg_program_zlp(hsotg, hs_ep);
+                       /* transfer will be completed on next complete interrupt */
+                       return;
+               }
        }
  
        if (hs_ep->index == 0 && hsotg->ep0_state == DWC2_EP0_DATA_IN) {
@@@ -3901,9 -3902,27 +3903,27 @@@ static void dwc2_hsotg_ep_stop_xfr(stru
                                         __func__);
                }
        } else {
+               /* Mask GINTSTS_GOUTNAKEFF interrupt */
+               dwc2_hsotg_disable_gsint(hsotg, GINTSTS_GOUTNAKEFF);
                if (!(dwc2_readl(hsotg, GINTSTS) & GINTSTS_GOUTNAKEFF))
                        dwc2_set_bit(hsotg, DCTL, DCTL_SGOUTNAK);
  
+               if (!using_dma(hsotg)) {
+                       /* Wait for GINTSTS_RXFLVL interrupt */
+                       if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS,
+                                                   GINTSTS_RXFLVL, 100)) {
+                               dev_warn(hsotg->dev, "%s: timeout GINTSTS.RXFLVL\n",
+                                        __func__);
+                       } else {
+                               /*
+                                * Pop GLOBAL OUT NAK status packet from RxFIFO
+                                * to assert GOUTNAKEFF interrupt
+                                */
+                               dwc2_readl(hsotg, GRXSTSP);
+                       }
+               }
                /* Wait for global nak to take effect */
                if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS,
                                            GINTSTS_GOUTNAKEFF, 100))
@@@ -4047,7 -4066,6 +4067,7 @@@ static int dwc2_hsotg_ep_enable(struct 
        hs_ep->isochronous = 0;
        hs_ep->periodic = 0;
        hs_ep->halted = 0;
 +      hs_ep->wedged = 0;
        hs_ep->interval = desc->bInterval;
  
        switch (ep_type) {
@@@ -4288,27 -4306,6 +4308,27 @@@ static int dwc2_hsotg_ep_dequeue(struc
        return 0;
  }
  
 +/**
 + * dwc2_gadget_ep_set_wedge - set wedge on a given endpoint
 + * @ep: The endpoint to be wedged.
 + *
 + */
 +static int dwc2_gadget_ep_set_wedge(struct usb_ep *ep)
 +{
 +      struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
 +      struct dwc2_hsotg *hs = hs_ep->parent;
 +
 +      unsigned long   flags;
 +      int             ret;
 +
 +      spin_lock_irqsave(&hs->lock, flags);
 +      hs_ep->wedged = 1;
 +      ret = dwc2_hsotg_ep_sethalt(ep, 1, false);
 +      spin_unlock_irqrestore(&hs->lock, flags);
 +
 +      return ret;
 +}
 +
  /**
   * dwc2_hsotg_ep_sethalt - set halt on a given endpoint
   * @ep: The endpoint to set halt.
@@@ -4360,7 -4357,6 +4380,7 @@@ static int dwc2_hsotg_ep_sethalt(struc
                                epctl |= DXEPCTL_EPDIS;
                } else {
                        epctl &= ~DXEPCTL_STALL;
 +                      hs_ep->wedged = 0;
                        xfertype = epctl & DXEPCTL_EPTYPE_MASK;
                        if (xfertype == DXEPCTL_EPTYPE_BULK ||
                            xfertype == DXEPCTL_EPTYPE_INTERRUPT)
                epctl = dwc2_readl(hs, epreg);
  
                if (value) {
+                       /* Unmask GOUTNAKEFF interrupt */
+                       dwc2_hsotg_en_gsint(hs, GINTSTS_GOUTNAKEFF);
                        if (!(dwc2_readl(hs, GINTSTS) & GINTSTS_GOUTNAKEFF))
                                dwc2_set_bit(hs, DCTL, DCTL_SGOUTNAK);
                        // STALL bit will be set in GOUTNAKEFF interrupt handler
                } else {
                        epctl &= ~DXEPCTL_STALL;
 +                      hs_ep->wedged = 0;
                        xfertype = epctl & DXEPCTL_EPTYPE_MASK;
                        if (xfertype == DXEPCTL_EPTYPE_BULK ||
                            xfertype == DXEPCTL_EPTYPE_INTERRUPT)
@@@ -4417,7 -4415,6 +4440,7 @@@ static const struct usb_ep_ops dwc2_hso
        .queue          = dwc2_hsotg_ep_queue_lock,
        .dequeue        = dwc2_hsotg_ep_dequeue,
        .set_halt       = dwc2_hsotg_ep_sethalt_lock,
 +      .set_wedge      = dwc2_gadget_ep_set_wedge,
        /* note, don't believe we have any call for the fifo routines */
  };
  
diff --combined drivers/usb/dwc3/core.h
@@@ -1023,7 -1023,6 +1023,7 @@@ struct dwc3_scratchpad_array 
   * @rx_max_burst_prd: max periodic ESS receive burst size
   * @tx_thr_num_pkt_prd: periodic ESS transmit packet count
   * @tx_max_burst_prd: max periodic ESS transmit burst size
 + * @tx_fifo_resize_max_num: max number of fifos allocated during txfifo resize
   * @hsphy_interface: "utmi" or "ulpi"
   * @connected: true when we're connected to a host, false otherwise
   * @delayed_status: true when gadget driver asks for delayed status
   *    1       - utmi_l1_suspend_n
   * @is_fpga: true when we are using the FPGA board
   * @pending_events: true when we have pending IRQs to be handled
 + * @do_fifo_resize: true when txfifo resizing is enabled for dwc3 endpoints
   * @pullups_connected: true when Run/Stop bit is set
   * @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
   * @three_stage_setup: set if we perform a three phase setup
   * @dis_split_quirk: set to disable split boundary.
   * @imod_interval: set the interrupt moderation interval in 250ns
   *                    increments or 0 to disable.
 + * @max_cfg_eps: current max number of IN eps used across all USB configs.
 + * @last_fifo_depth: last fifo depth used to determine next fifo ram start
 + *                 address.
 + * @num_ep_resized: carries the current number endpoints which have had its tx
 + *                fifo resized.
   */
  struct dwc3 {
        struct work_struct      drd_work;
        u8                      rx_max_burst_prd;
        u8                      tx_thr_num_pkt_prd;
        u8                      tx_max_burst_prd;
 +      u8                      tx_fifo_resize_max_num;
  
        const char              *hsphy_interface;
  
        unsigned                is_utmi_l1_suspend:1;
        unsigned                is_fpga:1;
        unsigned                pending_events:1;
 +      unsigned                do_fifo_resize:1;
        unsigned                pullups_connected:1;
        unsigned                setup_packet_pending:1;
        unsigned                three_stage_setup:1;
        unsigned                dis_metastability_quirk:1;
  
        unsigned                dis_split_quirk:1;
+       unsigned                async_callbacks:1;
  
        u16                     imod_interval;
 +
 +      int                     max_cfg_eps;
 +      int                     last_fifo_depth;
 +      int                     num_ep_resized;
  };
  
  #define INCRX_BURST_MODE 0
@@@ -1525,7 -1513,6 +1526,7 @@@ int dwc3_send_gadget_ep_cmd(struct dwc3
                struct dwc3_gadget_ep_cmd_params *params);
  int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned int cmd,
                u32 param);
 +void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc);
  #else
  static inline int dwc3_gadget_init(struct dwc3 *dwc)
  { return 0; }
@@@ -1545,8 -1532,6 +1546,8 @@@ static inline int dwc3_send_gadget_ep_c
  static inline int dwc3_send_gadget_generic_command(struct dwc3 *dwc,
                int cmd, u32 param)
  { return 0; }
 +static inline void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc)
 +{ }
  #endif
  
  #if IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
diff --combined drivers/usb/dwc3/ep0.c
@@@ -597,11 -597,13 +597,13 @@@ static int dwc3_ep0_set_address(struct 
  
  static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
  {
-       int ret;
+       int ret = -EINVAL;
  
-       spin_unlock(&dwc->lock);
-       ret = dwc->gadget_driver->setup(dwc->gadget, ctrl);
-       spin_lock(&dwc->lock);
+       if (dwc->async_callbacks) {
+               spin_unlock(&dwc->lock);
+               ret = dwc->gadget_driver->setup(dwc->gadget, ctrl);
+               spin_lock(&dwc->lock);
+       }
        return ret;
  }
  
@@@ -619,8 -621,6 +621,8 @@@ static int dwc3_ep0_set_config(struct d
                return -EINVAL;
  
        case USB_STATE_ADDRESS:
 +              dwc3_gadget_clear_tx_fifos(dwc);
 +
                ret = dwc3_ep0_delegate_req(dwc, ctrl);
                /* if the cfg matches and the cfg is non zero */
                if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
@@@ -631,187 -631,6 +631,187 @@@ static int dwc3_gadget_set_ep_config(st
  static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
                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
@@@ -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;
@@@ -2683,7 -2498,6 +2683,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);
@@@ -2771,51 -2585,16 +2771,61 @@@ 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);
+       unsigned long           flags;
+       spin_lock_irqsave(&dwc->lock, flags);
+       dwc->async_callbacks = enable;
+       spin_unlock_irqrestore(&dwc->lock, flags);
+ }
  static const struct usb_gadget_ops dwc3_gadget_ops = {
        .get_frame              = dwc3_gadget_get_frame,
        .wakeup                 = dwc3_gadget_wakeup,
        .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,
  };
  
  /* -------------------------------------------------------------------------- */
@@@ -3463,7 -3242,7 +3474,7 @@@ static void dwc3_endpoint_interrupt(str
  
  static void dwc3_disconnect_gadget(struct dwc3 *dwc)
  {
-       if (dwc->gadget_driver && dwc->gadget_driver->disconnect) {
+       if (dwc->async_callbacks && dwc->gadget_driver->disconnect) {
                spin_unlock(&dwc->lock);
                dwc->gadget_driver->disconnect(dwc->gadget);
                spin_lock(&dwc->lock);
  
  static void dwc3_suspend_gadget(struct dwc3 *dwc)
  {
-       if (dwc->gadget_driver && dwc->gadget_driver->suspend) {
+       if (dwc->async_callbacks && dwc->gadget_driver->suspend) {
                spin_unlock(&dwc->lock);
                dwc->gadget_driver->suspend(dwc->gadget);
                spin_lock(&dwc->lock);
  
  static void dwc3_resume_gadget(struct dwc3 *dwc)
  {
-       if (dwc->gadget_driver && dwc->gadget_driver->resume) {
+       if (dwc->async_callbacks && dwc->gadget_driver->resume) {
                spin_unlock(&dwc->lock);
                dwc->gadget_driver->resume(dwc->gadget);
                spin_lock(&dwc->lock);
@@@ -3493,7 -3272,7 +3504,7 @@@ static void dwc3_reset_gadget(struct dw
        if (!dwc->gadget_driver)
                return;
  
-       if (dwc->gadget->speed != USB_SPEED_UNKNOWN) {
+       if (dwc->async_callbacks && dwc->gadget->speed != USB_SPEED_UNKNOWN) {
                spin_unlock(&dwc->lock);
                usb_gadget_udc_reset(dwc->gadget, dwc->gadget_driver);
                spin_lock(&dwc->lock);
@@@ -3817,7 -3596,7 +3828,7 @@@ static void dwc3_gadget_wakeup_interrup
         * implemented.
         */
  
-       if (dwc->gadget_driver && dwc->gadget_driver->resume) {
+       if (dwc->async_callbacks && dwc->gadget_driver->resume) {
                spin_unlock(&dwc->lock);
                dwc->gadget_driver->resume(dwc->gadget);
                spin_lock(&dwc->lock);
@@@ -207,8 -207,7 +207,7 @@@ static int renesas_check_rom_state(stru
                        return 0;
  
                case RENESAS_ROM_STATUS_NO_RESULT: /* No result yet */
-                       dev_dbg(&pdev->dev, "Unknown ROM status ...\n");
-                       break;
+                       return 0;
  
                case RENESAS_ROM_STATUS_ERROR: /* Error State */
                default: /* All other states are marked as "Reserved states" */
@@@ -225,12 -224,13 +224,13 @@@ static int renesas_fw_check_running(str
        u8 fw_state;
        int err;
  
-       /*
-        * Only if device has ROM and loaded FW we can skip loading and
-        * return success. Otherwise (even unknown state), attempt to load FW.
-        */
-       if (renesas_check_rom(pdev) && !renesas_check_rom_state(pdev))
-               return 0;
+       /* Check if device has ROM and loaded, if so skip everything */
+       err = renesas_check_rom(pdev);
+       if (err) { /* we have rom */
+               err = renesas_check_rom_state(pdev);
+               if (!err)
+                       return err;
+       }
  
        /*
         * Test if the device is actually needing the firmware. As most
@@@ -595,7 -595,7 +595,7 @@@ int renesas_xhci_check_request_fw(struc
  
        err = renesas_fw_check_running(pdev);
        /* Continue ahead, if the firmware is already running. */
 -      if (err == 0)
 +      if (!err)
                return 0;
  
        if (err != 1)
@@@ -620,4 -620,9 +620,4 @@@ exit
  }
  EXPORT_SYMBOL_GPL(renesas_xhci_check_request_fw);
  
 -void renesas_xhci_pci_exit(struct pci_dev *dev)
 -{
 -}
 -EXPORT_SYMBOL_GPL(renesas_xhci_pci_exit);
 -
  MODULE_LICENSE("GPL v2");
@@@ -449,6 -449,8 +449,6 @@@ static void xhci_pci_remove(struct pci_
        struct xhci_hcd *xhci;
  
        xhci = hcd_to_xhci(pci_get_drvdata(dev));
 -      if (xhci->quirks & XHCI_RENESAS_FW_QUIRK)
 -              renesas_xhci_pci_exit(dev);
  
        xhci->xhc_state |= XHCI_STATE_REMOVING;
  
@@@ -634,7 -636,14 +634,14 @@@ static const struct pci_device_id pci_i
        { /* end: all zeroes */ }
  };
  MODULE_DEVICE_TABLE(pci, pci_ids);
+ /*
+  * Without CONFIG_USB_XHCI_PCI_RENESAS renesas_xhci_check_request_fw() won't
+  * load firmware, so don't encumber the xhci-pci driver with it.
+  */
+ #if IS_ENABLED(CONFIG_USB_XHCI_PCI_RENESAS)
  MODULE_FIRMWARE("renesas_usb_fw.mem");
+ #endif
  
  /* pci driver glue; this is a "new style" PCI driver module */
  static struct pci_driver xhci_pci_driver = {