Add dedicated transmit function and transmit completion handler for
XDP which are a lot simpler than the original functions for SKB.

Signed-off-by: Michael Chan <michael.c...@broadcom.com>
Tested-by: Andy Gospodarek <go...@broadcom.com>
---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     | 34 +++++-----
 drivers/net/ethernet/broadcom/bnxt/bnxt.h     | 14 +++++
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 90 +++++++++++++++++++++++++++
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h |  2 +
 4 files changed, 125 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c 
b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index ae1f400..826915c 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -212,16 +212,7 @@ static bool bnxt_vf_pciid(enum board_idx idx)
 #define BNXT_CP_DB_IRQ_DIS(db)                                         \
                writel(DB_CP_IRQ_DIS_FLAGS, db)
 
-static inline u32 bnxt_tx_avail(struct bnxt *bp, struct bnxt_tx_ring_info *txr)
-{
-       /* Tell compiler to fetch tx indices from memory. */
-       barrier();
-
-       return bp->tx_ring_size -
-               ((txr->tx_prod - txr->tx_cons) & bp->tx_ring_mask);
-}
-
-static const u16 bnxt_lhint_arr[] = {
+const u16 bnxt_lhint_arr[] = {
        TX_BD_FLAGS_LHINT_512_AND_SMALLER,
        TX_BD_FLAGS_LHINT_512_TO_1023,
        TX_BD_FLAGS_LHINT_1024_TO_2047,
@@ -613,9 +604,8 @@ static inline u8 *__bnxt_alloc_rx_data(struct bnxt *bp, 
dma_addr_t *mapping,
        return data;
 }
 
-static inline int bnxt_alloc_rx_data(struct bnxt *bp,
-                                    struct bnxt_rx_ring_info *rxr,
-                                    u16 prod, gfp_t gfp)
+int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
+                      u16 prod, gfp_t gfp)
 {
        struct rx_bd *rxbd = &rxr->rx_desc_ring[RX_RING(prod)][RX_IDX(prod)];
        struct bnxt_sw_rx_bd *rx_buf = &rxr->rx_buf_ring[prod];
@@ -1771,6 +1761,17 @@ static int bnxt_poll_work(struct bnxt *bp, struct 
bnxt_napi *bnapi, int budget)
        if (tx_pkts)
                bnapi->tx_int(bp, bnapi, tx_pkts);
 
+       if (event & BNXT_TX_EVENT) {
+               struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
+               void __iomem *db = txr->tx_doorbell;
+               u16 prod = txr->tx_prod;
+
+               /* Sync BD data before updating doorbell */
+               wmb();
+
+               writel(DB_KEY_TX | prod, db);
+               writel(DB_KEY_TX | prod, db);
+       }
        if (event & BNXT_RX_EVENT) {
                struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
 
@@ -3056,9 +3057,12 @@ static int bnxt_alloc_mem(struct bnxt *bp, bool 
irq_re_init)
                        bp->tx_ring[i].bnapi = bp->bnapi[j];
                        bp->bnapi[j]->tx_ring = &bp->tx_ring[i];
                        bp->tx_ring_map[i] = bp->tx_nr_rings_xdp + i;
-                       if (i < bp->tx_nr_rings_xdp)
+                       if (i < bp->tx_nr_rings_xdp) {
                                bp->bnapi[j]->flags |= BNXT_NAPI_FLAG_XDP;
-                       bp->bnapi[j]->tx_int = bnxt_tx_int;
+                               bp->bnapi[j]->tx_int = bnxt_tx_int_xdp;
+                       } else {
+                               bp->bnapi[j]->tx_int = bnxt_tx_int;
+                       }
                }
 
                rc = bnxt_alloc_stats(bp);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h 
b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 007e779..cf7d33f 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -513,6 +513,7 @@ struct rx_tpa_end_cmp_ext {
 
 #define BNXT_RX_EVENT  1
 #define BNXT_AGG_EVENT 2
+#define BNXT_TX_EVENT  4
 
 struct bnxt_sw_tx_bd {
        union {
@@ -1190,6 +1191,19 @@ struct bnxt {
 #define SFF_MODULE_ID_QSFP28                   0x11
 #define BNXT_MAX_PHY_I2C_RESP_SIZE             64
 
+static inline u32 bnxt_tx_avail(struct bnxt *bp, struct bnxt_tx_ring_info *txr)
+{
+       /* Tell compiler to fetch tx indices from memory. */
+       barrier();
+
+       return bp->tx_ring_size -
+               ((txr->tx_prod - txr->tx_cons) & bp->tx_ring_mask);
+}
+
+extern const u16 bnxt_lhint_arr[];
+
+int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
+                      u16 prod, gfp_t gfp);
 void bnxt_reuse_rx_data(struct bnxt_rx_ring_info *rxr, u16 cons, void *data);
 void bnxt_set_tpa_flags(struct bnxt *bp);
 void bnxt_set_ring_params(struct bnxt *);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c 
b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
index 133e515..a9770ed 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
@@ -8,6 +8,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <linux/pci.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/if_vlan.h>
@@ -18,6 +19,69 @@
 #include "bnxt_xdp.h"
 
 #ifdef CONFIG_BNXT_XDP
+static int bnxt_xmit_xdp(struct bnxt *bp, struct bnxt_napi *bnapi,
+                        struct page *page, dma_addr_t mapping, u32 offset,
+                        u32 len)
+{
+       struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
+       struct bnxt_sw_tx_bd *tx_buf;
+       struct tx_bd_ext *txbd1;
+       struct tx_bd *txbd;
+       u32 flags;
+       u16 prod;
+
+       if (bnxt_tx_avail(bp, txr) < 2)
+               return -ENOSPC;
+
+       prod = txr->tx_prod;
+       txbd = &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)];
+
+       tx_buf = &txr->tx_buf_ring[prod];
+       tx_buf->page = page;
+       dma_unmap_addr_set(tx_buf, mapping, mapping);
+       flags = (len << TX_BD_LEN_SHIFT) | TX_BD_TYPE_LONG_TX_BD |
+               (2 << TX_BD_FLAGS_BD_CNT_SHIFT) | TX_BD_FLAGS_PACKET_END |
+               bnxt_lhint_arr[len >> 9];
+       txbd->tx_bd_len_flags_type = cpu_to_le32(flags);
+       txbd->tx_bd_opaque = prod;
+       txbd->tx_bd_haddr = cpu_to_le64(mapping + offset);
+
+       prod = NEXT_TX(prod);
+       txbd1 = (struct tx_bd_ext *)
+               &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)];
+
+       txbd1->tx_bd_hsize_lflags = cpu_to_le32(0);
+       txbd1->tx_bd_mss = cpu_to_le32(0);
+       txbd1->tx_bd_cfa_action = cpu_to_le32(0);
+       txbd1->tx_bd_cfa_meta = cpu_to_le32(0);
+
+       prod = NEXT_TX(prod);
+       txr->tx_prod = prod;
+       return 0;
+}
+
+void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
+{
+       struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
+       struct device *dev = &bp->pdev->dev;
+       u16 cons = txr->tx_cons;
+       int i;
+
+       for (i = 0; i < nr_pkts; i++) {
+               struct bnxt_sw_tx_bd *tx_buf;
+
+               tx_buf = &txr->tx_buf_ring[cons];
+               cons = NEXT_TX(cons);
+               cons = NEXT_TX(cons);
+
+               dma_unmap_page(dev, dma_unmap_addr(tx_buf, mapping), PAGE_SIZE,
+                              bp->rx_dir);
+               __free_page(tx_buf->page);
+               tx_buf->page = NULL;
+       }
+       txr->tx_cons = cons;
+}
+
 /* returns the following:
  * true    - packet consumed by XDP and new buffer is allocated.
  * false   - packet should be passed to the stack.
@@ -43,6 +107,26 @@ bool bnxt_rx_xdp(struct bnxt_rx_ring_info *rxr, u16 cons, 
void *data,
        case XDP_PASS:
                return false;
 
+       case XDP_TX: {
+               struct bnxt_napi *bnapi = rxr->bnapi;
+               struct bnxt *bp = bnapi->bp;
+               int rc;
+
+               rc = bnxt_alloc_rx_data(bp, rxr, rxr->rx_prod, GFP_ATOMIC);
+               if (unlikely(rc)) {
+                       bnxt_reuse_rx_data(rxr, cons, data);
+                       return true;
+               }
+               if (bnxt_xmit_xdp(bp, bnapi, data, dma_addr, NET_IP_ALIGN,
+                                 len)) {
+                       dma_unmap_page(&bp->pdev->dev, dma_addr, PAGE_SIZE,
+                                      bp->rx_dir);
+                       __free_page(data);
+                       return true;
+               }
+               *event |= BNXT_TX_EVENT;
+               return true;
+       }
        default:
                bpf_warn_invalid_xdp_action(act);
                /* Fall thru */
@@ -138,4 +222,10 @@ int bnxt_xdp(struct net_device *dev, struct netdev_xdp 
*xdp)
        }
        return rc;
 }
+
+#else
+
+void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
+{
+}
 #endif
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h 
b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
index 066a411..835eca5 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
@@ -10,6 +10,8 @@
 #ifndef BNXT_XDP_H
 #define BNXT_XDP_H
 
+void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts);
+
 #ifdef CONFIG_BNXT_XDP
 bool bnxt_rx_xdp(struct bnxt_rx_ring_info *rxr, u16 cons, void *data,
                 u8 *data_ptr, unsigned int len, dma_addr_t dma_addr,
-- 
1.8.3.1

Reply via email to