From: Jun Yang <[email protected]>

Extend the DPCON standalone Rx scheduler with a second scheduling mode
so callers can choose how packets reach the poll path. The mode is
selected at init time through a new enum rte_dpaa2_sch_mode argument to
rte_dpaa2_scheduler_init():

pull
   The original behaviour. A single shared DPCON channel is allocated
   and ethdev Rx queues are attached to it up front; packets are pulled
   from that channel via the plain or prefetch receive path.

push
   A per-lcore DPCON plus DPCI pair is allocated lazily on first
   receive. The DPCI is linked to the DPCON, the pending Rx queues are
   attached, and the DPCON channel is added as a static dequeue channel
   so frames are pushed into the software portal DQRR and consumed
   in place (dpaa2_scheduler_dpci_recv).

To support push mode, struct dpaa2_sch_dev now holds per-lcore dpcon
and dpci arrays and a per-lcore linked flag instead of a single DPCON
pointer. rte_dpaa2_scheduler_add() defers hardware attach for push mode
(recording the queue and doing the attach on the first receive on each
lcore), while pull mode still attaches immediately. start and destroy
are updated to walk the per-lcore arrays: destroy stops linked DPCONs,
frees both the DPCON and DPCI devices, and reports the first stop error
while still freeing everything.

Signed-off-by: Jun Yang <[email protected]>
---
 drivers/event/dpaa2/dpaa2_scheduler.c | 189 ++++++++++++++++++++++----
 drivers/net/dpaa2/rte_pmd_dpaa2.h     |   7 +-
 2 files changed, 167 insertions(+), 29 deletions(-)

diff --git a/drivers/event/dpaa2/dpaa2_scheduler.c 
b/drivers/event/dpaa2/dpaa2_scheduler.c
index e553c4d3f6..51956ac1e5 100644
--- a/drivers/event/dpaa2/dpaa2_scheduler.c
+++ b/drivers/event/dpaa2/dpaa2_scheduler.c
@@ -41,9 +41,12 @@ struct dpaa2_sch_port_queue {
 };
 
 struct dpaa2_sch_dev {
-       struct dpaa2_dpcon_dev *dpcon_dev;
+       struct dpaa2_dpcon_dev *dpcon_dev[RTE_MAX_LCORE];
+       struct dpaa2_dpci_dev *dpci_dev[RTE_MAX_LCORE];
+       uint8_t linked[RTE_MAX_LCORE];
        struct dpaa2_sch_port_queue port_queue[DPAA2_SCH_PORT_QUEUE_MAX_NUM];
        uint8_t port_queue_num;
+       enum rte_dpaa2_sch_mode sch_mode;
        struct queue_storage_info_t q_storage[RTE_MAX_LCORE];
        uint16_t (*rx_schedule)(struct dpaa2_sch_dev *dev,
                struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
@@ -83,11 +86,110 @@ dpaa2_qbman_pull_desc_channel_set(struct qbman_pull_desc 
*pulldesc,
                iova_storage, 1);
 }
 
+static uint16_t
+dpaa2_scheduler_dpci_recv(struct dpaa2_sch_dev *sch_dev,
+       struct rte_mbuf **mbuf, uint16_t nb_pkts)
+{
+       const struct qbman_result *dq;
+       struct dpaa2_dpcon_dev *dpcon_dev;
+       struct dpaa2_dpci_dev *dpci_dev;
+       struct dpaa2_dpio_dev *dpio_dev;
+       struct qbman_swp *swp;
+       const struct qbman_fd *fd;
+       struct dpaa2_queue *rxq;
+       struct dpaa2_sch_port_queue *port_queue;
+       struct rte_event_eth_rx_adapter_queue_conf *queue_conf;
+       uint16_t num_pkts = 0, i = 0;
+       int ret;
+       struct dpaa2_dev_priv *priv;
+       uint32_t cpu = rte_lcore_id();
+
+       if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) {
+               ret = dpaa2_affine_qbman_ethrx_swp();
+               if (ret) {
+                       DPAA2_EVENTDEV_ERR("Failure(%d) in affining portal", 
ret);
+                       return 0;
+               }
+       }
+       dpio_dev = DPAA2_PER_LCORE_ETHRX_DPIO;
+       swp = DPAA2_PER_LCORE_ETHRX_PORTAL;
+       if (likely(sch_dev->linked[cpu] == sch_dev->port_queue_num))
+               goto start_dq;
+       if (!sch_dev->dpcon_dev[cpu])
+               sch_dev->dpcon_dev[cpu] = rte_dpaa2_alloc_dpcon_dev();
+       if (!sch_dev->dpci_dev[cpu])
+               sch_dev->dpci_dev[cpu] = rte_dpaa2_alloc_dpci_dev();
+       if (!sch_dev->dpcon_dev[cpu] || !sch_dev->dpci_dev[cpu])
+               return 0;
+       dpcon_dev = sch_dev->dpcon_dev[cpu];
+       dpci_dev = sch_dev->dpci_dev[cpu];
+       ret = rte_dpaa2_dpci_link_attach(dpci_dev, DPCI_DEST_DPCON,
+               dpcon_dev->dpcon_id, 0, NULL, NULL);
+       if (ret) {
+               DPAA2_EVENTDEV_ERR("DPCI link attaches dpcon failed: err(%d)", 
ret);
+               return 0;
+       }
+       for (i = 0; i < sch_dev->port_queue_num; i++) {
+               port_queue = &sch_dev->port_queue[i];
+               if (port_queue->configured)
+                       continue;
+               queue_conf = &port_queue->queue_conf;
+               dpaa2_eth_eventq_prio_dpcon_to_ev(port_queue->priority,
+                       dpcon_dev, queue_conf);
+               ret = dpaa2_eth_eventq_attach(port_queue->eth_dev,
+                       port_queue->rxq_id, dpcon_dev, queue_conf);
+               if (ret) {
+                       DPAA2_EVENTDEV_ERR("Failure(%d) attaching %s-rxq%d to 
eventq",
+                               ret, port_queue->eth_dev->data->name,
+                               port_queue->rxq_id);
+                       return 0;
+               }
+               port_queue->configured = true;
+       }
+       ret = dpio_add_static_dequeue_channel(dpio_dev->dpio,
+                       CMD_PRI_LOW, dpio_dev->token,
+                       dpcon_dev->dpcon_id,
+                       &dpcon_dev->channel_index);
+       if (ret) {
+               DPAA2_EVENTDEV_ERR("Failure(%d) adding dpcon%d to static dq 
channel",
+                       ret, dpcon_dev->dpcon_id);
+               return 0;
+       }
+
+       qbman_swp_push_set(swp, dpcon_dev->channel_index, 1);
+       sch_dev->linked[cpu] = sch_dev->port_queue_num;
+
+start_dq:
+       do {
+               dq = qbman_swp_dqrr_next(swp);
+               if (!dq)
+                       goto quit;
+
+               qbman_swp_prefetch_dqrr_next(swp);
+
+               fd = qbman_result_DQ_fd(dq);
+               rxq = (void *)qbman_result_DQ_fqd_ctx(dq);
+               priv = rxq->eth_data->dev_private;
+               if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg))
+                       mbuf[num_pkts] = dpaa2_eth_sg_fd_to_mbuf_export(priv, 
fd);
+               else
+                       mbuf[num_pkts] = dpaa2_eth_fd_to_mbuf_export(priv, fd);
+               dpaa2_dev_rx_mbuf_flc_offload_export(mbuf[num_pkts], fd);
+               dpaa2_dev_rx_print_parser_result(priv, fd, mbuf[num_pkts]);
+               qbman_swp_dqrr_consume(swp, dq);
+
+               num_pkts++;
+       } while (num_pkts < nb_pkts);
+
+quit:
+       return num_pkts;
+}
+
 static uint16_t
 dpaa2_scheduler_recv(struct dpaa2_sch_dev *sch_dev,
        struct rte_mbuf **mbuf, uint16_t nb_pkts)
 {
-       struct dpaa2_dpcon_dev *dpcon_dev = sch_dev->dpcon_dev;
+       struct dpaa2_dpcon_dev *dpcon_dev = sch_dev->dpcon_dev[0];
        uint16_t ch_id = dpcon_dev->qbman_ch_id;
        struct qbman_result *dq_sch_storage;
        uint16_t total_nb_pkts = nb_pkts;
@@ -179,7 +281,7 @@ static uint16_t
 dpaa2_scheduler_prefetch_recv(struct dpaa2_sch_dev *sch_dev,
        struct rte_mbuf **mbuf, uint16_t nb_pkts)
 {
-       struct dpaa2_dpcon_dev *dpcon_dev = sch_dev->dpcon_dev;
+       struct dpaa2_dpcon_dev *dpcon_dev = sch_dev->dpcon_dev[0];
        uint16_t ch_id = dpcon_dev->qbman_ch_id, pull_size;
        struct qbman_result *dq_storage, *dq_storage1 = NULL, *active;
        struct qbman_pull_desc pulldesc;
@@ -314,7 +416,7 @@ dpaa2_scheduler_prefetch_recv(struct dpaa2_sch_dev *sch_dev,
 }
 
 RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dpaa2_scheduler_init, 26.11)
-void *rte_dpaa2_scheduler_init(void)
+void *rte_dpaa2_scheduler_init(enum rte_dpaa2_sch_mode sch_mode)
 {
        struct dpaa2_dpcon_dev *dpcon_dev = NULL;
        struct dpaa2_sch_dev *sch_dev = NULL;
@@ -331,16 +433,24 @@ void *rte_dpaa2_scheduler_init(void)
        if (ret)
                goto err;
 
-       dpcon_dev = rte_dpaa2_alloc_dpcon_dev();
-       if (!dpcon_dev) {
-               DPAA2_EVENTDEV_ERR("Failed alloc dpcon device!!");
+       if (sch_mode == RTE_DPAA2_SCH_PULL) {
+               dpcon_dev = rte_dpaa2_alloc_dpcon_dev();
+               if (!dpcon_dev) {
+                       DPAA2_EVENTDEV_ERR("Failed alloc dpcon device!!");
+                       goto err;
+               }
+               sch_dev->dpcon_dev[0] = dpcon_dev;
+               if (prefetch_enable)
+                       sch_dev->rx_schedule = dpaa2_scheduler_prefetch_recv;
+               else
+                       sch_dev->rx_schedule = dpaa2_scheduler_recv;
+       } else if (sch_mode == RTE_DPAA2_SCH_PUSH) {
+               sch_dev->rx_schedule = dpaa2_scheduler_dpci_recv;
+       } else {
+               DPAA2_EVENTDEV_ERR("Invalid schedule mode(%d)!!", sch_mode);
                goto err;
        }
-       sch_dev->dpcon_dev = dpcon_dev;
-       if (prefetch_enable)
-               sch_dev->rx_schedule = dpaa2_scheduler_prefetch_recv;
-       else
-               sch_dev->rx_schedule = dpaa2_scheduler_recv;
+       sch_dev->sch_mode = sch_mode;
 
        return sch_dev;
 err:
@@ -361,15 +471,22 @@ int rte_dpaa2_scheduler_start(void *scheduler_handle)
        struct dpaa2_sch_dev *sch_dev = scheduler_handle;
        int32_t ret = 0;
 
-       if (sch_dev->dpcon_dev) {
-               ret = rte_dpaa2_dpcon_start(sch_dev->dpcon_dev);
-               if (ret)
+       if (sch_dev->sch_mode == RTE_DPAA2_SCH_PUSH)
+               goto start_quit;
+
+       if (sch_dev->dpcon_dev[0]) {
+               ret = rte_dpaa2_dpcon_start(sch_dev->dpcon_dev[0]);
+               if (ret) {
                        DPAA2_EVENTDEV_ERR("Failed(%d) to start dpcon", ret);
+                       return ret;
+               }
+               sch_dev->linked[0] = 1;
        } else {
                DPAA2_EVENTDEV_ERR("No dpcon allocated");
                ret = -ENODEV;
        }
 
+start_quit:
        return ret;
 }
 
@@ -377,15 +494,27 @@ 
RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dpaa2_scheduler_destroy, 26.11)
 int rte_dpaa2_scheduler_destroy(void *scheduler_handle)
 {
        struct dpaa2_sch_dev *sch_dev = scheduler_handle;
-       int32_t ret = 0;
+       struct dpaa2_dpcon_dev *dpcon_dev;
+       struct dpaa2_dpci_dev *dpci_dev;
+       int32_t ret = 0, _ret, i;
 
-       if (sch_dev->dpcon_dev) {
-               ret = rte_dpaa2_dpcon_stop(sch_dev->dpcon_dev);
-               if (ret) {
-                       DPAA2_EVENTDEV_ERR("Failed(%d) to stop dpcon", ret);
-                       /** Free anyway.*/
+       for (i = 0; i < RTE_MAX_LCORE; i++) {
+               dpcon_dev = sch_dev->dpcon_dev[i];
+               dpci_dev = sch_dev->dpci_dev[i];
+               if (dpcon_dev) {
+                       if (sch_dev->linked[i]) {
+                               _ret = rte_dpaa2_dpcon_stop(dpcon_dev);
+                               if (_ret) {
+                                       DPAA2_EVENTDEV_ERR("Failed(%d) to stop 
dpcon[%d]", _ret, i);
+                                       /** Free anyway.*/
+                                       ret = _ret;
+                               }
+                       }
+                       rte_dpaa2_free_dpcon_dev(dpcon_dev);
                }
-               rte_dpaa2_free_dpcon_dev(sch_dev->dpcon_dev);
+               if (dpci_dev)
+                       rte_dpaa2_free_dpci_dev(dpci_dev);
+               sch_dev->linked[i] = 0;
        }
 
        rte_free(sch_dev);
@@ -421,17 +550,21 @@ int rte_dpaa2_scheduler_add(void *scheduler_handle,
        }
 
        memset(&queue_conf, 0, sizeof(struct 
rte_event_eth_rx_adapter_queue_conf));
-       dpcon_dev = sch_dev->dpcon_dev;
-       dpaa2_eth_eventq_prio_dpcon_to_ev(priority, dpcon_dev, &queue_conf);
-       queue_conf.ev.sched_type = RTE_SCHED_TYPE_PARALLEL;
-       ret = dpaa2_eth_eventq_attach(dev, rxq_id, dpcon_dev, &queue_conf);
+       ret = 0;
+       if (sch_dev->sch_mode == RTE_DPAA2_SCH_PULL) {
+               dpcon_dev = sch_dev->dpcon_dev[0];
+               dpaa2_eth_eventq_prio_dpcon_to_ev(priority, dpcon_dev, 
&queue_conf);
+               queue_conf.ev.sched_type = RTE_SCHED_TYPE_PARALLEL;
+               ret = dpaa2_eth_eventq_attach(dev, rxq_id, dpcon_dev, 
&queue_conf);
+       }
        if (!ret) {
                sch_dev->port_queue[sch_dev->port_queue_num].eth_dev = dev;
                sch_dev->port_queue[sch_dev->port_queue_num].rxq_id = rxq_id;
                sch_dev->port_queue[sch_dev->port_queue_num].priority = 
priority;
                
rte_memcpy(&sch_dev->port_queue[sch_dev->port_queue_num].queue_conf,
                        &queue_conf, sizeof(struct 
rte_event_eth_rx_adapter_queue_conf));
-               sch_dev->port_queue[sch_dev->port_queue_num].configured = true;
+               if (sch_dev->sch_mode == RTE_DPAA2_SCH_PULL)
+                       sch_dev->port_queue[sch_dev->port_queue_num].configured 
= true;
                sch_dev->port_queue_num++;
        }
 
@@ -454,5 +587,5 @@ rte_dpaa2_scheduler_max_prio(void *scheduler_handle)
 {
        struct dpaa2_sch_dev *sch_dev = scheduler_handle;
 
-       return sch_dev->dpcon_dev->num_priorities;
+       return sch_dev->dpcon_dev[0]->num_priorities;
 }
diff --git a/drivers/net/dpaa2/rte_pmd_dpaa2.h 
b/drivers/net/dpaa2/rte_pmd_dpaa2.h
index eb038011c9..5125ec5bf7 100644
--- a/drivers/net/dpaa2/rte_pmd_dpaa2.h
+++ b/drivers/net/dpaa2/rte_pmd_dpaa2.h
@@ -129,9 +129,14 @@ int
 rte_pmd_dpaa2_rx_get_offset(uint16_t port_id, struct rte_mbuf *m,
        uint8_t *l3_off, uint8_t *l4_off, uint8_t *l5_off);
 
+enum rte_dpaa2_sch_mode {
+       RTE_DPAA2_SCH_PULL,
+       RTE_DPAA2_SCH_PUSH
+};
+
 __rte_experimental
 void *
-rte_dpaa2_scheduler_init(void);
+rte_dpaa2_scheduler_init(enum rte_dpaa2_sch_mode sch_mode);
 __rte_experimental
 int
 rte_dpaa2_scheduler_start(void *scheduler_handle);
-- 
2.43.0

Reply via email to