import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / xhci / xhci-mtk-scheduler.c
1 #include <linux/xhci/xhci-mtk-scheduler.h>
2 #include <linux/kernel.h> /* printk() */
3
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];
8
9 int mtk_xhci_scheduler_init(void)
10 {
11 int i;
12
13 for (i = 0; i < MAX_EP_NUM; i++) {
14 ss_out_eps[i] = NULL;
15 }
16 for (i = 0; i < MAX_EP_NUM; i++) {
17 ss_in_eps[i] = NULL;
18 }
19 for (i = 0; i < MAX_EP_NUM; i++) {
20 hs_eps[i] = NULL;
21 }
22 for (i = 0; i < MAX_EP_NUM; i++) {
23 tt_intr_eps[i] = NULL;
24 }
25 return 0;
26 }
27
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)
31 {
32
33 struct sch_ep **ep_array;
34 int i;
35
36 if (is_in && dev_speed == USB_SPEED_SUPER) {
37 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;
40 } else if (dev_speed == USB_SPEED_HIGH || (isTT && ep_type == USB_EP_ISOC)) {
41 ep_array = (struct sch_ep **)hs_eps;
42 } else {
43 ep_array = (struct sch_ep **)tt_intr_eps;
44 }
45 for (i = 0; i < MAX_EP_NUM; i++) {
46 if (ep_array[i] == NULL) {
47 tmp_ep->dev_speed = dev_speed;
48 tmp_ep->isTT = isTT;
49 tmp_ep->is_in = is_in;
50 tmp_ep->ep_type = ep_type;
51 tmp_ep->maxp = maxp;
52 tmp_ep->interval = interval;
53 tmp_ep->burst = burst;
54 tmp_ep->mult = mult;
55 tmp_ep->offset = offset;
56 tmp_ep->repeat = repeat;
57 tmp_ep->pkts = pkts;
58 tmp_ep->cs_count = cs_count;
59 tmp_ep->burst_mode = burst_mode;
60 tmp_ep->bw_cost = bw_cost;
61 tmp_ep->ep = ep;
62 ep_array[i] = tmp_ep;
63 return SCH_SUCCESS;
64 }
65 }
66 return SCH_FAIL;
67 }
68
69 int count_ss_bw(int is_in, int ep_type, int maxp, int interval, int burst, int mult, int offset,
70 int repeat, int td_size)
71 {
72 int i, j, k;
73 int bw_required[3];
74 int final_bw_required;
75 int bw_required_per_repeat;
76 int tmp_bw_required;
77 struct sch_ep *cur_sch_ep;
78 struct sch_ep **ep_array;
79 int cur_offset;
80 int cur_ep_offset;
81 int tmp_offset;
82 int tmp_interval;
83 int ep_offset;
84 int ep_interval;
85 int ep_repeat;
86 int ep_mult;
87
88 if (is_in) {
89 ep_array = (struct sch_ep **)ss_in_eps;
90 } else {
91 ep_array = (struct sch_ep **)ss_out_eps;
92 }
93
94 bw_required[0] = 0;
95 bw_required[1] = 0;
96 bw_required[2] = 0;
97
98 if (repeat == 0) {
99 final_bw_required = 0;
100 for (i = 0; i < MAX_EP_NUM; i++) {
101 cur_sch_ep = ep_array[i];
102 if (cur_sch_ep == NULL) {
103 continue;
104 }
105 ep_interval = cur_sch_ep->interval;
106 ep_offset = cur_sch_ep->offset;
107 if (cur_sch_ep->repeat == 0) {
108 if (ep_interval >= interval) {
109 tmp_offset = ep_offset + ep_interval - offset;
110 tmp_interval = interval;
111 } else {
112 tmp_offset = offset + interval - ep_offset;
113 tmp_interval = ep_interval;
114 }
115 if (tmp_offset % tmp_interval == 0) {
116 final_bw_required += cur_sch_ep->bw_cost;
117 }
118 } else {
119 ep_repeat = cur_sch_ep->repeat;
120 ep_mult = cur_sch_ep->mult;
121 for (k = 0; k <= ep_mult; k++) {
122 cur_ep_offset = ep_offset + (k * ep_mult);
123 if (ep_interval >= interval) {
124 tmp_offset = cur_ep_offset + ep_interval - offset;
125 tmp_interval = interval;
126 } else {
127 tmp_offset = offset + interval - cur_ep_offset;
128 tmp_interval = ep_interval;
129 }
130 if (tmp_offset % tmp_interval == 0) {
131 final_bw_required += cur_sch_ep->bw_cost;
132 break;
133 }
134 }
135 }
136 }
137 final_bw_required += td_size;
138 } else {
139 bw_required_per_repeat = maxp * (burst + 1);
140 for (j = 0; j <= mult; j++) {
141 tmp_bw_required = 0;
142 cur_offset = offset + (j * repeat);
143 for (i = 0; i < MAX_EP_NUM; i++) {
144 cur_sch_ep = ep_array[i];
145 if (cur_sch_ep == NULL) {
146 continue;
147 }
148 ep_interval = cur_sch_ep->interval;
149 ep_offset = cur_sch_ep->offset;
150 if (cur_sch_ep->repeat == 0) {
151 if (ep_interval >= interval) {
152 tmp_offset = ep_offset + ep_interval - cur_offset;
153 tmp_interval = interval;
154 } else {
155 tmp_offset = cur_offset + interval - ep_offset;
156 tmp_interval = ep_interval;
157 }
158 if (tmp_offset % tmp_interval == 0) {
159 tmp_bw_required += cur_sch_ep->bw_cost;
160 }
161 } else {
162 ep_repeat = cur_sch_ep->repeat;
163 ep_mult = cur_sch_ep->mult;
164 for (k = 0; k <= ep_mult; k++) {
165 cur_ep_offset = ep_offset + (k * ep_repeat);
166 if (ep_interval >= interval) {
167 tmp_offset =
168 cur_ep_offset + ep_interval -
169 cur_offset;
170 tmp_interval = interval;
171 } else {
172 tmp_offset =
173 cur_offset + interval - cur_ep_offset;
174 tmp_interval = ep_interval;
175 }
176 if (tmp_offset % tmp_interval == 0) {
177 tmp_bw_required += cur_sch_ep->bw_cost;
178 break;
179 }
180 }
181 }
182 }
183 bw_required[j] = tmp_bw_required;
184 }
185 final_bw_required = SS_BW_BOUND;
186 for (j = 0; j <= mult; j++) {
187 if (bw_required[j] < final_bw_required) {
188 final_bw_required = bw_required[j];
189 }
190 }
191 final_bw_required += bw_required_per_repeat;
192 }
193 return final_bw_required;
194 }
195
196 int count_hs_bw(int ep_type, int maxp, int interval, int offset, int td_size)
197 {
198 int i;
199 int bw_required;
200 struct sch_ep *cur_sch_ep;
201 int tmp_offset;
202 int tmp_interval;
203 int ep_offset;
204 int ep_interval;
205 int cur_tt_isoc_interval; /* for isoc tt check */
206
207 bw_required = 0;
208 for (i = 0; i < MAX_EP_NUM; i++) {
209
210 cur_sch_ep = (struct sch_ep *)hs_eps[i];
211 if (cur_sch_ep == NULL) {
212 continue;
213 }
214 ep_offset = cur_sch_ep->offset;
215 ep_interval = cur_sch_ep->interval;
216
217 if (cur_sch_ep->isTT && cur_sch_ep->ep_type == USB_EP_ISOC) {
218 cur_tt_isoc_interval = ep_interval << 3;
219 if (ep_interval >= interval) {
220 tmp_offset = ep_offset + cur_tt_isoc_interval - offset;
221 tmp_interval = interval;
222 } else {
223 tmp_offset = offset + interval - ep_offset;
224 tmp_interval = cur_tt_isoc_interval;
225 }
226 if (cur_sch_ep->is_in) {
227 if ((tmp_offset % tmp_interval >= 2)
228 && (tmp_offset % tmp_interval <= cur_sch_ep->cs_count)) {
229 bw_required += 188;
230 }
231 } else {
232 if (tmp_offset % tmp_interval <= cur_sch_ep->cs_count) {
233 bw_required += 188;
234 }
235 }
236 } else {
237 if (ep_interval >= interval) {
238 tmp_offset = ep_offset + ep_interval - offset;
239 tmp_interval = interval;
240 } else {
241 tmp_offset = offset + interval - ep_offset;
242 tmp_interval = ep_interval;
243 }
244 if (tmp_offset % tmp_interval == 0) {
245 bw_required += cur_sch_ep->bw_cost;
246 }
247 }
248 }
249 bw_required += td_size;
250 return bw_required;
251 }
252
253 int count_tt_isoc_bw(int is_in, int maxp, int interval, int offset, int td_size)
254 {
255 char is_cs;
256 int s_frame, s_mframe, cur_mframe;
257 int bw_required, max_bw;
258 int ss_cs_count;
259 int cs_mframe;
260 int i, j;
261 struct sch_ep *cur_sch_ep;
262 int ep_offset;
263 int ep_interval;
264 int tt_isoc_interval; /* for isoc tt check */
265 int cur_tt_isoc_interval; /* for isoc tt check */
266 int tmp_offset;
267 int tmp_interval;
268
269 is_cs = 0;
270
271 tt_isoc_interval = interval << 3; /* frame to mframe */
272 if (is_in) {
273 is_cs = 1;
274 }
275 s_frame = offset / 8;
276 s_mframe = offset % 8;
277 ss_cs_count = (maxp + (188 - 1)) / 188;
278 if (is_cs) {
279 cs_mframe = offset % 8 + 2 + ss_cs_count;
280 if (cs_mframe <= 6)
281 ss_cs_count += 2;
282 else if (cs_mframe == 7)
283 ss_cs_count++;
284 else if (cs_mframe > 8)
285 return -1;
286 }
287 max_bw = 0;
288 if (is_in) {
289 i = 2;
290 }
291 for (cur_mframe = offset + i; i < ss_cs_count; cur_mframe++, i++) {
292 bw_required = 0;
293 for (j = 0; j < MAX_EP_NUM; j++) {
294 cur_sch_ep = (struct sch_ep *)hs_eps[j];
295 if (cur_sch_ep == NULL) {
296 continue;
297 }
298 ep_offset = cur_sch_ep->offset;
299 ep_interval = cur_sch_ep->interval;
300 if (cur_sch_ep->isTT && cur_sch_ep->ep_type == USB_EP_ISOC) {
301 /* isoc tt */
302 /* check if mframe offset overlap */
303 /* if overlap, add 188 to the bw */
304 cur_tt_isoc_interval = ep_interval << 3;
305 if (cur_tt_isoc_interval >= tt_isoc_interval) {
306 tmp_offset =
307 (ep_offset + cur_tt_isoc_interval) - cur_mframe;
308 tmp_interval = tt_isoc_interval;
309 } else {
310 tmp_offset = (cur_mframe + tt_isoc_interval) - ep_offset;
311 tmp_interval = cur_tt_isoc_interval;
312 }
313 if (cur_sch_ep->is_in) {
314 if ((tmp_offset % tmp_interval >= 2)
315 && (tmp_offset % tmp_interval <=
316 cur_sch_ep->cs_count)) {
317 bw_required += 188;
318 }
319 } else {
320 if (tmp_offset % tmp_interval <= cur_sch_ep->cs_count) {
321 bw_required += 188;
322 }
323 }
324
325 } else if (cur_sch_ep->ep_type == USB_EP_INT
326 || cur_sch_ep->ep_type == USB_EP_ISOC) {
327 /* check if mframe */
328 if (ep_interval >= tt_isoc_interval) {
329 tmp_offset = (ep_offset + ep_interval) - cur_mframe;
330 tmp_interval = tt_isoc_interval;
331 } else {
332 tmp_offset = (cur_mframe + tt_isoc_interval) - ep_offset;
333 tmp_interval = ep_interval;
334 }
335 if (tmp_offset % tmp_interval == 0) {
336 bw_required += cur_sch_ep->bw_cost;
337 }
338 }
339 }
340 bw_required += 188;
341 if (bw_required > max_bw) {
342 max_bw = bw_required;
343 }
344 }
345 return max_bw;
346 }
347
348 int count_tt_intr_bw(int interval, int frame_offset)
349 {
350 /* check all eps in tt_intr_eps */
351 int ret;
352 int i;
353 int ep_offset;
354 int ep_interval;
355 int tmp_offset;
356 int tmp_interval;
357 struct sch_ep *cur_sch_ep;
358
359 ret = SCH_SUCCESS;
360
361 for (i = 0; i < MAX_EP_NUM; i++) {
362 cur_sch_ep = (struct sch_ep *)tt_intr_eps[i];
363 if (cur_sch_ep == NULL) {
364 continue;
365 }
366 ep_offset = cur_sch_ep->offset;
367 ep_interval = cur_sch_ep->interval;
368 if (ep_interval >= interval) {
369 tmp_offset = ep_offset + ep_interval - frame_offset;
370 tmp_interval = interval;
371 } else {
372 tmp_offset = frame_offset + interval - ep_offset;
373 tmp_interval = ep_interval;
374 }
375
376 if (tmp_offset % tmp_interval == 0) {
377 return SCH_FAIL;
378 }
379 }
380 return SCH_SUCCESS;
381 }
382
383 struct sch_ep *mtk_xhci_scheduler_remove_ep(int dev_speed, int is_in, int isTT, int ep_type,
384 mtk_u32 *ep)
385 {
386 int i;
387 struct sch_ep **ep_array;
388 struct sch_ep *cur_ep;
389
390 if (is_in && dev_speed == USB_SPEED_SUPER) {
391 ep_array = (struct sch_ep **)ss_in_eps;
392 } else if (dev_speed == USB_SPEED_SUPER) {
393 ep_array = (struct sch_ep **)ss_out_eps;
394 } else if (dev_speed == USB_SPEED_HIGH || (isTT && ep_type == USB_EP_ISOC)) {
395 ep_array = (struct sch_ep **)hs_eps;
396 } else {
397 ep_array = (struct sch_ep **)tt_intr_eps;
398 }
399 for (i = 0; i < MAX_EP_NUM; i++) {
400 cur_ep = (struct sch_ep *)ep_array[i];
401 if (cur_ep != NULL && cur_ep->ep == ep) {
402 ep_array[i] = NULL;
403 return cur_ep;
404 }
405 }
406 return NULL;
407 }
408
409 int mtk_xhci_scheduler_add_ep(int dev_speed, int is_in, int isTT, int ep_type, int maxp,
410 int interval, int burst, int mult, mtk_u32 *ep, mtk_u32 *ep_ctx,
411 struct sch_ep *sch_ep)
412 {
413 mtk_u32 bPkts = 0;
414 mtk_u32 bCsCount = 0;
415 mtk_u32 bBm = 1;
416 mtk_u32 bOffset = 0;
417 mtk_u32 bRepeat = 0;
418 int ret;
419 struct mtk_xhci_ep_ctx *temp_ep_ctx;
420 int td_size;
421 int mframe_idx, frame_idx;
422 int bw_cost;
423 int cur_bw, best_bw, best_bw_idx, repeat, max_repeat, best_bw_repeat;
424 int cur_offset, cs_mframe;
425 int break_out;
426 int frame_interval;
427
428 best_bw_repeat = 0;
429 printk(KERN_ERR
430 "add_ep parameters, dev_speed %d, is_in %d, isTT %d, ep_type %d, maxp %d, interval %d, burst %d, mult %d, ep 0x%p, ep_ctx 0x%p, sch_ep 0x%p\n",
431 dev_speed, is_in, isTT, ep_type, maxp, interval, burst, mult, ep,
432 ep_ctx, sch_ep);
433 if (isTT && ep_type == USB_EP_INT
434 && ((dev_speed == USB_SPEED_LOW) || (dev_speed == USB_SPEED_FULL))) {
435 frame_interval = interval >> 3;
436 for (frame_idx = 0; frame_idx < frame_interval; frame_idx++) {
437 printk(KERN_ERR "check tt_intr_bw interval %d, frame_idx %d\n",
438 frame_interval, frame_idx);
439 if (count_tt_intr_bw(frame_interval, frame_idx) == SCH_SUCCESS) {
440 printk(KERN_ERR "check OK............\n");
441 bOffset = frame_idx << 3;
442 bPkts = 1;
443 bCsCount = 3;
444 bw_cost = maxp;
445 bRepeat = 0;
446 if (add_sch_ep
447 (dev_speed, is_in, isTT, ep_type, maxp, frame_interval, burst,
448 mult, bOffset, bRepeat, bPkts, bCsCount, bBm, maxp, ep,
449 sch_ep) == SCH_FAIL) {
450 return SCH_FAIL;
451 }
452 ret = SCH_SUCCESS;
453 break;
454 }
455 }
456 } else if (isTT && ep_type == USB_EP_ISOC) {
457 best_bw = HS_BW_BOUND;
458 best_bw_idx = -1;
459 cur_bw = 0;
460 td_size = maxp;
461 break_out = 0;
462 frame_interval = interval >> 3;
463 for (frame_idx = 0; frame_idx < frame_interval && !break_out; frame_idx++) {
464 for (mframe_idx = 0; mframe_idx < 8; mframe_idx++) {
465 cur_offset = (frame_idx * 8) + mframe_idx;
466 cur_bw =
467 count_tt_isoc_bw(is_in, maxp, frame_interval, cur_offset,
468 td_size);
469 if (cur_bw > 0 && cur_bw < best_bw) {
470 best_bw_idx = cur_offset;
471 best_bw = cur_bw;
472 if (cur_bw == td_size || cur_bw < (HS_BW_BOUND >> 1)) {
473 break_out = 1;
474 break;
475 }
476 }
477 }
478 }
479 if (best_bw_idx == -1) {
480 return SCH_FAIL;
481 } else {
482 bOffset = best_bw_idx;
483 bPkts = 1;
484 bCsCount = maxp + (188 - 1) / 188;
485 if (is_in) {
486 cs_mframe = bOffset % 8 + 2 + bCsCount;
487 if (cs_mframe <= 6)
488 bCsCount += 2;
489 else if (cs_mframe == 7)
490 bCsCount++;
491 }
492 bw_cost = 188;
493 bRepeat = 0;
494 if (add_sch_ep
495 (dev_speed, is_in, isTT, ep_type, maxp, interval, burst, mult, bOffset,
496 bRepeat, bPkts, bCsCount, bBm, bw_cost, ep, sch_ep) == SCH_FAIL) {
497 return SCH_FAIL;
498 }
499 ret = SCH_SUCCESS;
500 }
501 } else if ((dev_speed == USB_SPEED_FULL || dev_speed == USB_SPEED_LOW)
502 && ep_type == USB_EP_INT) {
503 bPkts = 1;
504 ret = SCH_SUCCESS;
505 } else if (dev_speed == USB_SPEED_FULL && ep_type == USB_EP_ISOC) {
506 bPkts = 1;
507 ret = SCH_SUCCESS;
508 } else if (dev_speed == USB_SPEED_HIGH && (ep_type == USB_EP_INT || ep_type == USB_EP_ISOC)) {
509 best_bw = HS_BW_BOUND;
510 best_bw_idx = -1;
511 cur_bw = 0;
512 td_size = maxp * (burst + 1);
513 for (cur_offset = 0; cur_offset < interval; cur_offset++) {
514 cur_bw = count_hs_bw(ep_type, maxp, interval, cur_offset, td_size);
515 if (cur_bw > 0 && cur_bw < best_bw) {
516 best_bw_idx = cur_offset;
517 best_bw = cur_bw;
518 if (cur_bw == td_size || cur_bw < (HS_BW_BOUND >> 1)) {
519 break;
520 }
521 }
522 }
523 if (best_bw_idx == -1) {
524 return SCH_FAIL;
525 } else {
526 bOffset = best_bw_idx;
527 bPkts = burst + 1;
528 bCsCount = 0;
529 bw_cost = td_size;
530 bRepeat = 0;
531 if (add_sch_ep
532 (dev_speed, is_in, isTT, ep_type, maxp, interval, burst, mult, bOffset,
533 bRepeat, bPkts, bCsCount, bBm, bw_cost, ep, sch_ep) == SCH_FAIL) {
534 return SCH_FAIL;
535 }
536 ret = SCH_SUCCESS;
537 }
538 } else if (dev_speed == USB_SPEED_SUPER
539 && (ep_type == USB_EP_INT || ep_type == USB_EP_ISOC)) {
540 best_bw = SS_BW_BOUND;
541 best_bw_idx = -1;
542 cur_bw = 0;
543 td_size = maxp * (mult + 1) * (burst + 1);
544 if (mult == 0) {
545 max_repeat = 0;
546 } else {
547 max_repeat = (interval - 1) / (mult + 1);
548 }
549 break_out = 0;
550 for (frame_idx = 0; (frame_idx < interval) && !break_out; frame_idx++) {
551 for (repeat = max_repeat; repeat >= 0; repeat--) {
552 cur_bw =
553 count_ss_bw(is_in, ep_type, maxp, interval, burst, mult,
554 frame_idx, repeat, td_size);
555 printk(KERN_ERR
556 "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;
561 best_bw = cur_bw;
562 if (cur_bw <= td_size || cur_bw < (HS_BW_BOUND >> 1)) {
563 break_out = 1;
564 break;
565 }
566 }
567 }
568 }
569 printk(KERN_ERR "final best idx %d, best repeat %d\n", best_bw_idx, best_bw_repeat);
570 if (best_bw_idx == -1) {
571 return SCH_FAIL;
572 } else {
573 bOffset = best_bw_idx;
574 bCsCount = 0;
575 bRepeat = best_bw_repeat;
576 if (bRepeat == 0) {
577 bw_cost = (burst + 1) * (mult + 1) * maxp;
578 bPkts = (burst + 1) * (mult + 1);
579 } else {
580 bw_cost = (burst + 1) * maxp;
581 bPkts = (burst + 1);
582 }
583 if (add_sch_ep
584 (dev_speed, is_in, isTT, ep_type, maxp, interval, burst, mult, bOffset,
585 bRepeat, bPkts, bCsCount, bBm, bw_cost, ep, sch_ep) == SCH_FAIL) {
586 return SCH_FAIL;
587 }
588 ret = SCH_SUCCESS;
589 }
590 } else {
591 bPkts = 1;
592 ret = SCH_SUCCESS;
593 }
594 if (ret == SCH_SUCCESS) {
595 temp_ep_ctx = (struct mtk_xhci_ep_ctx *)ep_ctx;
596 temp_ep_ctx->reserved[0] |= (BPKTS(bPkts) | BCSCOUNT(bCsCount) | BBM(bBm));
597 temp_ep_ctx->reserved[1] |= (BOFFSET(bOffset) | BREPEAT(bRepeat));
598 printk(KERN_ERR "[DBG] BPKTS: %x, BCSCOUNT: %x, BBM: %x\n", (unsigned int)bPkts,
599 (unsigned int)bCsCount, (unsigned int)bBm);
600 printk(KERN_ERR "[DBG] BOFFSET: %x, BREPEAT: %x\n", (unsigned int)bOffset,
601 (unsigned int)bRepeat);
602 return SCH_SUCCESS;
603 } else {
604 return SCH_FAIL;
605 }
606 }