@@ -385,24 +385,66 @@ static void dwc3_free_trb_pool(struct dwc3_ep *dep)
385385 dep -> trb_pool_dma = 0 ;
386386}
387387
388+ static int dwc3_gadget_set_xfer_resource (struct dwc3 * dwc , struct dwc3_ep * dep );
389+
390+ /**
391+ * dwc3_gadget_start_config - Configure EP resources
392+ * @dwc: pointer to our controller context structure
393+ * @dep: endpoint that is being enabled
394+ *
395+ * The assignment of transfer resources cannot perfectly follow the
396+ * data book due to the fact that the controller driver does not have
397+ * all knowledge of the configuration in advance. It is given this
398+ * information piecemeal by the composite gadget framework after every
399+ * SET_CONFIGURATION and SET_INTERFACE. Trying to follow the databook
400+ * programming model in this scenario can cause errors. For two
401+ * reasons:
402+ *
403+ * 1) The databook says to do DEPSTARTCFG for every SET_CONFIGURATION
404+ * and SET_INTERFACE (8.1.5). This is incorrect in the scenario of
405+ * multiple interfaces.
406+ *
407+ * 2) The databook does not mention doing more DEPXFERCFG for new
408+ * endpoint on alt setting (8.1.6).
409+ *
410+ * The following simplified method is used instead:
411+ *
412+ * All hardware endpoints can be assigned a transfer resource and this
413+ * setting will stay persistent until either a core reset or
414+ * hibernation. So whenever we do a DEPSTARTCFG(0) we can go ahead and
415+ * do DEPXFERCFG for every hardware endpoint as well. We are
416+ * guaranteed that there are as many transfer resources as endpoints.
417+ *
418+ * This function is called for each endpoint when it is being enabled
419+ * but is triggered only when called for EP0-out, which always happens
420+ * first, and which should only happen in one of the above conditions.
421+ */
388422static int dwc3_gadget_start_config (struct dwc3 * dwc , struct dwc3_ep * dep )
389423{
390424 struct dwc3_gadget_ep_cmd_params params ;
391425 u32 cmd ;
426+ int i ;
427+ int ret ;
428+
429+ if (dep -> number )
430+ return 0 ;
392431
393432 memset (& params , 0x00 , sizeof (params ));
433+ cmd = DWC3_DEPCMD_DEPSTARTCFG ;
394434
395- if (dep -> number != 1 ) {
396- cmd = DWC3_DEPCMD_DEPSTARTCFG ;
397- /* XferRscIdx == 0 for ep0 and 2 for the remaining */
398- if (dep -> number > 1 ) {
399- if (dwc -> start_config_issued )
400- return 0 ;
401- dwc -> start_config_issued = true;
402- cmd |= DWC3_DEPCMD_PARAM (2 );
403- }
435+ ret = dwc3_send_gadget_ep_cmd (dwc , 0 , cmd , & params );
436+ if (ret )
437+ return ret ;
404438
405- return dwc3_send_gadget_ep_cmd (dwc , 0 , cmd , & params );
439+ for (i = 0 ; i < DWC3_ENDPOINTS_NUM ; i ++ ) {
440+ struct dwc3_ep * dep = dwc -> eps [i ];
441+
442+ if (!dep )
443+ continue ;
444+
445+ ret = dwc3_gadget_set_xfer_resource (dwc , dep );
446+ if (ret )
447+ return ret ;
406448 }
407449
408450 return 0 ;
@@ -516,10 +558,6 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
516558 struct dwc3_trb * trb_st_hw ;
517559 struct dwc3_trb * trb_link ;
518560
519- ret = dwc3_gadget_set_xfer_resource (dwc , dep );
520- if (ret )
521- return ret ;
522-
523561 dep -> endpoint .desc = desc ;
524562 dep -> comp_desc = comp_desc ;
525563 dep -> type = usb_endpoint_type (desc );
@@ -1636,8 +1674,6 @@ static int dwc3_gadget_start(struct usb_gadget *g,
16361674 }
16371675 dwc3_writel (dwc -> regs , DWC3_DCFG , reg );
16381676
1639- dwc -> start_config_issued = false;
1640-
16411677 /* Start with SuperSpeed Default */
16421678 dwc3_gadget_ep0_desc .wMaxPacketSize = cpu_to_le16 (512 );
16431679
@@ -2237,7 +2273,6 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
22372273 dwc3_writel (dwc -> regs , DWC3_DCTL , reg );
22382274
22392275 dwc3_disconnect_gadget (dwc );
2240- dwc -> start_config_issued = false;
22412276
22422277 dwc -> gadget .speed = USB_SPEED_UNKNOWN ;
22432278 dwc -> setup_packet_pending = false;
@@ -2288,7 +2323,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
22882323
22892324 dwc3_stop_active_transfers (dwc );
22902325 dwc3_clear_stall_all_ep (dwc );
2291- dwc -> start_config_issued = false;
22922326
22932327 /* Reset device address to zero */
22942328 reg = dwc3_readl (dwc -> regs , DWC3_DCFG );
0 commit comments