From: Beilei Xing <beilei.x...@intel.com>

Add Rx/Tx burst for port representor.

Signed-off-by: Beilei Xing <beilei.x...@intel.com>
---
 drivers/net/cpfl/cpfl_representor.c |  83 +++++++++++++++++++
 drivers/net/cpfl/cpfl_rxtx.c        | 121 ++++++++++++++++++++++++++++
 drivers/net/cpfl/cpfl_rxtx.h        |   4 +
 3 files changed, 208 insertions(+)

diff --git a/drivers/net/cpfl/cpfl_representor.c 
b/drivers/net/cpfl/cpfl_representor.c
index 79cb7f76d4..51b70ea346 100644
--- a/drivers/net/cpfl/cpfl_representor.c
+++ b/drivers/net/cpfl/cpfl_representor.c
@@ -491,6 +491,87 @@ static const struct eth_dev_ops cpfl_repr_dev_ops = {
        .stats_reset            = idpf_repr_stats_reset,
 };
 
+#define MAX_IDPF_REPRENSENTOR_BURST  128
+static uint16_t
+cpfl_repr_rx_burst(void *rxq,
+                  struct rte_mbuf **rx_pkts,
+                  uint16_t nb_pkts)
+{
+       struct cpfl_repr_rx_queue *rx_queue = rxq;
+       struct rte_ring *ring = rx_queue->rx_ring;
+       struct rte_mbuf *mbuf[MAX_IDPF_REPRENSENTOR_BURST] = {NULL};
+       unsigned int nb_recv;
+       uint16_t i;
+
+       if (unlikely(!ring))
+               return 0;
+
+       nb_recv = rte_ring_dequeue_burst(ring, (void **)mbuf,
+                                        RTE_MIN(nb_pkts, 
MAX_IDPF_REPRENSENTOR_BURST), NULL);
+       for (i = 0; i < nb_recv; i++) {
+               if (mbuf[i]->pool != rx_queue->mb_pool) {
+                       /* need copy if mpools used for vport and represntor 
queue are different */
+                       rx_pkts[i] = rte_pktmbuf_copy(mbuf[i], 
rx_queue->mb_pool, 0, UINT32_MAX);
+                       rte_pktmbuf_free(mbuf[i]);
+               } else {
+                       rx_pkts[i] = mbuf[i];
+               }
+       }
+
+       __atomic_fetch_add(&rx_queue->stats.packets, nb_recv, __ATOMIC_RELAXED);
+       /* TODO: bytes stats */
+       return nb_recv;
+}
+
+static uint16_t
+cpfl_get_vsi_from_vf_representor(struct cpfl_repr *repr)
+{
+       return repr->vport_info->vport_info.vsi_id;
+}
+
+static uint16_t
+cpfl_repr_tx_burst(void *txq,
+                  struct rte_mbuf **tx_pkts,
+                  uint16_t nb_pkts)
+{
+       struct cpfl_repr_tx_queue *tx_queue = txq;
+       struct idpf_tx_queue *hw_txq = &tx_queue->txq->base;
+       struct cpfl_repr *repr;
+       uint16_t vsi_id;
+       uint16_t nb;
+
+       if (unlikely(!tx_queue->txq))
+               return 0;
+
+       repr = tx_queue->repr;
+
+       if (!hw_txq) {
+               PMD_INIT_LOG(ERR, "No Queue associated with representor 
host_id: %d, %s %d",
+                            repr->repr_id.host_id,
+                            (repr->repr_id.type == RTE_ETH_REPRESENTOR_VF) ? 
"vf" : "pf",
+                            (repr->repr_id.type == RTE_ETH_REPRESENTOR_VF) ? 
repr->repr_id.vf_id :
+                            repr->repr_id.pf_id);
+               return 0;
+       }
+
+       if (repr->repr_id.type == RTE_ETH_REPRESENTOR_VF) {
+               vsi_id = cpfl_get_vsi_from_vf_representor(repr);
+       } else {
+               /* TODO: RTE_ETH_REPRESENTOR_PF */
+               PMD_INIT_LOG(ERR, "Get vsi from pf representor is not 
supported.");
+               return 0;
+       }
+
+       rte_spinlock_lock(&tx_queue->txq->lock);
+       nb = cpfl_xmit_pkts_to_vsi(tx_queue->txq, tx_pkts, nb_pkts, vsi_id);
+       rte_spinlock_unlock(&tx_queue->txq->lock);
+
+       __atomic_fetch_add(&tx_queue->stats.packets, nb, __ATOMIC_RELAXED);
+       __atomic_fetch_add(&tx_queue->stats.errors, nb, __ATOMIC_RELAXED);
+       /* TODO: bytes stats */
+       return nb;
+}
+
 static int
 cpfl_repr_init(struct rte_eth_dev *eth_dev, void *init_param)
 {
@@ -507,6 +588,8 @@ cpfl_repr_init(struct rte_eth_dev *eth_dev, void 
*init_param)
                repr->func_up = true;
 
        eth_dev->dev_ops = &cpfl_repr_dev_ops;
+       eth_dev->rx_pkt_burst = cpfl_repr_rx_burst;
+       eth_dev->tx_pkt_burst = cpfl_repr_tx_burst;
 
        eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
        /* bit[15:14] type
diff --git a/drivers/net/cpfl/cpfl_rxtx.c b/drivers/net/cpfl/cpfl_rxtx.c
index df6a8c1940..882efe04cf 100644
--- a/drivers/net/cpfl/cpfl_rxtx.c
+++ b/drivers/net/cpfl/cpfl_rxtx.c
@@ -616,6 +616,9 @@ cpfl_tx_queue_setup(struct rte_eth_dev *dev, uint16_t 
queue_idx,
        txq->ops = &def_txq_ops;
        cpfl_vport->nb_data_txq++;
        txq->q_set = true;
+
+       rte_spinlock_init(&cpfl_txq->lock);
+
        dev->data->tx_queues[queue_idx] = cpfl_txq;
 
        return 0;
@@ -1409,6 +1412,124 @@ cpfl_stop_queues(struct rte_eth_dev *dev)
        }
 }
 
+static inline void
+cpfl_set_tx_switch_ctx(uint16_t vsi_id, bool is_vsi,
+                      volatile union idpf_flex_tx_ctx_desc *ctx_desc)
+{
+       uint16_t cmd_dtype;
+
+       /* Use TX Native TSO Context Descriptor to carry VSI
+        * so TSO is not supported
+        */
+       if (is_vsi) {
+               cmd_dtype = IDPF_TX_DESC_DTYPE_FLEX_TSO_CTX |
+                       IDPF_TX_FLEX_CTX_DESC_CMD_SWTCH_TARGETVSI;
+               ctx_desc->tso.qw0.mss_rt =
+                       rte_cpu_to_le_16((uint16_t)vsi_id &
+                                IDPF_TXD_FLEX_CTX_MSS_RT_M);
+       } else {
+               cmd_dtype = IDPF_TX_DESC_DTYPE_FLEX_TSO_CTX |
+                       IDPF_TX_FLEX_CTX_DESC_CMD_SWTCH_UPLNK;
+       }
+
+       ctx_desc->tso.qw1.cmd_dtype = rte_cpu_to_le_16(cmd_dtype);
+}
+
+/* Transmit pkts to destination VSI,
+ * much similar as idpf_splitq_xmit_pkts
+ */
+uint16_t
+cpfl_xmit_pkts_to_vsi(struct cpfl_tx_queue *cpfl_txq, struct rte_mbuf 
**tx_pkts,
+                     uint16_t nb_pkts, uint16_t vsi_id)
+{
+       volatile struct idpf_flex_tx_sched_desc *txr;
+       volatile struct idpf_flex_tx_sched_desc *txd;
+       volatile union idpf_flex_tx_ctx_desc *ctx_desc;
+       struct idpf_tx_entry *sw_ring;
+       struct idpf_tx_entry *txe, *txn;
+       uint16_t nb_used, tx_id, sw_id;
+       struct idpf_tx_queue *txq;
+       struct rte_mbuf *tx_pkt;
+       uint16_t nb_to_clean;
+       uint16_t nb_tx = 0;
+
+       if (unlikely(!cpfl_txq))
+               return nb_tx;
+
+       txq = &cpfl_txq->base;
+       if (unlikely(!txq) || unlikely(!txq->q_started))
+               return nb_tx;
+
+       txr = txq->desc_ring;
+       sw_ring = txq->sw_ring;
+       tx_id = txq->tx_tail;
+       sw_id = txq->sw_tail;
+       txe = &sw_ring[sw_id];
+
+       for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
+               tx_pkt = tx_pkts[nb_tx];
+
+               if (txq->nb_free <= txq->free_thresh) {
+                       /* TODO: Need to refine, refer to idpf_splitq_xmit_pkts 
*/
+                       nb_to_clean = 2 * txq->rs_thresh;
+                       while (nb_to_clean--)
+                               idpf_split_tx_free(txq->complq);
+               }
+
+               if (txq->nb_free < tx_pkt->nb_segs + 1)
+                       break;
+               /* need context desc carry target vsi, no TSO support. */
+               nb_used = tx_pkt->nb_segs + 1;
+
+               /* context descriptor prepare*/
+               ctx_desc = (volatile union idpf_flex_tx_ctx_desc *)&txr[tx_id];
+
+               cpfl_set_tx_switch_ctx(vsi_id, true, ctx_desc);
+               tx_id++;
+               if (tx_id == txq->nb_tx_desc)
+                       tx_id = 0;
+
+               do {
+                       txd = &txr[tx_id];
+                       txn = &sw_ring[txe->next_id];
+                       txe->mbuf = tx_pkt;
+
+                       /* Setup TX descriptor */
+                       txd->buf_addr =
+                               rte_cpu_to_le_64(rte_mbuf_data_iova(tx_pkt));
+                       txd->qw1.cmd_dtype = IDPF_TX_DESC_DTYPE_FLEX_FLOW_SCHE;
+                       txd->qw1.rxr_bufsize = tx_pkt->data_len;
+                       txd->qw1.compl_tag = sw_id;
+                       tx_id++;
+                       if (tx_id == txq->nb_tx_desc)
+                               tx_id = 0;
+                       sw_id = txe->next_id;
+                       txe = txn;
+                       tx_pkt = tx_pkt->next;
+               } while (tx_pkt);
+
+               /* fill the last descriptor with End of Packet (EOP) bit */
+               txd->qw1.cmd_dtype |= IDPF_TXD_FLEX_FLOW_CMD_EOP;
+
+               txq->nb_free = (uint16_t)(txq->nb_free - nb_used);
+               txq->nb_used = (uint16_t)(txq->nb_used + nb_used);
+
+               if (txq->nb_used >= 32) {
+                       txd->qw1.cmd_dtype |= IDPF_TXD_FLEX_FLOW_CMD_RE;
+                       /* Update txq RE bit counters */
+                       txq->nb_used = 0;
+               }
+       }
+
+       /* update the tail pointer if any packets were processed */
+       if (likely(nb_tx)) {
+               IDPF_PCI_REG_WRITE(txq->qtx_tail, tx_id);
+               txq->tx_tail = tx_id;
+               txq->sw_tail = sw_id;
+       }
+       return nb_tx;
+}
+
 uint16_t
 cpfl_dummy_recv_pkts(__rte_unused void *queue,
                     __rte_unused struct rte_mbuf **tx_pkts,
diff --git a/drivers/net/cpfl/cpfl_rxtx.h b/drivers/net/cpfl/cpfl_rxtx.h
index 914a0485b5..463ab73323 100644
--- a/drivers/net/cpfl/cpfl_rxtx.h
+++ b/drivers/net/cpfl/cpfl_rxtx.h
@@ -72,6 +72,7 @@ struct cpfl_txq_hairpin_info {
 struct cpfl_tx_queue {
        struct idpf_tx_queue base;
        struct cpfl_txq_hairpin_info hairpin_info;
+       rte_spinlock_t lock;
 };
 
 static inline uint16_t
@@ -124,4 +125,7 @@ uint16_t cpfl_dummy_recv_pkts(void *queue,
 uint16_t cpfl_dummy_xmit_pkts(void *queue,
                              struct rte_mbuf **tx_pkts,
                              uint16_t nb_pkts);
+uint16_t cpfl_xmit_pkts_to_vsi(struct cpfl_tx_queue *txq,
+                              struct rte_mbuf **tx_pkts,
+                              uint16_t nb_pkts, uint16_t vsi_id);
 #endif /* _CPFL_RXTX_H_ */
-- 
2.34.1

Reply via email to