qman_test_api.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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 = cpu_to_be32(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 = cpu_to_be32(be32_to_cpu(fd->cmd) + 1);
  81. }
  82. /* The only part of the 'fd' we can't memcmp() is the ppid */
  83. static bool fd_neq(const struct qm_fd *a, const struct qm_fd *b)
  84. {
  85. bool neq = qm_fd_addr_get64(a) != qm_fd_addr_get64(b);
  86. neq |= qm_fd_get_format(a) != qm_fd_get_format(b);
  87. neq |= a->cfg != b->cfg;
  88. neq |= a->cmd != b->cmd;
  89. return neq;
  90. }
  91. /* test */
  92. static int do_enqueues(struct qman_fq *fq)
  93. {
  94. unsigned int loop;
  95. int err = 0;
  96. for (loop = 0; loop < NUM_ENQUEUES; loop++) {
  97. if (qman_enqueue(fq, &fd)) {
  98. pr_crit("qman_enqueue() failed\n");
  99. err = -EIO;
  100. }
  101. fd_inc(&fd);
  102. }
  103. return err;
  104. }
  105. int qman_test_api(void)
  106. {
  107. unsigned int flags, frmcnt;
  108. int err;
  109. struct qman_fq *fq = &fq_base;
  110. pr_info("%s(): Starting\n", __func__);
  111. fd_init(&fd);
  112. fd_init(&fd_dq);
  113. /* Initialise (parked) FQ */
  114. err = qman_create_fq(0, FQ_FLAGS, fq);
  115. if (err) {
  116. pr_crit("qman_create_fq() failed\n");
  117. goto failed;
  118. }
  119. err = qman_init_fq(fq, QMAN_INITFQ_FLAG_LOCAL, NULL);
  120. if (err) {
  121. pr_crit("qman_init_fq() failed\n");
  122. goto failed;
  123. }
  124. /* Do enqueues + VDQCR, twice. (Parked FQ) */
  125. err = do_enqueues(fq);
  126. if (err)
  127. goto failed;
  128. pr_info("VDQCR (till-empty);\n");
  129. frmcnt = QM_VDQCR_NUMFRAMES_TILLEMPTY;
  130. err = qman_volatile_dequeue(fq, VDQCR_FLAGS, frmcnt);
  131. if (err) {
  132. pr_crit("qman_volatile_dequeue() failed\n");
  133. goto failed;
  134. }
  135. err = do_enqueues(fq);
  136. if (err)
  137. goto failed;
  138. pr_info("VDQCR (%d of %d);\n", NUM_PARTIAL, NUM_ENQUEUES);
  139. frmcnt = QM_VDQCR_NUMFRAMES_SET(NUM_PARTIAL);
  140. err = qman_volatile_dequeue(fq, VDQCR_FLAGS, frmcnt);
  141. if (err) {
  142. pr_crit("qman_volatile_dequeue() failed\n");
  143. goto failed;
  144. }
  145. pr_info("VDQCR (%d of %d);\n", NUM_ENQUEUES - NUM_PARTIAL,
  146. NUM_ENQUEUES);
  147. frmcnt = QM_VDQCR_NUMFRAMES_SET(NUM_ENQUEUES - NUM_PARTIAL);
  148. err = qman_volatile_dequeue(fq, VDQCR_FLAGS, frmcnt);
  149. if (err) {
  150. pr_err("qman_volatile_dequeue() failed\n");
  151. goto failed;
  152. }
  153. err = do_enqueues(fq);
  154. if (err)
  155. goto failed;
  156. pr_info("scheduled dequeue (till-empty)\n");
  157. err = qman_schedule_fq(fq);
  158. if (err) {
  159. pr_crit("qman_schedule_fq() failed\n");
  160. goto failed;
  161. }
  162. wait_event(waitqueue, sdqcr_complete);
  163. /* Retire and OOS the FQ */
  164. err = qman_retire_fq(fq, &flags);
  165. if (err < 0) {
  166. pr_crit("qman_retire_fq() failed\n");
  167. goto failed;
  168. }
  169. wait_event(waitqueue, retire_complete);
  170. if (flags & QMAN_FQ_STATE_BLOCKOOS) {
  171. err = -EIO;
  172. pr_crit("leaking frames\n");
  173. goto failed;
  174. }
  175. err = qman_oos_fq(fq);
  176. if (err) {
  177. pr_crit("qman_oos_fq() failed\n");
  178. goto failed;
  179. }
  180. qman_destroy_fq(fq);
  181. pr_info("%s(): Finished\n", __func__);
  182. return 0;
  183. failed:
  184. WARN_ON(1);
  185. return err;
  186. }
  187. static enum qman_cb_dqrr_result cb_dqrr(struct qman_portal *p,
  188. struct qman_fq *fq,
  189. const struct qm_dqrr_entry *dq)
  190. {
  191. if (WARN_ON(fd_neq(&fd_dq, &dq->fd))) {
  192. pr_err("BADNESS: dequeued frame doesn't match;\n");
  193. return qman_cb_dqrr_consume;
  194. }
  195. fd_inc(&fd_dq);
  196. if (!(dq->stat & QM_DQRR_STAT_UNSCHEDULED) && !fd_neq(&fd_dq, &fd)) {
  197. sdqcr_complete = 1;
  198. wake_up(&waitqueue);
  199. }
  200. return qman_cb_dqrr_consume;
  201. }
  202. static void cb_ern(struct qman_portal *p, struct qman_fq *fq,
  203. const union qm_mr_entry *msg)
  204. {
  205. pr_crit("cb_ern() unimplemented");
  206. WARN_ON(1);
  207. }
  208. static void cb_fqs(struct qman_portal *p, struct qman_fq *fq,
  209. const union qm_mr_entry *msg)
  210. {
  211. u8 verb = (msg->verb & QM_MR_VERB_TYPE_MASK);
  212. if ((verb != QM_MR_VERB_FQRN) && (verb != QM_MR_VERB_FQRNI)) {
  213. pr_crit("unexpected FQS message");
  214. WARN_ON(1);
  215. return;
  216. }
  217. pr_info("Retirement message received\n");
  218. retire_complete = 1;
  219. wake_up(&waitqueue);
  220. }