doc: fix names of UIO drivers
[dpdk.git] / app / test-eventdev / test_order_common.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Cavium, Inc
3  */
4
5 #include "test_order_common.h"
6
7 int
8 order_test_result(struct evt_test *test, struct evt_options *opt)
9 {
10         RTE_SET_USED(opt);
11         struct test_order *t = evt_test_priv(test);
12
13         return t->result;
14 }
15
16 static inline int
17 order_producer(void *arg)
18 {
19         struct prod_data *p  = arg;
20         struct test_order *t = p->t;
21         struct evt_options *opt = t->opt;
22         const uint8_t dev_id = p->dev_id;
23         const uint8_t port = p->port_id;
24         struct rte_mempool *pool = t->pool;
25         const uint64_t nb_pkts = t->nb_pkts;
26         uint32_t *producer_flow_seq = t->producer_flow_seq;
27         const uint32_t nb_flows = t->nb_flows;
28         uint64_t count = 0;
29         struct rte_mbuf *m;
30         struct rte_event ev;
31
32         if (opt->verbose_level > 1)
33                 printf("%s(): lcore %d dev_id %d port=%d queue=%d\n",
34                          __func__, rte_lcore_id(), dev_id, port, p->queue_id);
35
36         ev.event = 0;
37         ev.op = RTE_EVENT_OP_NEW;
38         ev.queue_id = p->queue_id;
39         ev.sched_type = RTE_SCHED_TYPE_ORDERED;
40         ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL;
41         ev.event_type =  RTE_EVENT_TYPE_CPU;
42         ev.sub_event_type = 0; /* stage 0 */
43
44         while (count < nb_pkts && t->err == false) {
45                 m = rte_pktmbuf_alloc(pool);
46                 if (m == NULL)
47                         continue;
48
49                 const flow_id_t flow = (uintptr_t)m % nb_flows;
50                 /* Maintain seq number per flow */
51                 *order_mbuf_seqn(t, m) = producer_flow_seq[flow]++;
52                 order_flow_id_save(t, flow, m, &ev);
53
54                 while (rte_event_enqueue_burst(dev_id, port, &ev, 1) != 1) {
55                         if (t->err)
56                                 break;
57                         rte_pause();
58                 }
59
60                 count++;
61         }
62         return 0;
63 }
64
65 int
66 order_opt_check(struct evt_options *opt)
67 {
68         if (opt->prod_type != EVT_PROD_TYPE_SYNT) {
69                 evt_err("Invalid producer type '%s' valid producer '%s'",
70                         evt_prod_id_to_name(opt->prod_type),
71                         evt_prod_id_to_name(EVT_PROD_TYPE_SYNT));
72                 return -1;
73         }
74
75         /* 1 producer + N workers + main */
76         if (rte_lcore_count() < 3) {
77                 evt_err("test need minimum 3 lcores");
78                 return -1;
79         }
80
81         /* Validate worker lcores */
82         if (evt_lcores_has_overlap(opt->wlcores, rte_get_main_lcore())) {
83                 evt_err("worker lcores overlaps with main lcore");
84                 return -1;
85         }
86
87         if (evt_nr_active_lcores(opt->plcores) == 0) {
88                 evt_err("missing the producer lcore");
89                 return -1;
90         }
91
92         if (evt_nr_active_lcores(opt->plcores) != 1) {
93                 evt_err("only one producer lcore must be selected");
94                 return -1;
95         }
96
97         int plcore = evt_get_first_active_lcore(opt->plcores);
98
99         if (plcore < 0) {
100                 evt_err("failed to find active producer");
101                 return plcore;
102         }
103
104         if (evt_lcores_has_overlap(opt->wlcores, plcore)) {
105                 evt_err("worker lcores overlaps producer lcore");
106                 return -1;
107         }
108         if (evt_has_disabled_lcore(opt->wlcores)) {
109                 evt_err("one or more workers lcores are not enabled");
110                 return -1;
111         }
112         if (!evt_has_active_lcore(opt->wlcores)) {
113                 evt_err("minimum one worker is required");
114                 return -1;
115         }
116
117         /* Validate producer lcore */
118         if (plcore == (int)rte_get_main_lcore()) {
119                 evt_err("producer lcore and main lcore should be different");
120                 return -1;
121         }
122         if (!rte_lcore_is_enabled(plcore)) {
123                 evt_err("producer lcore is not enabled");
124                 return -1;
125         }
126
127         /* Fixups */
128         if (opt->nb_pkts == 0)
129                 opt->nb_pkts = INT64_MAX;
130
131         return 0;
132 }
133
134 int
135 order_test_setup(struct evt_test *test, struct evt_options *opt)
136 {
137         void *test_order;
138         struct test_order *t;
139         static const struct rte_mbuf_dynfield flow_id_dynfield_desc = {
140                 .name = "test_event_dynfield_flow_id",
141                 .size = sizeof(flow_id_t),
142                 .align = __alignof__(flow_id_t),
143         };
144         static const struct rte_mbuf_dynfield seqn_dynfield_desc = {
145                 .name = "test_event_dynfield_seqn",
146                 .size = sizeof(seqn_t),
147                 .align = __alignof__(seqn_t),
148         };
149
150         test_order = rte_zmalloc_socket(test->name, sizeof(struct test_order),
151                                 RTE_CACHE_LINE_SIZE, opt->socket_id);
152         if (test_order  == NULL) {
153                 evt_err("failed to allocate test_order memory");
154                 goto nomem;
155         }
156         test->test_priv = test_order;
157         t = evt_test_priv(test);
158
159         t->flow_id_dynfield_offset =
160                 rte_mbuf_dynfield_register(&flow_id_dynfield_desc);
161         if (t->flow_id_dynfield_offset < 0) {
162                 evt_err("failed to register mbuf field");
163                 return -rte_errno;
164         }
165
166         t->seqn_dynfield_offset =
167                 rte_mbuf_dynfield_register(&seqn_dynfield_desc);
168         if (t->seqn_dynfield_offset < 0) {
169                 evt_err("failed to register mbuf field");
170                 return -rte_errno;
171         }
172
173         t->producer_flow_seq = rte_zmalloc_socket("test_producer_flow_seq",
174                                  sizeof(*t->producer_flow_seq) * opt->nb_flows,
175                                 RTE_CACHE_LINE_SIZE, opt->socket_id);
176
177         if (t->producer_flow_seq  == NULL) {
178                 evt_err("failed to allocate t->producer_flow_seq memory");
179                 goto prod_nomem;
180         }
181
182         t->expected_flow_seq = rte_zmalloc_socket("test_expected_flow_seq",
183                                  sizeof(*t->expected_flow_seq) * opt->nb_flows,
184                                 RTE_CACHE_LINE_SIZE, opt->socket_id);
185
186         if (t->expected_flow_seq  == NULL) {
187                 evt_err("failed to allocate t->expected_flow_seq memory");
188                 goto exp_nomem;
189         }
190         rte_atomic64_set(&t->outstand_pkts, opt->nb_pkts);
191         t->err = false;
192         t->nb_pkts = opt->nb_pkts;
193         t->nb_flows = opt->nb_flows;
194         t->result = EVT_TEST_FAILED;
195         t->opt = opt;
196         return 0;
197
198 exp_nomem:
199         rte_free(t->producer_flow_seq);
200 prod_nomem:
201         rte_free(test->test_priv);
202 nomem:
203         return -ENOMEM;
204 }
205
206 void
207 order_test_destroy(struct evt_test *test, struct evt_options *opt)
208 {
209         RTE_SET_USED(opt);
210         struct test_order *t = evt_test_priv(test);
211
212         rte_free(t->expected_flow_seq);
213         rte_free(t->producer_flow_seq);
214         rte_free(test->test_priv);
215 }
216
217 int
218 order_mempool_setup(struct evt_test *test, struct evt_options *opt)
219 {
220         struct test_order *t = evt_test_priv(test);
221
222         t->pool  = rte_pktmbuf_pool_create(test->name, opt->pool_sz,
223                                         256 /* Cache */, 0,
224                                         512, /* Use very small mbufs */
225                                         opt->socket_id);
226         if (t->pool == NULL) {
227                 evt_err("failed to create mempool");
228                 return -ENOMEM;
229         }
230
231         return 0;
232 }
233
234 void
235 order_mempool_destroy(struct evt_test *test, struct evt_options *opt)
236 {
237         RTE_SET_USED(opt);
238         struct test_order *t = evt_test_priv(test);
239
240         rte_mempool_free(t->pool);
241 }
242
243 void
244 order_eventdev_destroy(struct evt_test *test, struct evt_options *opt)
245 {
246         RTE_SET_USED(test);
247
248         rte_event_dev_stop(opt->dev_id);
249         rte_event_dev_close(opt->dev_id);
250 }
251
252 void
253 order_opt_dump(struct evt_options *opt)
254 {
255         evt_dump_producer_lcores(opt);
256         evt_dump("nb_wrker_lcores", "%d", evt_nr_active_lcores(opt->wlcores));
257         evt_dump_worker_lcores(opt);
258         evt_dump("nb_evdev_ports", "%d", order_nb_event_ports(opt));
259 }
260
261 int
262 order_launch_lcores(struct evt_test *test, struct evt_options *opt,
263                         int (*worker)(void *))
264 {
265         int ret, lcore_id;
266         struct test_order *t = evt_test_priv(test);
267
268         int wkr_idx = 0;
269         /* launch workers */
270         RTE_LCORE_FOREACH_WORKER(lcore_id) {
271                 if (!(opt->wlcores[lcore_id]))
272                         continue;
273
274                 ret = rte_eal_remote_launch(worker, &t->worker[wkr_idx],
275                                          lcore_id);
276                 if (ret) {
277                         evt_err("failed to launch worker %d", lcore_id);
278                         return ret;
279                 }
280                 wkr_idx++;
281         }
282
283         /* launch producer */
284         int plcore = evt_get_first_active_lcore(opt->plcores);
285
286         ret = rte_eal_remote_launch(order_producer, &t->prod, plcore);
287         if (ret) {
288                 evt_err("failed to launch order_producer %d", plcore);
289                 return ret;
290         }
291
292         uint64_t cycles = rte_get_timer_cycles();
293         int64_t old_remaining  = -1;
294
295         while (t->err == false) {
296                 uint64_t new_cycles = rte_get_timer_cycles();
297                 int64_t remaining = rte_atomic64_read(&t->outstand_pkts);
298
299                 if (remaining <= 0) {
300                         t->result = EVT_TEST_SUCCESS;
301                         break;
302                 }
303
304                 if (new_cycles - cycles > rte_get_timer_hz() * 1) {
305                         printf(CLGRN"\r%"PRId64""CLNRM, remaining);
306                         fflush(stdout);
307                         if (old_remaining == remaining) {
308                                 rte_event_dev_dump(opt->dev_id, stdout);
309                                 evt_err("No schedules for seconds, deadlock");
310                                 t->err = true;
311                                 rte_smp_wmb();
312                                 break;
313                         }
314                         old_remaining = remaining;
315                         cycles = new_cycles;
316                 }
317         }
318         printf("\r");
319
320         return 0;
321 }
322
323 int
324 order_event_dev_port_setup(struct evt_test *test, struct evt_options *opt,
325                                 uint8_t nb_workers, uint8_t nb_queues)
326 {
327         int ret;
328         uint8_t port;
329         struct test_order *t = evt_test_priv(test);
330         struct rte_event_dev_info dev_info;
331
332         memset(&dev_info, 0, sizeof(struct rte_event_dev_info));
333         ret = rte_event_dev_info_get(opt->dev_id, &dev_info);
334         if (ret) {
335                 evt_err("failed to get eventdev info %d", opt->dev_id);
336                 return ret;
337         }
338
339         if (opt->wkr_deq_dep > dev_info.max_event_port_dequeue_depth)
340                 opt->wkr_deq_dep = dev_info.max_event_port_dequeue_depth;
341
342         /* port configuration */
343         const struct rte_event_port_conf p_conf = {
344                         .dequeue_depth = opt->wkr_deq_dep,
345                         .enqueue_depth = dev_info.max_event_port_dequeue_depth,
346                         .new_event_threshold = dev_info.max_num_events,
347         };
348
349         /* setup one port per worker, linking to all queues */
350         for (port = 0; port < nb_workers; port++) {
351                 struct worker_data *w = &t->worker[port];
352
353                 w->dev_id = opt->dev_id;
354                 w->port_id = port;
355                 w->t = t;
356
357                 ret = rte_event_port_setup(opt->dev_id, port, &p_conf);
358                 if (ret) {
359                         evt_err("failed to setup port %d", port);
360                         return ret;
361                 }
362
363                 ret = rte_event_port_link(opt->dev_id, port, NULL, NULL, 0);
364                 if (ret != nb_queues) {
365                         evt_err("failed to link all queues to port %d", port);
366                         return -EINVAL;
367                 }
368         }
369         struct prod_data *p = &t->prod;
370
371         p->dev_id = opt->dev_id;
372         p->port_id = port; /* last port */
373         p->queue_id = 0;
374         p->t = t;
375
376         ret = rte_event_port_setup(opt->dev_id, port, &p_conf);
377         if (ret) {
378                 evt_err("failed to setup producer port %d", port);
379                 return ret;
380         }
381
382         return ret;
383 }