diff options
author | Anton Vorontsov <avorontsov@mvista.com> | 2010-06-30 02:39:12 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-30 14:35:42 -0400 |
commit | 7d3509774c2ef4ffd1c5fd2fac65dc4e071a6f21 (patch) | |
tree | 54d32c6f6f6c72fee208ab8dea9879697b613765 /drivers/net/gianfar.c | |
parent | 70777d03466e7a8a41b0d34677454c92f4e93d89 (diff) |
gianfar: Implement workaround for eTSEC74 erratum
MPC8313ECE says:
"If MACCFG2[Huge Frame]=0 and the Ethernet controller receives frames
which are larger than MAXFRM, the controller truncates the frames to
length MAXFRM and marks RxBD[TR]=1 to indicate the error. The controller
also erroneously marks RxBD[TR]=1 if the received frame length is MAXFRM
or MAXFRM-1, even though those frames are not truncated.
No truncation or truncation error occurs if MACCFG2[Huge Frame]=1."
There are two options to workaround the issue:
"1. Set MACCFG2[Huge Frame]=1, so no truncation occurs for invalid large
frames. Software can determine if a frame is larger than MAXFRM by
reading RxBD[LG] or RxBD[Data Length].
2. Set MAXFRM to 1538 (0x602) instead of the default 1536 (0x600), so
normal-length frames are not marked as truncated. Software can examine
RxBD[Data Length] to determine if the frame was larger than MAXFRM-2."
This patch implements the first workaround option by setting HUGEFRAME
bit, and gfar_clean_rx_ring() already checks the RxBD[Data Length].
Signed-off-by: Anton Vorontsov <avorontsov@mvista.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/gianfar.c')
-rw-r--r-- | drivers/net/gianfar.c | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index c52f3712ecd3..cee8ae714731 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -85,6 +85,7 @@ | |||
85 | #include <linux/net_tstamp.h> | 85 | #include <linux/net_tstamp.h> |
86 | 86 | ||
87 | #include <asm/io.h> | 87 | #include <asm/io.h> |
88 | #include <asm/reg.h> | ||
88 | #include <asm/irq.h> | 89 | #include <asm/irq.h> |
89 | #include <asm/uaccess.h> | 90 | #include <asm/uaccess.h> |
90 | #include <linux/module.h> | 91 | #include <linux/module.h> |
@@ -928,6 +929,24 @@ static void gfar_init_filer_table(struct gfar_private *priv) | |||
928 | } | 929 | } |
929 | } | 930 | } |
930 | 931 | ||
932 | static void gfar_detect_errata(struct gfar_private *priv) | ||
933 | { | ||
934 | struct device *dev = &priv->ofdev->dev; | ||
935 | unsigned int pvr = mfspr(SPRN_PVR); | ||
936 | unsigned int svr = mfspr(SPRN_SVR); | ||
937 | unsigned int mod = (svr >> 16) & 0xfff6; /* w/o E suffix */ | ||
938 | unsigned int rev = svr & 0xffff; | ||
939 | |||
940 | /* MPC8313 Rev 2.0 and higher; All MPC837x */ | ||
941 | if ((pvr == 0x80850010 && mod == 0x80b0 && rev >= 0x0020) || | ||
942 | (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0)) | ||
943 | priv->errata |= GFAR_ERRATA_74; | ||
944 | |||
945 | if (priv->errata) | ||
946 | dev_info(dev, "enabled errata workarounds, flags: 0x%x\n", | ||
947 | priv->errata); | ||
948 | } | ||
949 | |||
931 | /* Set up the ethernet device structure, private data, | 950 | /* Set up the ethernet device structure, private data, |
932 | * and anything else we need before we start */ | 951 | * and anything else we need before we start */ |
933 | static int gfar_probe(struct of_device *ofdev, | 952 | static int gfar_probe(struct of_device *ofdev, |
@@ -960,6 +979,8 @@ static int gfar_probe(struct of_device *ofdev, | |||
960 | dev_set_drvdata(&ofdev->dev, priv); | 979 | dev_set_drvdata(&ofdev->dev, priv); |
961 | regs = priv->gfargrp[0].regs; | 980 | regs = priv->gfargrp[0].regs; |
962 | 981 | ||
982 | gfar_detect_errata(priv); | ||
983 | |||
963 | /* Stop the DMA engine now, in case it was running before */ | 984 | /* Stop the DMA engine now, in case it was running before */ |
964 | /* (The firmware could have used it, and left it running). */ | 985 | /* (The firmware could have used it, and left it running). */ |
965 | gfar_halt(dev); | 986 | gfar_halt(dev); |
@@ -974,7 +995,10 @@ static int gfar_probe(struct of_device *ofdev, | |||
974 | gfar_write(®s->maccfg1, tempval); | 995 | gfar_write(®s->maccfg1, tempval); |
975 | 996 | ||
976 | /* Initialize MACCFG2. */ | 997 | /* Initialize MACCFG2. */ |
977 | gfar_write(®s->maccfg2, MACCFG2_INIT_SETTINGS); | 998 | tempval = MACCFG2_INIT_SETTINGS; |
999 | if (gfar_has_errata(priv, GFAR_ERRATA_74)) | ||
1000 | tempval |= MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK; | ||
1001 | gfar_write(®s->maccfg2, tempval); | ||
978 | 1002 | ||
979 | /* Initialize ECNTRL */ | 1003 | /* Initialize ECNTRL */ |
980 | gfar_write(®s->ecntrl, ECNTRL_INIT_SETTINGS); | 1004 | gfar_write(®s->ecntrl, ECNTRL_INIT_SETTINGS); |
@@ -2300,7 +2324,8 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu) | |||
2300 | * to allow huge frames, and to check the length */ | 2324 | * to allow huge frames, and to check the length */ |
2301 | tempval = gfar_read(®s->maccfg2); | 2325 | tempval = gfar_read(®s->maccfg2); |
2302 | 2326 | ||
2303 | if (priv->rx_buffer_size > DEFAULT_RX_BUFFER_SIZE) | 2327 | if (priv->rx_buffer_size > DEFAULT_RX_BUFFER_SIZE || |
2328 | gfar_has_errata(priv, GFAR_ERRATA_74)) | ||
2304 | tempval |= (MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK); | 2329 | tempval |= (MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK); |
2305 | else | 2330 | else |
2306 | tempval &= ~(MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK); | 2331 | tempval &= ~(MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK); |