Commit 08e2e5fcd2e06670b62e1680a3934c0e55c72810
Committed by
Rafal Jaworowski
1 parent
8d17979d03
Exists in
master
and in
54 other branches
[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>
Showing 1 changed file with 21 additions and 13 deletions Side-by-side Diff
cpu/mpc512x/fec.c
... | ... | @@ -32,6 +32,9 @@ |
32 | 32 | int fec512x_miiphy_write(char *devname, uint8 phyAddr, uint8 regAddr, uint16 data); |
33 | 33 | int mpc512x_fec_init_phy(struct eth_device *dev, bd_t * bis); |
34 | 34 | |
35 | +static uchar rx_buff[FEC_MAX_PKT_SIZE]; | |
36 | +static int rx_buff_idx = 0; | |
37 | + | |
35 | 38 | /********************************************************************/ |
36 | 39 | #if (DEBUG & 0x2) |
37 | 40 | static void mpc512x_fec_phydump (char *devname) |
... | ... | @@ -235,7 +238,7 @@ |
235 | 238 | fec->eth->op_pause = 0x00010020; |
236 | 239 | |
237 | 240 | /* Frame length=1518; MII mode */ |
238 | - fec->eth->r_cntrl = 0x05ee000c; | |
241 | + fec->eth->r_cntrl = 0x05ee0024; | |
239 | 242 | |
240 | 243 | /* Half-duplex, heartbeat disabled */ |
241 | 244 | fec->eth->x_cntrl = 0x00000000; |
... | ... | @@ -520,8 +523,7 @@ |
520 | 523 | mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv; |
521 | 524 | volatile FEC_RBD *pRbd = &fec->bdBase->rbd[fec->rbdIndex]; |
522 | 525 | unsigned long ievent; |
523 | - int frame_length, len = 0; | |
524 | - uchar buff[FEC_MAX_PKT_SIZE]; | |
526 | + int frame_length = 0; | |
525 | 527 | |
526 | 528 | #if (DEBUG & 0x1) |
527 | 529 | printf ("mpc512x_fec_recv %d Start...\n", fec->rbdIndex); |
528 | 530 | |
529 | 531 | |
530 | 532 | |
531 | 533 | |
... | ... | @@ -555,31 +557,37 @@ |
555 | 557 | } |
556 | 558 | |
557 | 559 | if (!(pRbd->status & FEC_RBD_EMPTY)) { |
558 | - if ((pRbd->status & FEC_RBD_LAST) && | |
559 | - !(pRbd->status & FEC_RBD_ERR) && | |
560 | + if (!(pRbd->status & FEC_RBD_ERR) && | |
560 | 561 | ((pRbd->dataLength - 4) > 14)) { |
561 | 562 | |
562 | 563 | /* |
563 | 564 | * Get buffer size |
564 | 565 | */ |
565 | - frame_length = pRbd->dataLength - 4; | |
566 | - | |
566 | + if (pRbd->status & FEC_RBD_LAST) | |
567 | + frame_length = pRbd->dataLength - 4; | |
568 | + else | |
569 | + frame_length = pRbd->dataLength; | |
567 | 570 | #if (DEBUG & 0x20) |
568 | 571 | { |
569 | 572 | int i; |
570 | - printf ("recv data hdr:"); | |
573 | + printf ("recv data length 0x%08x data hdr: ", | |
574 | + pRbd->dataLength); | |
571 | 575 | for (i = 0; i < 14; i++) |
572 | 576 | printf ("%x ", *((uint8*)pRbd->dataPointer + i)); |
573 | 577 | printf("\n"); |
574 | 578 | } |
575 | 579 | #endif |
576 | - | |
577 | 580 | /* |
578 | 581 | * Fill the buffer and pass it to upper layers |
579 | 582 | */ |
580 | - memcpy (buff, (void*)pRbd->dataPointer, frame_length); | |
581 | - NetReceive ((uchar*)buff, frame_length); | |
582 | - len = frame_length; | |
583 | + memcpy (&rx_buff[rx_buff_idx], (void*)pRbd->dataPointer, | |
584 | + frame_length - rx_buff_idx); | |
585 | + rx_buff_idx = frame_length; | |
586 | + | |
587 | + if (pRbd->status & FEC_RBD_LAST) { | |
588 | + NetReceive ((uchar*)rx_buff, frame_length); | |
589 | + rx_buff_idx = 0; | |
590 | + } | |
583 | 591 | } |
584 | 592 | |
585 | 593 | /* |
... | ... | @@ -590,7 +598,7 @@ |
590 | 598 | |
591 | 599 | /* Try to fill Buffer Descriptors */ |
592 | 600 | fec->eth->r_des_active = 0x01000000; /* Descriptor polling active */ |
593 | - return len; | |
601 | + return frame_length; | |
594 | 602 | } |
595 | 603 | |
596 | 604 | /********************************************************************/ |