diff options
Diffstat (limited to 'drivers/net/ethernet/broadcom/bnx2x')
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 30 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 60 |
3 files changed, 81 insertions, 11 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 00706c4b090c..6312e636e37b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -78,8 +78,8 @@ static inline void bnx2x_move_fp(struct bnx2x *bp, int from, int to) new_txdata_index = new_max_eth_txqs + FCOE_TXQ_IDX_OFFSET; } - memcpy(&bp->bnx2x_txq[old_txdata_index], - &bp->bnx2x_txq[new_txdata_index], + memcpy(&bp->bnx2x_txq[new_txdata_index], + &bp->bnx2x_txq[old_txdata_index], sizeof(struct bnx2x_fp_txdata)); to_fp->txdata_ptr[0] = &bp->bnx2x_txq[new_txdata_index]; } @@ -112,6 +112,31 @@ void bnx2x_fill_fw_str(struct bnx2x *bp, char *buf, size_t buf_len) } } +/** + * bnx2x_shrink_eth_fp - guarantees fastpath structures stay intact + * + * @bp: driver handle + * @delta: number of eth queues which were not allocated + */ +static void bnx2x_shrink_eth_fp(struct bnx2x *bp, int delta) +{ + int i, cos, old_eth_num = BNX2X_NUM_ETH_QUEUES(bp); + + /* Queue pointer cannot be re-set on an fp-basis, as moving pointer + * backward along the array could cause memory to be overriden + */ + for (cos = 1; cos < bp->max_cos; cos++) { + for (i = 0; i < old_eth_num - delta; i++) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + int new_idx = cos * (old_eth_num - delta) + i; + + memcpy(&bp->bnx2x_txq[new_idx], fp->txdata_ptr[cos], + sizeof(struct bnx2x_fp_txdata)); + fp->txdata_ptr[cos] = &bp->bnx2x_txq[new_idx]; + } + } +} + int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */ /* free skb in the packet ring at pos idx @@ -4136,6 +4161,7 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp) int delta = BNX2X_NUM_ETH_QUEUES(bp) - i; WARN_ON(delta < 0); + bnx2x_shrink_eth_fp(bp, delta); if (CNIC_SUPPORT(bp)) /* move non eth FPs next to last eth FP * must be done in that order diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 292634f0e90b..d7029c895471 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -2768,10 +2768,10 @@ static int bnx2x_set_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info) } else if ((info->flow_type == UDP_V6_FLOW) && (bp->rss_conf_obj.udp_rss_v6 != udp_rss_requested)) { bp->rss_conf_obj.udp_rss_v6 = udp_rss_requested; - return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0); DP(BNX2X_MSG_ETHTOOL, "rss re-configured, UDP 4-tupple %s\n", udp_rss_requested ? "enabled" : "disabled"); + return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0); } else { return 0; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index a296758a6e1a..f808ed031ee7 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -128,6 +128,17 @@ MODULE_PARM_DESC(debug, " Default debug msglevel"); struct workqueue_struct *bnx2x_wq; +struct bnx2x_mac_vals { + u32 xmac_addr; + u32 xmac_val; + u32 emac_addr; + u32 emac_val; + u32 umac_addr; + u32 umac_val; + u32 bmac_addr; + u32 bmac_val[2]; +}; + enum bnx2x_board_type { BCM57710 = 0, BCM57711, @@ -9548,12 +9559,19 @@ static inline void bnx2x_undi_int_disable(struct bnx2x *bp) bnx2x_undi_int_disable_e1h(bp); } -static void bnx2x_prev_unload_close_mac(struct bnx2x *bp) +static void bnx2x_prev_unload_close_mac(struct bnx2x *bp, + struct bnx2x_mac_vals *vals) { u32 val, base_addr, offset, mask, reset_reg; bool mac_stopped = false; u8 port = BP_PORT(bp); + /* reset addresses as they also mark which values were changed */ + vals->bmac_addr = 0; + vals->umac_addr = 0; + vals->xmac_addr = 0; + vals->emac_addr = 0; + reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2); if (!CHIP_IS_E3(bp)) { @@ -9575,14 +9593,18 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp) */ wb_data[0] = REG_RD(bp, base_addr + offset); wb_data[1] = REG_RD(bp, base_addr + offset + 0x4); + vals->bmac_addr = base_addr + offset; + vals->bmac_val[0] = wb_data[0]; + vals->bmac_val[1] = wb_data[1]; wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE; - REG_WR(bp, base_addr + offset, wb_data[0]); - REG_WR(bp, base_addr + offset + 0x4, wb_data[1]); + REG_WR(bp, vals->bmac_addr, wb_data[0]); + REG_WR(bp, vals->bmac_addr + 0x4, wb_data[1]); } BNX2X_DEV_INFO("Disable emac Rx\n"); - REG_WR(bp, NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4, 0); - + vals->emac_addr = NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4; + vals->emac_val = REG_RD(bp, vals->emac_addr); + REG_WR(bp, vals->emac_addr, 0); mac_stopped = true; } else { if (reset_reg & MISC_REGISTERS_RESET_REG_2_XMAC) { @@ -9593,14 +9615,18 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp) val & ~(1 << 1)); REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI, val | (1 << 1)); - REG_WR(bp, base_addr + XMAC_REG_CTRL, 0); + vals->xmac_addr = base_addr + XMAC_REG_CTRL; + vals->xmac_val = REG_RD(bp, vals->xmac_addr); + REG_WR(bp, vals->xmac_addr, 0); mac_stopped = true; } mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port; if (mask & reset_reg) { BNX2X_DEV_INFO("Disable umac Rx\n"); base_addr = BP_PORT(bp) ? GRCBASE_UMAC1 : GRCBASE_UMAC0; - REG_WR(bp, base_addr + UMAC_REG_COMMAND_CONFIG, 0); + vals->umac_addr = base_addr + UMAC_REG_COMMAND_CONFIG; + vals->umac_val = REG_RD(bp, vals->umac_addr); + REG_WR(bp, vals->umac_addr, 0); mac_stopped = true; } } @@ -9792,12 +9818,16 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) { u32 reset_reg, tmp_reg = 0, rc; bool prev_undi = false; + struct bnx2x_mac_vals mac_vals; + /* It is possible a previous function received 'common' answer, * but hasn't loaded yet, therefore creating a scenario of * multiple functions receiving 'common' on the same path. */ BNX2X_DEV_INFO("Common unload Flow\n"); + memset(&mac_vals, 0, sizeof(mac_vals)); + if (bnx2x_prev_is_path_marked(bp)) return bnx2x_prev_mcp_done(bp); @@ -9808,7 +9838,10 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) u32 timer_count = 1000; /* Close the MAC Rx to prevent BRB from filling up */ - bnx2x_prev_unload_close_mac(bp); + bnx2x_prev_unload_close_mac(bp, &mac_vals); + + /* close LLH filters towards the BRB */ + bnx2x_set_rx_filter(&bp->link_params, 0); /* Check if the UNDI driver was previously loaded * UNDI driver initializes CID offset for normal bell to 0x7 @@ -9855,6 +9888,17 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) /* No packets are in the pipeline, path is ready for reset */ bnx2x_reset_common(bp); + if (mac_vals.xmac_addr) + REG_WR(bp, mac_vals.xmac_addr, mac_vals.xmac_val); + if (mac_vals.umac_addr) + REG_WR(bp, mac_vals.umac_addr, mac_vals.umac_val); + if (mac_vals.emac_addr) + REG_WR(bp, mac_vals.emac_addr, mac_vals.emac_val); + if (mac_vals.bmac_addr) { + REG_WR(bp, mac_vals.bmac_addr, mac_vals.bmac_val[0]); + REG_WR(bp, mac_vals.bmac_addr + 4, mac_vals.bmac_val[1]); + } + rc = bnx2x_prev_mark_path(bp, prev_undi); if (rc) { bnx2x_prev_mcp_done(bp); |