bnxt_en: Add a set of TX rings to support XDP.
authorMichael Chan <michael.chan@broadcom.com>
Mon, 6 Feb 2017 21:55:40 +0000 (16:55 -0500)
committerDavid S. Miller <davem@davemloft.net>
Tue, 7 Feb 2017 18:30:59 +0000 (13:30 -0500)
Add logic for an extra set of TX rings for XDP.  If enabled, this
set of TX rings equals the number of RX rings and shares the same
IRQ as the RX ring set.  A new field bp->tx_nr_rings_xdp is added
to keep track of these TX XDP rings.  Adjust all other relevant functions
to handle bp->tx_nr_rings_xdp.

Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c

index 811bc825bf90a86d32d6b2cfd7f9ff7650db095e..412a8de8c2c83b605df1b3e1d5238001e16da6fc 100644 (file)
@@ -2218,6 +2218,8 @@ static int bnxt_alloc_tx_rings(struct bnxt *bp)
                        memset(txr->tx_push, 0, sizeof(struct tx_push_bd));
                }
                ring->queue_id = bp->q_info[j].queue_id;
+               if (i < bp->tx_nr_rings_xdp)
+                       continue;
                if (i % bp->tx_nr_rings_per_tc == (bp->tx_nr_rings_per_tc - 1))
                        j++;
        }
@@ -3042,8 +3044,10 @@ static int bnxt_alloc_mem(struct bnxt *bp, bool irq_re_init)
                for (i = 0; i < bp->tx_nr_rings; i++, j++) {
                        bp->tx_ring[i].bnapi = bp->bnapi[j];
                        bp->bnapi[j]->tx_ring = &bp->tx_ring[i];
-                       bp->tx_ring_map[i] = i;
-                       bp->tx_ring[i].txq_index = i;
+                       bp->tx_ring_map[i] = bp->tx_nr_rings_xdp + i;
+                       if (i >= bp->tx_nr_rings_xdp)
+                               bp->tx_ring[i].txq_index = i -
+                                       bp->tx_nr_rings_xdp;
                }
 
                rc = bnxt_alloc_stats(bp);
@@ -4966,7 +4970,8 @@ static int bnxt_set_real_num_queues(struct bnxt *bp)
        int rc;
        struct net_device *dev = bp->dev;
 
-       rc = netif_set_real_num_tx_queues(dev, bp->tx_nr_rings);
+       rc = netif_set_real_num_tx_queues(dev, bp->tx_nr_rings -
+                                         bp->tx_nr_rings_xdp);
        if (rc)
                return rc;
 
@@ -6582,7 +6587,7 @@ static void bnxt_sp_task(struct work_struct *work)
 }
 
 /* Under rtnl_lock */
-int bnxt_reserve_rings(struct bnxt *bp, int tx, int rx, int tcs)
+int bnxt_reserve_rings(struct bnxt *bp, int tx, int rx, int tcs, int tx_xdp)
 {
        int max_rx, max_tx, tx_sets = 1;
        int tx_rings_needed;
@@ -6602,12 +6607,12 @@ int bnxt_reserve_rings(struct bnxt *bp, int tx, int rx, int tcs)
        if (max_rx < rx)
                return -ENOMEM;
 
-       tx_rings_needed = tx * tx_sets;
+       tx_rings_needed = tx * tx_sets + tx_xdp;
        if (max_tx < tx_rings_needed)
                return -ENOMEM;
 
        if (bnxt_hwrm_reserve_tx_rings(bp, &tx_rings_needed) ||
-           tx_rings_needed < (tx * tx_sets))
+           tx_rings_needed < (tx * tx_sets + tx_xdp))
                return -ENOMEM;
        return 0;
 }
@@ -6788,8 +6793,8 @@ int bnxt_setup_mq_tc(struct net_device *dev, u8 tc)
        if (bp->flags & BNXT_FLAG_SHARED_RINGS)
                sh = true;
 
-       rc = bnxt_reserve_rings(bp, bp->tx_nr_rings_per_tc,
-                               bp->rx_nr_rings, tc);
+       rc = bnxt_reserve_rings(bp, bp->tx_nr_rings_per_tc, bp->rx_nr_rings,
+                               tc, bp->tx_nr_rings_xdp);
        if (rc)
                return rc;
 
index 97ccce184694fc3191fc591e0d6e0efcf62d11c1..4c3289a7fea8a6a549c87aa59ec9e1a2c5e0ad7e 100644 (file)
@@ -1026,6 +1026,7 @@ struct bnxt {
        int                     tx_nr_pages;
        int                     tx_nr_rings;
        int                     tx_nr_rings_per_tc;
+       int                     tx_nr_rings_xdp;
 
        int                     tx_wake_thresh;
        int                     tx_push_thresh;
@@ -1203,7 +1204,7 @@ int bnxt_hwrm_set_link_setting(struct bnxt *, bool, bool);
 int bnxt_hwrm_fw_set_time(struct bnxt *);
 int bnxt_open_nic(struct bnxt *, bool, bool);
 int bnxt_close_nic(struct bnxt *, bool, bool);
-int bnxt_reserve_rings(struct bnxt *bp, int tx, int rx, int tcs);
+int bnxt_reserve_rings(struct bnxt *bp, int tx, int rx, int tcs, int tx_xdp);
 int bnxt_setup_mq_tc(struct net_device *dev, u8 tc);
 int bnxt_get_max_rings(struct bnxt *, int *, int *, bool);
 void bnxt_restore_pf_fw_resources(struct bnxt *bp);
index 6f2568d2354e78af5500e19c7274b52738f4f8c7..7aa248db10c60408ed9aa9102d06f234835442f3 100644 (file)
@@ -389,6 +389,7 @@ static int bnxt_set_channels(struct net_device *dev,
        struct bnxt *bp = netdev_priv(dev);
        int req_tx_rings, req_rx_rings, tcs;
        bool sh = false;
+       int tx_xdp = 0;
        int rc = 0;
 
        if (channel->other_count)
@@ -413,7 +414,14 @@ static int bnxt_set_channels(struct net_device *dev,
 
        req_tx_rings = sh ? channel->combined_count : channel->tx_count;
        req_rx_rings = sh ? channel->combined_count : channel->rx_count;
-       rc = bnxt_reserve_rings(bp, req_tx_rings, req_rx_rings, tcs);
+       if (bp->tx_nr_rings_xdp) {
+               if (!sh) {
+                       netdev_err(dev, "Only combined mode supported when XDP is enabled.\n");
+                       return -EINVAL;
+               }
+               tx_xdp = req_rx_rings;
+       }
+       rc = bnxt_reserve_rings(bp, req_tx_rings, req_rx_rings, tcs, tx_xdp);
        if (rc) {
                netdev_warn(dev, "Unable to allocate the requested rings\n");
                return rc;
@@ -442,10 +450,10 @@ static int bnxt_set_channels(struct net_device *dev,
                bp->rx_nr_rings = channel->rx_count;
                bp->tx_nr_rings_per_tc = channel->tx_count;
        }
-
-       bp->tx_nr_rings = bp->tx_nr_rings_per_tc;
+       bp->tx_nr_rings_xdp = tx_xdp;
+       bp->tx_nr_rings = bp->tx_nr_rings_per_tc + tx_xdp;
        if (tcs > 1)
-               bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs;
+               bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs + tx_xdp;
 
        bp->cp_nr_rings = sh ? max_t(int, bp->tx_nr_rings, bp->rx_nr_rings) :
                               bp->tx_nr_rings + bp->rx_nr_rings;