@@ -996,8 +996,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action)
996
996
997
997
/*
998
998
* 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.
1001
1000
*
1002
1001
* However, if the controller is capable of
1003
1002
* TXF_FLUSH_BYPASS, then IN direction endpoints will
@@ -3300,6 +3299,50 @@ static int dwc3_gadget_init_out_endpoint(struct dwc3_ep *dep)
3300
3299
return dwc3_alloc_trb_pool (dep );
3301
3300
}
3302
3301
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
+
3303
3346
static int dwc3_gadget_init_endpoint (struct dwc3 * dwc , u8 epnum )
3304
3347
{
3305
3348
struct dwc3_ep * dep ;
@@ -3345,6 +3388,7 @@ static int dwc3_gadget_init_endpoint(struct dwc3 *dwc, u8 epnum)
3345
3388
INIT_LIST_HEAD (& dep -> pending_list );
3346
3389
INIT_LIST_HEAD (& dep -> started_list );
3347
3390
INIT_LIST_HEAD (& dep -> cancelled_list );
3391
+ INIT_DELAYED_WORK (& dep -> nostream_work , dwc3_nostream_work );
3348
3392
3349
3393
dwc3_debugfs_create_endpoint_dir (dep );
3350
3394
@@ -3744,66 +3788,27 @@ static void dwc3_gadget_endpoint_command_complete(struct dwc3_ep *dep,
3744
3788
static void dwc3_gadget_endpoint_stream_event (struct dwc3_ep * dep ,
3745
3789
const struct dwc3_event_depevt * event )
3746
3790
{
3747
- struct dwc3 * dwc = dep -> dwc ;
3748
-
3749
3791
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 ;
3752
3796
}
3753
3797
3754
3798
/* Note: NoStream rejection event param value is 0 and not 0xFFFF */
3755
3799
switch (event -> parameters ) {
3756
3800
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 ;
3771
3804
break ;
3772
3805
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 ));
3802
3810
break ;
3803
3811
}
3804
-
3805
- out :
3806
- dep -> flags &= ~DWC3_EP_IGNORE_NEXT_NOSTREAM ;
3807
3812
}
3808
3813
3809
3814
static void dwc3_endpoint_interrupt (struct dwc3 * dwc ,
0 commit comments