Advertisement
Guest User

Example dwc2 microframe schedule test code

a guest
Nov 9th, 2015
201
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.58 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 dev_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 TOTAL_PERIODIC_USEC 630
  229.  
  230. struct dwc2_qh {
  231.     unsigned short frame_usecs[8];
  232.     int usecs;
  233.  
  234.     /* For bitmap */
  235.     int start_usecs;
  236. };
  237.  
  238. struct dwc2_hsotg {
  239.     unsigned short frame_usecs[8];
  240.  
  241.     unsigned long periodic_bitmap[DIV_ROUND_UP(TOTAL_PERIODIC_USEC,
  242.                            BITS_PER_LONG)];
  243. };
  244.  
  245. static const unsigned short max_uframe_usecs[8] = {
  246.     100, 100, 100, 100, 100, 100, 30, 0
  247. };
  248.  
  249. static void bitmap_to_old(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
  250. {
  251.     unsigned long start = qh->start_usecs / 100;
  252.     int j;
  253.     int utime;
  254.  
  255.     for (utime = qh->usecs, j = start; utime > 0 && j < 8; j++) {
  256.         qh->frame_usecs[j] = min_t(u16, utime,
  257.                         hsotg->frame_usecs[j]);
  258.         utime -= qh->frame_usecs[j];
  259.         hsotg->frame_usecs[j] -= qh->frame_usecs[j];
  260.     }
  261. }
  262.  
  263. static int find_single_uframe_bitmap(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
  264. {
  265.     unsigned short frame_start = 0;
  266.     unsigned short utime = qh->usecs;
  267.     int i;
  268.  
  269.     for (i = 0; i < ARRAY_SIZE(max_uframe_usecs); i++) {
  270.         unsigned short frame_time = max_uframe_usecs[i];
  271.         unsigned long start;
  272.  
  273.         /* Look for a chunk starting at begin of this frame */
  274.         start = bitmap_find_next_zero_area(hsotg->periodic_bitmap,
  275.                            TOTAL_PERIODIC_USEC,
  276.                            frame_start, utime, 0);
  277.  
  278.         /* The chunk has to totally fit in this frame */
  279.         if (start - frame_start + utime <= frame_time) {
  280.             bitmap_set(hsotg->periodic_bitmap, start, utime);
  281.             qh->start_usecs = start;
  282.             bitmap_to_old(hsotg, qh);
  283.             dev_dbg(hsotg->dev, "%s: assigned %d us @ %d us\n",
  284.                 __func__, qh->usecs, qh->start_usecs);
  285.             return i;
  286.         }
  287.  
  288.         frame_start += frame_time;
  289.     }
  290.     dev_dbg(hsotg->dev, "%s: failed to assign %d us\n",
  291.         __func__, qh->usecs);
  292.     return -ENOSPC;
  293. }
  294.  
  295. static int find_multi_uframe_bitmap(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
  296. {
  297.     unsigned short utime = qh->usecs;
  298.     unsigned long start;
  299.  
  300.     start = bitmap_find_next_zero_area(hsotg->periodic_bitmap,
  301.                        TOTAL_PERIODIC_USEC, 0, utime, 0);
  302.     if (start >= TOTAL_PERIODIC_USEC) {
  303.         dev_dbg(hsotg->dev, "%s: failed to assign %d us\n",
  304.             __func__, qh->usecs);
  305.         return -ENOSPC;
  306.     }
  307.  
  308.     bitmap_set(hsotg->periodic_bitmap, start, qh->usecs);
  309.     qh->start_usecs = start;
  310.     bitmap_to_old(hsotg, qh);
  311.  
  312.     dev_dbg(hsotg->dev, "%s: assigned %d us @ %d us\n",
  313.         __func__, qh->usecs, qh->start_usecs);
  314.  
  315.     return start / 100;
  316. }
  317.  
  318. static int find_multi_uframe_old(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
  319. {
  320.     unsigned short utime = qh->usecs;
  321.     unsigned short xtime;
  322.     int t_left;
  323.     int i;
  324.     int j;
  325.     int k;
  326.     for (i = 0; i < 8; i++) {
  327.         if (hsotg->frame_usecs[i] <= 0)
  328.             continue;
  329.         /*
  330.          * we need n consecutive slots so use j as a start slot
  331.          * j plus j+1 must be enough time (for now)
  332.          */
  333.         xtime = hsotg->frame_usecs[i];
  334.         for (j = i + 1; j < 8; j++) {
  335.             /*
  336.              * if we add this frame remaining time to xtime we may
  337.              * be OK, if not we need to test j for a complete frame
  338.              */
  339.             if (xtime + hsotg->frame_usecs[j] < utime) {
  340.                 if (hsotg->frame_usecs[j] <
  341.                     max_uframe_usecs[j])
  342.                     continue;
  343.             }
  344.             if (xtime >= utime) {
  345.                 t_left = utime;
  346.                 for (k = i; k < 8; k++) {
  347.                     t_left -= hsotg->frame_usecs[k];
  348.                     if (t_left <= 0) {
  349.                         qh->frame_usecs[k] +=
  350.                         hsotg->frame_usecs[k]
  351.                         + t_left;
  352.                         hsotg->frame_usecs[k] = -t_left;
  353.                         return i;
  354.                     } else {
  355.                         qh->frame_usecs[k] +=
  356.                         hsotg->frame_usecs[k];
  357.                         hsotg->frame_usecs[k] = 0;
  358.                     }
  359.                 }
  360.             }
  361.             /* add the frame time to x time */
  362.             xtime += hsotg->frame_usecs[j];
  363.             /* we must have a fully available next frame or break */
  364.             if (xtime < utime &&
  365.                 hsotg->frame_usecs[j] == max_uframe_usecs[j])
  366.                 continue;
  367.         }
  368.     }
  369.     return -ENOSPC;
  370. }
  371.  
  372.  
  373. static void unschedule(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
  374. {
  375.     int i;
  376.  
  377.     for (i = 0; i < 8; i++) {
  378.         hsotg->frame_usecs[i] += qh->frame_usecs[i];
  379.         qh->frame_usecs[i] = 0;
  380.     }
  381.  
  382.     bitmap_clear(hsotg->periodic_bitmap, qh->start_usecs, qh->usecs);
  383. }
  384.  
  385. #define NUM_QH 26
  386.  
  387. void print_one(char result[], int *char_num, int usecs, int qh_num)
  388. {
  389.     int count = usecs / 10;
  390.  
  391.     while (count && result[*char_num]) {
  392.         //    printf("%s %c %d %d %d\n", result, 'A' + *char_num, usecs, qh_num, count);
  393.  
  394.         if (result[*char_num] == ' ') {
  395.             result[*char_num] = 'A' + qh_num;
  396.             count--;
  397.         }
  398.         (*char_num)++;
  399.     }
  400.  
  401.     if (count)
  402.         printf("ERROR\n");
  403. }
  404.  
  405. void print_qhs(struct dwc2_qh qhs[])
  406. {
  407.     char result[] =
  408.     "          |          |          |          |          |          |   |";
  409.         int qh_num;
  410.         int uframe;
  411.  
  412.         for (uframe = 0; uframe < 8; uframe++) {
  413.             int char_num = uframe * 11;
  414.             int first = -1;
  415.             int last = -1;
  416.  
  417.             for (qh_num = 0; qh_num < NUM_QH; qh_num++) {
  418.                 struct dwc2_qh *qh = qhs + qh_num;
  419.                 if (uframe != 0 && qh->frame_usecs[uframe] && qh->frame_usecs[uframe-1]) {
  420.                     first = qh_num;
  421.                     continue;
  422.                 }
  423.                 if (uframe != 7 && qh->frame_usecs[uframe] && qh->frame_usecs[uframe+1])
  424.                     last = qh_num;
  425.             }
  426.  
  427.             if (first != -1)
  428.                 print_one(result, &char_num, qhs[first].frame_usecs[uframe], first);
  429.  
  430.             for (qh_num = 0; qh_num < NUM_QH; qh_num++) {
  431.                 if (qh_num == first || qh_num == last)
  432.                     continue;
  433.  
  434.                 print_one(result, &char_num, qhs[qh_num].frame_usecs[uframe], qh_num);
  435.             }
  436.  
  437.             if (last != -1) {
  438.                 char_num = (uframe + 1) * 11 - 1 - (qhs[last].frame_usecs[uframe] / 10);
  439.                 print_one(result, &char_num, qhs[last].frame_usecs[uframe], last);
  440.             }
  441.         }
  442.  
  443.         puts(result);
  444. }
  445.  
  446. int main (int argc, char *argv[])
  447. {
  448.     const int test_old = 1;
  449.     const int test_new_single = 0;
  450.  
  451.     struct dwc2_hsotg hsotg = { };
  452.     struct dwc2_qh qhs[NUM_QH] = { };
  453.     int i;
  454.  
  455.     memcpy(hsotg.frame_usecs, max_uframe_usecs, sizeof(max_uframe_usecs));
  456.  
  457.     for (i = 0; i < 1000; i++) {
  458.         if ((rand() % 4) == 0) {
  459.             /* Delete */
  460.             int to_delete = rand() % NUM_QH;
  461.  
  462.             if (qhs[to_delete].usecs) {
  463.                 printf("Delete %c (%3d us):       ", 'A' + to_delete, qhs[to_delete].usecs);
  464.                 unschedule(&hsotg, qhs + to_delete);
  465.                 qhs[to_delete].usecs = 0;
  466.                 print_qhs(qhs);
  467.             }
  468.         } else {
  469.             int to_add = rand() % NUM_QH;
  470.  
  471.             if (!qhs[to_add].usecs) {
  472.                 int usecs = (rand() % 30) * 10 + 10;
  473.                 int single = 0;
  474.                 int ret;
  475.  
  476.                 qhs[to_add].usecs = usecs;
  477.                 if (test_old)
  478.                     ret = find_multi_uframe_old(&hsotg, qhs + to_add);
  479.                 else {
  480.                     if (test_new_single && usecs < 100 && ((rand() % 3) == 0)) {
  481.                         single = 1;
  482.                         ret = find_single_uframe_bitmap(&hsotg, qhs + to_add);
  483.                     } else {
  484.                         ret = find_multi_uframe_bitmap(&hsotg, qhs + to_add);
  485.                     }
  486.                 }
  487.  
  488.                 if (ret >= 0) {
  489.                     printf("Add %c (%3d us - %d) OK:   ", 'A' + to_add, usecs, single);
  490.                     print_qhs(qhs);
  491.                 } else {
  492.                     printf("Add %c (%3d us - %d) fail: \n", 'A' + to_add, usecs, single);
  493.                     //print_qhs(qhs);
  494.                     qhs[to_add].usecs = 0;
  495.                 }
  496.             }
  497.         }
  498.     }
  499.  
  500.     return 0;
  501. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement