aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/broadcom
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2012-02-05 10:24:38 -0500
committerDavid S. Miller <davem@davemloft.net>2012-02-05 22:42:00 -0500
commitb033281f618fa40ee1b24a60cd8043b4979bfee4 (patch)
tree78458117b284cd7989b14c6e821645282a56f6bc /drivers/net/ethernet/broadcom
parentb9d6d2dbf45b038a94c63295203525101a9fbbb7 (diff)
bnx2: Add support for ethtool --show-channels|--set-channels
Allow the user to override the default number of RSS/TSS rings. Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/broadcom')
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.c99
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.h3
2 files changed, 93 insertions, 9 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 0a4c5405dcf4..2ab31daef80f 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -6246,7 +6246,16 @@ static int
6246bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi) 6246bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
6247{ 6247{
6248 int cpus = num_online_cpus(); 6248 int cpus = num_online_cpus();
6249 int msix_vecs = min(cpus + 1, RX_MAX_RINGS); 6249 int msix_vecs;
6250
6251 if (!bp->num_req_rx_rings)
6252 msix_vecs = max(cpus + 1, bp->num_req_tx_rings);
6253 else if (!bp->num_req_tx_rings)
6254 msix_vecs = max(cpus, bp->num_req_rx_rings);
6255 else
6256 msix_vecs = max(bp->num_req_rx_rings, bp->num_req_tx_rings);
6257
6258 msix_vecs = min(msix_vecs, RX_MAX_RINGS);
6250 6259
6251 bp->irq_tbl[0].handler = bnx2_interrupt; 6260 bp->irq_tbl[0].handler = bnx2_interrupt;
6252 strcpy(bp->irq_tbl[0].name, bp->dev->name); 6261 strcpy(bp->irq_tbl[0].name, bp->dev->name);
@@ -6270,10 +6279,18 @@ bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
6270 } 6279 }
6271 } 6280 }
6272 6281
6273 bp->num_tx_rings = rounddown_pow_of_two(bp->irq_nvecs); 6282 if (!bp->num_req_tx_rings)
6283 bp->num_tx_rings = rounddown_pow_of_two(bp->irq_nvecs);
6284 else
6285 bp->num_tx_rings = min(bp->irq_nvecs, bp->num_req_tx_rings);
6286
6287 if (!bp->num_req_rx_rings)
6288 bp->num_rx_rings = bp->irq_nvecs;
6289 else
6290 bp->num_rx_rings = min(bp->irq_nvecs, bp->num_req_rx_rings);
6291
6274 netif_set_real_num_tx_queues(bp->dev, bp->num_tx_rings); 6292 netif_set_real_num_tx_queues(bp->dev, bp->num_tx_rings);
6275 6293
6276 bp->num_rx_rings = bp->irq_nvecs;
6277 return netif_set_real_num_rx_queues(bp->dev, bp->num_rx_rings); 6294 return netif_set_real_num_rx_queues(bp->dev, bp->num_rx_rings);
6278} 6295}
6279 6296
@@ -7162,7 +7179,7 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
7162} 7179}
7163 7180
7164static int 7181static int
7165bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) 7182bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx, bool reset_irq)
7166{ 7183{
7167 if (netif_running(bp->dev)) { 7184 if (netif_running(bp->dev)) {
7168 /* Reset will erase chipset stats; save them */ 7185 /* Reset will erase chipset stats; save them */
@@ -7170,7 +7187,12 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
7170 7187
7171 bnx2_netif_stop(bp, true); 7188 bnx2_netif_stop(bp, true);
7172 bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); 7189 bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
7173 __bnx2_free_irq(bp); 7190 if (reset_irq) {
7191 bnx2_free_irq(bp);
7192 bnx2_del_napi(bp);
7193 } else {
7194 __bnx2_free_irq(bp);
7195 }
7174 bnx2_free_skbs(bp); 7196 bnx2_free_skbs(bp);
7175 bnx2_free_mem(bp); 7197 bnx2_free_mem(bp);
7176 } 7198 }
@@ -7179,9 +7201,16 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
7179 bp->tx_ring_size = tx; 7201 bp->tx_ring_size = tx;
7180 7202
7181 if (netif_running(bp->dev)) { 7203 if (netif_running(bp->dev)) {
7182 int rc; 7204 int rc = 0;
7205
7206 if (reset_irq) {
7207 rc = bnx2_setup_int_mode(bp, disable_msi);
7208 bnx2_init_napi(bp);
7209 }
7210
7211 if (!rc)
7212 rc = bnx2_alloc_mem(bp);
7183 7213
7184 rc = bnx2_alloc_mem(bp);
7185 if (!rc) 7214 if (!rc)
7186 rc = bnx2_request_irq(bp); 7215 rc = bnx2_request_irq(bp);
7187 7216
@@ -7217,7 +7246,8 @@ bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
7217 7246
7218 return -EINVAL; 7247 return -EINVAL;
7219 } 7248 }
7220 rc = bnx2_change_ring_size(bp, ering->rx_pending, ering->tx_pending); 7249 rc = bnx2_change_ring_size(bp, ering->rx_pending, ering->tx_pending,
7250 false);
7221 return rc; 7251 return rc;
7222} 7252}
7223 7253
@@ -7605,6 +7635,54 @@ bnx2_set_features(struct net_device *dev, netdev_features_t features)
7605 return 0; 7635 return 0;
7606} 7636}
7607 7637
7638static void bnx2_get_channels(struct net_device *dev,
7639 struct ethtool_channels *channels)
7640{
7641 struct bnx2 *bp = netdev_priv(dev);
7642 u32 max_rx_rings = 1;
7643 u32 max_tx_rings = 1;
7644
7645 if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !disable_msi) {
7646 max_rx_rings = RX_MAX_RINGS;
7647 max_tx_rings = TX_MAX_RINGS;
7648 }
7649
7650 channels->max_rx = max_rx_rings;
7651 channels->max_tx = max_tx_rings;
7652 channels->max_other = 0;
7653 channels->max_combined = 0;
7654 channels->rx_count = bp->num_rx_rings;
7655 channels->tx_count = bp->num_tx_rings;
7656 channels->other_count = 0;
7657 channels->combined_count = 0;
7658}
7659
7660static int bnx2_set_channels(struct net_device *dev,
7661 struct ethtool_channels *channels)
7662{
7663 struct bnx2 *bp = netdev_priv(dev);
7664 u32 max_rx_rings = 1;
7665 u32 max_tx_rings = 1;
7666 int rc = 0;
7667
7668 if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !disable_msi) {
7669 max_rx_rings = RX_MAX_RINGS;
7670 max_tx_rings = TX_MAX_RINGS;
7671 }
7672 if (channels->rx_count > max_rx_rings ||
7673 channels->tx_count > max_tx_rings)
7674 return -EINVAL;
7675
7676 bp->num_req_rx_rings = channels->rx_count;
7677 bp->num_req_tx_rings = channels->tx_count;
7678
7679 if (netif_running(dev))
7680 rc = bnx2_change_ring_size(bp, bp->rx_ring_size,
7681 bp->tx_ring_size, true);
7682
7683 return rc;
7684}
7685
7608static const struct ethtool_ops bnx2_ethtool_ops = { 7686static const struct ethtool_ops bnx2_ethtool_ops = {
7609 .get_settings = bnx2_get_settings, 7687 .get_settings = bnx2_get_settings,
7610 .set_settings = bnx2_set_settings, 7688 .set_settings = bnx2_set_settings,
@@ -7629,6 +7707,8 @@ static const struct ethtool_ops bnx2_ethtool_ops = {
7629 .set_phys_id = bnx2_set_phys_id, 7707 .set_phys_id = bnx2_set_phys_id,
7630 .get_ethtool_stats = bnx2_get_ethtool_stats, 7708 .get_ethtool_stats = bnx2_get_ethtool_stats,
7631 .get_sset_count = bnx2_get_sset_count, 7709 .get_sset_count = bnx2_get_sset_count,
7710 .get_channels = bnx2_get_channels,
7711 .set_channels = bnx2_set_channels,
7632}; 7712};
7633 7713
7634/* Called with rtnl_lock */ 7714/* Called with rtnl_lock */
@@ -7710,7 +7790,8 @@ bnx2_change_mtu(struct net_device *dev, int new_mtu)
7710 return -EINVAL; 7790 return -EINVAL;
7711 7791
7712 dev->mtu = new_mtu; 7792 dev->mtu = new_mtu;
7713 return bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size); 7793 return bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size,
7794 false);
7714} 7795}
7715 7796
7716#ifdef CONFIG_NET_POLL_CONTROLLER 7797#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/broadcom/bnx2.h b/drivers/net/ethernet/broadcom/bnx2.h
index 1db2d51ba3f1..dc06bda73be7 100644
--- a/drivers/net/ethernet/broadcom/bnx2.h
+++ b/drivers/net/ethernet/broadcom/bnx2.h
@@ -6933,6 +6933,9 @@ struct bnx2 {
6933 u8 num_tx_rings; 6933 u8 num_tx_rings;
6934 u8 num_rx_rings; 6934 u8 num_rx_rings;
6935 6935
6936 int num_req_tx_rings;
6937 int num_req_rx_rings;
6938
6936 u32 leds_save; 6939 u32 leds_save;
6937 u32 idle_chk_status_idx; 6940 u32 idle_chk_status_idx;
6938 6941