提交 255ca311 编写于 作者: M Matt Carlson 提交者: David S. Miller

tg3: Prevent tx BD corruption

This patch prevents a tx BD corruption bug by preventing the device from
powering down the PLL from L1 if the link speed is 10Mbps or 100Mbps.

The same bits are also used to prevent a system hang during chip reset
resulting from a complicated set of events that ultimately leads to
PCIe block register corruption.
Signed-off-by: NMatt Carlson <mcarlson@broadcom.com>
Reviewed-by: NMichael Chan <mchan@broadcom.com>
Reviewed-by: NBenjamin Li <benli@broadcom.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 521e6b90
...@@ -3167,6 +3167,15 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) ...@@ -3167,6 +3167,15 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
pci_write_config_word(tp->pdev, pci_write_config_word(tp->pdev,
tp->pcie_cap + PCI_EXP_LNKCTL, tp->pcie_cap + PCI_EXP_LNKCTL,
newlnkctl); newlnkctl);
} else if (tp->tg3_flags3 & TG3_FLG3_TOGGLE_10_100_L1PLLPD) {
u32 newreg, oldreg = tr32(TG3_PCIE_LNKCTL);
if (tp->link_config.active_speed == SPEED_100 ||
tp->link_config.active_speed == SPEED_10)
newreg = oldreg & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN;
else
newreg = oldreg | TG3_PCIE_LNKCTL_L1_PLL_PD_EN;
if (newreg != oldreg)
tw32(TG3_PCIE_LNKCTL, newreg);
} }
if (current_link_up != netif_carrier_ok(tp->dev)) { if (current_link_up != netif_carrier_ok(tp->dev)) {
...@@ -6160,6 +6169,11 @@ static int tg3_chip_reset(struct tg3 *tp) ...@@ -6160,6 +6169,11 @@ static int tg3_chip_reset(struct tg3 *tp)
smp_mb(); smp_mb();
synchronize_irq(tp->pdev->irq); synchronize_irq(tp->pdev->irq);
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) {
val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN;
tw32(TG3_PCIE_LNKCTL, val | TG3_PCIE_LNKCTL_L1_PLL_PD_DIS);
}
/* do the reset */ /* do the reset */
val = GRC_MISC_CFG_CORECLK_RESET; val = GRC_MISC_CFG_CORECLK_RESET;
...@@ -6726,6 +6740,15 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) ...@@ -6726,6 +6740,15 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
tw32(TG3_CORR_ERR_STAT, TG3_CORR_ERR_STAT_CLEAR); tw32(TG3_CORR_ERR_STAT, TG3_CORR_ERR_STAT_CLEAR);
} }
if (tp->tg3_flags3 & TG3_FLG3_TOGGLE_10_100_L1PLLPD) {
val = tr32(TG3_PCIE_LNKCTL);
if (tp->tg3_flags3 & TG3_FLG3_CLKREQ_BUG)
val |= TG3_PCIE_LNKCTL_L1_PLL_PD_DIS;
else
val &= ~TG3_PCIE_LNKCTL_L1_PLL_PD_DIS;
tw32(TG3_PCIE_LNKCTL, val);
}
/* This works around an issue with Athlon chipsets on /* This works around an issue with Athlon chipsets on
* B3 tigon3 silicon. This bit has no effect on any * B3 tigon3 silicon. This bit has no effect on any
* other revision. But do not set this on PCI Express * other revision. But do not set this on PCI Express
...@@ -12274,6 +12297,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) ...@@ -12274,6 +12297,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
tp->tg3_flags3 |= TG3_FLG3_USE_PHYLIB; tp->tg3_flags3 |= TG3_FLG3_USE_PHYLIB;
if ((tp->pci_chip_rev_id == CHIPREV_ID_57780_A1 &&
tr32(RCVLPC_STATS_ENABLE) & RCVLPC_STATSENAB_ASF_FIX) ||
tp->pci_chip_rev_id == CHIPREV_ID_57780_A0)
tp->tg3_flags3 |= TG3_FLG3_TOGGLE_10_100_L1PLLPD;
err = tg3_mdio_init(tp); err = tg3_mdio_init(tp);
if (err) if (err)
return err; return err;
......
...@@ -866,6 +866,7 @@ ...@@ -866,6 +866,7 @@
#define RCVLPC_STATSCTRL_ENABLE 0x00000001 #define RCVLPC_STATSCTRL_ENABLE 0x00000001
#define RCVLPC_STATSCTRL_FASTUPD 0x00000002 #define RCVLPC_STATSCTRL_FASTUPD 0x00000002
#define RCVLPC_STATS_ENABLE 0x00002018 #define RCVLPC_STATS_ENABLE 0x00002018
#define RCVLPC_STATSENAB_ASF_FIX 0x00000002
#define RCVLPC_STATSENAB_DACK_FIX 0x00040000 #define RCVLPC_STATSENAB_DACK_FIX 0x00040000
#define RCVLPC_STATSENAB_LNGBRST_RFIX 0x00400000 #define RCVLPC_STATSENAB_LNGBRST_RFIX 0x00400000
#define RCVLPC_STATS_INCMASK 0x0000201c #define RCVLPC_STATS_INCMASK 0x0000201c
...@@ -1704,7 +1705,12 @@ ...@@ -1704,7 +1705,12 @@
#define PCIE_PWR_MGMT_L1_THRESH_MSK 0x0000ff00 #define PCIE_PWR_MGMT_L1_THRESH_MSK 0x0000ff00
#define PCIE_PWR_MGMT_L1_THRESH_4MS 0x0000ff00 #define PCIE_PWR_MGMT_L1_THRESH_4MS 0x0000ff00
#define PCIE_PWR_MGMT_EXT_ASPM_TMR_EN 0x01000000 #define PCIE_PWR_MGMT_EXT_ASPM_TMR_EN 0x01000000
/* 0x7d2c --> 0x7e70 unused */ /* 0x7d2c --> 0x7d54 unused */
#define TG3_PCIE_LNKCTL 0x00007d54
#define TG3_PCIE_LNKCTL_L1_PLL_PD_EN 0x00000008
#define TG3_PCIE_LNKCTL_L1_PLL_PD_DIS 0x00000080
/* 0x7d58 --> 0x7e70 unused */
#define TG3_PCIE_EIDLE_DELAY 0x00007e70 #define TG3_PCIE_EIDLE_DELAY 0x00007e70
#define TG3_PCIE_EIDLE_DELAY_MASK 0x0000001f #define TG3_PCIE_EIDLE_DELAY_MASK 0x0000001f
...@@ -2650,6 +2656,7 @@ struct tg3 { ...@@ -2650,6 +2656,7 @@ struct tg3 {
#define TG3_FLG3_PHY_ENABLE_APD 0x00001000 #define TG3_FLG3_PHY_ENABLE_APD 0x00001000
#define TG3_FLG3_5755_PLUS 0x00002000 #define TG3_FLG3_5755_PLUS 0x00002000
#define TG3_FLG3_NO_NVRAM 0x00004000 #define TG3_FLG3_NO_NVRAM 0x00004000
#define TG3_FLG3_TOGGLE_10_100_L1PLLPD 0x00008000
struct timer_list timer; struct timer_list timer;
u16 timer_counter; u16 timer_counter;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册