summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrzegorz Bernacki <gjb@semihalf.com>2007-09-07 17:09:21 +0200
committerRafal Jaworowski <raj@semihalf.com>2007-09-07 17:09:21 +0200
commit08e2e5fcd2e06670b62e1680a3934c0e55c72810 (patch)
tree92988fe44f332772ec304765efc694652099ae78
parent8d17979d0359492a822a0a409d26e3a3549b4cd4 (diff)
downloadtalos-obmc-uboot-08e2e5fcd2e06670b62e1680a3934c0e55c72810.tar.gz
talos-obmc-uboot-08e2e5fcd2e06670b62e1680a3934c0e55c72810.zip
[MPC512x] Proper handling of larger frames in the FEC driver
When frame larger than local RX buffer is received, it is split and handled by two buffer descriptors. Prior to this patch the FEC driver discarded contents of a buffer descriptor without the 'LAST' bit set, so the first part of the frame was lost in case of larger frames. This fix allows to safely combine the two pieces into the whole frame. Signed-off-by: Grzegorz Bernacki <gjb@semihalf.com>
-rw-r--r--cpu/mpc512x/fec.c34
1 files changed, 21 insertions, 13 deletions
diff --git a/cpu/mpc512x/fec.c b/cpu/mpc512x/fec.c
index 3c142a9e58..8104576177 100644
--- a/cpu/mpc512x/fec.c
+++ b/cpu/mpc512x/fec.c
@@ -32,6 +32,9 @@ int fec512x_miiphy_read(char *devname, uint8 phyAddr, uint8 regAddr, uint16 * re
int fec512x_miiphy_write(char *devname, uint8 phyAddr, uint8 regAddr, uint16 data);
int mpc512x_fec_init_phy(struct eth_device *dev, bd_t * bis);
+static uchar rx_buff[FEC_MAX_PKT_SIZE];
+static int rx_buff_idx = 0;
+
/********************************************************************/
#if (DEBUG & 0x2)
static void mpc512x_fec_phydump (char *devname)
@@ -235,7 +238,7 @@ static int mpc512x_fec_init (struct eth_device *dev, bd_t * bis)
fec->eth->op_pause = 0x00010020;
/* Frame length=1518; MII mode */
- fec->eth->r_cntrl = 0x05ee000c;
+ fec->eth->r_cntrl = 0x05ee0024;
/* Half-duplex, heartbeat disabled */
fec->eth->x_cntrl = 0x00000000;
@@ -520,8 +523,7 @@ static int mpc512x_fec_recv (struct eth_device *dev)
mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv;
volatile FEC_RBD *pRbd = &fec->bdBase->rbd[fec->rbdIndex];
unsigned long ievent;
- int frame_length, len = 0;
- uchar buff[FEC_MAX_PKT_SIZE];
+ int frame_length = 0;
#if (DEBUG & 0x1)
printf ("mpc512x_fec_recv %d Start...\n", fec->rbdIndex);
@@ -555,31 +557,37 @@ static int mpc512x_fec_recv (struct eth_device *dev)
}
if (!(pRbd->status & FEC_RBD_EMPTY)) {
- if ((pRbd->status & FEC_RBD_LAST) &&
- !(pRbd->status & FEC_RBD_ERR) &&
+ if (!(pRbd->status & FEC_RBD_ERR) &&
((pRbd->dataLength - 4) > 14)) {
/*
* Get buffer size
*/
- frame_length = pRbd->dataLength - 4;
-
+ if (pRbd->status & FEC_RBD_LAST)
+ frame_length = pRbd->dataLength - 4;
+ else
+ frame_length = pRbd->dataLength;
#if (DEBUG & 0x20)
{
int i;
- printf ("recv data hdr:");
+ printf ("recv data length 0x%08x data hdr: ",
+ pRbd->dataLength);
for (i = 0; i < 14; i++)
printf ("%x ", *((uint8*)pRbd->dataPointer + i));
printf("\n");
}
#endif
-
/*
* Fill the buffer and pass it to upper layers
*/
- memcpy (buff, (void*)pRbd->dataPointer, frame_length);
- NetReceive ((uchar*)buff, frame_length);
- len = frame_length;
+ memcpy (&rx_buff[rx_buff_idx], (void*)pRbd->dataPointer,
+ frame_length - rx_buff_idx);
+ rx_buff_idx = frame_length;
+
+ if (pRbd->status & FEC_RBD_LAST) {
+ NetReceive ((uchar*)rx_buff, frame_length);
+ rx_buff_idx = 0;
+ }
}
/*
@@ -590,7 +598,7 @@ static int mpc512x_fec_recv (struct eth_device *dev)
/* Try to fill Buffer Descriptors */
fec->eth->r_des_active = 0x01000000; /* Descriptor polling active */
- return len;
+ return frame_length;
}
/********************************************************************/
OpenPOWER on IntegriCloud