diff options
Diffstat (limited to 'drivers/net/ethernet/broadcom/bnx2.c')
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2.c | 106 |
1 files changed, 94 insertions, 12 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index 021fb818007a..7105989ba658 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c | |||
@@ -2625,10 +2625,8 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp) | |||
2625 | u32 val; | 2625 | u32 val; |
2626 | 2626 | ||
2627 | good_mbuf = kmalloc(512 * sizeof(u16), GFP_KERNEL); | 2627 | good_mbuf = kmalloc(512 * sizeof(u16), GFP_KERNEL); |
2628 | if (good_mbuf == NULL) { | 2628 | if (good_mbuf == NULL) |
2629 | pr_err("Failed to allocate memory in %s\n", __func__); | ||
2630 | return -ENOMEM; | 2629 | return -ENOMEM; |
2631 | } | ||
2632 | 2630 | ||
2633 | REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, | 2631 | REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, |
2634 | BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE); | 2632 | BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE); |
@@ -6248,7 +6246,16 @@ static int | |||
6248 | bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi) | 6246 | bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi) |
6249 | { | 6247 | { |
6250 | int cpus = num_online_cpus(); | 6248 | int cpus = num_online_cpus(); |
6251 | 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); | ||
6252 | 6259 | ||
6253 | bp->irq_tbl[0].handler = bnx2_interrupt; | 6260 | bp->irq_tbl[0].handler = bnx2_interrupt; |
6254 | strcpy(bp->irq_tbl[0].name, bp->dev->name); | 6261 | strcpy(bp->irq_tbl[0].name, bp->dev->name); |
@@ -6272,10 +6279,18 @@ bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi) | |||
6272 | } | 6279 | } |
6273 | } | 6280 | } |
6274 | 6281 | ||
6275 | 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 | |||
6276 | 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); |
6277 | 6293 | ||
6278 | bp->num_rx_rings = bp->irq_nvecs; | ||
6279 | 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); |
6280 | } | 6295 | } |
6281 | 6296 | ||
@@ -6550,6 +6565,9 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
6550 | } | 6565 | } |
6551 | txbd->tx_bd_vlan_tag_flags |= TX_BD_FLAGS_END; | 6566 | txbd->tx_bd_vlan_tag_flags |= TX_BD_FLAGS_END; |
6552 | 6567 | ||
6568 | /* Sync BD data before updating TX mailbox */ | ||
6569 | wmb(); | ||
6570 | |||
6553 | netdev_tx_sent_queue(txq, skb->len); | 6571 | netdev_tx_sent_queue(txq, skb->len); |
6554 | 6572 | ||
6555 | prod = NEXT_TX_BD(prod); | 6573 | prod = NEXT_TX_BD(prod); |
@@ -7164,7 +7182,7 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) | |||
7164 | } | 7182 | } |
7165 | 7183 | ||
7166 | static int | 7184 | static int |
7167 | bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) | 7185 | bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx, bool reset_irq) |
7168 | { | 7186 | { |
7169 | if (netif_running(bp->dev)) { | 7187 | if (netif_running(bp->dev)) { |
7170 | /* Reset will erase chipset stats; save them */ | 7188 | /* Reset will erase chipset stats; save them */ |
@@ -7172,7 +7190,12 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) | |||
7172 | 7190 | ||
7173 | bnx2_netif_stop(bp, true); | 7191 | bnx2_netif_stop(bp, true); |
7174 | bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); | 7192 | bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); |
7175 | __bnx2_free_irq(bp); | 7193 | if (reset_irq) { |
7194 | bnx2_free_irq(bp); | ||
7195 | bnx2_del_napi(bp); | ||
7196 | } else { | ||
7197 | __bnx2_free_irq(bp); | ||
7198 | } | ||
7176 | bnx2_free_skbs(bp); | 7199 | bnx2_free_skbs(bp); |
7177 | bnx2_free_mem(bp); | 7200 | bnx2_free_mem(bp); |
7178 | } | 7201 | } |
@@ -7181,9 +7204,16 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) | |||
7181 | bp->tx_ring_size = tx; | 7204 | bp->tx_ring_size = tx; |
7182 | 7205 | ||
7183 | if (netif_running(bp->dev)) { | 7206 | if (netif_running(bp->dev)) { |
7184 | int rc; | 7207 | int rc = 0; |
7208 | |||
7209 | if (reset_irq) { | ||
7210 | rc = bnx2_setup_int_mode(bp, disable_msi); | ||
7211 | bnx2_init_napi(bp); | ||
7212 | } | ||
7213 | |||
7214 | if (!rc) | ||
7215 | rc = bnx2_alloc_mem(bp); | ||
7185 | 7216 | ||
7186 | rc = bnx2_alloc_mem(bp); | ||
7187 | if (!rc) | 7217 | if (!rc) |
7188 | rc = bnx2_request_irq(bp); | 7218 | rc = bnx2_request_irq(bp); |
7189 | 7219 | ||
@@ -7219,7 +7249,8 @@ bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) | |||
7219 | 7249 | ||
7220 | return -EINVAL; | 7250 | return -EINVAL; |
7221 | } | 7251 | } |
7222 | rc = bnx2_change_ring_size(bp, ering->rx_pending, ering->tx_pending); | 7252 | rc = bnx2_change_ring_size(bp, ering->rx_pending, ering->tx_pending, |
7253 | false); | ||
7223 | return rc; | 7254 | return rc; |
7224 | } | 7255 | } |
7225 | 7256 | ||
@@ -7607,6 +7638,54 @@ bnx2_set_features(struct net_device *dev, netdev_features_t features) | |||
7607 | return 0; | 7638 | return 0; |
7608 | } | 7639 | } |
7609 | 7640 | ||
7641 | static void bnx2_get_channels(struct net_device *dev, | ||
7642 | struct ethtool_channels *channels) | ||
7643 | { | ||
7644 | struct bnx2 *bp = netdev_priv(dev); | ||
7645 | u32 max_rx_rings = 1; | ||
7646 | u32 max_tx_rings = 1; | ||
7647 | |||
7648 | if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !disable_msi) { | ||
7649 | max_rx_rings = RX_MAX_RINGS; | ||
7650 | max_tx_rings = TX_MAX_RINGS; | ||
7651 | } | ||
7652 | |||
7653 | channels->max_rx = max_rx_rings; | ||
7654 | channels->max_tx = max_tx_rings; | ||
7655 | channels->max_other = 0; | ||
7656 | channels->max_combined = 0; | ||
7657 | channels->rx_count = bp->num_rx_rings; | ||
7658 | channels->tx_count = bp->num_tx_rings; | ||
7659 | channels->other_count = 0; | ||
7660 | channels->combined_count = 0; | ||
7661 | } | ||
7662 | |||
7663 | static int bnx2_set_channels(struct net_device *dev, | ||
7664 | struct ethtool_channels *channels) | ||
7665 | { | ||
7666 | struct bnx2 *bp = netdev_priv(dev); | ||
7667 | u32 max_rx_rings = 1; | ||
7668 | u32 max_tx_rings = 1; | ||
7669 | int rc = 0; | ||
7670 | |||
7671 | if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !disable_msi) { | ||
7672 | max_rx_rings = RX_MAX_RINGS; | ||
7673 | max_tx_rings = TX_MAX_RINGS; | ||
7674 | } | ||
7675 | if (channels->rx_count > max_rx_rings || | ||
7676 | channels->tx_count > max_tx_rings) | ||
7677 | return -EINVAL; | ||
7678 | |||
7679 | bp->num_req_rx_rings = channels->rx_count; | ||
7680 | bp->num_req_tx_rings = channels->tx_count; | ||
7681 | |||
7682 | if (netif_running(dev)) | ||
7683 | rc = bnx2_change_ring_size(bp, bp->rx_ring_size, | ||
7684 | bp->tx_ring_size, true); | ||
7685 | |||
7686 | return rc; | ||
7687 | } | ||
7688 | |||
7610 | static const struct ethtool_ops bnx2_ethtool_ops = { | 7689 | static const struct ethtool_ops bnx2_ethtool_ops = { |
7611 | .get_settings = bnx2_get_settings, | 7690 | .get_settings = bnx2_get_settings, |
7612 | .set_settings = bnx2_set_settings, | 7691 | .set_settings = bnx2_set_settings, |
@@ -7631,6 +7710,8 @@ static const struct ethtool_ops bnx2_ethtool_ops = { | |||
7631 | .set_phys_id = bnx2_set_phys_id, | 7710 | .set_phys_id = bnx2_set_phys_id, |
7632 | .get_ethtool_stats = bnx2_get_ethtool_stats, | 7711 | .get_ethtool_stats = bnx2_get_ethtool_stats, |
7633 | .get_sset_count = bnx2_get_sset_count, | 7712 | .get_sset_count = bnx2_get_sset_count, |
7713 | .get_channels = bnx2_get_channels, | ||
7714 | .set_channels = bnx2_set_channels, | ||
7634 | }; | 7715 | }; |
7635 | 7716 | ||
7636 | /* Called with rtnl_lock */ | 7717 | /* Called with rtnl_lock */ |
@@ -7712,7 +7793,8 @@ bnx2_change_mtu(struct net_device *dev, int new_mtu) | |||
7712 | return -EINVAL; | 7793 | return -EINVAL; |
7713 | 7794 | ||
7714 | dev->mtu = new_mtu; | 7795 | dev->mtu = new_mtu; |
7715 | return bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size); | 7796 | return bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size, |
7797 | false); | ||
7716 | } | 7798 | } |
7717 | 7799 | ||
7718 | #ifdef CONFIG_NET_POLL_CONTROLLER | 7800 | #ifdef CONFIG_NET_POLL_CONTROLLER |