qman_test_api.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /* Copyright 2008 - 2016 Freescale Semiconductor, Inc.
  2. *
  3. * Redistribution and use in source and binary forms, with or without
  4. * modification, are permitted provided that the following conditions are met:
  5. * * Redistributions of source code must retain the above copyright
  6. * notice, this list of conditions and the following disclaimer.
  7. * * Redistributions in binary form must reproduce the above copyright
  8. * notice, this list of conditions and the following disclaimer in the
  9. * documentation and/or other materials provided with the distribution.
  10. * * Neither the name of Freescale Semiconductor nor the
  11. * names of its contributors may be used to endorse or promote products
  12. * derived from this software without specific prior written permission.
  13. *
  14. * ALTERNATIVELY, this software may be distributed under the terms of the
  15. * GNU General Public License ("GPL") as published by the Free Software
  16. * Foundation, either version 2 of that License or (at your option) any
  17. * later version.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
  20. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
  23. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #include "qman_test.h"
  31. #define CGR_ID 27
  32. #define POOL_ID 2
  33. #define FQ_FLAGS QMAN_FQ_FLAG_DYNAMIC_FQID
  34. #define NUM_ENQUEUES 10
  35. #define NUM_PARTIAL 4
  36. #define PORTAL_SDQCR (QM_SDQCR_SOURCE_CHANNELS | \
  37. QM_SDQCR_TYPE_PRIO_QOS | \
  38. QM_SDQCR_TOKEN_SET(0x98) | \
  39. QM_SDQCR_CHANNELS_DEDICATED | \
  40. QM_SDQCR_CHANNELS_POOL(POOL_ID))
  41. #define PORTAL_OPAQUE ((void *)0xf00dbeef)
  42. #define VDQCR_FLAGS (QMAN_VOLATILE_FLAG_WAIT | QMAN_VOLATILE_FLAG_FINISH)
  43. static enum qman_cb_dqrr_result cb_dqrr(struct qman_portal *,
  44. struct qman_fq *,
  45. const struct qm_dqrr_entry *);
  46. static void cb_ern(struct qman_portal *, struct qman_fq *,
  47. const union qm_mr_entry *);
  48. static void cb_fqs(struct qman_portal *, struct qman_fq *,
  49. const union qm_mr_entry *);
  50. static struct qm_fd fd, fd_dq;
  51. static struct qman_fq fq_base = {
  52. .cb.dqrr = cb_dqrr,
  53. .cb.ern = cb_ern,
  54. .cb.fqs = cb_fqs
  55. };
  56. static DECLARE_WAIT_QUEUE_HEAD(waitqueue);
  57. static int retire_complete, sdqcr_complete;
  58. /* Helpers for initialising and "incrementing" a frame descriptor */
  59. static void fd_init(struct qm_fd *fd)
  60. {
  61. qm_fd_addr_set64(fd, 0xabdeadbeefLLU);
  62. qm_fd_set_contig_big(fd, 0x0000ffff);
  63. fd->cmd = 0xfeedf00d;
  64. }
  65. static void fd_inc(struct qm_fd *fd)
  66. {
  67. u64 t = qm_fd_addr_get64(fd);
  68. int z = t >> 40;
  69. unsigned int len, off;
  70. enum qm_fd_format fmt;
  71. t <<= 1;
  72. if (z)
  73. t |= 1;
  74. qm_fd_addr_set64(fd, t);
  75. fmt = qm_fd_get_format(fd);
  76. off = qm_fd_get_offset(fd);
  77. len = qm_fd_get_length(fd);
  78. len--;
  79. qm_fd_set_param(fd, fmt, off, len);
  80. fd->cmd++;
  81. }
  82. /* The only part of the 'fd' we can't memcmp() is the ppid */
  83. static int fd_cmp(const struct qm_fd *a, const struct qm_fd *b)
  84. {
  85. int r = (qm_fd_addr_get64(a) == qm_fd_addr_get64(b)) ? 0 : -1;
  86. if (!r) {
  87. enum qm_fd_format fmt_a, fmt_b;
  88. fmt_a = qm_fd_get_format(a);
  89. fmt_b = qm_fd_get_format(b);
  90. r = fmt_a - fmt_b;
  91. }
  92. if (!r)
  93. r = a->cfg - b->cfg;
  94. if (!r)
  95. r = a->cmd - b->cmd;
  96. return r;
  97. }
  98. /* test */
  99. static int do_enqueues(struct qman_fq *fq)
  100. {
  101. unsigned int loop;
  102. int err = 0;
  103. for (loop = 0; loop < NUM_ENQUEUES; loop++) {
  104. if (qman_enqueue(fq, &fd)) {
  105. pr_crit("qman_enqueue() failed\n");
  106. err = -EIO;
  107. }
  108. fd_inc(&fd);
  109. }
  110. return err;
  111. }
  112. int qman_test_api(void)
  113. {
  114. unsigned int flags, frmcnt;
  115. int err;
  116. struct qman_fq *fq = &fq_base;
  117. pr_info("%s(): Starting\n", __func__);
  118. fd_init(&fd);
  119. fd_init(&fd_dq);
  120. /* Initialise (parked) FQ */
  121. err = qman_create_fq(0, FQ_FLAGS, fq);
  122. if (err) {
  123. pr_crit("qman_create_fq() failed\n");
  124. goto failed;
  125. }
  126. err = qman_init_fq(fq, QMAN_INITFQ_FLAG_LOCAL, NULL);
  127. if (err) {
  128. pr_crit("qman_init_fq() failed\n");
  129. goto failed;
  130. }
  131. /* Do enqueues + VDQCR, twice. (Parked FQ) */
  132. err = do_enqueues(fq);
  133. if (err)
  134. goto failed;
  135. pr_info("VDQCR (till-empty);\n");
  136. frmcnt = QM_VDQCR_NUMFRAMES_TILLEMPTY;
  137. err = qman_volatile_dequeue(fq, VDQCR_FLAGS, frmcnt);
  138. if (err) {
  139. pr_crit("qman_volatile_dequeue() failed\n");
  140. goto failed;
  141. }
  142. err = do_enqueues(fq);
  143. if (err)
  144. goto failed;
  145. pr_info("VDQCR (%d of %d);\n", NUM_PARTIAL, NUM_ENQUEUES);
  146. frmcnt = QM_VDQCR_NUMFRAMES_SET(NUM_PARTIAL);
  147. err = qman_volatile_dequeue(fq, VDQCR_FLAGS, frmcnt);
  148. if (err) {
  149. pr_crit("qman_volatile_dequeue() failed\n");
  150. goto failed;
  151. }
  152. pr_info("VDQCR (%d of %d);\n", NUM_ENQUEUES - NUM_PARTIAL,
  153. NUM_ENQUEUES);
  154. frmcnt = QM_VDQCR_NUMFRAMES_SET(NUM_ENQUEUES - NUM_PARTIAL);
  155. err = qman_volatile_dequeue(fq, VDQCR_FLAGS, frmcnt);
  156. if (err) {
  157. pr_err("qman_volatile_dequeue() failed\n");
  158. goto failed;
  159. }
  160. err = do_enqueues(fq);
  161. if (err)
  162. goto failed;
  163. pr_info("scheduled dequeue (till-empty)\n");
  164. err = qman_schedule_fq(fq);
  165. if (err) {
  166. pr_crit("qman_schedule_fq() failed\n");
  167. goto failed;
  168. }
  169. wait_event(waitqueue, sdqcr_complete);
  170. /* Retire and OOS the FQ */
  171. err = qman_retire_fq(fq, &flags);
  172. if (err < 0) {
  173. pr_crit("qman_retire_fq() failed\n");
  174. goto failed;
  175. }
  176. wait_event(waitqueue, retire_complete);
  177. if (flags & QMAN_FQ_STATE_BLOCKOOS) {
  178. err = -EIO;
  179. pr_crit("leaking frames\n");
  180. goto failed;
  181. }
  182. err = qman_oos_fq(fq);
  183. if (err) {
  184. pr_crit("qman_oos_fq() failed\n");
  185. goto failed;
  186. }
  187. qman_destroy_fq(fq);
  188. pr_info("%s(): Finished\n", __func__);
  189. return 0;
  190. failed:
  191. WARN_ON(1);
  192. return err;
  193. }
  194. static enum qman_cb_dqrr_result cb_dqrr(struct qman_portal *p,
  195. struct qman_fq *fq,
  196. const struct qm_dqrr_entry *dq)
  197. {
  198. if (WARN_ON(fd_cmp(&fd_dq, &dq->fd))) {
  199. pr_err("BADNESS: dequeued frame doesn't match;\n");
  200. return qman_cb_dqrr_consume;
  201. }
  202. fd_inc(&fd_dq);
  203. if (!(dq->stat & QM_DQRR_STAT_UNSCHEDULED) && !fd_cmp(&fd_dq, &fd)) {
  204. sdqcr_complete = 1;
  205. wake_up(&waitqueue);
  206. }
  207. return qman_cb_dqrr_consume;
  208. }
  209. static void cb_ern(struct qman_portal *p, struct qman_fq *fq,
  210. const union qm_mr_entry *msg)
  211. {
  212. pr_crit("cb_ern() unimplemented");
  213. WARN_ON(1);
  214. }
  215. static void cb_fqs(struct qman_portal *p, struct qman_fq *fq,
  216. const union qm_mr_entry *msg)
  217. {
  218. u8 verb = (msg->verb & QM_MR_VERB_TYPE_MASK);
  219. if ((verb != QM_MR_VERB_FQRN) && (verb != QM_MR_VERB_FQRNI)) {
  220. pr_crit("unexpected FQS message");
  221. WARN_ON(1);
  222. return;
  223. }
  224. pr_info("Retirement message received\n");
  225. retire_complete = 1;
  226. wake_up(&waitqueue);
  227. }