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 | |
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')
-rw-r--r-- | drivers/net/tg3.c | 28 | ||||
-rw-r--r-- | drivers/net/tg3.h | 9 |
2 files changed, 36 insertions, 1 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; |
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index c613cbb40c2d..bb8591ea3300 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h | |||
@@ -866,6 +866,7 @@ | |||
866 | #define RCVLPC_STATSCTRL_ENABLE 0x00000001 | 866 | #define RCVLPC_STATSCTRL_ENABLE 0x00000001 |
867 | #define RCVLPC_STATSCTRL_FASTUPD 0x00000002 | 867 | #define RCVLPC_STATSCTRL_FASTUPD 0x00000002 |
868 | #define RCVLPC_STATS_ENABLE 0x00002018 | 868 | #define RCVLPC_STATS_ENABLE 0x00002018 |
869 | #define RCVLPC_STATSENAB_ASF_FIX 0x00000002 | ||
869 | #define RCVLPC_STATSENAB_DACK_FIX 0x00040000 | 870 | #define RCVLPC_STATSENAB_DACK_FIX 0x00040000 |
870 | #define RCVLPC_STATSENAB_LNGBRST_RFIX 0x00400000 | 871 | #define RCVLPC_STATSENAB_LNGBRST_RFIX 0x00400000 |
871 | #define RCVLPC_STATS_INCMASK 0x0000201c | 872 | #define RCVLPC_STATS_INCMASK 0x0000201c |
@@ -1704,7 +1705,12 @@ | |||
1704 | #define PCIE_PWR_MGMT_L1_THRESH_MSK 0x0000ff00 | 1705 | #define PCIE_PWR_MGMT_L1_THRESH_MSK 0x0000ff00 |
1705 | #define PCIE_PWR_MGMT_L1_THRESH_4MS 0x0000ff00 | 1706 | #define PCIE_PWR_MGMT_L1_THRESH_4MS 0x0000ff00 |
1706 | #define PCIE_PWR_MGMT_EXT_ASPM_TMR_EN 0x01000000 | 1707 | #define PCIE_PWR_MGMT_EXT_ASPM_TMR_EN 0x01000000 |
1707 | /* 0x7d2c --> 0x7e70 unused */ | 1708 | /* 0x7d2c --> 0x7d54 unused */ |
1709 | |||
1710 | #define TG3_PCIE_LNKCTL 0x00007d54 | ||
1711 | #define TG3_PCIE_LNKCTL_L1_PLL_PD_EN 0x00000008 | ||
1712 | #define TG3_PCIE_LNKCTL_L1_PLL_PD_DIS 0x00000080 | ||
1713 | /* 0x7d58 --> 0x7e70 unused */ | ||
1708 | 1714 | ||
1709 | #define TG3_PCIE_EIDLE_DELAY 0x00007e70 | 1715 | #define TG3_PCIE_EIDLE_DELAY 0x00007e70 |
1710 | #define TG3_PCIE_EIDLE_DELAY_MASK 0x0000001f | 1716 | #define TG3_PCIE_EIDLE_DELAY_MASK 0x0000001f |
@@ -2650,6 +2656,7 @@ struct tg3 { | |||
2650 | #define TG3_FLG3_PHY_ENABLE_APD 0x00001000 | 2656 | #define TG3_FLG3_PHY_ENABLE_APD 0x00001000 |
2651 | #define TG3_FLG3_5755_PLUS 0x00002000 | 2657 | #define TG3_FLG3_5755_PLUS 0x00002000 |
2652 | #define TG3_FLG3_NO_NVRAM 0x00004000 | 2658 | #define TG3_FLG3_NO_NVRAM 0x00004000 |
2659 | #define TG3_FLG3_TOGGLE_10_100_L1PLLPD 0x00008000 | ||
2653 | 2660 | ||
2654 | struct timer_list timer; | 2661 | struct timer_list timer; |
2655 | u16 timer_counter; | 2662 | u16 timer_counter; |