1 #include "xhci-mtk-scheduler.h"
2 #include <linux/kernel.h> /* printk() */
4 static struct sch_ep
**ss_out_eps
[MAX_EP_NUM
];
5 static struct sch_ep
**ss_in_eps
[MAX_EP_NUM
];
6 static struct sch_ep
**hs_eps
[MAX_EP_NUM
]; //including tt isoc
7 static struct sch_ep
**tt_intr_eps
[MAX_EP_NUM
];
10 int mtk_xhci_scheduler_init(void){
13 for(i
=0; i
<MAX_EP_NUM
; i
++){
16 for(i
=0; i
<MAX_EP_NUM
; i
++){
19 for(i
=0; i
<MAX_EP_NUM
; i
++){
22 for(i
=0; i
<MAX_EP_NUM
; i
++){
23 tt_intr_eps
[i
] = NULL
;
28 int add_sch_ep(int dev_speed
, int is_in
, int isTT
, int ep_type
, int maxp
, int interval
, int burst
29 , int mult
, int offset
, int repeat
, int pkts
, int cs_count
, int burst_mode
30 , int bw_cost
, mtk_u32
*ep
, struct sch_ep
*tmp_ep
){
32 struct sch_ep
**ep_array
;
35 if(is_in
&& dev_speed
== USB_SPEED_SUPER
){
36 ep_array
= (struct sch_ep
**)ss_in_eps
;
38 else if(dev_speed
== USB_SPEED_SUPER
){
39 ep_array
= (struct sch_ep
**)ss_out_eps
;
41 else if(dev_speed
== USB_SPEED_HIGH
|| (isTT
&& ep_type
== USB_EP_ISOC
)){
42 ep_array
= (struct sch_ep
**)hs_eps
;
45 ep_array
= (struct sch_ep
**)tt_intr_eps
;
47 for(i
=0; i
<MAX_EP_NUM
; i
++){
48 if(ep_array
[i
] == NULL
){
49 tmp_ep
->dev_speed
= dev_speed
;
51 tmp_ep
->is_in
= is_in
;
52 tmp_ep
->ep_type
= ep_type
;
54 tmp_ep
->interval
= interval
;
55 tmp_ep
->burst
= burst
;
57 tmp_ep
->offset
= offset
;
58 tmp_ep
->repeat
= repeat
;
60 tmp_ep
->cs_count
= cs_count
;
61 tmp_ep
->burst_mode
= burst_mode
;
62 tmp_ep
->bw_cost
= bw_cost
;
71 int count_ss_bw(int is_in
, int ep_type
, int maxp
, int interval
, int burst
, int mult
, int offset
, int repeat
75 int final_bw_required
;
76 int bw_required_per_repeat
;
78 struct sch_ep
*cur_sch_ep
;
79 struct sch_ep
**ep_array
;
90 ep_array
= (struct sch_ep
**)ss_in_eps
;
93 ep_array
= (struct sch_ep
**)ss_out_eps
;
101 final_bw_required
= 0;
102 for(i
=0; i
<MAX_EP_NUM
; i
++){
103 cur_sch_ep
= ep_array
[i
];
104 if(cur_sch_ep
== NULL
){
107 ep_interval
= cur_sch_ep
->interval
;
108 ep_offset
= cur_sch_ep
->offset
;
109 if(cur_sch_ep
->repeat
== 0){
110 if(ep_interval
>= interval
){
111 tmp_offset
= ep_offset
+ ep_interval
- offset
;
112 tmp_interval
= interval
;
115 tmp_offset
= offset
+ interval
- ep_offset
;
116 tmp_interval
= ep_interval
;
118 if(tmp_offset
% tmp_interval
== 0){
119 final_bw_required
+= cur_sch_ep
->bw_cost
;
123 ep_repeat
= cur_sch_ep
->repeat
;
124 ep_mult
= cur_sch_ep
->mult
;
125 for(k
=0; k
<=ep_mult
; k
++){
126 cur_ep_offset
= ep_offset
+(k
*ep_mult
);
127 if(ep_interval
>= interval
){
128 tmp_offset
= cur_ep_offset
+ ep_interval
- offset
;
129 tmp_interval
= interval
;
132 tmp_offset
= offset
+ interval
- cur_ep_offset
;
133 tmp_interval
= ep_interval
;
135 if(tmp_offset
% tmp_interval
== 0){
136 final_bw_required
+= cur_sch_ep
->bw_cost
;
142 final_bw_required
+= td_size
;
145 bw_required_per_repeat
= maxp
* (burst
+1);
146 for(j
=0; j
<=mult
; j
++){
148 cur_offset
= offset
+(j
*repeat
);
149 for(i
=0; i
<MAX_EP_NUM
; i
++){
150 cur_sch_ep
= ep_array
[i
];
151 if(cur_sch_ep
== NULL
){
154 ep_interval
= cur_sch_ep
->interval
;
155 ep_offset
= cur_sch_ep
->offset
;
156 if(cur_sch_ep
->repeat
== 0){
157 if(ep_interval
>= interval
){
158 tmp_offset
= ep_offset
+ ep_interval
- cur_offset
;
159 tmp_interval
= interval
;
162 tmp_offset
= cur_offset
+ interval
- ep_offset
;
163 tmp_interval
= ep_interval
;
165 if(tmp_offset
% tmp_interval
== 0){
166 tmp_bw_required
+= cur_sch_ep
->bw_cost
;
170 ep_repeat
= cur_sch_ep
->repeat
;
171 ep_mult
= cur_sch_ep
->mult
;
172 for(k
=0; k
<=ep_mult
; k
++){
173 cur_ep_offset
= ep_offset
+(k
*ep_repeat
);
174 if(ep_interval
>= interval
){
175 tmp_offset
= cur_ep_offset
+ ep_interval
- cur_offset
;
176 tmp_interval
= interval
;
179 tmp_offset
= cur_offset
+ interval
- cur_ep_offset
;
180 tmp_interval
= ep_interval
;
182 if(tmp_offset
% tmp_interval
== 0){
183 tmp_bw_required
+= cur_sch_ep
->bw_cost
;
189 bw_required
[j
] = tmp_bw_required
;
191 final_bw_required
= SS_BW_BOUND
;
192 for(j
=0; j
<=mult
; j
++){
193 if(bw_required
[j
] < final_bw_required
){
194 final_bw_required
= bw_required
[j
];
197 final_bw_required
+= bw_required_per_repeat
;
199 return final_bw_required
;
202 int count_hs_bw(int ep_type
, int maxp
, int interval
, int offset
, int td_size
){
205 struct sch_ep
*cur_sch_ep
;
210 int cur_tt_isoc_interval
; //for isoc tt check
213 for(i
=0; i
<MAX_EP_NUM
; i
++){
215 cur_sch_ep
= (struct sch_ep
*)hs_eps
[i
];
216 if(cur_sch_ep
== NULL
){
219 ep_offset
= cur_sch_ep
->offset
;
220 ep_interval
= cur_sch_ep
->interval
;
222 if(cur_sch_ep
->isTT
&& cur_sch_ep
->ep_type
== USB_EP_ISOC
){
223 cur_tt_isoc_interval
= ep_interval
<<3;
224 if(ep_interval
>= interval
){
225 tmp_offset
= ep_offset
+ cur_tt_isoc_interval
- offset
;
226 tmp_interval
= interval
;
229 tmp_offset
= offset
+ interval
- ep_offset
;
230 tmp_interval
= cur_tt_isoc_interval
;
232 if(cur_sch_ep
->is_in
){
233 if((tmp_offset
%tmp_interval
>=2) && (tmp_offset
%tmp_interval
<= cur_sch_ep
->cs_count
)){
238 if(tmp_offset
%tmp_interval
<= cur_sch_ep
->cs_count
){
244 if(ep_interval
>= interval
){
245 tmp_offset
= ep_offset
+ ep_interval
- offset
;
246 tmp_interval
= interval
;
249 tmp_offset
= offset
+ interval
- ep_offset
;
250 tmp_interval
= ep_interval
;
252 if(tmp_offset
%tmp_interval
== 0){
253 bw_required
+= cur_sch_ep
->bw_cost
;
257 bw_required
+= td_size
;
261 int count_tt_isoc_bw(int is_in
, int maxp
, int interval
, int offset
, int td_size
){
263 int mframe_idx
, frame_idx
, s_frame
, s_mframe
, cur_mframe
;
264 int bw_required
, max_bw
;
269 struct sch_ep
*cur_sch_ep
;
273 int tt_isoc_interval
; //for isoc tt check
274 int cur_tt_isoc_interval
; //for isoc tt check
280 tt_isoc_interval
= interval
<<3; //frame to mframe
286 ss_cs_count
= (maxp
+ (188 - 1))/188;
288 cs_mframe
= offset
%8 + 2 + ss_cs_count
;
291 else if (cs_mframe
== 7)
293 else if (cs_mframe
> 8)
300 for(cur_mframe
= offset
+i
; i
<ss_cs_count
; cur_mframe
++, i
++){
302 for(j
=0; j
<MAX_EP_NUM
; j
++){
303 cur_sch_ep
= (struct sch_ep
*)hs_eps
[j
];
304 if(cur_sch_ep
== NULL
){
307 ep_offset
= cur_sch_ep
->offset
;
308 ep_interval
= cur_sch_ep
->interval
;
309 if(cur_sch_ep
->isTT
&& cur_sch_ep
->ep_type
== USB_EP_ISOC
){
311 //check if mframe offset overlap
312 //if overlap, add 188 to the bw
313 cur_tt_isoc_interval
= ep_interval
<<3;
314 if(cur_tt_isoc_interval
>= tt_isoc_interval
){
315 tmp_offset
= (ep_offset
+cur_tt_isoc_interval
) - cur_mframe
;
316 tmp_interval
= tt_isoc_interval
;
319 tmp_offset
= (cur_mframe
+tt_isoc_interval
) - ep_offset
;
320 tmp_interval
= cur_tt_isoc_interval
;
322 if(cur_sch_ep
->is_in
){
323 if((tmp_offset
%tmp_interval
>=2) && (tmp_offset
%tmp_interval
<= cur_sch_ep
->cs_count
)){
328 if(tmp_offset
%tmp_interval
<= cur_sch_ep
->cs_count
){
334 else if(cur_sch_ep
->ep_type
== USB_EP_INT
|| cur_sch_ep
->ep_type
== USB_EP_ISOC
){
336 if(ep_interval
>= tt_isoc_interval
){
337 tmp_offset
= (ep_offset
+ep_interval
) - cur_mframe
;
338 tmp_interval
= tt_isoc_interval
;
341 tmp_offset
= (cur_mframe
+tt_isoc_interval
) - ep_offset
;
342 tmp_interval
= ep_interval
;
344 if(tmp_offset
%tmp_interval
== 0){
345 bw_required
+= cur_sch_ep
->bw_cost
;
350 if(bw_required
> max_bw
){
351 max_bw
= bw_required
;
357 int count_tt_intr_bw(int interval
, int frame_offset
){
358 //check all eps in tt_intr_eps
366 struct sch_ep
*cur_sch_ep
;
368 for(i
=0; i
<MAX_EP_NUM
; i
++){
369 cur_sch_ep
= (struct sch_ep
*)tt_intr_eps
[i
];
370 if(cur_sch_ep
== NULL
){
373 ep_offset
= cur_sch_ep
->offset
;
374 ep_interval
= cur_sch_ep
->interval
;
375 if(ep_interval
>= interval
){
376 tmp_offset
= ep_offset
+ ep_interval
- frame_offset
;
377 tmp_interval
= interval
;
380 tmp_offset
= frame_offset
+ interval
- ep_offset
;
381 tmp_interval
= ep_interval
;
384 if(tmp_offset
%tmp_interval
==0){
391 struct sch_ep
* mtk_xhci_scheduler_remove_ep(int dev_speed
, int is_in
, int isTT
, int ep_type
, mtk_u32
*ep
){
393 struct sch_ep
**ep_array
;
394 struct sch_ep
*cur_ep
;
396 if (is_in
&& dev_speed
== USB_SPEED_SUPER
) {
397 ep_array
= (struct sch_ep
**)ss_in_eps
;
399 else if (dev_speed
== USB_SPEED_SUPER
) {
400 ep_array
= (struct sch_ep
**)ss_out_eps
;
402 else if (dev_speed
== USB_SPEED_HIGH
|| (isTT
&& ep_type
== USB_EP_ISOC
)) {
403 ep_array
= (struct sch_ep
**)hs_eps
;
406 ep_array
= (struct sch_ep
**)tt_intr_eps
;
408 for (i
= 0; i
< MAX_EP_NUM
; i
++) {
409 cur_ep
= (struct sch_ep
*)ep_array
[i
];
410 if(cur_ep
!= NULL
&& cur_ep
->ep
== ep
){
418 int mtk_xhci_scheduler_add_ep(int dev_speed
, int is_in
, int isTT
, int ep_type
, int maxp
, int interval
, int burst
419 , int mult
, mtk_u32
*ep
, mtk_u32
*ep_ctx
, struct sch_ep
*sch_ep
){
421 mtk_u32 bCsCount
= 0;
426 struct mtk_xhci_ep_ctx
*temp_ep_ctx
;
428 int mframe_idx
, frame_idx
;
430 int cur_bw
, best_bw
, best_bw_idx
,repeat
, max_repeat
, best_bw_repeat
;
431 int cur_offset
, cs_mframe
;
435 printk(KERN_ERR
"add_ep parameters, dev_speed %d, is_in %d, isTT %d, ep_type %d, maxp %d, interval %d, burst %d, mult %d, ep 0x%x, ep_ctx 0x%x, sch_ep 0x%x\n", dev_speed
, is_in
, isTT
, ep_type
, maxp
436 , interval
, burst
, mult
, ep
, ep_ctx
, sch_ep
);
437 if(isTT
&& ep_type
== USB_EP_INT
&& ((dev_speed
== USB_SPEED_LOW
) || (dev_speed
== USB_SPEED_FULL
))){
438 frame_interval
= interval
>> 3;
439 for(frame_idx
=0; frame_idx
<frame_interval
; frame_idx
++){
440 printk(KERN_ERR
"check tt_intr_bw interval %d, frame_idx %d\n", frame_interval
, frame_idx
);
441 if(count_tt_intr_bw(frame_interval
, frame_idx
) == SCH_SUCCESS
){
442 printk(KERN_ERR
"check OK............\n");
443 bOffset
= frame_idx
<<3;
448 if(add_sch_ep(dev_speed
, is_in
, isTT
, ep_type
, maxp
, frame_interval
, burst
, mult
449 , bOffset
, bRepeat
, bPkts
, bCsCount
, bBm
, maxp
, ep
, sch_ep
) == SCH_FAIL
){
457 else if(isTT
&& ep_type
== USB_EP_ISOC
){
458 best_bw
= HS_BW_BOUND
;
463 frame_interval
= interval
>>3;
464 for(frame_idx
=0; frame_idx
<frame_interval
&& !break_out
; frame_idx
++){
465 for(mframe_idx
=0; mframe_idx
<8; mframe_idx
++){
466 cur_offset
= (frame_idx
*8) + mframe_idx
;
467 cur_bw
= count_tt_isoc_bw(is_in
, maxp
, frame_interval
, cur_offset
, td_size
);
468 if(cur_bw
> 0 && cur_bw
< best_bw
){
469 best_bw_idx
= cur_offset
;
471 if(cur_bw
== td_size
|| cur_bw
< (HS_BW_BOUND
>>1)){
478 if(best_bw_idx
== -1){
482 bOffset
= best_bw_idx
;
484 bCsCount
= (maxp
+ (188 - 1)) / 188;
486 cs_mframe
= bOffset
%8 + 2 + bCsCount
;
489 else if (cs_mframe
== 7)
494 if(add_sch_ep( dev_speed
, is_in
, isTT
, ep_type
, maxp
, interval
, burst
, mult
495 , bOffset
, bRepeat
, bPkts
, bCsCount
, bBm
, bw_cost
, ep
, sch_ep
) == SCH_FAIL
){
501 else if((dev_speed
== USB_SPEED_FULL
|| dev_speed
== USB_SPEED_LOW
) && ep_type
== USB_EP_INT
){
505 else if(dev_speed
== USB_SPEED_FULL
&& ep_type
== USB_EP_ISOC
){
509 else if(dev_speed
== USB_SPEED_HIGH
&& (ep_type
== USB_EP_INT
|| ep_type
== USB_EP_ISOC
)){
510 best_bw
= HS_BW_BOUND
;
513 td_size
= maxp
*(burst
+1);
514 for(cur_offset
= 0; cur_offset
<interval
; cur_offset
++){
515 cur_bw
= count_hs_bw(ep_type
, maxp
, interval
, cur_offset
, td_size
);
516 if(cur_bw
> 0 && cur_bw
< best_bw
){
517 best_bw_idx
= cur_offset
;
519 if(cur_bw
== td_size
|| cur_bw
< (HS_BW_BOUND
>>1)){
524 if(best_bw_idx
== -1){
528 bOffset
= best_bw_idx
;
533 if(add_sch_ep(dev_speed
, is_in
, isTT
, ep_type
, maxp
, interval
, burst
, mult
534 , bOffset
, bRepeat
, bPkts
, bCsCount
, bBm
, bw_cost
, ep
, sch_ep
) == SCH_FAIL
){
540 else if(dev_speed
== USB_SPEED_SUPER
&& (ep_type
== USB_EP_INT
|| ep_type
== USB_EP_ISOC
)){
541 best_bw
= SS_BW_BOUND
;
544 td_size
= maxp
* (mult
+1) * (burst
+1);
549 max_repeat
= (interval
-1)/(mult
+1);
552 for(frame_idx
= 0; (frame_idx
< interval
) && !break_out
; frame_idx
++){
553 for(repeat
= max_repeat
; repeat
>= 0; repeat
--){
554 cur_bw
= count_ss_bw(is_in
, ep_type
, maxp
, interval
, burst
, mult
, frame_idx
556 printk(KERN_ERR
"count_ss_bw, frame_idx %d, repeat %d, td_size %d, result bw %d\n"
557 , frame_idx
, repeat
, td_size
, cur_bw
);
558 if(cur_bw
> 0 && cur_bw
< best_bw
){
559 best_bw_idx
= frame_idx
;
560 best_bw_repeat
= repeat
;
562 if(cur_bw
<= td_size
|| cur_bw
< (HS_BW_BOUND
>>1)){
569 printk(KERN_ERR
"final best idx %d, best repeat %d\n", best_bw_idx
, best_bw_repeat
);
570 if(best_bw_idx
== -1){
574 bOffset
= best_bw_idx
;
576 bRepeat
= best_bw_repeat
;
578 bw_cost
= (burst
+1)*(mult
+1)*maxp
;
579 bPkts
= (burst
+1)*(mult
+1);
582 bw_cost
= (burst
+1)*maxp
;
585 if(add_sch_ep(dev_speed
, is_in
, isTT
, ep_type
, maxp
, interval
, burst
, mult
586 , bOffset
, bRepeat
, bPkts
, bCsCount
, bBm
, bw_cost
, ep
, sch_ep
) == SCH_FAIL
){
596 if(ret
== SCH_SUCCESS
){
597 temp_ep_ctx
= (struct mtk_xhci_ep_ctx
*)ep_ctx
;
598 temp_ep_ctx
->reserved
[0] |= (BPKTS(bPkts
) | BCSCOUNT(bCsCount
) | BBM(bBm
));
599 temp_ep_ctx
->reserved
[1] |= (BOFFSET(bOffset
) | BREPEAT(bRepeat
));
601 printk(KERN_DEBUG
"[DBG] BPKTS: %x, BCSCOUNT: %x, BBM: %x\n", bPkts
, bCsCount
, bBm
);
602 printk(KERN_DEBUG
"[DBG] BOFFSET: %x, BREPEAT: %x\n", bOffset
, bRepeat
);