Don't rely on GM_GP_CTRL register contents when mii(4) layer reports
link state changes. Instead, build new speed/duplex/flow-control settings from the values reported from PHY. This should fix speed/duplex/flow-control mismatches between GMAC and PHY which resulted in very poor Rx performance due to lots of out-of-order packet delivery. Reported by: Arno J. Klaassen <arno AT heho DOT snv DOT jussieu DOT fr> Tested by: Arno J. Klaassen <arno AT heho DOT snv DOT jussieu DOT fr>
This commit is contained in:
parent
8825eb7340
commit
c72796ebf4
@ -445,7 +445,7 @@ msk_link_task(void *arg, int pending)
|
|||||||
struct msk_if_softc *sc_if;
|
struct msk_if_softc *sc_if;
|
||||||
struct mii_data *mii;
|
struct mii_data *mii;
|
||||||
struct ifnet *ifp;
|
struct ifnet *ifp;
|
||||||
uint32_t gmac, ane;
|
uint32_t gmac;
|
||||||
|
|
||||||
sc_if = (struct msk_if_softc *)arg;
|
sc_if = (struct msk_if_softc *)arg;
|
||||||
sc = sc_if->msk_softc;
|
sc = sc_if->msk_softc;
|
||||||
@ -465,42 +465,36 @@ msk_link_task(void *arg, int pending)
|
|||||||
} else
|
} else
|
||||||
sc_if->msk_link = 0;
|
sc_if->msk_link = 0;
|
||||||
|
|
||||||
gmac = GMAC_READ_2(sc, sc_if->msk_port, GM_GP_CTRL);
|
|
||||||
ane = 0;
|
|
||||||
if (sc_if->msk_link != 0) {
|
if (sc_if->msk_link != 0) {
|
||||||
/* Enable Tx FIFO Underrun. */
|
/* Enable Tx FIFO Underrun. */
|
||||||
CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, GMAC_IRQ_MSK),
|
CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, GMAC_IRQ_MSK),
|
||||||
GM_IS_TX_FF_UR | GM_IS_RX_FF_OR);
|
GM_IS_TX_FF_UR | GM_IS_RX_FF_OR);
|
||||||
|
/*
|
||||||
|
* Because mii(4) notify msk(4) that it detected link status
|
||||||
|
* change, there is no need to enable automatic
|
||||||
|
* speed/flow-control/duplex updates.
|
||||||
|
*/
|
||||||
|
gmac = GM_GPCR_AU_ALL_DIS;
|
||||||
switch (IFM_SUBTYPE(mii->mii_media_active)) {
|
switch (IFM_SUBTYPE(mii->mii_media_active)) {
|
||||||
case IFM_AUTO:
|
|
||||||
ane = 1;
|
|
||||||
break;
|
|
||||||
case IFM_1000_SX:
|
case IFM_1000_SX:
|
||||||
case IFM_1000_T:
|
case IFM_1000_T:
|
||||||
gmac &= ~GM_GPCR_SPEED_100;
|
|
||||||
gmac |= GM_GPCR_SPEED_1000;
|
gmac |= GM_GPCR_SPEED_1000;
|
||||||
break;
|
break;
|
||||||
case IFM_100_TX:
|
case IFM_100_TX:
|
||||||
gmac |= GM_GPCR_SPEED_100;
|
gmac |= GM_GPCR_SPEED_100;
|
||||||
gmac &= ~GM_GPCR_SPEED_1000;
|
|
||||||
break;
|
break;
|
||||||
case IFM_10_T:
|
case IFM_10_T:
|
||||||
gmac &= ~(GM_GPCR_SPEED_100 | GM_GPCR_SPEED_1000);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ane == 0)
|
|
||||||
gmac |= GM_GPCR_AU_ALL_DIS;
|
|
||||||
else
|
|
||||||
gmac &= ~GM_GPCR_AU_ALL_DIS;
|
|
||||||
if (((mii->mii_media_active & IFM_GMASK) & IFM_FDX) != 0)
|
if (((mii->mii_media_active & IFM_GMASK) & IFM_FDX) != 0)
|
||||||
gmac |= GM_GPCR_DUP_FULL;
|
gmac |= GM_GPCR_DUP_FULL;
|
||||||
/* Enable Rx flow control. */
|
/* Disable Rx flow control. */
|
||||||
if (((mii->mii_media_active & IFM_GMASK) & IFM_FLAG0) != 0)
|
if (((mii->mii_media_active & IFM_GMASK) & IFM_FLAG0) == 0)
|
||||||
gmac &= ~GM_GPCR_FC_RX_DIS;
|
gmac |= GM_GPCR_FC_RX_DIS;
|
||||||
/* Enable Tx flow control. */
|
/* Disable Tx flow control. */
|
||||||
if (((mii->mii_media_active & IFM_GMASK) & IFM_FLAG1) != 0)
|
if (((mii->mii_media_active & IFM_GMASK) & IFM_FLAG1) == 0)
|
||||||
gmac &= ~GM_GPCR_FC_TX_DIS;
|
gmac |= GM_GPCR_FC_TX_DIS;
|
||||||
gmac |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
|
gmac |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
|
||||||
GMAC_WRITE_2(sc, sc_if->msk_port, GM_GP_CTRL, gmac);
|
GMAC_WRITE_2(sc, sc_if->msk_port, GM_GP_CTRL, gmac);
|
||||||
/* Read again to ensure writing. */
|
/* Read again to ensure writing. */
|
||||||
@ -530,6 +524,7 @@ msk_link_task(void *arg, int pending)
|
|||||||
msk_phy_writereg(sc_if, PHY_ADDR_MARV,
|
msk_phy_writereg(sc_if, PHY_ADDR_MARV,
|
||||||
PHY_MARV_INT_MASK, 0);
|
PHY_MARV_INT_MASK, 0);
|
||||||
/* Disable Rx/Tx MAC. */
|
/* Disable Rx/Tx MAC. */
|
||||||
|
gmac = GMAC_READ_2(sc, sc_if->msk_port, GM_GP_CTRL);
|
||||||
gmac &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
|
gmac &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
|
||||||
GMAC_WRITE_2(sc, sc_if->msk_port, GM_GP_CTRL, gmac);
|
GMAC_WRITE_2(sc, sc_if->msk_port, GM_GP_CTRL, gmac);
|
||||||
/* Read again to ensure writing. */
|
/* Read again to ensure writing. */
|
||||||
|
Loading…
Reference in New Issue
Block a user