Commit b033281f authored by Michael Chan's avatar Michael Chan Committed by David S. Miller

bnx2: Add support for ethtool --show-channels|--set-channels

Allow the user to override the default number of RSS/TSS rings.
Signed-off-by: default avatarMichael Chan <mchan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b9d6d2db
...@@ -6246,7 +6246,16 @@ static int ...@@ -6246,7 +6246,16 @@ static int
bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi) bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
{ {
int cpus = num_online_cpus(); 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; bp->irq_tbl[0].handler = bnx2_interrupt;
strcpy(bp->irq_tbl[0].name, bp->dev->name); strcpy(bp->irq_tbl[0].name, bp->dev->name);
...@@ -6270,10 +6279,18 @@ bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi) ...@@ -6270,10 +6279,18 @@ bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
} }
} }
if (!bp->num_req_tx_rings)
bp->num_tx_rings = rounddown_pow_of_two(bp->irq_nvecs); bp->num_tx_rings = rounddown_pow_of_two(bp->irq_nvecs);
netif_set_real_num_tx_queues(bp->dev, bp->num_tx_rings); 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; 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);
return netif_set_real_num_rx_queues(bp->dev, bp->num_rx_rings); return netif_set_real_num_rx_queues(bp->dev, bp->num_rx_rings);
} }
...@@ -7162,7 +7179,7 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) ...@@ -7162,7 +7179,7 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
} }
static int 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)) { if (netif_running(bp->dev)) {
/* Reset will erase chipset stats; save them */ /* Reset will erase chipset stats; save them */
...@@ -7170,7 +7187,12 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) ...@@ -7170,7 +7187,12 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
bnx2_netif_stop(bp, true); bnx2_netif_stop(bp, true);
bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
if (reset_irq) {
bnx2_free_irq(bp);
bnx2_del_napi(bp);
} else {
__bnx2_free_irq(bp); __bnx2_free_irq(bp);
}
bnx2_free_skbs(bp); bnx2_free_skbs(bp);
bnx2_free_mem(bp); bnx2_free_mem(bp);
} }
...@@ -7179,9 +7201,16 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) ...@@ -7179,9 +7201,16 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
bp->tx_ring_size = tx; bp->tx_ring_size = tx;
if (netif_running(bp->dev)) { 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) if (!rc)
rc = bnx2_request_irq(bp); rc = bnx2_request_irq(bp);
...@@ -7217,7 +7246,8 @@ bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) ...@@ -7217,7 +7246,8 @@ bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
return -EINVAL; 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; return rc;
} }
...@@ -7605,6 +7635,54 @@ bnx2_set_features(struct net_device *dev, netdev_features_t features) ...@@ -7605,6 +7635,54 @@ bnx2_set_features(struct net_device *dev, netdev_features_t features)
return 0; 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 = { static const struct ethtool_ops bnx2_ethtool_ops = {
.get_settings = bnx2_get_settings, .get_settings = bnx2_get_settings,
.set_settings = bnx2_set_settings, .set_settings = bnx2_set_settings,
...@@ -7629,6 +7707,8 @@ static const struct ethtool_ops bnx2_ethtool_ops = { ...@@ -7629,6 +7707,8 @@ static const struct ethtool_ops bnx2_ethtool_ops = {
.set_phys_id = bnx2_set_phys_id, .set_phys_id = bnx2_set_phys_id,
.get_ethtool_stats = bnx2_get_ethtool_stats, .get_ethtool_stats = bnx2_get_ethtool_stats,
.get_sset_count = bnx2_get_sset_count, .get_sset_count = bnx2_get_sset_count,
.get_channels = bnx2_get_channels,
.set_channels = bnx2_set_channels,
}; };
/* Called with rtnl_lock */ /* Called with rtnl_lock */
...@@ -7710,7 +7790,8 @@ bnx2_change_mtu(struct net_device *dev, int new_mtu) ...@@ -7710,7 +7790,8 @@ bnx2_change_mtu(struct net_device *dev, int new_mtu)
return -EINVAL; return -EINVAL;
dev->mtu = new_mtu; 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 #ifdef CONFIG_NET_POLL_CONTROLLER
......
...@@ -6933,6 +6933,9 @@ struct bnx2 { ...@@ -6933,6 +6933,9 @@ struct bnx2 {
u8 num_tx_rings; u8 num_tx_rings;
u8 num_rx_rings; u8 num_rx_rings;
int num_req_tx_rings;
int num_req_rx_rings;
u32 leds_save; u32 leds_save;
u32 idle_chk_status_idx; u32 idle_chk_status_idx;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment