diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2009-08-25 06:07:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-08-26 18:47:47 -0400 |
commit | 255ca311b650caece3ec4f78b88ef298664d561f (patch) | |
tree | cf26fdfb0fb9f5fba78bb59a82f37abb132d4b62 /drivers/net/tg3.c | |
parent | 521e6b90dd3f0392062845d7ef13e6e41bb99d8a (diff) |
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: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r-- | drivers/net/tg3.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index e8def28877ce..595ddf2eb7d2 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -3167,6 +3167,15 @@ relink: | |||
3167 | pci_write_config_word(tp->pdev, | 3167 | pci_write_config_word(tp->pdev, |
3168 | tp->pcie_cap + PCI_EXP_LNKCTL, | 3168 | tp->pcie_cap + PCI_EXP_LNKCTL, |
3169 | newlnkctl); | 3169 | newlnkctl); |
3170 | } else if (tp->tg3_flags3 & TG3_FLG3_TOGGLE_10_100_L1PLLPD) { | ||
3171 | u32 newreg, oldreg = tr32(TG3_PCIE_LNKCTL); | ||
3172 | if (tp->link_config.active_speed == SPEED_100 || | ||
3173 | tp->link_config.active_speed == SPEED_10) | ||
3174 | newreg = oldreg & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN; | ||
3175 | else | ||
3176 | newreg = oldreg | TG3_PCIE_LNKCTL_L1_PLL_PD_EN; | ||
3177 | if (newreg != oldreg) | ||
3178 | tw32(TG3_PCIE_LNKCTL, newreg); | ||
3170 | } | 3179 | } |
3171 | 3180 | ||
3172 | if (current_link_up != netif_carrier_ok(tp->dev)) { | 3181 | if (current_link_up != netif_carrier_ok(tp->dev)) { |
@@ -6160,6 +6169,11 @@ static int tg3_chip_reset(struct tg3 *tp) | |||
6160 | smp_mb(); | 6169 | smp_mb(); |
6161 | synchronize_irq(tp->pdev->irq); | 6170 | synchronize_irq(tp->pdev->irq); |
6162 | 6171 | ||
6172 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) { | ||
6173 | val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN; | ||
6174 | tw32(TG3_PCIE_LNKCTL, val | TG3_PCIE_LNKCTL_L1_PLL_PD_DIS); | ||
6175 | } | ||
6176 | |||
6163 | /* do the reset */ | 6177 | /* do the reset */ |
6164 | val = GRC_MISC_CFG_CORECLK_RESET; | 6178 | val = GRC_MISC_CFG_CORECLK_RESET; |
6165 | 6179 | ||
@@ -6726,6 +6740,15 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) | |||
6726 | tw32(TG3_CORR_ERR_STAT, TG3_CORR_ERR_STAT_CLEAR); | 6740 | tw32(TG3_CORR_ERR_STAT, TG3_CORR_ERR_STAT_CLEAR); |
6727 | } | 6741 | } |
6728 | 6742 | ||
6743 | if (tp->tg3_flags3 & TG3_FLG3_TOGGLE_10_100_L1PLLPD) { | ||
6744 | val = tr32(TG3_PCIE_LNKCTL); | ||
6745 | if (tp->tg3_flags3 & TG3_FLG3_CLKREQ_BUG) | ||
6746 | val |= TG3_PCIE_LNKCTL_L1_PLL_PD_DIS; | ||
6747 | else | ||
6748 | val &= ~TG3_PCIE_LNKCTL_L1_PLL_PD_DIS; | ||
6749 | tw32(TG3_PCIE_LNKCTL, val); | ||
6750 | } | ||
6751 | |||
6729 | /* This works around an issue with Athlon chipsets on | 6752 | /* This works around an issue with Athlon chipsets on |
6730 | * B3 tigon3 silicon. This bit has no effect on any | 6753 | * B3 tigon3 silicon. This bit has no effect on any |
6731 | * other revision. But do not set this on PCI Express | 6754 | * other revision. But do not set this on PCI Express |
@@ -12274,6 +12297,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
12274 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) | 12297 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) |
12275 | tp->tg3_flags3 |= TG3_FLG3_USE_PHYLIB; | 12298 | tp->tg3_flags3 |= TG3_FLG3_USE_PHYLIB; |
12276 | 12299 | ||
12300 | if ((tp->pci_chip_rev_id == CHIPREV_ID_57780_A1 && | ||
12301 | tr32(RCVLPC_STATS_ENABLE) & RCVLPC_STATSENAB_ASF_FIX) || | ||
12302 | tp->pci_chip_rev_id == CHIPREV_ID_57780_A0) | ||
12303 | tp->tg3_flags3 |= TG3_FLG3_TOGGLE_10_100_L1PLLPD; | ||
12304 | |||
12277 | err = tg3_mdio_init(tp); | 12305 | err = tg3_mdio_init(tp); |
12278 | if (err) | 12306 | if (err) |
12279 | return err; | 12307 | return err; |