net/mlx5: fix multi-segment packet wraparound
[dpdk.git] / drivers / event / sw / sw_evdev_selftest.c
index c89f7de..9768d3a 100644 (file)
 #include <rte_service_component.h>
 #include <rte_bus_vdev.h>
 
-#include "test.h"
+#include "sw_evdev.h"
 
 #define MAX_PORTS 16
 #define MAX_QIDS 16
 #define NUM_PACKETS (1<<18)
+#define DEQUEUE_DEPTH 128
 
 static int evdev;
 
@@ -39,6 +40,16 @@ struct test {
        uint32_t service_id;
 };
 
+typedef uint8_t counter_dynfield_t;
+static int counter_dynfield_offset = -1;
+
+static inline counter_dynfield_t *
+counter_field(struct rte_mbuf *mbuf)
+{
+       return RTE_MBUF_DYNFIELD(mbuf, \
+                       counter_dynfield_offset, counter_dynfield_t *);
+}
+
 static struct rte_event release_ev;
 
 static inline struct rte_mbuf *
@@ -147,7 +158,7 @@ init(struct test *t, int nb_queues, int nb_ports)
                        .nb_event_ports = nb_ports,
                        .nb_event_queue_flows = 1024,
                        .nb_events_limit = 4096,
-                       .nb_event_port_dequeue_depth = 128,
+                       .nb_event_port_dequeue_depth = DEQUEUE_DEPTH,
                        .nb_event_port_enqueue_depth = 128,
        };
        int ret;
@@ -171,7 +182,6 @@ create_ports(struct test *t, int num_ports)
                        .new_event_threshold = 1024,
                        .dequeue_depth = 32,
                        .enqueue_depth = 64,
-                       .disable_implicit_release = 0,
        };
        if (num_ports > MAX_PORTS)
                return -1;
@@ -375,7 +385,7 @@ run_prio_packet_test(struct test *t)
                        printf("%d: gen of pkt failed\n", __LINE__);
                        return -1;
                }
-               arp->seqn = MAGIC_SEQN[i];
+               *rte_event_pmd_selftest_seqn(arp) = MAGIC_SEQN[i];
 
                ev = (struct rte_event){
                        .priority = PRIORITY[i],
@@ -384,7 +394,7 @@ run_prio_packet_test(struct test *t)
                        .mbuf = arp
                };
                err = rte_event_enqueue_burst(evdev, t->port[0], &ev, 1);
-               if (err < 0) {
+               if (err != 1) {
                        printf("%d: error failed to enqueue\n", __LINE__);
                        return -1;
                }
@@ -414,7 +424,7 @@ run_prio_packet_test(struct test *t)
                rte_event_dev_dump(evdev, stdout);
                return -1;
        }
-       if (ev.mbuf->seqn != MAGIC_SEQN[1]) {
+       if (*rte_event_pmd_selftest_seqn(ev.mbuf) != MAGIC_SEQN[1]) {
                printf("%d: first packet out not highest priority\n",
                                __LINE__);
                rte_event_dev_dump(evdev, stdout);
@@ -428,7 +438,7 @@ run_prio_packet_test(struct test *t)
                rte_event_dev_dump(evdev, stdout);
                return -1;
        }
-       if (ev2.mbuf->seqn != MAGIC_SEQN[0]) {
+       if (*rte_event_pmd_selftest_seqn(ev2.mbuf) != MAGIC_SEQN[0]) {
                printf("%d: second packet out not lower priority\n",
                                __LINE__);
                rte_event_dev_dump(evdev, stdout);
@@ -472,11 +482,11 @@ test_single_directed_packet(struct test *t)
        }
 
        const uint32_t MAGIC_SEQN = 4711;
-       arp->seqn = MAGIC_SEQN;
+       *rte_event_pmd_selftest_seqn(arp) = MAGIC_SEQN;
 
        /* generate pkt and enqueue */
        err = rte_event_enqueue_burst(evdev, rx_enq, &ev, 1);
-       if (err < 0) {
+       if (err != 1) {
                printf("%d: error failed to enqueue\n", __LINE__);
                return -1;
        }
@@ -511,7 +521,7 @@ test_single_directed_packet(struct test *t)
                return -1;
        }
 
-       if (ev.mbuf->seqn != MAGIC_SEQN) {
+       if (*rte_event_pmd_selftest_seqn(ev.mbuf) != MAGIC_SEQN) {
                printf("%d: error magic sequence number not dequeued\n",
                                __LINE__);
                return -1;
@@ -545,7 +555,7 @@ test_directed_forward_credits(struct test *t)
 
        for (i = 0; i < 1000; i++) {
                err = rte_event_enqueue_burst(evdev, 0, &ev, 1);
-               if (err < 0) {
+               if (err != 1) {
                        printf("%d: error failed to enqueue\n", __LINE__);
                        return -1;
                }
@@ -706,7 +716,7 @@ burst_packets(struct test *t)
                };
                /* generate pkt and enqueue */
                err = rte_event_enqueue_burst(evdev, t->port[rx_port], &ev, 1);
-               if (err < 0) {
+               if (err != 1) {
                        printf("%d: Failed to enqueue\n", __LINE__);
                        return -1;
                }
@@ -794,7 +804,7 @@ abuse_inflights(struct test *t)
 
        /* Enqueue op only */
        err = rte_event_enqueue_burst(evdev, t->port[rx_enq], &release_ev, 1);
-       if (err < 0) {
+       if (err != 1) {
                printf("%d: Failed to enqueue\n", __LINE__);
                return -1;
        }
@@ -863,15 +873,15 @@ xstats_tests(struct test *t)
        int ret = rte_event_dev_xstats_names_get(evdev,
                                        RTE_EVENT_DEV_XSTATS_DEVICE,
                                        0, xstats_names, ids, XSTATS_MAX);
-       if (ret != 6) {
-               printf("%d: expected 6 stats, got return %d\n", __LINE__, ret);
+       if (ret != 8) {
+               printf("%d: expected 8 stats, got return %d\n", __LINE__, ret);
                return -1;
        }
        ret = rte_event_dev_xstats_get(evdev,
                                        RTE_EVENT_DEV_XSTATS_DEVICE,
                                        0, ids, values, ret);
-       if (ret != 6) {
-               printf("%d: expected 6 stats, got return %d\n", __LINE__, ret);
+       if (ret != 8) {
+               printf("%d: expected 8 stats, got return %d\n", __LINE__, ret);
                return -1;
        }
 
@@ -929,7 +939,7 @@ xstats_tests(struct test *t)
                ev.op = RTE_EVENT_OP_NEW;
                ev.mbuf = arp;
                ev.flow_id = 7;
-               arp->seqn = i;
+               *rte_event_pmd_selftest_seqn(arp) = i;
 
                int err = rte_event_enqueue_burst(evdev, t->port[0], &ev, 1);
                if (err != 1) {
@@ -949,7 +959,7 @@ xstats_tests(struct test *t)
        ret = rte_event_dev_xstats_get(evdev,
                                        RTE_EVENT_DEV_XSTATS_DEVICE,
                                        0, ids, values, num_stats);
-       static const uint64_t expected[] = {3, 3, 0, 1, 0, 0};
+       static const uint64_t expected[] = {3, 3, 0, 1, 0, 0, 4, 1};
        for (i = 0; (signed int)i < ret; i++) {
                if (expected[i] != values[i]) {
                        printf(
@@ -965,7 +975,7 @@ xstats_tests(struct test *t)
                                        0, NULL, 0);
 
        /* ensure reset statistics are zero-ed */
-       static const uint64_t expected_zero[] = {0, 0, 0, 0, 0, 0};
+       static const uint64_t expected_zero[] = {0, 0, 0, 0, 0, 0, 0, 0};
        ret = rte_event_dev_xstats_get(evdev,
                                        RTE_EVENT_DEV_XSTATS_DEVICE,
                                        0, ids, values, num_stats);
@@ -1226,7 +1236,6 @@ port_reconfig_credits(struct test *t)
                                .new_event_threshold = 128,
                                .dequeue_depth = 32,
                                .enqueue_depth = 64,
-                               .disable_implicit_release = 0,
                };
                if (rte_event_port_setup(evdev, 0, &port_conf) < 0) {
                        printf("%d Error setting up port\n", __LINE__);
@@ -1316,7 +1325,6 @@ port_single_lb_reconfig(struct test *t)
                .new_event_threshold = 128,
                .dequeue_depth = 32,
                .enqueue_depth = 64,
-               .disable_implicit_release = 0,
        };
        if (rte_event_port_setup(evdev, 0, &port_conf) < 0) {
                printf("%d Error setting up port\n", __LINE__);
@@ -1452,7 +1460,7 @@ xstats_id_reset_tests(struct test *t)
        for (i = 0; i < XSTATS_MAX; i++)
                ids[i] = i;
 
-#define NUM_DEV_STATS 6
+#define NUM_DEV_STATS 8
        /* Device names / values */
        int num_stats = rte_event_dev_xstats_names_get(evdev,
                                        RTE_EVENT_DEV_XSTATS_DEVICE,
@@ -1482,7 +1490,7 @@ xstats_id_reset_tests(struct test *t)
                ev.queue_id = t->qid[i];
                ev.op = RTE_EVENT_OP_NEW;
                ev.mbuf = arp;
-               arp->seqn = i;
+               *rte_event_pmd_selftest_seqn(arp) = i;
 
                int err = rte_event_enqueue_burst(evdev, t->port[0], &ev, 1);
                if (err != 1) {
@@ -1496,8 +1504,10 @@ xstats_id_reset_tests(struct test *t)
        static const char * const dev_names[] = {
                "dev_rx", "dev_tx", "dev_drop", "dev_sched_calls",
                "dev_sched_no_iq_enq", "dev_sched_no_cq_enq",
+               "dev_sched_last_iter_bitmask",
+               "dev_sched_progress_last_iter"
        };
-       uint64_t dev_expected[] = {NPKTS, NPKTS, 0, 1, 0, 0};
+       uint64_t dev_expected[] = {NPKTS, NPKTS, 0, 1, 0, 0, 4, 1};
        for (i = 0; (int)i < ret; i++) {
                unsigned int id;
                uint64_t val = rte_event_dev_xstats_by_name_get(evdev,
@@ -1510,8 +1520,8 @@ xstats_id_reset_tests(struct test *t)
                }
                if (val != dev_expected[i]) {
                        printf("%d: %s value incorrect, expected %"
-                               PRIu64" got %d\n", __LINE__, dev_names[i],
-                               dev_expected[i], id);
+                               PRIu64" got %"PRIu64"\n", __LINE__,
+                               dev_names[i], dev_expected[i], val);
                        goto fail;
                }
                /* reset to zero */
@@ -1534,11 +1544,11 @@ xstats_id_reset_tests(struct test *t)
                }
        };
 
-/* 48 is stat offset from start of the devices whole xstats.
+/* 49 is stat offset from start of the devices whole xstats.
  * This WILL break every time we add a statistic to a port
  * or the device, but there is no other way to test
  */
-#define PORT_OFF 48
+#define PORT_OFF 50
 /* num stats for the tested port. CQ size adds more stats to a port */
 #define NUM_PORT_STATS 21
 /* the port to test. */
@@ -1662,7 +1672,7 @@ xstats_id_reset_tests(struct test *t)
 /* queue offset from start of the devices whole xstats.
  * This will break every time we add a statistic to a device/port/queue
  */
-#define QUEUE_OFF 90
+#define QUEUE_OFF 92
        const uint32_t queue = 0;
        num_stats = rte_event_dev_xstats_names_get(evdev,
                                        RTE_EVENT_DEV_XSTATS_QUEUE, queue,
@@ -1870,7 +1880,7 @@ qid_priorities(struct test *t)
                ev.queue_id = t->qid[i];
                ev.op = RTE_EVENT_OP_NEW;
                ev.mbuf = arp;
-               arp->seqn = i;
+               *rte_event_pmd_selftest_seqn(arp) = i;
 
                int err = rte_event_enqueue_burst(evdev, t->port[0], &ev, 1);
                if (err != 1) {
@@ -1891,7 +1901,7 @@ qid_priorities(struct test *t)
                return -1;
        }
        for (i = 0; i < 3; i++) {
-               if (ev[i].mbuf->seqn != 2-i) {
+               if (*rte_event_pmd_selftest_seqn(ev[i].mbuf) != 2-i) {
                        printf(
                                "%d: qid priority test: seqn %d incorrectly prioritized\n",
                                        __LINE__, i);
@@ -1902,6 +1912,77 @@ qid_priorities(struct test *t)
        return 0;
 }
 
+static int
+unlink_in_progress(struct test *t)
+{
+       /* Test unlinking API, in particular that when an unlink request has
+        * not yet been seen by the scheduler thread, that the
+        * unlink_in_progress() function returns the number of unlinks.
+        */
+       unsigned int i;
+       /* Create instance with 1 ports, and 3 qids */
+       if (init(t, 3, 1) < 0 ||
+                       create_ports(t, 1) < 0) {
+               printf("%d: Error initializing device\n", __LINE__);
+               return -1;
+       }
+
+       for (i = 0; i < 3; i++) {
+               /* Create QID */
+               const struct rte_event_queue_conf conf = {
+                       .schedule_type = RTE_SCHED_TYPE_ATOMIC,
+                       /* increase priority (0 == highest), as we go */
+                       .priority = RTE_EVENT_DEV_PRIORITY_NORMAL - i,
+                       .nb_atomic_flows = 1024,
+                       .nb_atomic_order_sequences = 1024,
+               };
+
+               if (rte_event_queue_setup(evdev, i, &conf) < 0) {
+                       printf("%d: error creating qid %d\n", __LINE__, i);
+                       return -1;
+               }
+               t->qid[i] = i;
+       }
+       t->nb_qids = i;
+       /* map all QIDs to port */
+       rte_event_port_link(evdev, t->port[0], NULL, NULL, 0);
+
+       if (rte_event_dev_start(evdev) < 0) {
+               printf("%d: Error with start call\n", __LINE__);
+               return -1;
+       }
+
+       /* unlink all ports to have outstanding unlink requests */
+       int ret = rte_event_port_unlink(evdev, t->port[0], NULL, 0);
+       if (ret < 0) {
+               printf("%d: Failed to unlink queues\n", __LINE__);
+               return -1;
+       }
+
+       /* get active unlinks here, expect 3 */
+       int unlinks_in_progress =
+               rte_event_port_unlinks_in_progress(evdev, t->port[0]);
+       if (unlinks_in_progress != 3) {
+               printf("%d: Expected num unlinks in progress == 3, got %d\n",
+                               __LINE__, unlinks_in_progress);
+               return -1;
+       }
+
+       /* run scheduler service on this thread to ack the unlinks */
+       rte_service_run_iter_on_app_lcore(t->service_id, 1);
+
+       /* active unlinks expected as 0 as scheduler thread has acked */
+       unlinks_in_progress =
+               rte_event_port_unlinks_in_progress(evdev, t->port[0]);
+       if (unlinks_in_progress != 0) {
+               printf("%d: Expected num unlinks in progress == 0, got %d\n",
+                               __LINE__, unlinks_in_progress);
+       }
+
+       cleanup(t);
+       return 0;
+}
+
 static int
 load_balancing(struct test *t)
 {
@@ -1954,7 +2035,7 @@ load_balancing(struct test *t)
                };
                /* generate pkt and enqueue */
                err = rte_event_enqueue_burst(evdev, t->port[rx_enq], &ev, 1);
-               if (err < 0) {
+               if (err != 1) {
                        printf("%d: Failed to enqueue\n", __LINE__);
                        return -1;
                }
@@ -2053,7 +2134,7 @@ load_balancing_history(struct test *t)
                }
                arp->hash.rss = flows1[i];
                err = rte_event_enqueue_burst(evdev, t->port[rx_enq], &ev, 1);
-               if (err < 0) {
+               if (err != 1) {
                        printf("%d: Failed to enqueue\n", __LINE__);
                        return -1;
                }
@@ -2103,7 +2184,7 @@ load_balancing_history(struct test *t)
                arp->hash.rss = flows2[i];
 
                err = rte_event_enqueue_burst(evdev, t->port[rx_enq], &ev, 1);
-               if (err < 0) {
+               if (err != 1) {
                        printf("%d: Failed to enqueue\n", __LINE__);
                        return -1;
                }
@@ -2213,7 +2294,7 @@ invalid_qid(struct test *t)
                };
                /* generate pkt and enqueue */
                err = rte_event_enqueue_burst(evdev, t->port[rx_enq], &ev, 1);
-               if (err < 0) {
+               if (err != 1) {
                        printf("%d: Failed to enqueue\n", __LINE__);
                        return -1;
                }
@@ -2297,10 +2378,10 @@ single_packet(struct test *t)
        ev.mbuf = arp;
        ev.queue_id = 0;
        ev.flow_id = 3;
-       arp->seqn = MAGIC_SEQN;
+       *rte_event_pmd_selftest_seqn(arp) = MAGIC_SEQN;
 
        err = rte_event_enqueue_burst(evdev, t->port[rx_enq], &ev, 1);
-       if (err < 0) {
+       if (err != 1) {
                printf("%d: Failed to enqueue\n", __LINE__);
                return -1;
        }
@@ -2337,14 +2418,14 @@ single_packet(struct test *t)
        }
 
        err = test_event_dev_stats_get(evdev, &stats);
-       if (ev.mbuf->seqn != MAGIC_SEQN) {
+       if (*rte_event_pmd_selftest_seqn(ev.mbuf) != MAGIC_SEQN) {
                printf("%d: magic sequence number not dequeued\n", __LINE__);
                return -1;
        }
 
        rte_pktmbuf_free(ev.mbuf);
        err = rte_event_enqueue_burst(evdev, t->port[wrk_enq], &release_ev, 1);
-       if (err < 0) {
+       if (err != 1) {
                printf("%d: Failed to enqueue\n", __LINE__);
                return -1;
        }
@@ -2610,7 +2691,7 @@ parallel_basic(struct test *t, int check_order)
                ev.queue_id = t->qid[0];
                ev.op = RTE_EVENT_OP_NEW;
                ev.mbuf = mbufs[i];
-               mbufs[i]->seqn = MAGIC_SEQN + i;
+               *rte_event_pmd_selftest_seqn(mbufs[i]) = MAGIC_SEQN + i;
 
                /* generate pkt and enqueue */
                err = rte_event_enqueue_burst(evdev, t->port[rx_port], &ev, 1);
@@ -2665,10 +2746,12 @@ parallel_basic(struct test *t, int check_order)
        /* Check to see if the sequence numbers are in expected order */
        if (check_order) {
                for (j = 0 ; j < deq_pkts ; j++) {
-                       if (deq_ev[j].mbuf->seqn != MAGIC_SEQN + j) {
-                               printf(
-                                       "%d: Incorrect sequence number(%d) from port %d\n",
-                                       __LINE__, mbufs_out[j]->seqn, tx_port);
+                       if (*rte_event_pmd_selftest_seqn(deq_ev[j].mbuf) !=
+                                       MAGIC_SEQN + j) {
+                               printf("%d: Incorrect sequence number(%d) from port %d\n",
+                                       __LINE__,
+                                       *rte_event_pmd_selftest_seqn(mbufs_out[j]),
+                                       tx_port);
                                return -1;
                        }
                }
@@ -2807,6 +2890,78 @@ err:
        return -1;
 }
 
+static void
+flush(uint8_t dev_id __rte_unused, struct rte_event event, void *arg)
+{
+       *((uint8_t *) arg) += (event.u64 == 0xCA11BACC) ? 1 : 0;
+}
+
+static int
+dev_stop_flush(struct test *t) /* test to check we can properly flush events */
+{
+       const struct rte_event new_ev = {
+               .op = RTE_EVENT_OP_NEW,
+               .u64 = 0xCA11BACC,
+               .queue_id = 0
+       };
+       struct rte_event ev = new_ev;
+       uint8_t count = 0;
+       int i;
+
+       if (init(t, 1, 1) < 0 ||
+           create_ports(t, 1) < 0 ||
+           create_atomic_qids(t, 1) < 0) {
+               printf("%d: Error initializing device\n", __LINE__);
+               return -1;
+       }
+
+       /* Link the queue so *_start() doesn't error out */
+       if (rte_event_port_link(evdev, t->port[0], NULL, NULL, 0) != 1) {
+               printf("%d: Error linking queue to port\n", __LINE__);
+               goto err;
+       }
+
+       if (rte_event_dev_start(evdev) < 0) {
+               printf("%d: Error with start call\n", __LINE__);
+               goto err;
+       }
+
+       for (i = 0; i < DEQUEUE_DEPTH + 1; i++) {
+               if (rte_event_enqueue_burst(evdev, t->port[0], &ev, 1) != 1) {
+                       printf("%d: Error enqueuing events\n", __LINE__);
+                       goto err;
+               }
+       }
+
+       /* Schedule the events from the port to the IQ. At least one event
+        * should be remaining in the queue.
+        */
+       rte_service_run_iter_on_app_lcore(t->service_id, 1);
+
+       if (rte_event_dev_stop_flush_callback_register(evdev, flush, &count)) {
+               printf("%d: Error installing the flush callback\n", __LINE__);
+               goto err;
+       }
+
+       cleanup(t);
+
+       if (count == 0) {
+               printf("%d: Error executing the flush callback\n", __LINE__);
+               goto err;
+       }
+
+       if (rte_event_dev_stop_flush_callback_register(evdev, NULL, NULL)) {
+               printf("%d: Error uninstalling the flush callback\n", __LINE__);
+               goto err;
+       }
+
+       return 0;
+err:
+       rte_event_dev_dump(evdev, stdout);
+       cleanup(t);
+       return -1;
+}
+
 static int
 worker_loopback_worker_fn(void *arg)
 {
@@ -2846,8 +3001,8 @@ worker_loopback_worker_fn(void *arg)
                        }
 
                        ev[i].queue_id = 0;
-                       ev[i].mbuf->udata64++;
-                       if (ev[i].mbuf->udata64 != 16) {
+                       (*counter_field(ev[i].mbuf))++;
+                       if (*counter_field(ev[i].mbuf) != 16) {
                                ev[i].op = RTE_EVENT_OP_FORWARD;
                                enqd = rte_event_enqueue_burst(evdev, port,
                                                &ev[i], 1);
@@ -2887,7 +3042,7 @@ worker_loopback_producer_fn(void *arg)
                        m = rte_pktmbuf_alloc(t->mbuf_pool);
                } while (m == NULL);
 
-               m->udata64 = 0;
+               *counter_field(m) = 0;
 
                struct rte_event ev = {
                                .op = RTE_EVENT_OP_NEW,
@@ -2920,6 +3075,18 @@ worker_loopback(struct test *t, uint8_t disable_implicit_release)
        int err;
        int w_lcore, p_lcore;
 
+       static const struct rte_mbuf_dynfield counter_dynfield_desc = {
+               .name = "rte_event_sw_dynfield_selftest_counter",
+               .size = sizeof(counter_dynfield_t),
+               .align = __alignof__(counter_dynfield_t),
+       };
+       counter_dynfield_offset =
+               rte_mbuf_dynfield_register(&counter_dynfield_desc);
+       if (counter_dynfield_offset < 0) {
+               printf("Error registering mbuf field\n");
+               return -rte_errno;
+       }
+
        if (init(t, 8, 2) < 0 ||
                        create_atomic_qids(t, 8) < 0) {
                printf("%d: Error initializing device\n", __LINE__);
@@ -2935,7 +3102,8 @@ worker_loopback(struct test *t, uint8_t disable_implicit_release)
         * only be initialized once - and this needs to be set for multiple runs
         */
        conf.new_event_threshold = 512;
-       conf.disable_implicit_release = disable_implicit_release;
+       conf.event_port_cfg = disable_implicit_release ?
+               RTE_EVENT_PORT_CFG_DISABLE_IMPL_REL : 0;
 
        if (rte_event_port_setup(evdev, 0, &conf) < 0) {
                printf("Error setting up RX port\n");
@@ -2964,7 +3132,7 @@ worker_loopback(struct test *t, uint8_t disable_implicit_release)
 
        p_lcore = rte_get_next_lcore(
                        /* start core */ -1,
-                       /* skip master */ 1,
+                       /* skip main */ 1,
                        /* wrap */ 0);
        w_lcore = rte_get_next_lcore(p_lcore, 1, 0);
 
@@ -2972,8 +3140,8 @@ worker_loopback(struct test *t, uint8_t disable_implicit_release)
        rte_eal_remote_launch(worker_loopback_worker_fn, t, w_lcore);
 
        print_cycles = cycles = rte_get_timer_cycles();
-       while (rte_eal_get_lcore_state(p_lcore) != FINISHED ||
-                       rte_eal_get_lcore_state(w_lcore) != FINISHED) {
+       while (rte_eal_get_lcore_state(p_lcore) != WAIT ||
+                       rte_eal_get_lcore_state(w_lcore) != WAIT) {
 
                rte_service_run_iter_on_app_lcore(t->service_id, 1);
 
@@ -3013,36 +3181,39 @@ worker_loopback(struct test *t, uint8_t disable_implicit_release)
 
 static struct rte_mempool *eventdev_func_mempool;
 
-static int
+int
 test_sw_eventdev(void)
 {
-       struct test *t = malloc(sizeof(struct test));
+       struct test *t;
        int ret;
 
+       t = malloc(sizeof(struct test));
+       if (t == NULL)
+               return -1;
        /* manually initialize the op, older gcc's complain on static
         * initialization of struct elements that are a bitfield.
         */
        release_ev.op = RTE_EVENT_OP_RELEASE;
 
-       const char *eventdev_name = "event_sw0";
+       const char *eventdev_name = "event_sw";
        evdev = rte_event_dev_get_dev_id(eventdev_name);
        if (evdev < 0) {
                printf("%d: Eventdev %s not found - creating.\n",
                                __LINE__, eventdev_name);
                if (rte_vdev_init(eventdev_name, NULL) < 0) {
                        printf("Error creating eventdev\n");
-                       return -1;
+                       goto test_fail;
                }
                evdev = rte_event_dev_get_dev_id(eventdev_name);
                if (evdev < 0) {
                        printf("Error finding newly created eventdev\n");
-                       return -1;
+                       goto test_fail;
                }
        }
 
        if (rte_event_dev_service_id_get(evdev, &t->service_id) < 0) {
                printf("Failed to get service ID for software event dev\n");
-               return -1;
+               goto test_fail;
        }
 
        rte_service_runstate_set(t->service_id, 1);
@@ -3059,7 +3230,7 @@ test_sw_eventdev(void)
                                rte_socket_id());
                if (!eventdev_func_mempool) {
                        printf("ERROR creating mempool\n");
-                       return -1;
+                       goto test_fail;
                }
        }
        t->mbuf_pool = eventdev_func_mempool;
@@ -3067,146 +3238,158 @@ test_sw_eventdev(void)
        ret = test_single_directed_packet(t);
        if (ret != 0) {
                printf("ERROR - Single Directed Packet test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running Directed Forward Credit test...\n");
        ret = test_directed_forward_credits(t);
        if (ret != 0) {
                printf("ERROR - Directed Forward Credit test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running Single Load Balanced Packet test...\n");
        ret = single_packet(t);
        if (ret != 0) {
                printf("ERROR - Single Packet test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running Unordered Basic test...\n");
        ret = unordered_basic(t);
        if (ret != 0) {
                printf("ERROR -  Unordered Basic test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running Ordered Basic test...\n");
        ret = ordered_basic(t);
        if (ret != 0) {
                printf("ERROR -  Ordered Basic test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running Burst Packets test...\n");
        ret = burst_packets(t);
        if (ret != 0) {
                printf("ERROR - Burst Packets test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running Load Balancing test...\n");
        ret = load_balancing(t);
        if (ret != 0) {
                printf("ERROR - Load Balancing test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running Prioritized Directed test...\n");
        ret = test_priority_directed(t);
        if (ret != 0) {
                printf("ERROR - Prioritized Directed test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running Prioritized Atomic test...\n");
        ret = test_priority_atomic(t);
        if (ret != 0) {
                printf("ERROR - Prioritized Atomic test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
 
        printf("*** Running Prioritized Ordered test...\n");
        ret = test_priority_ordered(t);
        if (ret != 0) {
                printf("ERROR - Prioritized Ordered test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running Prioritized Unordered test...\n");
        ret = test_priority_unordered(t);
        if (ret != 0) {
                printf("ERROR - Prioritized Unordered test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running Invalid QID test...\n");
        ret = invalid_qid(t);
        if (ret != 0) {
                printf("ERROR - Invalid QID test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running Load Balancing History test...\n");
        ret = load_balancing_history(t);
        if (ret != 0) {
                printf("ERROR - Load Balancing History test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running Inflight Count test...\n");
        ret = inflight_counts(t);
        if (ret != 0) {
                printf("ERROR - Inflight Count test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running Abuse Inflights test...\n");
        ret = abuse_inflights(t);
        if (ret != 0) {
                printf("ERROR - Abuse Inflights test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running XStats test...\n");
        ret = xstats_tests(t);
        if (ret != 0) {
                printf("ERROR - XStats test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running XStats ID Reset test...\n");
        ret = xstats_id_reset_tests(t);
        if (ret != 0) {
                printf("ERROR - XStats ID Reset test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running XStats Brute Force test...\n");
        ret = xstats_brute_force(t);
        if (ret != 0) {
                printf("ERROR - XStats Brute Force test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running XStats ID Abuse test...\n");
        ret = xstats_id_abuse_tests(t);
        if (ret != 0) {
                printf("ERROR - XStats ID Abuse test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running QID Priority test...\n");
        ret = qid_priorities(t);
        if (ret != 0) {
                printf("ERROR - QID Priority test FAILED.\n");
-               return ret;
+               goto test_fail;
+       }
+       printf("*** Running Unlink-in-progress test...\n");
+       ret = unlink_in_progress(t);
+       if (ret != 0) {
+               printf("ERROR - Unlink in progress test FAILED.\n");
+               goto test_fail;
        }
        printf("*** Running Ordered Reconfigure test...\n");
        ret = ordered_reconfigure(t);
        if (ret != 0) {
                printf("ERROR - Ordered Reconfigure test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running Port LB Single Reconfig test...\n");
        ret = port_single_lb_reconfig(t);
        if (ret != 0) {
                printf("ERROR - Port LB Single Reconfig test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running Port Reconfig Credits test...\n");
        ret = port_reconfig_credits(t);
        if (ret != 0) {
                printf("ERROR - Port Reconfig Credits Reset test FAILED.\n");
-               return ret;
+               goto test_fail;
        }
        printf("*** Running Head-of-line-blocking test...\n");
        ret = holb(t);
        if (ret != 0) {
                printf("ERROR - Head-of-line-blocking test FAILED.\n");
-               return ret;
+               goto test_fail;
+       }
+       printf("*** Running Stop Flush test...\n");
+       ret = dev_stop_flush(t);
+       if (ret != 0) {
+               printf("ERROR - Stop Flush test FAILED.\n");
+               goto test_fail;
        }
        if (rte_lcore_count() >= 3) {
                printf("*** Running Worker loopback test...\n");
@@ -3220,7 +3403,7 @@ test_sw_eventdev(void)
                ret = worker_loopback(t, 1);
                if (ret != 0) {
                        printf("ERROR - Worker loopback test FAILED.\n");
-                       return ret;
+                       goto test_fail;
                }
        } else {
                printf("### Not enough cores for worker loopback tests.\n");
@@ -3233,7 +3416,10 @@ test_sw_eventdev(void)
         */
        free(t);
 
+       printf("SW Eventdev Selftest Successful.\n");
        return 0;
+test_fail:
+       free(t);
+       printf("SW Eventdev Selftest Failed.\n");
+       return -1;
 }
-
-REGISTER_TEST_COMMAND(eventdev_sw_autotest, test_sw_eventdev);