@@ -996,8 +996,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action)
996996
997997 /*
998998 * All stream eps will reinitiate stream on NoStream
999- * rejection until we can determine that the host can
1000- * prime after the first transfer.
999+ * rejection.
10011000 *
10021001 * However, if the controller is capable of
10031002 * TXF_FLUSH_BYPASS, then IN direction endpoints will
@@ -3300,6 +3299,50 @@ static int dwc3_gadget_init_out_endpoint(struct dwc3_ep *dep)
33003299 return dwc3_alloc_trb_pool (dep );
33013300}
33023301
3302+ #define nostream_work_to_dep (w ) (container_of(to_delayed_work(w), struct dwc3_ep, nostream_work))
3303+ static void dwc3_nostream_work (struct work_struct * work )
3304+ {
3305+ struct dwc3_ep * dep = nostream_work_to_dep (work );
3306+ struct dwc3 * dwc = dep -> dwc ;
3307+ unsigned long flags ;
3308+
3309+ spin_lock_irqsave (& dwc -> lock , flags );
3310+ if (dep -> flags & DWC3_EP_STREAM_PRIMED )
3311+ goto out ;
3312+
3313+ if ((dep -> flags & DWC3_EP_IGNORE_NEXT_NOSTREAM ) ||
3314+ (!DWC3_MST_CAPABLE (& dwc -> hwparams ) &&
3315+ !(dep -> flags & DWC3_EP_WAIT_TRANSFER_COMPLETE )))
3316+ goto out ;
3317+ /*
3318+ * If the host rejects a stream due to no active stream, by the
3319+ * USB and xHCI spec, the endpoint will be put back to idle
3320+ * state. When the host is ready (buffer added/updated), it will
3321+ * prime the endpoint to inform the usb device controller. This
3322+ * triggers the device controller to issue ERDY to restart the
3323+ * stream. However, some hosts don't follow this and keep the
3324+ * endpoint in the idle state. No prime will come despite host
3325+ * streams are updated, and the device controller will not be
3326+ * triggered to generate ERDY to move the next stream data. To
3327+ * workaround this and maintain compatibility with various
3328+ * hosts, force to reinitiate the stream until the host is ready
3329+ * instead of waiting for the host to prime the endpoint.
3330+ */
3331+ if (DWC3_VER_IS_WITHIN (DWC32 , 100 A , ANY )) {
3332+ unsigned int cmd = DWC3_DGCMD_SET_ENDPOINT_PRIME ;
3333+
3334+ dwc3_send_gadget_generic_command (dwc , cmd , dep -> number );
3335+ } else {
3336+ dep -> flags |= DWC3_EP_DELAY_START ;
3337+ dwc3_stop_active_transfer (dep , true, true);
3338+ spin_unlock_irqrestore (& dwc -> lock , flags );
3339+ return ;
3340+ }
3341+ out :
3342+ dep -> flags &= ~DWC3_EP_IGNORE_NEXT_NOSTREAM ;
3343+ spin_unlock_irqrestore (& dwc -> lock , flags );
3344+ }
3345+
33033346static int dwc3_gadget_init_endpoint (struct dwc3 * dwc , u8 epnum )
33043347{
33053348 struct dwc3_ep * dep ;
@@ -3345,6 +3388,7 @@ static int dwc3_gadget_init_endpoint(struct dwc3 *dwc, u8 epnum)
33453388 INIT_LIST_HEAD (& dep -> pending_list );
33463389 INIT_LIST_HEAD (& dep -> started_list );
33473390 INIT_LIST_HEAD (& dep -> cancelled_list );
3391+ INIT_DELAYED_WORK (& dep -> nostream_work , dwc3_nostream_work );
33483392
33493393 dwc3_debugfs_create_endpoint_dir (dep );
33503394
@@ -3744,66 +3788,27 @@ static void dwc3_gadget_endpoint_command_complete(struct dwc3_ep *dep,
37443788static void dwc3_gadget_endpoint_stream_event (struct dwc3_ep * dep ,
37453789 const struct dwc3_event_depevt * event )
37463790{
3747- struct dwc3 * dwc = dep -> dwc ;
3748-
37493791 if (event -> status == DEPEVT_STREAMEVT_FOUND ) {
3750- dep -> flags |= DWC3_EP_FIRST_STREAM_PRIMED ;
3751- goto out ;
3792+ cancel_delayed_work (& dep -> nostream_work );
3793+ dep -> flags |= DWC3_EP_STREAM_PRIMED ;
3794+ dep -> flags &= ~DWC3_EP_IGNORE_NEXT_NOSTREAM ;
3795+ return ;
37523796 }
37533797
37543798 /* Note: NoStream rejection event param value is 0 and not 0xFFFF */
37553799 switch (event -> parameters ) {
37563800 case DEPEVT_STREAM_PRIME :
3757- /*
3758- * If the host can properly transition the endpoint state from
3759- * idle to prime after a NoStream rejection, there's no need to
3760- * force restarting the endpoint to reinitiate the stream. To
3761- * simplify the check, assume the host follows the USB spec if
3762- * it primed the endpoint more than once.
3763- */
3764- if (dep -> flags & DWC3_EP_FORCE_RESTART_STREAM ) {
3765- if (dep -> flags & DWC3_EP_FIRST_STREAM_PRIMED )
3766- dep -> flags &= ~DWC3_EP_FORCE_RESTART_STREAM ;
3767- else
3768- dep -> flags |= DWC3_EP_FIRST_STREAM_PRIMED ;
3769- }
3770-
3801+ cancel_delayed_work (& dep -> nostream_work );
3802+ dep -> flags |= DWC3_EP_STREAM_PRIMED ;
3803+ dep -> flags &= ~DWC3_EP_IGNORE_NEXT_NOSTREAM ;
37713804 break ;
37723805 case DEPEVT_STREAM_NOSTREAM :
3773- if ((dep -> flags & DWC3_EP_IGNORE_NEXT_NOSTREAM ) ||
3774- !(dep -> flags & DWC3_EP_FORCE_RESTART_STREAM ) ||
3775- (!DWC3_MST_CAPABLE (& dwc -> hwparams ) &&
3776- !(dep -> flags & DWC3_EP_WAIT_TRANSFER_COMPLETE )))
3777- break ;
3778-
3779- /*
3780- * If the host rejects a stream due to no active stream, by the
3781- * USB and xHCI spec, the endpoint will be put back to idle
3782- * state. When the host is ready (buffer added/updated), it will
3783- * prime the endpoint to inform the usb device controller. This
3784- * triggers the device controller to issue ERDY to restart the
3785- * stream. However, some hosts don't follow this and keep the
3786- * endpoint in the idle state. No prime will come despite host
3787- * streams are updated, and the device controller will not be
3788- * triggered to generate ERDY to move the next stream data. To
3789- * workaround this and maintain compatibility with various
3790- * hosts, force to reinitiate the stream until the host is ready
3791- * instead of waiting for the host to prime the endpoint.
3792- */
3793- if (DWC3_VER_IS_WITHIN (DWC32 , 100 A , ANY )) {
3794- unsigned int cmd = DWC3_DGCMD_SET_ENDPOINT_PRIME ;
3795-
3796- dwc3_send_gadget_generic_command (dwc , cmd , dep -> number );
3797- } else {
3798- dep -> flags |= DWC3_EP_DELAY_START ;
3799- dwc3_stop_active_transfer (dep , true, true);
3800- return ;
3801- }
3806+ dep -> flags &= ~DWC3_EP_STREAM_PRIMED ;
3807+ if (dep -> flags & DWC3_EP_FORCE_RESTART_STREAM )
3808+ queue_delayed_work (system_wq , & dep -> nostream_work ,
3809+ msecs_to_jiffies (100 ));
38023810 break ;
38033811 }
3804-
3805- out :
3806- dep -> flags &= ~DWC3_EP_IGNORE_NEXT_NOSTREAM ;
38073812}
38083813
38093814static void dwc3_endpoint_interrupt (struct dwc3 * dwc ,
0 commit comments