diff options
author | David S. Miller <[email protected]> | 2016-11-09 18:45:36 -0500 |
---|---|---|
committer | David S. Miller <[email protected]> | 2016-11-09 18:45:36 -0500 |
commit | fd6f24d75ab07fd122c2910d343caa703f712873 (patch) | |
tree | 22ef540a7817db2a24cc612ecd9dd71b973ea92e | |
parent | cdb26d3387f0cdf7b2a2eea581385173547ef21f (diff) | |
parent | df63022e182de4041b65ae22df1950d3416b577e (diff) |
Merge branch 'qcom-emac-pause'
Timur Tabi says:
====================
net: qcom/emac: ensure that pause frames are enabled
The qcom emac driver experiences significant packet loss (through frame
check sequence errors) if flow control is not enabled and the phy is
not configured to allow pause frames to pass through it. Therefore, we
need to enable flow control and force the phy to pass pause frames.
====================
Signed-off-by: David S. Miller <[email protected]>
-rw-r--r-- | drivers/net/ethernet/qualcomm/emac/emac-mac.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-mac.c b/drivers/net/ethernet/qualcomm/emac/emac-mac.c index 6fb3bee904d3..0b4deb31e742 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac-mac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac-mac.c @@ -575,10 +575,11 @@ void emac_mac_start(struct emac_adapter *adpt) mac |= TXEN | RXEN; /* enable RX/TX */ - /* We don't have ethtool support yet, so force flow-control mode - * to 'full' always. - */ - mac |= TXFC | RXFC; + /* Configure MAC flow control to match the PHY's settings. */ + if (phydev->pause) + mac |= RXFC; + if (phydev->pause != phydev->asym_pause) + mac |= TXFC; /* setup link speed */ mac &= ~SPEED_MASK; @@ -1003,6 +1004,12 @@ int emac_mac_up(struct emac_adapter *adpt) writel((u32)~DIS_INT, adpt->base + EMAC_INT_STATUS); writel(adpt->irq.mask, adpt->base + EMAC_INT_MASK); + /* Enable pause frames. Without this feature, the EMAC has been shown + * to receive (and drop) frames with FCS errors at gigabit connections. + */ + adpt->phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; + adpt->phydev->advertising |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; + adpt->phydev->irq = PHY_IGNORE_INTERRUPT; phy_start(adpt->phydev); |