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);