diff options
Diffstat (limited to 'drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c')
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 60 |
1 files changed, 52 insertions, 8 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 940ef859dc60..5523da3afcdc 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
@@ -127,6 +127,17 @@ MODULE_PARM_DESC(debug, " Default debug msglevel"); | |||
127 | 127 | ||
128 | struct workqueue_struct *bnx2x_wq; | 128 | struct workqueue_struct *bnx2x_wq; |
129 | 129 | ||
130 | struct bnx2x_mac_vals { | ||
131 | u32 xmac_addr; | ||
132 | u32 xmac_val; | ||
133 | u32 emac_addr; | ||
134 | u32 emac_val; | ||
135 | u32 umac_addr; | ||
136 | u32 umac_val; | ||
137 | u32 bmac_addr; | ||
138 | u32 bmac_val[2]; | ||
139 | }; | ||
140 | |||
130 | enum bnx2x_board_type { | 141 | enum bnx2x_board_type { |
131 | BCM57710 = 0, | 142 | BCM57710 = 0, |
132 | BCM57711, | 143 | BCM57711, |
@@ -9420,12 +9431,19 @@ static inline void bnx2x_undi_int_disable(struct bnx2x *bp) | |||
9420 | bnx2x_undi_int_disable_e1h(bp); | 9431 | bnx2x_undi_int_disable_e1h(bp); |
9421 | } | 9432 | } |
9422 | 9433 | ||
9423 | static void bnx2x_prev_unload_close_mac(struct bnx2x *bp) | 9434 | static void bnx2x_prev_unload_close_mac(struct bnx2x *bp, |
9435 | struct bnx2x_mac_vals *vals) | ||
9424 | { | 9436 | { |
9425 | u32 val, base_addr, offset, mask, reset_reg; | 9437 | u32 val, base_addr, offset, mask, reset_reg; |
9426 | bool mac_stopped = false; | 9438 | bool mac_stopped = false; |
9427 | u8 port = BP_PORT(bp); | 9439 | u8 port = BP_PORT(bp); |
9428 | 9440 | ||
9441 | /* reset addresses as they also mark which values were changed */ | ||
9442 | vals->bmac_addr = 0; | ||
9443 | vals->umac_addr = 0; | ||
9444 | vals->xmac_addr = 0; | ||
9445 | vals->emac_addr = 0; | ||
9446 | |||
9429 | reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2); | 9447 | reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2); |
9430 | 9448 | ||
9431 | if (!CHIP_IS_E3(bp)) { | 9449 | if (!CHIP_IS_E3(bp)) { |
@@ -9447,14 +9465,18 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp) | |||
9447 | */ | 9465 | */ |
9448 | wb_data[0] = REG_RD(bp, base_addr + offset); | 9466 | wb_data[0] = REG_RD(bp, base_addr + offset); |
9449 | wb_data[1] = REG_RD(bp, base_addr + offset + 0x4); | 9467 | wb_data[1] = REG_RD(bp, base_addr + offset + 0x4); |
9468 | vals->bmac_addr = base_addr + offset; | ||
9469 | vals->bmac_val[0] = wb_data[0]; | ||
9470 | vals->bmac_val[1] = wb_data[1]; | ||
9450 | wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE; | 9471 | wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE; |
9451 | REG_WR(bp, base_addr + offset, wb_data[0]); | 9472 | REG_WR(bp, vals->bmac_addr, wb_data[0]); |
9452 | REG_WR(bp, base_addr + offset + 0x4, wb_data[1]); | 9473 | REG_WR(bp, vals->bmac_addr + 0x4, wb_data[1]); |
9453 | 9474 | ||
9454 | } | 9475 | } |
9455 | BNX2X_DEV_INFO("Disable emac Rx\n"); | 9476 | BNX2X_DEV_INFO("Disable emac Rx\n"); |
9456 | REG_WR(bp, NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4, 0); | 9477 | vals->emac_addr = NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4; |
9457 | 9478 | vals->emac_val = REG_RD(bp, vals->emac_addr); | |
9479 | REG_WR(bp, vals->emac_addr, 0); | ||
9458 | mac_stopped = true; | 9480 | mac_stopped = true; |
9459 | } else { | 9481 | } else { |
9460 | if (reset_reg & MISC_REGISTERS_RESET_REG_2_XMAC) { | 9482 | if (reset_reg & MISC_REGISTERS_RESET_REG_2_XMAC) { |
@@ -9465,14 +9487,18 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp) | |||
9465 | val & ~(1 << 1)); | 9487 | val & ~(1 << 1)); |
9466 | REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI, | 9488 | REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI, |
9467 | val | (1 << 1)); | 9489 | val | (1 << 1)); |
9468 | REG_WR(bp, base_addr + XMAC_REG_CTRL, 0); | 9490 | vals->xmac_addr = base_addr + XMAC_REG_CTRL; |
9491 | vals->xmac_val = REG_RD(bp, vals->xmac_addr); | ||
9492 | REG_WR(bp, vals->xmac_addr, 0); | ||
9469 | mac_stopped = true; | 9493 | mac_stopped = true; |
9470 | } | 9494 | } |
9471 | mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port; | 9495 | mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port; |
9472 | if (mask & reset_reg) { | 9496 | if (mask & reset_reg) { |
9473 | BNX2X_DEV_INFO("Disable umac Rx\n"); | 9497 | BNX2X_DEV_INFO("Disable umac Rx\n"); |
9474 | base_addr = BP_PORT(bp) ? GRCBASE_UMAC1 : GRCBASE_UMAC0; | 9498 | base_addr = BP_PORT(bp) ? GRCBASE_UMAC1 : GRCBASE_UMAC0; |
9475 | REG_WR(bp, base_addr + UMAC_REG_COMMAND_CONFIG, 0); | 9499 | vals->umac_addr = base_addr + UMAC_REG_COMMAND_CONFIG; |
9500 | vals->umac_val = REG_RD(bp, vals->umac_addr); | ||
9501 | REG_WR(bp, vals->umac_addr, 0); | ||
9476 | mac_stopped = true; | 9502 | mac_stopped = true; |
9477 | } | 9503 | } |
9478 | } | 9504 | } |
@@ -9664,12 +9690,16 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) | |||
9664 | { | 9690 | { |
9665 | u32 reset_reg, tmp_reg = 0, rc; | 9691 | u32 reset_reg, tmp_reg = 0, rc; |
9666 | bool prev_undi = false; | 9692 | bool prev_undi = false; |
9693 | struct bnx2x_mac_vals mac_vals; | ||
9694 | |||
9667 | /* It is possible a previous function received 'common' answer, | 9695 | /* It is possible a previous function received 'common' answer, |
9668 | * but hasn't loaded yet, therefore creating a scenario of | 9696 | * but hasn't loaded yet, therefore creating a scenario of |
9669 | * multiple functions receiving 'common' on the same path. | 9697 | * multiple functions receiving 'common' on the same path. |
9670 | */ | 9698 | */ |
9671 | BNX2X_DEV_INFO("Common unload Flow\n"); | 9699 | BNX2X_DEV_INFO("Common unload Flow\n"); |
9672 | 9700 | ||
9701 | memset(&mac_vals, 0, sizeof(mac_vals)); | ||
9702 | |||
9673 | if (bnx2x_prev_is_path_marked(bp)) | 9703 | if (bnx2x_prev_is_path_marked(bp)) |
9674 | return bnx2x_prev_mcp_done(bp); | 9704 | return bnx2x_prev_mcp_done(bp); |
9675 | 9705 | ||
@@ -9680,7 +9710,10 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) | |||
9680 | u32 timer_count = 1000; | 9710 | u32 timer_count = 1000; |
9681 | 9711 | ||
9682 | /* Close the MAC Rx to prevent BRB from filling up */ | 9712 | /* Close the MAC Rx to prevent BRB from filling up */ |
9683 | bnx2x_prev_unload_close_mac(bp); | 9713 | bnx2x_prev_unload_close_mac(bp, &mac_vals); |
9714 | |||
9715 | /* close LLH filters towards the BRB */ | ||
9716 | bnx2x_set_rx_filter(&bp->link_params, 0); | ||
9684 | 9717 | ||
9685 | /* Check if the UNDI driver was previously loaded | 9718 | /* Check if the UNDI driver was previously loaded |
9686 | * UNDI driver initializes CID offset for normal bell to 0x7 | 9719 | * UNDI driver initializes CID offset for normal bell to 0x7 |
@@ -9727,6 +9760,17 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) | |||
9727 | /* No packets are in the pipeline, path is ready for reset */ | 9760 | /* No packets are in the pipeline, path is ready for reset */ |
9728 | bnx2x_reset_common(bp); | 9761 | bnx2x_reset_common(bp); |
9729 | 9762 | ||
9763 | if (mac_vals.xmac_addr) | ||
9764 | REG_WR(bp, mac_vals.xmac_addr, mac_vals.xmac_val); | ||
9765 | if (mac_vals.umac_addr) | ||
9766 | REG_WR(bp, mac_vals.umac_addr, mac_vals.umac_val); | ||
9767 | if (mac_vals.emac_addr) | ||
9768 | REG_WR(bp, mac_vals.emac_addr, mac_vals.emac_val); | ||
9769 | if (mac_vals.bmac_addr) { | ||
9770 | REG_WR(bp, mac_vals.bmac_addr, mac_vals.bmac_val[0]); | ||
9771 | REG_WR(bp, mac_vals.bmac_addr + 4, mac_vals.bmac_val[1]); | ||
9772 | } | ||
9773 | |||
9730 | rc = bnx2x_prev_mark_path(bp, prev_undi); | 9774 | rc = bnx2x_prev_mark_path(bp, prev_undi); |
9731 | if (rc) { | 9775 | if (rc) { |
9732 | bnx2x_prev_mcp_done(bp); | 9776 | bnx2x_prev_mcp_done(bp); |