summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorClaudiu Manoil <claudiu.manoil@freescale.com>2013-07-30 08:40:04 (GMT)
committerFleming Andrew-AFLEMING <AFLEMING@freescale.com>2013-08-07 21:51:01 (GMT)
commitb3698257aac8d5b8db58535037575812b6208f79 (patch)
treefbd0e3d87f972c0795dab7e15192061a59836e98 /drivers/net
parenta8d022f84c57846be4b39ff740f86c8454c78b52 (diff)
downloadlinux-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/net')
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c31
-rw-r--r--drivers/net/ethernet/freescale/gianfar.h2
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(&regs->maccfg1, tempval);
+ /* the soft reset bit is not self-resetting, so we need to
+ * clear it before resuming normal operation
+ */
+ gfar_write(&regs->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(&regs->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(&regs->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];