]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
bnx2: Add support for ethtool --show-channels|--set-channels
authorMichael Chan <mchan@broadcom.com>
Sun, 5 Feb 2012 15:24:38 +0000 (15:24 +0000)
committerJoe Jin <joe.jin@oracle.com>
Wed, 16 May 2012 05:56:45 +0000 (13:56 +0800)
Allow the user to override the default number of RSS/TSS rings.

(cherry picked from commit b033281f618fa40ee1b24a60cd8043b4979bfee4)
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Joe Jin <joe.jin@oracle.com>
drivers/net/bnx2.c
drivers/net/bnx2.h

index c026af70d88ab6702cb93c2ca710d400d39fd1c0..e0b22cc3063e3913214148eb5bcf779c79561a90 100644 (file)
@@ -6240,7 +6240,16 @@ static int
 bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
 {
        int cpus = num_online_cpus();
-       int msix_vecs = min(cpus + 1, RX_MAX_RINGS);
+       int msix_vecs;
+
+       if (!bp->num_req_rx_rings)
+               msix_vecs = max(cpus + 1, bp->num_req_tx_rings);
+       else if (!bp->num_req_tx_rings)
+               msix_vecs = max(cpus, bp->num_req_rx_rings);
+       else
+               msix_vecs = max(bp->num_req_rx_rings, bp->num_req_tx_rings);
+
+       msix_vecs = min(msix_vecs, RX_MAX_RINGS);
 
        bp->irq_tbl[0].handler = bnx2_interrupt;
        strcpy(bp->irq_tbl[0].name, bp->dev->name);
@@ -6264,10 +6273,18 @@ bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
                }
        }
 
-       bp->num_tx_rings = rounddown_pow_of_two(bp->irq_nvecs);
+       if (!bp->num_req_tx_rings)
+               bp->num_tx_rings = rounddown_pow_of_two(bp->irq_nvecs);
+       else
+               bp->num_tx_rings = min(bp->irq_nvecs, bp->num_req_tx_rings);
+
+       if (!bp->num_req_rx_rings)
+               bp->num_rx_rings = bp->irq_nvecs;
+       else
+               bp->num_rx_rings = min(bp->irq_nvecs, bp->num_req_rx_rings);
+
        netif_set_real_num_tx_queues(bp->dev, bp->num_tx_rings);
 
-       bp->num_rx_rings = bp->irq_nvecs;
        return netif_set_real_num_rx_queues(bp->dev, bp->num_rx_rings);
 }
 
@@ -7156,7 +7173,7 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
 }
 
 static int
-bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
+bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx, bool reset_irq)
 {
        if (netif_running(bp->dev)) {
                /* Reset will erase chipset stats; save them */
@@ -7164,7 +7181,12 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
 
                bnx2_netif_stop(bp, true);
                bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
-               __bnx2_free_irq(bp);
+               if (reset_irq) {
+                       bnx2_free_irq(bp);
+                       bnx2_del_napi(bp);
+               } else {
+                       __bnx2_free_irq(bp);
+               }
                bnx2_free_skbs(bp);
                bnx2_free_mem(bp);
        }
@@ -7173,9 +7195,16 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
        bp->tx_ring_size = tx;
 
        if (netif_running(bp->dev)) {
-               int rc;
+               int rc = 0;
+
+               if (reset_irq) {
+                       rc = bnx2_setup_int_mode(bp, disable_msi);
+                       bnx2_init_napi(bp);
+               }
+
+               if (!rc)
+                       rc = bnx2_alloc_mem(bp);
 
-               rc = bnx2_alloc_mem(bp);
                if (!rc)
                        rc = bnx2_request_irq(bp);
 
@@ -7211,7 +7240,8 @@ bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
 
                return -EINVAL;
        }
-       rc = bnx2_change_ring_size(bp, ering->rx_pending, ering->tx_pending);
+       rc = bnx2_change_ring_size(bp, ering->rx_pending, ering->tx_pending,
+                                  false);
        return rc;
 }
 
@@ -7599,6 +7629,54 @@ bnx2_set_features(struct net_device *dev, u32 features)
        return 0;
 }
 
+static void bnx2_get_channels(struct net_device *dev,
+                             struct ethtool_channels *channels)
+{
+       struct bnx2 *bp = netdev_priv(dev);
+       u32 max_rx_rings = 1;
+       u32 max_tx_rings = 1;
+
+       if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !disable_msi) {
+               max_rx_rings = RX_MAX_RINGS;
+               max_tx_rings = TX_MAX_RINGS;
+       }
+
+       channels->max_rx = max_rx_rings;
+       channels->max_tx = max_tx_rings;
+       channels->max_other = 0;
+       channels->max_combined = 0;
+       channels->rx_count = bp->num_rx_rings;
+       channels->tx_count = bp->num_tx_rings;
+       channels->other_count = 0;
+       channels->combined_count = 0;
+}
+
+static int bnx2_set_channels(struct net_device *dev,
+                             struct ethtool_channels *channels)
+{
+       struct bnx2 *bp = netdev_priv(dev);
+       u32 max_rx_rings = 1;
+       u32 max_tx_rings = 1;
+       int rc = 0;
+
+       if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !disable_msi) {
+               max_rx_rings = RX_MAX_RINGS;
+               max_tx_rings = TX_MAX_RINGS;
+       }
+       if (channels->rx_count > max_rx_rings ||
+           channels->tx_count > max_tx_rings)
+               return -EINVAL;
+
+       bp->num_req_rx_rings = channels->rx_count;
+       bp->num_req_tx_rings = channels->tx_count;
+
+       if (netif_running(dev))
+               rc = bnx2_change_ring_size(bp, bp->rx_ring_size,
+                                          bp->tx_ring_size, true);
+
+       return rc;
+}
+
 static const struct ethtool_ops bnx2_ethtool_ops = {
        .get_settings           = bnx2_get_settings,
        .set_settings           = bnx2_set_settings,
@@ -7623,6 +7701,8 @@ static const struct ethtool_ops bnx2_ethtool_ops = {
        .set_phys_id            = bnx2_set_phys_id,
        .get_ethtool_stats      = bnx2_get_ethtool_stats,
        .get_sset_count         = bnx2_get_sset_count,
+       .get_channels           = bnx2_get_channels,
+       .set_channels           = bnx2_set_channels,
 };
 
 /* Called with rtnl_lock */
@@ -7704,7 +7784,8 @@ bnx2_change_mtu(struct net_device *dev, int new_mtu)
                return -EINVAL;
 
        dev->mtu = new_mtu;
-       return bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size);
+       return bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size,
+                                    false);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
index fc50d4267df878d7f50165ca7b85a0da2553bc6a..8589acdbe4c2b98a5eea7953def1a158c119d8ee 100644 (file)
@@ -6920,6 +6920,9 @@ struct bnx2 {
        u8                      num_tx_rings;
        u8                      num_rx_rings;
 
+       int                     num_req_tx_rings;
+       int                     num_req_rx_rings;
+
        u32                     leds_save;
        u32                     idle_chk_status_idx;