@@ -80,10 +80,98 @@ static u32 get_esit(struct xhci_ep_ctx *ep_ctx)
80
80
return esit ;
81
81
}
82
82
83
+ static struct mu3h_sch_tt * find_tt (struct usb_device * udev )
84
+ {
85
+ struct usb_tt * utt = udev -> tt ;
86
+ struct mu3h_sch_tt * tt , * * tt_index , * * ptt ;
87
+ unsigned int port ;
88
+ bool allocated_index = false;
89
+
90
+ if (!utt )
91
+ return NULL ; /* Not below a TT */
92
+
93
+ /*
94
+ * Find/create our data structure.
95
+ * For hubs with a single TT, we get it directly.
96
+ * For hubs with multiple TTs, there's an extra level of pointers.
97
+ */
98
+ tt_index = NULL ;
99
+ if (utt -> multi ) {
100
+ tt_index = utt -> hcpriv ;
101
+ if (!tt_index ) { /* Create the index array */
102
+ tt_index = kcalloc (utt -> hub -> maxchild ,
103
+ sizeof (* tt_index ), GFP_KERNEL );
104
+ if (!tt_index )
105
+ return ERR_PTR (- ENOMEM );
106
+ utt -> hcpriv = tt_index ;
107
+ allocated_index = true;
108
+ }
109
+ port = udev -> ttport - 1 ;
110
+ ptt = & tt_index [port ];
111
+ } else {
112
+ port = 0 ;
113
+ ptt = (struct mu3h_sch_tt * * ) & utt -> hcpriv ;
114
+ }
115
+
116
+ tt = * ptt ;
117
+ if (!tt ) { /* Create the mu3h_sch_tt */
118
+ tt = kzalloc (sizeof (* tt ), GFP_KERNEL );
119
+ if (!tt ) {
120
+ if (allocated_index ) {
121
+ utt -> hcpriv = NULL ;
122
+ kfree (tt_index );
123
+ }
124
+ return ERR_PTR (- ENOMEM );
125
+ }
126
+ INIT_LIST_HEAD (& tt -> ep_list );
127
+ tt -> usb_tt = utt ;
128
+ tt -> tt_port = port ;
129
+ * ptt = tt ;
130
+ }
131
+
132
+ return tt ;
133
+ }
134
+
135
+ /* Release the TT above udev, if it's not in use */
136
+ static void drop_tt (struct usb_device * udev )
137
+ {
138
+ struct usb_tt * utt = udev -> tt ;
139
+ struct mu3h_sch_tt * tt , * * tt_index , * * ptt ;
140
+ int i , cnt ;
141
+
142
+ if (!utt || !utt -> hcpriv )
143
+ return ; /* Not below a TT, or never allocated */
144
+
145
+ cnt = 0 ;
146
+ if (utt -> multi ) {
147
+ tt_index = utt -> hcpriv ;
148
+ ptt = & tt_index [udev -> ttport - 1 ];
149
+ /* How many entries are left in tt_index? */
150
+ for (i = 0 ; i < utt -> hub -> maxchild ; ++ i )
151
+ cnt += !!tt_index [i ];
152
+ } else {
153
+ tt_index = NULL ;
154
+ ptt = (struct mu3h_sch_tt * * )& utt -> hcpriv ;
155
+ }
156
+
157
+ tt = * ptt ;
158
+ if (!tt || !list_empty (& tt -> ep_list ))
159
+ return ; /* never allocated , or still in use*/
160
+
161
+ * ptt = NULL ;
162
+ kfree (tt );
163
+
164
+ if (cnt == 1 ) {
165
+ utt -> hcpriv = NULL ;
166
+ kfree (tt_index );
167
+ }
168
+ }
169
+
83
170
static struct mu3h_sch_ep_info * create_sch_ep (struct usb_device * udev ,
84
171
struct usb_host_endpoint * ep , struct xhci_ep_ctx * ep_ctx )
85
172
{
86
173
struct mu3h_sch_ep_info * sch_ep ;
174
+ struct mu3h_sch_tt * tt = NULL ;
87
175
u32 len_bw_budget_table ;
88
176
size_t mem_size ;
89
177
@@ -101,6 +189,15 @@ static struct mu3h_sch_ep_info *create_sch_ep(struct usb_device *udev,
101
189
if (!sch_ep )
102
190
return ERR_PTR (- ENOMEM );
103
191
192
+ if (is_fs_or_ls (udev -> speed )) {
193
+ tt = find_tt (udev );
194
+ if (IS_ERR (tt )) {
195
+ kfree (sch_ep );
196
+ return ERR_PTR (- ENOMEM );
197
+ }
198
+ }
199
+
200
+ sch_ep -> sch_tt = tt ;
104
201
sch_ep -> ep = ep ;
105
202
106
203
return sch_ep ;
@@ -128,6 +225,8 @@ static void setup_sch_info(struct usb_device *udev,
128
225
CTX_TO_MAX_ESIT_PAYLOAD (le32_to_cpu (ep_ctx -> tx_info ));
129
226
130
227
sch_ep -> esit = get_esit (ep_ctx );
228
+ sch_ep -> ep_type = ep_type ;
229
+ sch_ep -> maxpkt = maxpkt ;
131
230
sch_ep -> offset = 0 ;
132
231
sch_ep -> burst_mode = 0 ;
133
232
sch_ep -> repeat = 0 ;
@@ -197,8 +296,13 @@ static void setup_sch_info(struct usb_device *udev,
197
296
}
198
297
} else if (is_fs_or_ls (udev -> speed )) {
199
298
sch_ep -> pkts = 1 ; /* at most one packet for each microframe */
299
+
300
+ /*
301
+ * num_budget_microframes and cs_count will be updated when
302
+ * check TT for INT_OUT_EP, ISOC/INT_IN_EP type
303
+ */
200
304
sch_ep -> cs_count = DIV_ROUND_UP (maxpkt , FS_PAYLOAD_MAX );
201
- sch_ep -> num_budget_microframes = sch_ep -> cs_count + 2 ;
305
+ sch_ep -> num_budget_microframes = sch_ep -> cs_count ;
202
306
sch_ep -> bw_cost_per_microframe =
203
307
(maxpkt < FS_PAYLOAD_MAX ) ? maxpkt : FS_PAYLOAD_MAX ;
204
308
@@ -212,7 +316,13 @@ static void setup_sch_info(struct usb_device *udev,
212
316
} else { /* INT_IN_EP or ISOC_IN_EP */
213
317
bwb_table [0 ] = 0 ; /* start split */
214
318
bwb_table [1 ] = 0 ; /* idle */
215
- for (i = 2 ; i < sch_ep -> num_budget_microframes ; i ++ )
319
+ /*
320
+ * due to cs_count will be updated according to cs
321
+ * position, assign all remainder budget array
322
+ * elements as @bw_cost_per_microframe, but only first
323
+ * @num_budget_microframes elements will be used later
324
+ */
325
+ for (i = 2 ; i < TT_MICROFRAMES_MAX ; i ++ )
216
326
bwb_table [i ] = sch_ep -> bw_cost_per_microframe ;
217
327
}
218
328
}
@@ -264,6 +374,96 @@ static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
264
374
}
265
375
}
266
376
377
+ static int check_sch_tt (struct usb_device * udev ,
378
+ struct mu3h_sch_ep_info * sch_ep , u32 offset )
379
+ {
380
+ struct mu3h_sch_tt * tt = sch_ep -> sch_tt ;
381
+ u32 extra_cs_count ;
382
+ u32 fs_budget_start ;
383
+ u32 start_ss , last_ss ;
384
+ u32 start_cs , last_cs ;
385
+ int i ;
386
+
387
+ start_ss = offset % 8 ;
388
+ fs_budget_start = (start_ss + 1 ) % 8 ;
389
+
390
+ if (sch_ep -> ep_type == ISOC_OUT_EP ) {
391
+ last_ss = start_ss + sch_ep -> cs_count - 1 ;
392
+
393
+ /*
394
+ * usb_20 spec section11.18:
395
+ * must never schedule Start-Split in Y6
396
+ */
397
+ if (!(start_ss == 7 || last_ss < 6 ))
398
+ return - ERANGE ;
399
+
400
+ for (i = 0 ; i < sch_ep -> cs_count ; i ++ )
401
+ if (test_bit (offset + i , tt -> split_bit_map ))
402
+ return - ERANGE ;
403
+
404
+ } else {
405
+ u32 cs_count = DIV_ROUND_UP (sch_ep -> maxpkt , FS_PAYLOAD_MAX );
406
+
407
+ /*
408
+ * usb_20 spec section11.18:
409
+ * must never schedule Start-Split in Y6
410
+ */
411
+ if (start_ss == 6 )
412
+ return - ERANGE ;
413
+
414
+ /* one uframe for ss + one uframe for idle */
415
+ start_cs = (start_ss + 2 ) % 8 ;
416
+ last_cs = start_cs + cs_count - 1 ;
417
+
418
+ if (last_cs > 7 )
419
+ return - ERANGE ;
420
+
421
+ if (sch_ep -> ep_type == ISOC_IN_EP )
422
+ extra_cs_count = (last_cs == 7 ) ? 1 : 2 ;
423
+ else /* ep_type : INTR IN / INTR OUT */
424
+ extra_cs_count = (fs_budget_start == 6 ) ? 1 : 2 ;
425
+
426
+ cs_count += extra_cs_count ;
427
+ if (cs_count > 7 )
428
+ cs_count = 7 ; /* HW limit */
429
+
430
+ for (i = 0 ; i < cs_count + 2 ; i ++ ) {
431
+ if (test_bit (offset + i , tt -> split_bit_map ))
432
+ return - ERANGE ;
433
+ }
434
+
435
+ sch_ep -> cs_count = cs_count ;
436
+ /* one for ss, the other for idle */
437
+ sch_ep -> num_budget_microframes = cs_count + 2 ;
438
+
439
+ /*
440
+ * if interval=1, maxp >752, num_budge_micoframe is larger
441
+ * than sch_ep->esit, will overstep boundary
442
+ */
443
+ if (sch_ep -> num_budget_microframes > sch_ep -> esit )
444
+ sch_ep -> num_budget_microframes = sch_ep -> esit ;
445
+ }
446
+
447
+ return 0 ;
448
+ }
449
+
450
+ static void update_sch_tt (struct usb_device * udev ,
451
+ struct mu3h_sch_ep_info * sch_ep )
452
+ {
453
+ struct mu3h_sch_tt * tt = sch_ep -> sch_tt ;
454
+ u32 base , num_esit ;
455
+ int i , j ;
456
+
457
+ num_esit = XHCI_MTK_MAX_ESIT / sch_ep -> esit ;
458
+ for (i = 0 ; i < num_esit ; i ++ ) {
459
+ base = sch_ep -> offset + i * sch_ep -> esit ;
460
+ for (j = 0 ; j < sch_ep -> num_budget_microframes ; j ++ )
461
+ set_bit (base + j , tt -> split_bit_map );
462
+ }
463
+
464
+ list_add_tail (& sch_ep -> tt_endpoint , & tt -> ep_list );
465
+ }
466
+
267
467
static int check_sch_bw (struct usb_device * udev ,
268
468
struct mu3h_sch_bw_info * sch_bw , struct mu3h_sch_ep_info * sch_ep )
269
469
{
@@ -273,6 +473,10 @@ static int check_sch_bw(struct usb_device *udev,
273
473
u32 min_index ;
274
474
u32 worst_bw ;
275
475
u32 bw_boundary ;
476
+ u32 min_num_budget ;
477
+ u32 min_cs_count ;
478
+ bool tt_offset_ok = false;
479
+ int ret ;
276
480
277
481
esit = sch_ep -> esit ;
278
482
@@ -282,26 +486,30 @@ static int check_sch_bw(struct usb_device *udev,
282
486
*/
283
487
min_bw = ~0 ;
284
488
min_index = 0 ;
489
+ min_cs_count = sch_ep -> cs_count ;
490
+ min_num_budget = sch_ep -> num_budget_microframes ;
285
491
for (offset = 0 ; offset < esit ; offset ++ ) {
492
+ if (is_fs_or_ls (udev -> speed )) {
493
+ ret = check_sch_tt (udev , sch_ep , offset );
494
+ if (ret )
495
+ continue ;
496
+ else
497
+ tt_offset_ok = true;
498
+ }
499
+
286
500
if ((offset + sch_ep -> num_budget_microframes ) > sch_ep -> esit )
287
501
break ;
288
502
289
- /*
290
- * usb_20 spec section11.18:
291
- * must never schedule Start-Split in Y6
292
- */
293
- if (is_fs_or_ls (udev -> speed ) && (offset % 8 == 6 ))
294
- continue ;
295
-
296
503
worst_bw = get_max_bw (sch_bw , sch_ep , offset );
297
504
if (min_bw > worst_bw ) {
298
505
min_bw = worst_bw ;
299
506
min_index = offset ;
507
+ min_cs_count = sch_ep -> cs_count ;
508
+ min_num_budget = sch_ep -> num_budget_microframes ;
300
509
}
301
510
if (min_bw == 0 )
302
511
break ;
303
512
}
304
- sch_ep -> offset = min_index ;
305
513
306
514
bw_boundary = (udev -> speed == USB_SPEED_SUPER )
307
515
? SS_BW_BOUNDARY : HS_BW_BOUNDARY ;
@@ -310,6 +518,18 @@ static int check_sch_bw(struct usb_device *udev,
310
518
if (min_bw > bw_boundary )
311
519
return - ERANGE ;
312
520
521
+ sch_ep -> offset = min_index ;
522
+ sch_ep -> cs_count = min_cs_count ;
523
+ sch_ep -> num_budget_microframes = min_num_budget ;
524
+
525
+ if (is_fs_or_ls (udev -> speed )) {
526
+ /* all offset for tt is not ok*/
527
+ if (!tt_offset_ok )
528
+ return - ERANGE ;
529
+
530
+ update_sch_tt (udev , sch_ep );
531
+ }
532
+
313
533
/* update bus bandwidth info */
314
534
update_bus_bw (sch_bw , sch_ep , 1 );
315
535
@@ -415,6 +635,9 @@ int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
415
635
ret = check_sch_bw (udev , sch_bw , sch_ep );
416
636
if (ret ) {
417
637
xhci_err (xhci , "Not enough bandwidth!\n" );
638
+ if (is_fs_or_ls (udev -> speed ))
639
+ drop_tt (udev );
640
+
418
641
kfree (sch_ep );
419
642
return - ENOSPC ;
420
643
}
@@ -466,6 +689,10 @@ void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
466
689
if (sch_ep -> ep == ep ) {
467
690
update_bus_bw (sch_bw , sch_ep , 0 );
468
691
list_del (& sch_ep -> endpoint );
692
+ if (is_fs_or_ls (udev -> speed )) {
693
+ list_del (& sch_ep -> tt_endpoint );
694
+ drop_tt (udev );
695
+ }
469
696
kfree (sch_ep );
470
697
break ;
471
698
}
0 commit comments