]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
[MPC512x] Proper handling of larger frames in the FEC driver
authorGrzegorz Bernacki <gjb@semihalf.com>
Fri, 7 Sep 2007 15:09:21 +0000 (17:09 +0200)
committerRafal Jaworowski <raj@semihalf.com>
Fri, 7 Sep 2007 15:09:21 +0000 (17:09 +0200)
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>
cpu/mpc512x/fec.c

index 3c142a9e58b936240c7bd11ba7659044ef7b4e88..8104576177c5c63b963b4abd1ad9e7a6ef1ffa2c 100644 (file)
@@ -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);
 
 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)
 /********************************************************************/
 #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->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;
 
        /* 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;
        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);
 
 #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_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
                         */
                        ((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;
 #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
                                for (i = 0; i < 14; i++)
                                        printf ("%x ", *((uint8*)pRbd->dataPointer + i));
                                printf("\n");
                        }
 #endif
-
                        /*
                         *  Fill the buffer and pass it to upper layers
                         */
                        /*
                         *  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 */
 
        /* Try to fill Buffer Descriptors */
        fec->eth->r_des_active = 0x01000000;    /* Descriptor polling active */
-       return len;
+       return frame_length;
 }
 
 /********************************************************************/
 }
 
 /********************************************************************/