Skip to content

Commit

Permalink
tg3: Fix crc errors on jumbo frame receive
Browse files Browse the repository at this point in the history
[ Upstream commit daf3ec688e057f6060fb9bb0819feac7a8bbf45c ]

TG3_PHY_AUXCTL_SMDSP_ENABLE/DISABLE macros do a blind write to the phy
auxiliary control register and overwrite the EXT_PKT_LEN (bit 14) resulting
in intermittent crc errors on jumbo frames with some link partners. Change
the code to do a read/modify/write.

Signed-off-by: Nithin Nayak Sujir <nsujir@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Nithin Nayak Sujir authored and gregkh committed Feb 14, 2013
1 parent a10a3da commit eac7b44
Showing 1 changed file with 35 additions and 23 deletions.
58 changes: 35 additions & 23 deletions drivers/net/ethernet/broadcom/tg3.c
Expand Up @@ -1136,14 +1136,26 @@ static int tg3_phy_auxctl_write(struct tg3 *tp, int reg, u32 set)
return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg); return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg);
} }


#define TG3_PHY_AUXCTL_SMDSP_ENABLE(tp) \ static int tg3_phy_toggle_auxctl_smdsp(struct tg3 *tp, bool enable)
tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ {
MII_TG3_AUXCTL_ACTL_SMDSP_ENA | \ u32 val;
MII_TG3_AUXCTL_ACTL_TX_6DB) int err;

err = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, &val);


#define TG3_PHY_AUXCTL_SMDSP_DISABLE(tp) \ if (err)
tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ return err;
MII_TG3_AUXCTL_ACTL_TX_6DB); if (enable)

val |= MII_TG3_AUXCTL_ACTL_SMDSP_ENA;
else
val &= ~MII_TG3_AUXCTL_ACTL_SMDSP_ENA;

err = tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL,
val | MII_TG3_AUXCTL_ACTL_TX_6DB);

return err;
}


static int tg3_bmcr_reset(struct tg3 *tp) static int tg3_bmcr_reset(struct tg3 *tp)
{ {
Expand Down Expand Up @@ -2076,7 +2088,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp)


otp = tp->phy_otp; otp = tp->phy_otp;


if (TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) if (tg3_phy_toggle_auxctl_smdsp(tp, true))
return; return;


phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT); phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT);
Expand All @@ -2101,7 +2113,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp)
((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT); ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT);
tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy); tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy);


TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); tg3_phy_toggle_auxctl_smdsp(tp, false);
} }


static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)
Expand Down Expand Up @@ -2137,9 +2149,9 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)


if (!tp->setlpicnt) { if (!tp->setlpicnt) {
if (current_link_up == 1 && if (current_link_up == 1 &&
!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { !tg3_phy_toggle_auxctl_smdsp(tp, true)) {
tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000); tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000);
TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); tg3_phy_toggle_auxctl_smdsp(tp, false);
} }


val = tr32(TG3_CPMU_EEE_MODE); val = tr32(TG3_CPMU_EEE_MODE);
Expand All @@ -2155,11 +2167,11 @@ static void tg3_phy_eee_enable(struct tg3 *tp)
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
tg3_flag(tp, 57765_CLASS)) && tg3_flag(tp, 57765_CLASS)) &&
!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { !tg3_phy_toggle_auxctl_smdsp(tp, true)) {
val = MII_TG3_DSP_TAP26_ALNOKO | val = MII_TG3_DSP_TAP26_ALNOKO |
MII_TG3_DSP_TAP26_RMRXSTO; MII_TG3_DSP_TAP26_RMRXSTO;
tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val); tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val);
TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); tg3_phy_toggle_auxctl_smdsp(tp, false);
} }


val = tr32(TG3_CPMU_EEE_MODE); val = tr32(TG3_CPMU_EEE_MODE);
Expand Down Expand Up @@ -2303,7 +2315,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
tg3_writephy(tp, MII_CTRL1000, tg3_writephy(tp, MII_CTRL1000,
CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER); CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER);


err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); err = tg3_phy_toggle_auxctl_smdsp(tp, true);
if (err) if (err)
return err; return err;


Expand All @@ -2324,7 +2336,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200); tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200);
tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000); tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000);


TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); tg3_phy_toggle_auxctl_smdsp(tp, false);


tg3_writephy(tp, MII_CTRL1000, phy9_orig); tg3_writephy(tp, MII_CTRL1000, phy9_orig);


Expand Down Expand Up @@ -2413,10 +2425,10 @@ static int tg3_phy_reset(struct tg3 *tp)


out: out:
if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) && if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) &&
!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { !tg3_phy_toggle_auxctl_smdsp(tp, true)) {
tg3_phydsp_write(tp, 0x201f, 0x2aaa); tg3_phydsp_write(tp, 0x201f, 0x2aaa);
tg3_phydsp_write(tp, 0x000a, 0x0323); tg3_phydsp_write(tp, 0x000a, 0x0323);
TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); tg3_phy_toggle_auxctl_smdsp(tp, false);
} }


if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) { if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) {
Expand All @@ -2425,14 +2437,14 @@ static int tg3_phy_reset(struct tg3 *tp)
} }


if (tp->phy_flags & TG3_PHYFLG_BER_BUG) { if (tp->phy_flags & TG3_PHYFLG_BER_BUG) {
if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) {
tg3_phydsp_write(tp, 0x000a, 0x310b); tg3_phydsp_write(tp, 0x000a, 0x310b);
tg3_phydsp_write(tp, 0x201f, 0x9506); tg3_phydsp_write(tp, 0x201f, 0x9506);
tg3_phydsp_write(tp, 0x401f, 0x14e2); tg3_phydsp_write(tp, 0x401f, 0x14e2);
TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); tg3_phy_toggle_auxctl_smdsp(tp, false);
} }
} else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) { } else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) {
if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) {
tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) { if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) {
tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b); tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b);
Expand All @@ -2441,7 +2453,7 @@ static int tg3_phy_reset(struct tg3 *tp)
} else } else
tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b); tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b);


TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); tg3_phy_toggle_auxctl_smdsp(tp, false);
} }
} }


Expand Down Expand Up @@ -3858,7 +3870,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
tw32(TG3_CPMU_EEE_MODE, tw32(TG3_CPMU_EEE_MODE,
tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE); tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE);


err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); err = tg3_phy_toggle_auxctl_smdsp(tp, true);
if (!err) { if (!err) {
u32 err2; u32 err2;


Expand Down Expand Up @@ -3891,7 +3903,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
MII_TG3_DSP_CH34TP2_HIBW01); MII_TG3_DSP_CH34TP2_HIBW01);
} }


err2 = TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); err2 = tg3_phy_toggle_auxctl_smdsp(tp, false);
if (!err) if (!err)
err = err2; err = err2;
} }
Expand Down

0 comments on commit eac7b44

Please sign in to comment.