Advertisement
dianders

Example dwc2 microframe schedule test code for v3

Nov 16th, 2015
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.76 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. /* ****
  6. *
  7. * RANDOM CRAP FROM LINUX
  8. *
  9. * ****/
  10.  
  11. #define ENOSPC 28
  12. typedef unsigned short u16;
  13.  
  14. #define dwc2_sch_dbg(x, ...) do { if (0) printf(__VA_ARGS__); } while (0)
  15.  
  16. #define min_t(type, x, y) ({ \
  17. type __min1 = (x); \
  18. type __min2 = (y); \
  19. __min1 < __min2 ? __min1: __min2; })
  20.  
  21. #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
  22. #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
  23.  
  24.  
  25. /* ****
  26. *
  27. * BITMAP CODE
  28. *
  29. * ****/
  30.  
  31. //#define BITS_PER_LONG (sizeof (unsigned long) * 8)
  32. #define BITS_PER_LONG 64
  33. #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
  34. #define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
  35.  
  36. #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
  37. #define BITMAP_LAST_WORD_MASK(nbits) \
  38. ( \
  39. ((nbits) % BITS_PER_LONG) ? \
  40. (1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL \
  41. )
  42.  
  43.  
  44. #define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))
  45. #define __ALIGN_MASK(x, mask) __ALIGN_KERNEL_MASK((x), (mask))
  46.  
  47. #define ffz(x) __ffs(~(x))
  48. static __always_inline unsigned long __ffs(unsigned long word)
  49. {
  50. int num = 0;
  51.  
  52. #if BITS_PER_LONG == 64
  53. if ((word & 0xffffffff) == 0) {
  54. num += 32;
  55. word >>= 32;
  56. }
  57. #endif
  58. if ((word & 0xffff) == 0) {
  59. num += 16;
  60. word >>= 16;
  61. }
  62. if ((word & 0xff) == 0) {
  63. num += 8;
  64. word >>= 8;
  65. }
  66. if ((word & 0xf) == 0) {
  67. num += 4;
  68. word >>= 4;
  69. }
  70. if ((word & 0x3) == 0) {
  71. num += 2;
  72. word >>= 2;
  73. }
  74. if ((word & 0x1) == 0)
  75. num += 1;
  76. return num;
  77. }
  78.  
  79. unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
  80. unsigned long offset)
  81. {
  82. const unsigned long *p = addr + BITOP_WORD(offset);
  83. unsigned long result = offset & ~(BITS_PER_LONG-1);
  84. unsigned long tmp;
  85.  
  86. if (offset >= size)
  87. return size;
  88. size -= result;
  89. offset %= BITS_PER_LONG;
  90. if (offset) {
  91. tmp = *(p++);
  92. tmp |= ~0UL >> (BITS_PER_LONG - offset);
  93. if (size < BITS_PER_LONG)
  94. goto found_first;
  95. if (~tmp)
  96. goto found_middle;
  97. size -= BITS_PER_LONG;
  98. result += BITS_PER_LONG;
  99. }
  100. while (size & ~(BITS_PER_LONG-1)) {
  101. if (~(tmp = *(p++)))
  102. goto found_middle;
  103. result += BITS_PER_LONG;
  104. size -= BITS_PER_LONG;
  105. }
  106. if (!size)
  107. return result;
  108. tmp = *p;
  109.  
  110. found_first:
  111. tmp |= ~0UL << size;
  112. if (tmp == ~0UL) /* Are any bits zero? */
  113. return result + size; /* Nope. */
  114. found_middle:
  115. return result + ffz(tmp);
  116. }
  117.  
  118. unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
  119. unsigned long offset)
  120. {
  121. const unsigned long *p = addr + BITOP_WORD(offset);
  122. unsigned long result = offset & ~(BITS_PER_LONG-1);
  123. unsigned long tmp;
  124.  
  125. if (offset >= size)
  126. return size;
  127. size -= result;
  128. offset %= BITS_PER_LONG;
  129. if (offset) {
  130. tmp = *(p++);
  131. tmp &= (~0UL << offset);
  132. if (size < BITS_PER_LONG)
  133. goto found_first;
  134. if (tmp)
  135. goto found_middle;
  136. size -= BITS_PER_LONG;
  137. result += BITS_PER_LONG;
  138. }
  139. while (size & ~(BITS_PER_LONG-1)) {
  140. if ((tmp = *(p++)))
  141. goto found_middle;
  142. result += BITS_PER_LONG;
  143. size -= BITS_PER_LONG;
  144. }
  145. if (!size)
  146. return result;
  147. tmp = *p;
  148.  
  149. found_first:
  150. tmp &= (~0UL >> (BITS_PER_LONG - size));
  151. if (tmp == 0UL) /* Are any bits set? */
  152. return result + size; /* Nope. */
  153. found_middle:
  154. return result + __ffs(tmp);
  155. }
  156.  
  157. unsigned long bitmap_find_next_zero_area(unsigned long *map,
  158. unsigned long size,
  159. unsigned long start,
  160. unsigned int nr,
  161. unsigned long align_mask)
  162. {
  163. unsigned long index, end, i;
  164. again:
  165. index = find_next_zero_bit(map, size, start);
  166.  
  167. /* Align allocation */
  168. index = __ALIGN_MASK(index, align_mask);
  169.  
  170. end = index + nr;
  171. if (end > size)
  172. return end;
  173. i = find_next_bit(map, end, index);
  174. if (i < end) {
  175. start = i + 1;
  176. goto again;
  177. }
  178. return index;
  179. }
  180.  
  181. void bitmap_set(unsigned long *map, int start, int nr)
  182. {
  183. unsigned long *p = map + BIT_WORD(start);
  184. const int size = start + nr;
  185. int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
  186. unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
  187.  
  188. while (nr - bits_to_set >= 0) {
  189. *p |= mask_to_set;
  190. nr -= bits_to_set;
  191. bits_to_set = BITS_PER_LONG;
  192. mask_to_set = ~0UL;
  193. p++;
  194. }
  195. if (nr) {
  196. mask_to_set &= BITMAP_LAST_WORD_MASK(size);
  197. *p |= mask_to_set;
  198. }
  199. }
  200.  
  201. void bitmap_clear(unsigned long *map, int start, int nr)
  202. {
  203. unsigned long *p = map + BIT_WORD(start);
  204. const int size = start + nr;
  205. int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
  206. unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
  207.  
  208. while (nr - bits_to_clear >= 0) {
  209. *p &= ~mask_to_clear;
  210. nr -= bits_to_clear;
  211. bits_to_clear = BITS_PER_LONG;
  212. mask_to_clear = ~0UL;
  213. p++;
  214. }
  215. if (nr) {
  216. mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
  217. *p &= ~mask_to_clear;
  218. }
  219. }
  220.  
  221. /* ****
  222. *
  223. * END BITMAP CODE
  224. *
  225. * ****/
  226.  
  227.  
  228. #define EARLY_FRAME_USEC 100
  229. #define TOTAL_PERIODIC_USEC (6 * EARLY_FRAME_USEC + 30)
  230.  
  231. struct dwc2_qh {
  232. unsigned short frame_usecs[8];
  233. int usecs;
  234.  
  235. /* For bitmap */
  236. int start_usecs;
  237. };
  238.  
  239. struct dwc2_hsotg {
  240. unsigned short frame_usecs[8];
  241.  
  242. unsigned long periodic_bitmap[DIV_ROUND_UP(TOTAL_PERIODIC_USEC,
  243. BITS_PER_LONG)];
  244. };
  245.  
  246. static const unsigned short max_uframe_usecs[] = {
  247. EARLY_FRAME_USEC, EARLY_FRAME_USEC, EARLY_FRAME_USEC,
  248. EARLY_FRAME_USEC, EARLY_FRAME_USEC, EARLY_FRAME_USEC,
  249. 30, 0
  250. };
  251.  
  252. static void bitmap_to_old(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
  253. {
  254. unsigned long start = qh->start_usecs / 100;
  255. int j;
  256. int utime;
  257.  
  258. for (utime = qh->usecs, j = start; utime > 0 && j < 8; j++) {
  259. qh->frame_usecs[j] = min_t(u16, utime,
  260. hsotg->frame_usecs[j]);
  261. utime -= qh->frame_usecs[j];
  262. hsotg->frame_usecs[j] -= qh->frame_usecs[j];
  263. }
  264. }
  265.  
  266. static int find_single_uframe_bitmap(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
  267. {
  268. unsigned short frame_start = 0;
  269. unsigned short utime = qh->usecs;
  270. int i;
  271.  
  272. for (i = 0; i < ARRAY_SIZE(max_uframe_usecs); i++) {
  273. unsigned short frame_time = max_uframe_usecs[i];
  274. unsigned long start;
  275.  
  276. /* Look for a chunk starting at begin of this frame */
  277. start = bitmap_find_next_zero_area(hsotg->periodic_bitmap,
  278. frame_start + frame_time,
  279. frame_start, utime, 0);
  280.  
  281. /* The chunk has to totally fit in this frame */
  282. if (start < frame_start + frame_time) {
  283. bitmap_set(hsotg->periodic_bitmap, start, utime);
  284. qh->start_usecs = start;
  285. dwc2_sch_dbg(hsotg, "%s: assigned %d us @ %d us\n",
  286. __func__, qh->usecs, qh->start_usecs);
  287. return i;
  288. }
  289.  
  290. frame_start += frame_time;
  291. }
  292.  
  293. dwc2_sch_dbg(hsotg, "%s: failed to assign %d us\n",
  294. __func__, qh->usecs);
  295. return -ENOSPC;
  296. }
  297.  
  298. static int find_multi_uframe_bitmap(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
  299. {
  300. unsigned short utime = qh->usecs;
  301. unsigned long start;
  302.  
  303. start = bitmap_find_next_zero_area(hsotg->periodic_bitmap,
  304. TOTAL_PERIODIC_USEC, 0, utime, 0);
  305. if (start >= TOTAL_PERIODIC_USEC) {
  306. dwc2_sch_dbg(hsotg, "%s: failed to assign %d us\n",
  307. __func__, qh->usecs);
  308. return -ENOSPC;
  309. }
  310.  
  311. bitmap_set(hsotg->periodic_bitmap, start, qh->usecs);
  312. qh->start_usecs = start;
  313.  
  314. dwc2_sch_dbg(hsotg, "%s: assigned %d us @ %d us\n",
  315. __func__, qh->usecs, qh->start_usecs);
  316.  
  317. return start / EARLY_FRAME_USEC;
  318. }
  319.  
  320. static int find_multi_uframe_old(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
  321. {
  322. unsigned short utime = qh->usecs;
  323. unsigned short xtime;
  324. int t_left;
  325. int i;
  326. int j;
  327. int k;
  328. for (i = 0; i < 8; i++) {
  329. if (hsotg->frame_usecs[i] <= 0)
  330. continue;
  331. /*
  332. * we need n consecutive slots so use j as a start slot
  333. * j plus j+1 must be enough time (for now)
  334. */
  335. xtime = hsotg->frame_usecs[i];
  336. for (j = i + 1; j < 8; j++) {
  337. /*
  338. * if we add this frame remaining time to xtime we may
  339. * be OK, if not we need to test j for a complete frame
  340. */
  341. if (xtime + hsotg->frame_usecs[j] < utime) {
  342. if (hsotg->frame_usecs[j] <
  343. max_uframe_usecs[j])
  344. continue;
  345. }
  346. if (xtime >= utime) {
  347. t_left = utime;
  348. for (k = i; k < 8; k++) {
  349. t_left -= hsotg->frame_usecs[k];
  350. if (t_left <= 0) {
  351. qh->frame_usecs[k] +=
  352. hsotg->frame_usecs[k]
  353. + t_left;
  354. hsotg->frame_usecs[k] = -t_left;
  355. return i;
  356. } else {
  357. qh->frame_usecs[k] +=
  358. hsotg->frame_usecs[k];
  359. hsotg->frame_usecs[k] = 0;
  360. }
  361. }
  362. }
  363. /* add the frame time to x time */
  364. xtime += hsotg->frame_usecs[j];
  365. /* we must have a fully available next frame or break */
  366. if (xtime < utime &&
  367. hsotg->frame_usecs[j] == max_uframe_usecs[j])
  368. continue;
  369. }
  370. }
  371. return -ENOSPC;
  372. }
  373.  
  374.  
  375. static void unschedule(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
  376. {
  377. int i;
  378.  
  379. for (i = 0; i < 8; i++) {
  380. hsotg->frame_usecs[i] += qh->frame_usecs[i];
  381. qh->frame_usecs[i] = 0;
  382. }
  383.  
  384. bitmap_clear(hsotg->periodic_bitmap, qh->start_usecs, qh->usecs);
  385. }
  386.  
  387. #define NUM_QH 26
  388.  
  389. void print_one(char result[], int *char_num, int usecs, int qh_num)
  390. {
  391. int count = usecs / 10;
  392.  
  393. while (count && result[*char_num]) {
  394. // printf("%s %c %d %d %d\n", result, 'A' + *char_num, usecs, qh_num, count);
  395.  
  396. if (result[*char_num] == ' ') {
  397. result[*char_num] = 'A' + qh_num;
  398. count--;
  399. }
  400. (*char_num)++;
  401. }
  402.  
  403. if (count)
  404. printf("ERROR\n");
  405. }
  406.  
  407. void print_qhs(struct dwc2_qh qhs[])
  408. {
  409. char result[] =
  410. " | | | | | | |";
  411. int qh_num;
  412. int uframe;
  413.  
  414. for (uframe = 0; uframe < 8; uframe++) {
  415. int char_num = uframe * 11;
  416. int first = -1;
  417. int last = -1;
  418.  
  419. for (qh_num = 0; qh_num < NUM_QH; qh_num++) {
  420. struct dwc2_qh *qh = qhs + qh_num;
  421. if (uframe != 0 && qh->frame_usecs[uframe] && qh->frame_usecs[uframe-1]) {
  422. first = qh_num;
  423. continue;
  424. }
  425. if (uframe != 7 && qh->frame_usecs[uframe] && qh->frame_usecs[uframe+1])
  426. last = qh_num;
  427. }
  428.  
  429. if (first != -1)
  430. print_one(result, &char_num, qhs[first].frame_usecs[uframe], first);
  431.  
  432. for (qh_num = 0; qh_num < NUM_QH; qh_num++) {
  433. if (qh_num == first || qh_num == last)
  434. continue;
  435.  
  436. print_one(result, &char_num, qhs[qh_num].frame_usecs[uframe], qh_num);
  437. }
  438.  
  439. if (last != -1) {
  440. char_num = (uframe + 1) * 11 - 1 - (qhs[last].frame_usecs[uframe] / 10);
  441. print_one(result, &char_num, qhs[last].frame_usecs[uframe], last);
  442. }
  443. }
  444.  
  445. puts(result);
  446. }
  447.  
  448. int main (int argc, char *argv[])
  449. {
  450. const int test_old = 0;
  451. const int test_new_single = 1;
  452.  
  453. struct dwc2_hsotg hsotg = { };
  454. struct dwc2_qh qhs[NUM_QH] = { };
  455. int i;
  456.  
  457. memcpy(hsotg.frame_usecs, max_uframe_usecs, sizeof(max_uframe_usecs));
  458.  
  459. for (i = 0; i < 1000; i++) {
  460. if ((rand() % 4) == 0) {
  461. /* Delete */
  462. int to_delete = rand() % NUM_QH;
  463.  
  464. if (qhs[to_delete].usecs) {
  465. printf("Delete %c (%3d us): ", 'A' + to_delete, qhs[to_delete].usecs);
  466. unschedule(&hsotg, qhs + to_delete);
  467. qhs[to_delete].usecs = 0;
  468. print_qhs(qhs);
  469. }
  470. } else {
  471. int to_add = rand() % NUM_QH;
  472.  
  473. if (!qhs[to_add].usecs) {
  474. int usecs = (rand() % 30) * 10 + 10;
  475. int single = 0;
  476. int ret;
  477.  
  478. qhs[to_add].usecs = usecs;
  479. if (test_old)
  480. ret = find_multi_uframe_old(&hsotg, qhs + to_add);
  481. else {
  482. if (test_new_single && usecs < 100 && ((rand() % 3) == 0)) {
  483. single = 1;
  484. ret = find_single_uframe_bitmap(&hsotg, qhs + to_add);
  485. } else {
  486. ret = find_multi_uframe_bitmap(&hsotg, qhs + to_add);
  487. }
  488. if (ret >= 0)
  489. bitmap_to_old(&hsotg, qhs + to_add);
  490. }
  491.  
  492. if (ret >= 0) {
  493. printf("Add %c (%3d us - %d) OK: ", 'A' + to_add, usecs, single);
  494. print_qhs(qhs);
  495. } else {
  496. printf("Add %c (%3d us - %d) fail: \n", 'A' + to_add, usecs, single);
  497. //print_qhs(qhs);
  498. qhs[to_add].usecs = 0;
  499. }
  500. }
  501. }
  502. }
  503.  
  504. return 0;
  505. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement