Commit 7facc5fb authored by David S. Miller's avatar David S. Miller

Merge branch 'bnxt_en-fixes'

Michael Chan says:

====================
bnxt_en: Bug fixes.

Fixed autoneg logic and some related cleanups, fixed tx push operation,
and reduced default ring sizes.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 56bb7fd9 51dd55b5
...@@ -69,7 +69,7 @@ MODULE_VERSION(DRV_MODULE_VERSION); ...@@ -69,7 +69,7 @@ MODULE_VERSION(DRV_MODULE_VERSION);
#define BNXT_RX_DMA_OFFSET NET_SKB_PAD #define BNXT_RX_DMA_OFFSET NET_SKB_PAD
#define BNXT_RX_COPY_THRESH 256 #define BNXT_RX_COPY_THRESH 256
#define BNXT_TX_PUSH_THRESH 92 #define BNXT_TX_PUSH_THRESH 164
enum board_idx { enum board_idx {
BCM57301, BCM57301,
...@@ -223,11 +223,12 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -223,11 +223,12 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
} }
if (free_size == bp->tx_ring_size && length <= bp->tx_push_thresh) { if (free_size == bp->tx_ring_size && length <= bp->tx_push_thresh) {
struct tx_push_bd *push = txr->tx_push; struct tx_push_buffer *tx_push_buf = txr->tx_push;
struct tx_bd *tx_push = &push->txbd1; struct tx_push_bd *tx_push = &tx_push_buf->push_bd;
struct tx_bd_ext *tx_push1 = &push->txbd2; struct tx_bd_ext *tx_push1 = &tx_push->txbd2;
void *pdata = tx_push1 + 1; void *pdata = tx_push_buf->data;
int j; u64 *end;
int j, push_len;
/* Set COAL_NOW to be ready quickly for the next push */ /* Set COAL_NOW to be ready quickly for the next push */
tx_push->tx_bd_len_flags_type = tx_push->tx_bd_len_flags_type =
...@@ -247,6 +248,9 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -247,6 +248,9 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
tx_push1->tx_bd_cfa_meta = cpu_to_le32(vlan_tag_flags); tx_push1->tx_bd_cfa_meta = cpu_to_le32(vlan_tag_flags);
tx_push1->tx_bd_cfa_action = cpu_to_le32(cfa_action); tx_push1->tx_bd_cfa_action = cpu_to_le32(cfa_action);
end = PTR_ALIGN(pdata + length + 1, 8) - 1;
*end = 0;
skb_copy_from_linear_data(skb, pdata, len); skb_copy_from_linear_data(skb, pdata, len);
pdata += len; pdata += len;
for (j = 0; j < last_frag; j++) { for (j = 0; j < last_frag; j++) {
...@@ -261,22 +265,29 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -261,22 +265,29 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
pdata += skb_frag_size(frag); pdata += skb_frag_size(frag);
} }
memcpy(txbd, tx_push, sizeof(*txbd)); txbd->tx_bd_len_flags_type = tx_push->tx_bd_len_flags_type;
txbd->tx_bd_haddr = txr->data_mapping;
prod = NEXT_TX(prod); prod = NEXT_TX(prod);
txbd = &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)]; txbd = &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)];
memcpy(txbd, tx_push1, sizeof(*txbd)); memcpy(txbd, tx_push1, sizeof(*txbd));
prod = NEXT_TX(prod); prod = NEXT_TX(prod);
push->doorbell = tx_push->doorbell =
cpu_to_le32(DB_KEY_TX_PUSH | DB_LONG_TX_PUSH | prod); cpu_to_le32(DB_KEY_TX_PUSH | DB_LONG_TX_PUSH | prod);
txr->tx_prod = prod; txr->tx_prod = prod;
netdev_tx_sent_queue(txq, skb->len); netdev_tx_sent_queue(txq, skb->len);
__iowrite64_copy(txr->tx_doorbell, push, push_len = (length + sizeof(*tx_push) + 7) / 8;
(length + sizeof(*push) + 8) / 8); if (push_len > 16) {
__iowrite64_copy(txr->tx_doorbell, tx_push_buf, 16);
__iowrite64_copy(txr->tx_doorbell + 4, tx_push_buf + 1,
push_len - 16);
} else {
__iowrite64_copy(txr->tx_doorbell, tx_push_buf,
push_len);
}
tx_buf->is_push = 1; tx_buf->is_push = 1;
goto tx_done; goto tx_done;
} }
...@@ -1753,7 +1764,7 @@ static int bnxt_alloc_tx_rings(struct bnxt *bp) ...@@ -1753,7 +1764,7 @@ static int bnxt_alloc_tx_rings(struct bnxt *bp)
push_size = L1_CACHE_ALIGN(sizeof(struct tx_push_bd) + push_size = L1_CACHE_ALIGN(sizeof(struct tx_push_bd) +
bp->tx_push_thresh); bp->tx_push_thresh);
if (push_size > 128) { if (push_size > 256) {
push_size = 0; push_size = 0;
bp->tx_push_thresh = 0; bp->tx_push_thresh = 0;
} }
...@@ -1772,7 +1783,6 @@ static int bnxt_alloc_tx_rings(struct bnxt *bp) ...@@ -1772,7 +1783,6 @@ static int bnxt_alloc_tx_rings(struct bnxt *bp)
return rc; return rc;
if (bp->tx_push_size) { if (bp->tx_push_size) {
struct tx_bd *txbd;
dma_addr_t mapping; dma_addr_t mapping;
/* One pre-allocated DMA buffer to backup /* One pre-allocated DMA buffer to backup
...@@ -1786,13 +1796,11 @@ static int bnxt_alloc_tx_rings(struct bnxt *bp) ...@@ -1786,13 +1796,11 @@ static int bnxt_alloc_tx_rings(struct bnxt *bp)
if (!txr->tx_push) if (!txr->tx_push)
return -ENOMEM; return -ENOMEM;
txbd = &txr->tx_push->txbd1;
mapping = txr->tx_push_mapping + mapping = txr->tx_push_mapping +
sizeof(struct tx_push_bd); sizeof(struct tx_push_bd);
txbd->tx_bd_haddr = cpu_to_le64(mapping); txr->data_mapping = cpu_to_le64(mapping);
memset(txbd + 1, 0, sizeof(struct tx_bd_ext)); memset(txr->tx_push, 0, sizeof(struct tx_push_bd));
} }
ring->queue_id = bp->q_info[j].queue_id; ring->queue_id = bp->q_info[j].queue_id;
if (i % bp->tx_nr_rings_per_tc == (bp->tx_nr_rings_per_tc - 1)) if (i % bp->tx_nr_rings_per_tc == (bp->tx_nr_rings_per_tc - 1))
...@@ -5670,22 +5678,16 @@ static int bnxt_probe_phy(struct bnxt *bp) ...@@ -5670,22 +5678,16 @@ static int bnxt_probe_phy(struct bnxt *bp)
} }
/*initialize the ethool setting copy with NVM settings */ /*initialize the ethool setting copy with NVM settings */
if (BNXT_AUTO_MODE(link_info->auto_mode)) if (BNXT_AUTO_MODE(link_info->auto_mode)) {
link_info->autoneg |= BNXT_AUTONEG_SPEED; link_info->autoneg = BNXT_AUTONEG_SPEED |
BNXT_AUTONEG_FLOW_CTRL;
if (link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) { link_info->advertising = link_info->auto_link_speeds;
if (link_info->auto_pause_setting == BNXT_LINK_PAUSE_BOTH)
link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
link_info->req_flow_ctrl = link_info->auto_pause_setting; link_info->req_flow_ctrl = link_info->auto_pause_setting;
} else if (link_info->force_pause_setting & BNXT_LINK_PAUSE_BOTH) { } else {
link_info->req_link_speed = link_info->force_link_speed;
link_info->req_duplex = link_info->duplex_setting;
link_info->req_flow_ctrl = link_info->force_pause_setting; link_info->req_flow_ctrl = link_info->force_pause_setting;
} }
link_info->req_duplex = link_info->duplex_setting;
if (link_info->autoneg & BNXT_AUTONEG_SPEED)
link_info->req_link_speed = link_info->auto_link_speed;
else
link_info->req_link_speed = link_info->force_link_speed;
link_info->advertising = link_info->auto_link_speeds;
snprintf(phy_ver, PHY_VER_STR_LEN, " ph %d.%d.%d", snprintf(phy_ver, PHY_VER_STR_LEN, " ph %d.%d.%d",
link_info->phy_ver[0], link_info->phy_ver[0],
link_info->phy_ver[1], link_info->phy_ver[1],
......
...@@ -411,8 +411,8 @@ struct rx_tpa_end_cmp_ext { ...@@ -411,8 +411,8 @@ struct rx_tpa_end_cmp_ext {
#define BNXT_NUM_TESTS(bp) 0 #define BNXT_NUM_TESTS(bp) 0
#define BNXT_DEFAULT_RX_RING_SIZE 1023 #define BNXT_DEFAULT_RX_RING_SIZE 511
#define BNXT_DEFAULT_TX_RING_SIZE 512 #define BNXT_DEFAULT_TX_RING_SIZE 511
#define MAX_TPA 64 #define MAX_TPA 64
...@@ -523,10 +523,16 @@ struct bnxt_ring_struct { ...@@ -523,10 +523,16 @@ struct bnxt_ring_struct {
struct tx_push_bd { struct tx_push_bd {
__le32 doorbell; __le32 doorbell;
struct tx_bd txbd1; __le32 tx_bd_len_flags_type;
u32 tx_bd_opaque;
struct tx_bd_ext txbd2; struct tx_bd_ext txbd2;
}; };
struct tx_push_buffer {
struct tx_push_bd push_bd;
u32 data[25];
};
struct bnxt_tx_ring_info { struct bnxt_tx_ring_info {
struct bnxt_napi *bnapi; struct bnxt_napi *bnapi;
u16 tx_prod; u16 tx_prod;
...@@ -538,8 +544,9 @@ struct bnxt_tx_ring_info { ...@@ -538,8 +544,9 @@ struct bnxt_tx_ring_info {
dma_addr_t tx_desc_mapping[MAX_TX_PAGES]; dma_addr_t tx_desc_mapping[MAX_TX_PAGES];
struct tx_push_bd *tx_push; struct tx_push_buffer *tx_push;
dma_addr_t tx_push_mapping; dma_addr_t tx_push_mapping;
__le64 data_mapping;
#define BNXT_DEV_STATE_CLOSING 0x1 #define BNXT_DEV_STATE_CLOSING 0x1
u32 dev_state; u32 dev_state;
......
...@@ -486,15 +486,8 @@ static u32 bnxt_fw_to_ethtool_support_spds(struct bnxt_link_info *link_info) ...@@ -486,15 +486,8 @@ static u32 bnxt_fw_to_ethtool_support_spds(struct bnxt_link_info *link_info)
speed_mask |= SUPPORTED_2500baseX_Full; speed_mask |= SUPPORTED_2500baseX_Full;
if (fw_speeds & BNXT_LINK_SPEED_MSK_10GB) if (fw_speeds & BNXT_LINK_SPEED_MSK_10GB)
speed_mask |= SUPPORTED_10000baseT_Full; speed_mask |= SUPPORTED_10000baseT_Full;
/* TODO: support 25GB, 50GB with different cable type */
if (fw_speeds & BNXT_LINK_SPEED_MSK_20GB)
speed_mask |= SUPPORTED_20000baseMLD2_Full |
SUPPORTED_20000baseKR2_Full;
if (fw_speeds & BNXT_LINK_SPEED_MSK_40GB) if (fw_speeds & BNXT_LINK_SPEED_MSK_40GB)
speed_mask |= SUPPORTED_40000baseKR4_Full | speed_mask |= SUPPORTED_40000baseCR4_Full;
SUPPORTED_40000baseCR4_Full |
SUPPORTED_40000baseSR4_Full |
SUPPORTED_40000baseLR4_Full;
return speed_mask; return speed_mask;
} }
...@@ -514,15 +507,8 @@ static u32 bnxt_fw_to_ethtool_advertised_spds(struct bnxt_link_info *link_info) ...@@ -514,15 +507,8 @@ static u32 bnxt_fw_to_ethtool_advertised_spds(struct bnxt_link_info *link_info)
speed_mask |= ADVERTISED_2500baseX_Full; speed_mask |= ADVERTISED_2500baseX_Full;
if (fw_speeds & BNXT_LINK_SPEED_MSK_10GB) if (fw_speeds & BNXT_LINK_SPEED_MSK_10GB)
speed_mask |= ADVERTISED_10000baseT_Full; speed_mask |= ADVERTISED_10000baseT_Full;
/* TODO: how to advertise 20, 25, 40, 50GB with different cable type ?*/
if (fw_speeds & BNXT_LINK_SPEED_MSK_20GB)
speed_mask |= ADVERTISED_20000baseMLD2_Full |
ADVERTISED_20000baseKR2_Full;
if (fw_speeds & BNXT_LINK_SPEED_MSK_40GB) if (fw_speeds & BNXT_LINK_SPEED_MSK_40GB)
speed_mask |= ADVERTISED_40000baseKR4_Full | speed_mask |= ADVERTISED_40000baseCR4_Full;
ADVERTISED_40000baseCR4_Full |
ADVERTISED_40000baseSR4_Full |
ADVERTISED_40000baseLR4_Full;
return speed_mask; return speed_mask;
} }
...@@ -557,11 +543,12 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) ...@@ -557,11 +543,12 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
u16 ethtool_speed; u16 ethtool_speed;
cmd->supported = bnxt_fw_to_ethtool_support_spds(link_info); cmd->supported = bnxt_fw_to_ethtool_support_spds(link_info);
cmd->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
if (link_info->auto_link_speeds) if (link_info->auto_link_speeds)
cmd->supported |= SUPPORTED_Autoneg; cmd->supported |= SUPPORTED_Autoneg;
if (BNXT_AUTO_MODE(link_info->auto_mode)) { if (link_info->autoneg) {
cmd->advertising = cmd->advertising =
bnxt_fw_to_ethtool_advertised_spds(link_info); bnxt_fw_to_ethtool_advertised_spds(link_info);
cmd->advertising |= ADVERTISED_Autoneg; cmd->advertising |= ADVERTISED_Autoneg;
...@@ -570,28 +557,16 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) ...@@ -570,28 +557,16 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->autoneg = AUTONEG_DISABLE; cmd->autoneg = AUTONEG_DISABLE;
cmd->advertising = 0; cmd->advertising = 0;
} }
if (link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) { if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) {
if ((link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) == if ((link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) ==
BNXT_LINK_PAUSE_BOTH) { BNXT_LINK_PAUSE_BOTH) {
cmd->advertising |= ADVERTISED_Pause; cmd->advertising |= ADVERTISED_Pause;
cmd->supported |= SUPPORTED_Pause;
} else { } else {
cmd->advertising |= ADVERTISED_Asym_Pause; cmd->advertising |= ADVERTISED_Asym_Pause;
cmd->supported |= SUPPORTED_Asym_Pause;
if (link_info->auto_pause_setting & if (link_info->auto_pause_setting &
BNXT_LINK_PAUSE_RX) BNXT_LINK_PAUSE_RX)
cmd->advertising |= ADVERTISED_Pause; cmd->advertising |= ADVERTISED_Pause;
} }
} else if (link_info->force_pause_setting & BNXT_LINK_PAUSE_BOTH) {
if ((link_info->force_pause_setting & BNXT_LINK_PAUSE_BOTH) ==
BNXT_LINK_PAUSE_BOTH) {
cmd->supported |= SUPPORTED_Pause;
} else {
cmd->supported |= SUPPORTED_Asym_Pause;
if (link_info->force_pause_setting &
BNXT_LINK_PAUSE_RX)
cmd->supported |= SUPPORTED_Pause;
}
} }
cmd->port = PORT_NONE; cmd->port = PORT_NONE;
...@@ -670,6 +645,9 @@ static u16 bnxt_get_fw_auto_link_speeds(u32 advertising) ...@@ -670,6 +645,9 @@ static u16 bnxt_get_fw_auto_link_speeds(u32 advertising)
if (advertising & ADVERTISED_10000baseT_Full) if (advertising & ADVERTISED_10000baseT_Full)
fw_speed_mask |= BNXT_LINK_SPEED_MSK_10GB; fw_speed_mask |= BNXT_LINK_SPEED_MSK_10GB;
if (advertising & ADVERTISED_40000baseCR4_Full)
fw_speed_mask |= BNXT_LINK_SPEED_MSK_40GB;
return fw_speed_mask; return fw_speed_mask;
} }
...@@ -729,7 +707,7 @@ static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) ...@@ -729,7 +707,7 @@ static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
speed = ethtool_cmd_speed(cmd); speed = ethtool_cmd_speed(cmd);
link_info->req_link_speed = bnxt_get_fw_speed(dev, speed); link_info->req_link_speed = bnxt_get_fw_speed(dev, speed);
link_info->req_duplex = BNXT_LINK_DUPLEX_FULL; link_info->req_duplex = BNXT_LINK_DUPLEX_FULL;
link_info->autoneg &= ~BNXT_AUTONEG_SPEED; link_info->autoneg = 0;
link_info->advertising = 0; link_info->advertising = 0;
} }
...@@ -748,8 +726,7 @@ static void bnxt_get_pauseparam(struct net_device *dev, ...@@ -748,8 +726,7 @@ static void bnxt_get_pauseparam(struct net_device *dev,
if (BNXT_VF(bp)) if (BNXT_VF(bp))
return; return;
epause->autoneg = !!(link_info->auto_pause_setting & epause->autoneg = !!(link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL);
BNXT_LINK_PAUSE_BOTH);
epause->rx_pause = ((link_info->pause & BNXT_LINK_PAUSE_RX) != 0); epause->rx_pause = ((link_info->pause & BNXT_LINK_PAUSE_RX) != 0);
epause->tx_pause = ((link_info->pause & BNXT_LINK_PAUSE_TX) != 0); epause->tx_pause = ((link_info->pause & BNXT_LINK_PAUSE_TX) != 0);
} }
...@@ -765,6 +742,9 @@ static int bnxt_set_pauseparam(struct net_device *dev, ...@@ -765,6 +742,9 @@ static int bnxt_set_pauseparam(struct net_device *dev,
return rc; return rc;
if (epause->autoneg) { if (epause->autoneg) {
if (!(link_info->autoneg & BNXT_AUTONEG_SPEED))
return -EINVAL;
link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL; link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_BOTH; link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_BOTH;
} else { } else {
......
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