0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #include "qman_test.h"
0032
0033 #include <linux/dma-mapping.h>
0034 #include <linux/delay.h>
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085 struct bstrap {
0086 int (*fn)(void);
0087 atomic_t started;
0088 };
0089 static int bstrap_fn(void *bs)
0090 {
0091 struct bstrap *bstrap = bs;
0092 int err;
0093
0094 atomic_inc(&bstrap->started);
0095 err = bstrap->fn();
0096 if (err)
0097 return err;
0098 while (!kthread_should_stop())
0099 msleep(20);
0100 return 0;
0101 }
0102 static int on_all_cpus(int (*fn)(void))
0103 {
0104 int cpu;
0105
0106 for_each_cpu(cpu, cpu_online_mask) {
0107 struct bstrap bstrap = {
0108 .fn = fn,
0109 .started = ATOMIC_INIT(0)
0110 };
0111 struct task_struct *k = kthread_create(bstrap_fn, &bstrap,
0112 "hotpotato%d", cpu);
0113 int ret;
0114
0115 if (IS_ERR(k))
0116 return -ENOMEM;
0117 kthread_bind(k, cpu);
0118 wake_up_process(k);
0119
0120
0121
0122
0123
0124
0125 while (!atomic_read(&bstrap.started))
0126 msleep(20);
0127 ret = kthread_stop(k);
0128 if (ret)
0129 return ret;
0130 }
0131 return 0;
0132 }
0133
0134 struct hp_handler {
0135
0136
0137
0138
0139 struct qman_fq rx;
0140
0141 struct qman_fq tx;
0142
0143 u32 rx_mixer;
0144
0145 u32 tx_mixer;
0146
0147 dma_addr_t addr;
0148 u32 *frame_ptr;
0149
0150
0151
0152 u32 fqid_rx, fqid_tx;
0153
0154 struct list_head node;
0155
0156 unsigned int processor_id;
0157 } ____cacheline_aligned;
0158
0159 struct hp_cpu {
0160
0161 unsigned int processor_id;
0162
0163 struct list_head handlers;
0164
0165 struct list_head node;
0166
0167
0168
0169
0170 struct hp_handler *iterator;
0171 };
0172
0173
0174 static DEFINE_PER_CPU(struct hp_cpu, hp_cpus);
0175
0176
0177 static LIST_HEAD(hp_cpu_list);
0178 static DEFINE_SPINLOCK(hp_lock);
0179
0180 static unsigned int hp_cpu_list_length;
0181
0182
0183 static struct hp_handler *special_handler;
0184 static int loop_counter;
0185
0186
0187 static struct kmem_cache *hp_handler_slab;
0188
0189
0190 static void *__frame_ptr;
0191 static u32 *frame_ptr;
0192 static dma_addr_t frame_dma;
0193
0194
0195 static const struct qm_portal_config *pcfg;
0196
0197
0198 static DECLARE_WAIT_QUEUE_HEAD(queue);
0199
0200 #define HP_PER_CPU 2
0201 #define HP_LOOPS 8
0202
0203 #define HP_NUM_WORDS 80
0204
0205 #define HP_FIRST_WORD 0xabbaf00d
0206
0207 static inline u32 do_lfsr(u32 prev)
0208 {
0209 return (prev >> 1) ^ (-(prev & 1u) & 0xd0000001u);
0210 }
0211
0212 static int allocate_frame_data(void)
0213 {
0214 u32 lfsr = HP_FIRST_WORD;
0215 int loop;
0216
0217 if (!qman_dma_portal) {
0218 pr_crit("portal not available\n");
0219 return -EIO;
0220 }
0221
0222 pcfg = qman_get_qm_portal_config(qman_dma_portal);
0223
0224 __frame_ptr = kmalloc(4 * HP_NUM_WORDS, GFP_KERNEL);
0225 if (!__frame_ptr)
0226 return -ENOMEM;
0227
0228 frame_ptr = PTR_ALIGN(__frame_ptr, 64);
0229 for (loop = 0; loop < HP_NUM_WORDS; loop++) {
0230 frame_ptr[loop] = lfsr;
0231 lfsr = do_lfsr(lfsr);
0232 }
0233
0234 frame_dma = dma_map_single(pcfg->dev, frame_ptr, 4 * HP_NUM_WORDS,
0235 DMA_BIDIRECTIONAL);
0236 if (dma_mapping_error(pcfg->dev, frame_dma)) {
0237 pr_crit("dma mapping failure\n");
0238 kfree(__frame_ptr);
0239 return -EIO;
0240 }
0241
0242 return 0;
0243 }
0244
0245 static void deallocate_frame_data(void)
0246 {
0247 dma_unmap_single(pcfg->dev, frame_dma, 4 * HP_NUM_WORDS,
0248 DMA_BIDIRECTIONAL);
0249 kfree(__frame_ptr);
0250 }
0251
0252 static inline int process_frame_data(struct hp_handler *handler,
0253 const struct qm_fd *fd)
0254 {
0255 u32 *p = handler->frame_ptr;
0256 u32 lfsr = HP_FIRST_WORD;
0257 int loop;
0258
0259 if (qm_fd_addr_get64(fd) != handler->addr) {
0260 pr_crit("bad frame address, [%llX != %llX]\n",
0261 qm_fd_addr_get64(fd), handler->addr);
0262 return -EIO;
0263 }
0264 for (loop = 0; loop < HP_NUM_WORDS; loop++, p++) {
0265 *p ^= handler->rx_mixer;
0266 if (*p != lfsr) {
0267 pr_crit("corrupt frame data");
0268 return -EIO;
0269 }
0270 *p ^= handler->tx_mixer;
0271 lfsr = do_lfsr(lfsr);
0272 }
0273 return 0;
0274 }
0275
0276 static enum qman_cb_dqrr_result normal_dqrr(struct qman_portal *portal,
0277 struct qman_fq *fq,
0278 const struct qm_dqrr_entry *dqrr,
0279 bool sched_napi)
0280 {
0281 struct hp_handler *handler = (struct hp_handler *)fq;
0282
0283 if (process_frame_data(handler, &dqrr->fd)) {
0284 WARN_ON(1);
0285 goto skip;
0286 }
0287 if (qman_enqueue(&handler->tx, &dqrr->fd)) {
0288 pr_crit("qman_enqueue() failed");
0289 WARN_ON(1);
0290 }
0291 skip:
0292 return qman_cb_dqrr_consume;
0293 }
0294
0295 static enum qman_cb_dqrr_result special_dqrr(struct qman_portal *portal,
0296 struct qman_fq *fq,
0297 const struct qm_dqrr_entry *dqrr,
0298 bool sched_napi)
0299 {
0300 struct hp_handler *handler = (struct hp_handler *)fq;
0301
0302 process_frame_data(handler, &dqrr->fd);
0303 if (++loop_counter < HP_LOOPS) {
0304 if (qman_enqueue(&handler->tx, &dqrr->fd)) {
0305 pr_crit("qman_enqueue() failed");
0306 WARN_ON(1);
0307 goto skip;
0308 }
0309 } else {
0310 pr_info("Received final (%dth) frame\n", loop_counter);
0311 wake_up(&queue);
0312 }
0313 skip:
0314 return qman_cb_dqrr_consume;
0315 }
0316
0317 static int create_per_cpu_handlers(void)
0318 {
0319 struct hp_handler *handler;
0320 int loop;
0321 struct hp_cpu *hp_cpu = this_cpu_ptr(&hp_cpus);
0322
0323 hp_cpu->processor_id = smp_processor_id();
0324 spin_lock(&hp_lock);
0325 list_add_tail(&hp_cpu->node, &hp_cpu_list);
0326 hp_cpu_list_length++;
0327 spin_unlock(&hp_lock);
0328 INIT_LIST_HEAD(&hp_cpu->handlers);
0329 for (loop = 0; loop < HP_PER_CPU; loop++) {
0330 handler = kmem_cache_alloc(hp_handler_slab, GFP_KERNEL);
0331 if (!handler) {
0332 pr_crit("kmem_cache_alloc() failed");
0333 WARN_ON(1);
0334 return -EIO;
0335 }
0336 handler->processor_id = hp_cpu->processor_id;
0337 handler->addr = frame_dma;
0338 handler->frame_ptr = frame_ptr;
0339 list_add_tail(&handler->node, &hp_cpu->handlers);
0340 }
0341 return 0;
0342 }
0343
0344 static int destroy_per_cpu_handlers(void)
0345 {
0346 struct list_head *loop, *tmp;
0347 struct hp_cpu *hp_cpu = this_cpu_ptr(&hp_cpus);
0348
0349 spin_lock(&hp_lock);
0350 list_del(&hp_cpu->node);
0351 spin_unlock(&hp_lock);
0352 list_for_each_safe(loop, tmp, &hp_cpu->handlers) {
0353 u32 flags = 0;
0354 struct hp_handler *handler = list_entry(loop, struct hp_handler,
0355 node);
0356 if (qman_retire_fq(&handler->rx, &flags) ||
0357 (flags & QMAN_FQ_STATE_BLOCKOOS)) {
0358 pr_crit("qman_retire_fq(rx) failed, flags: %x", flags);
0359 WARN_ON(1);
0360 return -EIO;
0361 }
0362 if (qman_oos_fq(&handler->rx)) {
0363 pr_crit("qman_oos_fq(rx) failed");
0364 WARN_ON(1);
0365 return -EIO;
0366 }
0367 qman_destroy_fq(&handler->rx);
0368 qman_destroy_fq(&handler->tx);
0369 qman_release_fqid(handler->fqid_rx);
0370 list_del(&handler->node);
0371 kmem_cache_free(hp_handler_slab, handler);
0372 }
0373 return 0;
0374 }
0375
0376 static inline u8 num_cachelines(u32 offset)
0377 {
0378 u8 res = (offset + (L1_CACHE_BYTES - 1))
0379 / (L1_CACHE_BYTES);
0380 if (res > 3)
0381 return 3;
0382 return res;
0383 }
0384 #define STASH_DATA_CL \
0385 num_cachelines(HP_NUM_WORDS * 4)
0386 #define STASH_CTX_CL \
0387 num_cachelines(offsetof(struct hp_handler, fqid_rx))
0388
0389 static int init_handler(void *h)
0390 {
0391 struct qm_mcc_initfq opts;
0392 struct hp_handler *handler = h;
0393 int err;
0394
0395 if (handler->processor_id != smp_processor_id()) {
0396 err = -EIO;
0397 goto failed;
0398 }
0399
0400 memset(&handler->rx, 0, sizeof(handler->rx));
0401 if (handler == special_handler)
0402 handler->rx.cb.dqrr = special_dqrr;
0403 else
0404 handler->rx.cb.dqrr = normal_dqrr;
0405 err = qman_create_fq(handler->fqid_rx, 0, &handler->rx);
0406 if (err) {
0407 pr_crit("qman_create_fq(rx) failed");
0408 goto failed;
0409 }
0410 memset(&opts, 0, sizeof(opts));
0411 opts.we_mask = cpu_to_be16(QM_INITFQ_WE_FQCTRL |
0412 QM_INITFQ_WE_CONTEXTA);
0413 opts.fqd.fq_ctrl = cpu_to_be16(QM_FQCTRL_CTXASTASHING);
0414 qm_fqd_set_stashing(&opts.fqd, 0, STASH_DATA_CL, STASH_CTX_CL);
0415 err = qman_init_fq(&handler->rx, QMAN_INITFQ_FLAG_SCHED |
0416 QMAN_INITFQ_FLAG_LOCAL, &opts);
0417 if (err) {
0418 pr_crit("qman_init_fq(rx) failed");
0419 goto failed;
0420 }
0421
0422 memset(&handler->tx, 0, sizeof(handler->tx));
0423 err = qman_create_fq(handler->fqid_tx, QMAN_FQ_FLAG_NO_MODIFY,
0424 &handler->tx);
0425 if (err) {
0426 pr_crit("qman_create_fq(tx) failed");
0427 goto failed;
0428 }
0429
0430 return 0;
0431 failed:
0432 return err;
0433 }
0434
0435 static void init_handler_cb(void *h)
0436 {
0437 if (init_handler(h))
0438 WARN_ON(1);
0439 }
0440
0441 static int init_phase2(void)
0442 {
0443 int loop;
0444 u32 fqid = 0;
0445 u32 lfsr = 0xdeadbeef;
0446 struct hp_cpu *hp_cpu;
0447 struct hp_handler *handler;
0448
0449 for (loop = 0; loop < HP_PER_CPU; loop++) {
0450 list_for_each_entry(hp_cpu, &hp_cpu_list, node) {
0451 int err;
0452
0453 if (!loop)
0454 hp_cpu->iterator = list_first_entry(
0455 &hp_cpu->handlers,
0456 struct hp_handler, node);
0457 else
0458 hp_cpu->iterator = list_entry(
0459 hp_cpu->iterator->node.next,
0460 struct hp_handler, node);
0461
0462 hp_cpu->iterator->fqid_rx = fqid;
0463
0464 err = qman_alloc_fqid(&fqid);
0465 if (err) {
0466 pr_crit("qman_alloc_fqid() failed");
0467 return err;
0468 }
0469 hp_cpu->iterator->fqid_tx = fqid;
0470
0471 hp_cpu->iterator->rx_mixer = lfsr;
0472
0473 lfsr = do_lfsr(lfsr);
0474 hp_cpu->iterator->tx_mixer = lfsr;
0475 }
0476 }
0477
0478 hp_cpu = list_first_entry(&hp_cpu_list, struct hp_cpu, node);
0479 handler = list_first_entry(&hp_cpu->handlers, struct hp_handler, node);
0480 if (handler->fqid_rx != 0 || handler->rx_mixer != 0xdeadbeef)
0481 return 1;
0482 handler->fqid_rx = fqid;
0483 handler->rx_mixer = lfsr;
0484
0485 special_handler = handler;
0486 return 0;
0487 }
0488
0489 static int init_phase3(void)
0490 {
0491 int loop, err;
0492 struct hp_cpu *hp_cpu;
0493
0494 for (loop = 0; loop < HP_PER_CPU; loop++) {
0495 list_for_each_entry(hp_cpu, &hp_cpu_list, node) {
0496 if (!loop)
0497 hp_cpu->iterator = list_first_entry(
0498 &hp_cpu->handlers,
0499 struct hp_handler, node);
0500 else
0501 hp_cpu->iterator = list_entry(
0502 hp_cpu->iterator->node.next,
0503 struct hp_handler, node);
0504 preempt_disable();
0505 if (hp_cpu->processor_id == smp_processor_id()) {
0506 err = init_handler(hp_cpu->iterator);
0507 if (err)
0508 return err;
0509 } else {
0510 smp_call_function_single(hp_cpu->processor_id,
0511 init_handler_cb, hp_cpu->iterator, 1);
0512 }
0513 preempt_enable();
0514 }
0515 }
0516 return 0;
0517 }
0518
0519 static int send_first_frame(void *ignore)
0520 {
0521 u32 *p = special_handler->frame_ptr;
0522 u32 lfsr = HP_FIRST_WORD;
0523 int loop, err;
0524 struct qm_fd fd;
0525
0526 if (special_handler->processor_id != smp_processor_id()) {
0527 err = -EIO;
0528 goto failed;
0529 }
0530 memset(&fd, 0, sizeof(fd));
0531 qm_fd_addr_set64(&fd, special_handler->addr);
0532 qm_fd_set_contig_big(&fd, HP_NUM_WORDS * 4);
0533 for (loop = 0; loop < HP_NUM_WORDS; loop++, p++) {
0534 if (*p != lfsr) {
0535 err = -EIO;
0536 pr_crit("corrupt frame data");
0537 goto failed;
0538 }
0539 *p ^= special_handler->tx_mixer;
0540 lfsr = do_lfsr(lfsr);
0541 }
0542 pr_info("Sending first frame\n");
0543 err = qman_enqueue(&special_handler->tx, &fd);
0544 if (err) {
0545 pr_crit("qman_enqueue() failed");
0546 goto failed;
0547 }
0548
0549 return 0;
0550 failed:
0551 return err;
0552 }
0553
0554 static void send_first_frame_cb(void *ignore)
0555 {
0556 if (send_first_frame(NULL))
0557 WARN_ON(1);
0558 }
0559
0560 int qman_test_stash(void)
0561 {
0562 int err;
0563
0564 if (cpumask_weight(cpu_online_mask) < 2) {
0565 pr_info("%s(): skip - only 1 CPU\n", __func__);
0566 return 0;
0567 }
0568
0569 pr_info("%s(): Starting\n", __func__);
0570
0571 hp_cpu_list_length = 0;
0572 loop_counter = 0;
0573 hp_handler_slab = kmem_cache_create("hp_handler_slab",
0574 sizeof(struct hp_handler), L1_CACHE_BYTES,
0575 SLAB_HWCACHE_ALIGN, NULL);
0576 if (!hp_handler_slab) {
0577 err = -EIO;
0578 pr_crit("kmem_cache_create() failed");
0579 goto failed;
0580 }
0581
0582 err = allocate_frame_data();
0583 if (err)
0584 goto failed;
0585
0586
0587 pr_info("Creating %d handlers per cpu...\n", HP_PER_CPU);
0588 if (on_all_cpus(create_per_cpu_handlers)) {
0589 err = -EIO;
0590 pr_crit("on_each_cpu() failed");
0591 goto failed;
0592 }
0593 pr_info("Number of cpus: %d, total of %d handlers\n",
0594 hp_cpu_list_length, hp_cpu_list_length * HP_PER_CPU);
0595
0596 err = init_phase2();
0597 if (err)
0598 goto failed;
0599
0600 err = init_phase3();
0601 if (err)
0602 goto failed;
0603
0604 preempt_disable();
0605 if (special_handler->processor_id == smp_processor_id()) {
0606 err = send_first_frame(NULL);
0607 if (err)
0608 goto failed;
0609 } else {
0610 smp_call_function_single(special_handler->processor_id,
0611 send_first_frame_cb, NULL, 1);
0612 }
0613 preempt_enable();
0614
0615 wait_event(queue, loop_counter == HP_LOOPS);
0616 deallocate_frame_data();
0617 if (on_all_cpus(destroy_per_cpu_handlers)) {
0618 err = -EIO;
0619 pr_crit("on_each_cpu() failed");
0620 goto failed;
0621 }
0622 kmem_cache_destroy(hp_handler_slab);
0623 pr_info("%s(): Finished\n", __func__);
0624
0625 return 0;
0626 failed:
0627 WARN_ON(1);
0628 return err;
0629 }