diff options
author | Yaniv Rosner <yanivr@broadcom.com> | 2011-10-27 01:09:47 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-10-27 16:14:15 -0400 |
commit | ce7c048928473220394bb126b08596e92e998a36 (patch) | |
tree | cd84a01e6c6dd20f889cf23b66d71b05a880e045 | |
parent | a9077bfd0b3fdcd1051cc3d09bf8c28f9d4d506a (diff) |
bnx2x: Fix RX/TX problem caused by the MAC layer
This patch fixes a problem in which the host stops receiving data after
restarting the interface. This issue is caused by combination of incorrect
data path tap closure, along with missing MAC reset.
Signed-off-by: Yaniv Rosner <yanivr@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 45 |
1 files changed, 33 insertions, 12 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index a47db9dc6c50..23333e0a1ef4 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | |||
@@ -1494,6 +1494,18 @@ static void bnx2x_set_xumac_nig(struct link_params *params, | |||
1494 | NIG_REG_P0_MAC_PAUSE_OUT_EN, tx_pause_en); | 1494 | NIG_REG_P0_MAC_PAUSE_OUT_EN, tx_pause_en); |
1495 | } | 1495 | } |
1496 | 1496 | ||
1497 | static void bnx2x_umac_disable(struct link_params *params) | ||
1498 | { | ||
1499 | u32 umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0; | ||
1500 | struct bnx2x *bp = params->bp; | ||
1501 | if (!(REG_RD(bp, MISC_REG_RESET_REG_2) & | ||
1502 | (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port))) | ||
1503 | return; | ||
1504 | |||
1505 | /* Disable RX and TX */ | ||
1506 | REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, 0); | ||
1507 | } | ||
1508 | |||
1497 | static void bnx2x_umac_enable(struct link_params *params, | 1509 | static void bnx2x_umac_enable(struct link_params *params, |
1498 | struct link_vars *vars, u8 lb) | 1510 | struct link_vars *vars, u8 lb) |
1499 | { | 1511 | { |
@@ -1603,8 +1615,9 @@ static u8 bnx2x_is_4_port_mode(struct bnx2x *bp) | |||
1603 | } | 1615 | } |
1604 | 1616 | ||
1605 | /* Define the XMAC mode */ | 1617 | /* Define the XMAC mode */ |
1606 | static void bnx2x_xmac_init(struct bnx2x *bp, u32 max_speed) | 1618 | static void bnx2x_xmac_init(struct link_params *params, u32 max_speed) |
1607 | { | 1619 | { |
1620 | struct bnx2x *bp = params->bp; | ||
1608 | u32 is_port4mode = bnx2x_is_4_port_mode(bp); | 1621 | u32 is_port4mode = bnx2x_is_4_port_mode(bp); |
1609 | 1622 | ||
1610 | /** | 1623 | /** |
@@ -1614,7 +1627,8 @@ static void bnx2x_xmac_init(struct bnx2x *bp, u32 max_speed) | |||
1614 | * ports of the path | 1627 | * ports of the path |
1615 | **/ | 1628 | **/ |
1616 | 1629 | ||
1617 | if (is_port4mode && (REG_RD(bp, MISC_REG_RESET_REG_2) & | 1630 | if ((CHIP_NUM(bp) == CHIP_NUM_57840) && |
1631 | (REG_RD(bp, MISC_REG_RESET_REG_2) & | ||
1618 | MISC_REGISTERS_RESET_REG_2_XMAC)) { | 1632 | MISC_REGISTERS_RESET_REG_2_XMAC)) { |
1619 | DP(NETIF_MSG_LINK, | 1633 | DP(NETIF_MSG_LINK, |
1620 | "XMAC already out of reset in 4-port mode\n"); | 1634 | "XMAC already out of reset in 4-port mode\n"); |
@@ -1681,10 +1695,6 @@ static void bnx2x_xmac_disable(struct link_params *params) | |||
1681 | (pfc_ctrl | (1<<1))); | 1695 | (pfc_ctrl | (1<<1))); |
1682 | DP(NETIF_MSG_LINK, "Disable XMAC on port %x\n", port); | 1696 | DP(NETIF_MSG_LINK, "Disable XMAC on port %x\n", port); |
1683 | REG_WR(bp, xmac_base + XMAC_REG_CTRL, 0); | 1697 | REG_WR(bp, xmac_base + XMAC_REG_CTRL, 0); |
1684 | usleep_range(1000, 1000); | ||
1685 | bnx2x_set_xumac_nig(params, 0, 0); | ||
1686 | REG_WR(bp, xmac_base + XMAC_REG_CTRL, | ||
1687 | XMAC_CTRL_REG_SOFT_RESET); | ||
1688 | } | 1698 | } |
1689 | } | 1699 | } |
1690 | 1700 | ||
@@ -1697,7 +1707,7 @@ static int bnx2x_xmac_enable(struct link_params *params, | |||
1697 | 1707 | ||
1698 | xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0; | 1708 | xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0; |
1699 | 1709 | ||
1700 | bnx2x_xmac_init(bp, vars->line_speed); | 1710 | bnx2x_xmac_init(params, vars->line_speed); |
1701 | 1711 | ||
1702 | /* | 1712 | /* |
1703 | * This register determines on which events the MAC will assert | 1713 | * This register determines on which events the MAC will assert |
@@ -6310,8 +6320,10 @@ static int bnx2x_update_link_down(struct link_params *params, | |||
6310 | MISC_REGISTERS_RESET_REG_2_CLEAR, | 6320 | MISC_REGISTERS_RESET_REG_2_CLEAR, |
6311 | (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); | 6321 | (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); |
6312 | } | 6322 | } |
6313 | if (CHIP_IS_E3(bp)) | 6323 | if (CHIP_IS_E3(bp)) { |
6314 | bnx2x_xmac_disable(params); | 6324 | bnx2x_xmac_disable(params); |
6325 | bnx2x_umac_disable(params); | ||
6326 | } | ||
6315 | 6327 | ||
6316 | return 0; | 6328 | return 0; |
6317 | } | 6329 | } |
@@ -11810,8 +11822,10 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars, | |||
11810 | /* Stop BigMac rx */ | 11822 | /* Stop BigMac rx */ |
11811 | if (!CHIP_IS_E3(bp)) | 11823 | if (!CHIP_IS_E3(bp)) |
11812 | bnx2x_bmac_rx_disable(bp, port); | 11824 | bnx2x_bmac_rx_disable(bp, port); |
11813 | else | 11825 | else { |
11814 | bnx2x_xmac_disable(params); | 11826 | bnx2x_xmac_disable(params); |
11827 | bnx2x_umac_disable(params); | ||
11828 | } | ||
11815 | /* disable emac */ | 11829 | /* disable emac */ |
11816 | if (!CHIP_IS_E3(bp)) | 11830 | if (!CHIP_IS_E3(bp)) |
11817 | REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0); | 11831 | REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0); |
@@ -11849,14 +11863,21 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars, | |||
11849 | if (params->phy[INT_PHY].link_reset) | 11863 | if (params->phy[INT_PHY].link_reset) |
11850 | params->phy[INT_PHY].link_reset( | 11864 | params->phy[INT_PHY].link_reset( |
11851 | ¶ms->phy[INT_PHY], params); | 11865 | ¶ms->phy[INT_PHY], params); |
11852 | /* reset BigMac */ | ||
11853 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, | ||
11854 | (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); | ||
11855 | 11866 | ||
11856 | /* disable nig ingress interface */ | 11867 | /* disable nig ingress interface */ |
11857 | if (!CHIP_IS_E3(bp)) { | 11868 | if (!CHIP_IS_E3(bp)) { |
11869 | /* reset BigMac */ | ||
11870 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, | ||
11871 | (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); | ||
11858 | REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0); | 11872 | REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0); |
11859 | REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0); | 11873 | REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0); |
11874 | } else { | ||
11875 | u32 xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0; | ||
11876 | bnx2x_set_xumac_nig(params, 0, 0); | ||
11877 | if (REG_RD(bp, MISC_REG_RESET_REG_2) & | ||
11878 | MISC_REGISTERS_RESET_REG_2_XMAC) | ||
11879 | REG_WR(bp, xmac_base + XMAC_REG_CTRL, | ||
11880 | XMAC_CTRL_REG_SOFT_RESET); | ||
11860 | } | 11881 | } |
11861 | vars->link_up = 0; | 11882 | vars->link_up = 0; |
11862 | vars->phy_flags = 0; | 11883 | vars->phy_flags = 0; |