@@ -3186,9 +3186,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
3186
3186
struct xhci_td * td ;
3187
3187
struct scatterlist * sg ;
3188
3188
int num_sgs ;
3189
- int trb_buff_len , this_sg_len , running_total ;
3189
+ int trb_buff_len , this_sg_len , running_total , ret ;
3190
3190
unsigned int total_packet_count ;
3191
+ bool zero_length_needed ;
3191
3192
bool first_trb ;
3193
+ int last_trb_num ;
3192
3194
u64 addr ;
3193
3195
bool more_trbs_coming ;
3194
3196
@@ -3204,13 +3206,27 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
3204
3206
total_packet_count = DIV_ROUND_UP (urb -> transfer_buffer_length ,
3205
3207
usb_endpoint_maxp (& urb -> ep -> desc ));
3206
3208
3207
- trb_buff_len = prepare_transfer (xhci , xhci -> devs [slot_id ],
3209
+ ret = prepare_transfer (xhci , xhci -> devs [slot_id ],
3208
3210
ep_index , urb -> stream_id ,
3209
3211
num_trbs , urb , 0 , mem_flags );
3210
- if (trb_buff_len < 0 )
3211
- return trb_buff_len ;
3212
+ if (ret < 0 )
3213
+ return ret ;
3212
3214
3213
3215
urb_priv = urb -> hcpriv ;
3216
+
3217
+ /* Deal with URB_ZERO_PACKET - need one more td/trb */
3218
+ zero_length_needed = urb -> transfer_flags & URB_ZERO_PACKET &&
3219
+ urb_priv -> length == 2 ;
3220
+ if (zero_length_needed ) {
3221
+ num_trbs ++ ;
3222
+ xhci_dbg (xhci , "Creating zero length td.\n" );
3223
+ ret = prepare_transfer (xhci , xhci -> devs [slot_id ],
3224
+ ep_index , urb -> stream_id ,
3225
+ 1 , urb , 1 , mem_flags );
3226
+ if (ret < 0 )
3227
+ return ret ;
3228
+ }
3229
+
3214
3230
td = urb_priv -> td [0 ];
3215
3231
3216
3232
/*
@@ -3240,6 +3256,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
3240
3256
trb_buff_len = urb -> transfer_buffer_length ;
3241
3257
3242
3258
first_trb = true;
3259
+ last_trb_num = zero_length_needed ? 2 : 1 ;
3243
3260
/* Queue the first TRB, even if it's zero-length */
3244
3261
do {
3245
3262
u32 field = 0 ;
@@ -3257,12 +3274,15 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
3257
3274
/* Chain all the TRBs together; clear the chain bit in the last
3258
3275
* TRB to indicate it's the last TRB in the chain.
3259
3276
*/
3260
- if (num_trbs > 1 ) {
3277
+ if (num_trbs > last_trb_num ) {
3261
3278
field |= TRB_CHAIN ;
3262
- } else {
3263
- /* FIXME - add check for ZERO_PACKET flag before this */
3279
+ } else if (num_trbs == last_trb_num ) {
3264
3280
td -> last_trb = ep_ring -> enqueue ;
3265
3281
field |= TRB_IOC ;
3282
+ } else if (zero_length_needed && num_trbs == 1 ) {
3283
+ trb_buff_len = 0 ;
3284
+ urb_priv -> td [1 ]-> last_trb = ep_ring -> enqueue ;
3285
+ field |= TRB_IOC ;
3266
3286
}
3267
3287
3268
3288
/* Only set interrupt on short packet for IN endpoints */
@@ -3324,7 +3344,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
3324
3344
if (running_total + trb_buff_len > urb -> transfer_buffer_length )
3325
3345
trb_buff_len =
3326
3346
urb -> transfer_buffer_length - running_total ;
3327
- } while (running_total < urb -> transfer_buffer_length );
3347
+ } while (num_trbs > 0 );
3328
3348
3329
3349
check_trb_math (urb , num_trbs , running_total );
3330
3350
giveback_first_trb (xhci , slot_id , ep_index , urb -> stream_id ,
@@ -3342,7 +3362,9 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
3342
3362
int num_trbs ;
3343
3363
struct xhci_generic_trb * start_trb ;
3344
3364
bool first_trb ;
3365
+ int last_trb_num ;
3345
3366
bool more_trbs_coming ;
3367
+ bool zero_length_needed ;
3346
3368
int start_cycle ;
3347
3369
u32 field , length_field ;
3348
3370
@@ -3381,6 +3403,20 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
3381
3403
return ret ;
3382
3404
3383
3405
urb_priv = urb -> hcpriv ;
3406
+
3407
+ /* Deal with URB_ZERO_PACKET - need one more td/trb */
3408
+ zero_length_needed = urb -> transfer_flags & URB_ZERO_PACKET &&
3409
+ urb_priv -> length == 2 ;
3410
+ if (zero_length_needed ) {
3411
+ num_trbs ++ ;
3412
+ xhci_dbg (xhci , "Creating zero length td.\n" );
3413
+ ret = prepare_transfer (xhci , xhci -> devs [slot_id ],
3414
+ ep_index , urb -> stream_id ,
3415
+ 1 , urb , 1 , mem_flags );
3416
+ if (ret < 0 )
3417
+ return ret ;
3418
+ }
3419
+
3384
3420
td = urb_priv -> td [0 ];
3385
3421
3386
3422
/*
@@ -3402,7 +3438,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
3402
3438
trb_buff_len = urb -> transfer_buffer_length ;
3403
3439
3404
3440
first_trb = true;
3405
-
3441
+ last_trb_num = zero_length_needed ? 2 : 1 ;
3406
3442
/* Queue the first TRB, even if it's zero-length */
3407
3443
do {
3408
3444
u32 remainder = 0 ;
@@ -3468,7 +3504,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
3468
3504
trb_buff_len = urb -> transfer_buffer_length - running_total ;
3469
3505
if (trb_buff_len > TRB_MAX_BUFF_SIZE )
3470
3506
trb_buff_len = TRB_MAX_BUFF_SIZE ;
3471
- } while (running_total < urb -> transfer_buffer_length );
3507
+ } while (num_trbs > 0 );
3472
3508
3473
3509
check_trb_math (urb , num_trbs , running_total );
3474
3510
giveback_first_trb (xhci , slot_id , ep_index , urb -> stream_id ,
0 commit comments