diff options
author | Claudiu Manoil <claudiu.manoil@freescale.com> | 2013-07-30 08:40:04 (GMT) |
---|---|---|
committer | Fleming Andrew-AFLEMING <AFLEMING@freescale.com> | 2013-08-07 21:51:01 (GMT) |
commit | b3698257aac8d5b8db58535037575812b6208f79 (patch) | |
tree | fbd0e3d87f972c0795dab7e15192061a59836e98 /drivers | |
parent | a8d022f84c57846be4b39ff740f86c8454c78b52 (diff) | |
download | linux-fsl-qoriq-b3698257aac8d5b8db58535037575812b6208f79.tar.xz |
gianfar: Fix pause frame handling for half duplex links
MACCFG1 register bits to enable PAUSE frame handling are set by the
driver unconditionally. Per 802.3 standard, PAUSE frame handling is a
full duplex feature, and neither meaningful nor correct in half duplex.
Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com>
Change-Id: I3066169b9e96f1c29391ac7636a26ca4152129c3
Reviewed-on: http://git.am.freescale.net:8181/3650
Reviewed-by: Bucur Madalin-Cristian-B32716 <madalin.bucur@freescale.com>
Reviewed-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Tested-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/freescale/gianfar.c | 31 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/gianfar.h | 2 |
2 files changed, 31 insertions, 2 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index eb60e10..8e3b8e5 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -902,6 +902,9 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) FSL_GIANFAR_DEV_HAS_EXTENDED_HASH | FSL_GIANFAR_DEV_HAS_36BIT_ADDR; + /* default pause frame settings */ + priv->rx_pause = priv->tx_pause = true; + ctype = of_get_property(np, "phy-connection-type", NULL); /* We only care about rgmii-id. The rest are autodetected */ @@ -1232,8 +1235,10 @@ static int gfar_probe(struct platform_device *ofdev) /* We need to delay at least 3 TX clocks */ udelay(2); - tempval = (MACCFG1_TX_FLOW | MACCFG1_RX_FLOW); - gfar_write(®s->maccfg1, tempval); + /* the soft reset bit is not self-resetting, so we need to + * clear it before resuming normal operation + */ + gfar_write(®s->maccfg1, 0); /* Initialize MACCFG2. */ tempval = MACCFG2_INIT_SETTINGS; @@ -3983,6 +3988,25 @@ static irqreturn_t gfar_interrupt(int irq, void *grp_id) return IRQ_HANDLED; } +/* toggle pause frame settings */ +void gfar_configure_pause(struct gfar_private *priv, bool en) +{ + struct gfar __iomem *regs = priv->gfargrp[0].regs; + u32 tempval = gfar_read(®s->maccfg1); + + if (en && priv->rx_pause) + tempval |= MACCFG1_RX_FLOW; + else + tempval &= ~MACCFG1_RX_FLOW; + + if (en && priv->tx_pause) + tempval |= MACCFG1_TX_FLOW; + else + tempval &= ~MACCFG1_TX_FLOW; + + gfar_write(®s->maccfg1, tempval); +} + /* Called every time the controller might need to be made * aware of new link state. The PHY code conveys this * information through variables in the phydev structure, and this @@ -4014,6 +4038,9 @@ static void adjust_link(struct net_device *dev) else tempval |= MACCFG2_FULL_DUPLEX; + /* update pause frame settings */ + gfar_configure_pause(priv, !!phydev->duplex); + priv->oldduplex = phydev->duplex; } diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h index a856230..3909ef6 100644 --- a/drivers/net/ethernet/freescale/gianfar.h +++ b/drivers/net/ethernet/freescale/gianfar.h @@ -1319,6 +1319,8 @@ struct gfar_private { int oldspeed; int oldduplex; int oldlink; + bool rx_pause; + bool tx_pause; struct gfar_irqinfo *irqinfo[MAXGROUPS][GFAR_NUM_IRQS]; |