Changeset a19b915 in rtems


Ignore:
Timestamp:
Dec 11, 2013, 10:35:10 AM (6 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
14e1c677
Parents:
6eb1733
git-author:
Sebastian Huber <sebastian.huber@…> (12/11/13 10:35:10)
git-committer:
Sebastian Huber <sebastian.huber@…> (12/16/13 14:15:42)
Message:

bsp/genmcf548x: Fix network FIFO error handling

Use a buffer handling similar to the MPC5200B FEC driver to cope with
FIFO errors.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/m68k/genmcf548x/network/network.c

    r6eb1733 ra19b915  
    3737 *
    3838 */
     39
    3940#include <rtems.h>
    4041#include <rtems/error.h>
     
    6061#include <mcf548x/mcdma_glue.h>
    6162
    62 #define ETH_PROMISCOUS_MODE 1 /* FIXME: remove me */
    63 
    6463/*
    6564 * Number of interfaces supported by this driver
     
    6867
    6968#define FEC_WATCHDOG_TIMEOUT 5 /* check media every 5 seconds */
    70 /*
    71  * buffer descriptor handling
    72  */
    73 
    74 #define SET_BD_STATUS(bd, stat) {               \
    75     (bd)->statCtrl = stat;                      \
    76 }
    77 #define SET_BD_LENGTH(bd, len) {                \
    78     (bd)->length = len;                         \
    79 }
    80 #define SET_BD_BUFFER(bd, buf) {                \
    81     (bd)->dataPointer= (uint32_t)(buf);         \
    82 }
    83 #define GET_BD_STATUS(bd)               ((bd)->statCtrl)
    84 #define GET_BD_LENGTH(bd)               ((bd)->length)
    85 #define GET_BD_BUFFER(bd)               ((void *)((bd)->dataPointer))
    8669
    8770#define DMA_BD_RX_NUM   32 /* Number of receive buffer descriptors      */
    8871#define DMA_BD_TX_NUM   32 /* Number of transmit buffer descriptors     */
     72
     73#define FEC_EVENT RTEMS_EVENT_0
    8974
    9075/*
     
    133118                                         /(MCF548X_FEC1_IRQ_VECTOR      \
    134119                                           -MCF548X_FEC0_IRQ_VECTOR))
    135 
    136 #define FEC_RECV_TASK_NO        4
    137 #define FEC_XMIT_TASK_NO        5
    138120
    139121#define MCDMA_FEC_RX_CHAN(chan) (0 + NIFACES*(chan))
     
    150132                                      +(chan)*(MCF548X_FEC1_TX_INITIATOR        \
    151133                                               -MCF548X_FEC0_TX_INITIATOR))
    152 
    153 /*
    154  * RTEMS event used by interrupt handler to signal daemons.
    155  * This must *not* be the same event used by the TCP/IP task synchronization.
    156  */
    157 #define INTERRUPT_EVENT RTEMS_EVENT_1
    158 #define FATAL_INT_EVENT RTEMS_EVENT_3
    159 
    160 /*
    161  * RTEMS event used to start transmit daemon.
    162  * This must not be the same as INTERRUPT_EVENT.
    163  */
    164 #define START_TRANSMIT_EVENT RTEMS_EVENT_2
    165134
    166135/* BD and parameters are stored in SRAM(refer to sdma.h) */
     
    199168 MCF548X_FEC_EIMR_XFUN | MCF548X_FEC_EIMR_XFERR | MCF548X_FEC_EIMR_RFERR)
    200169
     170typedef enum {
     171  FEC_STATE_RESTART_0,
     172  FEC_STATE_RESTART_1,
     173  FEC_STATE_NORMAL,
     174} fec_state;
     175
    201176/*
    202177 * Device data
     
    207182  struct mbuf             **txMbuf;
    208183  int                     chan;
     184  fec_state               state;
    209185  int                     acceptBroadcast;
    210186  int                     rxBdCount;
    211187  int                     txBdCount;
    212   int                     txBdHead;
    213   int                     txBdTail;
    214   int                     txBdActiveCount;
    215188  MCD_bufDescFec          *rxBd;
    216189  MCD_bufDescFec          *txBd;
     
    233206  unsigned long           rxNonOctet;
    234207  unsigned long           rxBadCRC;
    235   unsigned long           rxOverrun;
     208  unsigned long           rxFIFOError;
    236209  unsigned long           rxCollision;
    237210
     
    240213  unsigned long           txLateCollision;
    241214  unsigned long           txUnderrun;
     215  unsigned long           txFIFOError;
    242216  unsigned long           txMisaligned;
    243217  unsigned long           rxNotFirst;
     
    247221static struct mcf548x_enet_struct enet_driver[NIFACES];
    248222
    249 extern int taskTable;
    250 static void mcf548x_fec_restart(struct mcf548x_enet_struct *sc);
    251 
    252 
    253 
    254 /*
    255  * Function:    mcf548x_fec_rx_bd_init
    256  *
    257  * Description: Initialize the receive buffer descriptor ring.
    258  *
    259  * Returns:             void
    260  *
    261  * Notes:       Space for the buffers of rx BDs is allocated by the rx deamon
    262  *
    263  */
    264 static void mcf548x_fec_rx_bd_init(struct mcf548x_enet_struct *sc) {
    265   int rxBdIndex;
    266   struct mbuf *m;
    267   struct ifnet *ifp = &sc->arpcom.ac_if;
    268 
    269   /*
    270    * Fill RX buffer descriptor ring.
    271    */
    272   for( rxBdIndex = 0; rxBdIndex < sc->rxBdCount; rxBdIndex++ ) {
    273     MGETHDR (m, M_WAIT, MT_DATA);
    274     MCLGET (m, M_WAIT);
    275 
    276     m->m_pkthdr.rcvif = ifp;
    277     sc->rxMbuf[rxBdIndex] = m;
    278     rtems_cache_invalidate_multiple_data_lines(mtod(m,const void *),
    279                                                ETHER_MAX_LEN);
    280     SET_BD_BUFFER(sc->rxBd+rxBdIndex,mtod(m, void *));
    281     SET_BD_LENGTH(sc->rxBd+rxBdIndex,ETHER_MAX_LEN);
    282     SET_BD_STATUS(sc->rxBd+rxBdIndex,
    283                   MCF548X_FEC_RBD_EMPTY
    284                   | MCF548X_FEC_RBD_INT
    285                   | ((rxBdIndex == sc->rxBdCount-1)
    286                      ? MCF548X_FEC_RBD_WRAP
    287                      : 0));
    288   }
    289 }
    290 
    291 /*
    292  * Function:    mcf548x_fec_rx_bd_cleanup
    293  *
    294  * Description: put all mbufs pending in rx BDs back to buffer pool
    295  *
    296  * Returns:             void
    297  *
    298  */
    299 static void mcf548x_fec_rx_bd_cleanup(struct mcf548x_enet_struct *sc) {
    300   int rxBdIndex;
    301   struct mbuf *m,*n;
    302 
    303   /*
    304    * Drain RX buffer descriptor ring.
    305    */
    306   for( rxBdIndex = 0; rxBdIndex < sc->rxBdCount; rxBdIndex++ ) {
    307     n = sc->rxMbuf[rxBdIndex];
    308     while (n != NULL) {
    309       m = n;
    310       MFREE(m,n);
    311     }
    312   }
     223static void mcf548x_fec_restart(struct mcf548x_enet_struct *sc, rtems_id otherDaemon);
     224
     225static void fec_send_event(rtems_id task)
     226{
     227  rtems_bsdnet_event_send(task, FEC_EVENT);
     228}
     229
     230static void fec_wait_for_event(void)
     231{
     232  rtems_event_set out;
     233  rtems_bsdnet_event_receive(
     234    FEC_EVENT,
     235    RTEMS_EVENT_ANY | RTEMS_WAIT,
     236    RTEMS_NO_TIMEOUT,
     237    &out
     238  );
     239}
     240
     241static void mcf548x_fec_request_restart(struct mcf548x_enet_struct *sc)
     242{
     243  sc->state = FEC_STATE_RESTART_0;
     244  fec_send_event(sc->txDaemonTid);
     245  fec_send_event(sc->rxDaemonTid);
    313246}
    314247
     
    350283  * as a shift-register with as many ex-ores as the radixes
    351284  * in the polynomium. This suggests that we represent the
    352   * polynomiumm itself as a 32-bit constant.
     285  * polynomiumm itsc as a 32-bit constant.
    353286  */
    354287  for(byte = 0; byte < 6; byte++)
     
    540473 *
    541474 */
    542 static int mcf548x_fec_reset(struct mcf548x_enet_struct *sc) {
     475static void mcf548x_fec_reset(struct mcf548x_enet_struct *sc) {
    543476  volatile int delay;
    544477  int chan     = sc->chan;
     
    567500   */
    568501  for (delay = 0;delay < 16*4;delay++) {};
    569 
    570   return true;
    571502}
    572503
     
    648579  */
    649580  MCF548X_FEC_ECR(chan) &= ~(MCF548X_FEC_ECR_ETHER_EN);
    650 
    651   /*
    652    * cleanup all buffers
    653    */
    654   mcf548x_fec_rx_bd_cleanup(sc);
    655 
    656   }
     581}
    657582
    658583/*
     
    683608  }
    684609  if (ievent & MCF548X_FEC_EIR_XFERR) {
    685     sc->txUnderrun++;
     610    sc->txFIFOError++;
    686611  }
    687612  if (ievent & MCF548X_FEC_EIR_RFERR) {
    688     sc->rxOverrun++;
     613    sc->rxFIFOError++;
    689614  }
    690615  /*
     
    693618  if (ievent & (MCF548X_FEC_EIR_RFERR | MCF548X_FEC_EIR_XFERR)) {
    694619    MCF548X_FEC_EIMR(chan) &=~(MCF548X_FEC_EIMR_RFERR | MCF548X_FEC_EIMR_XFERR);
    695     rtems_bsdnet_event_send(sc->rxDaemonTid, FATAL_INT_EVENT);
     620    printk("fifo\n");
     621    mcf548x_fec_request_restart(sc);
    696622  }
    697623}
     
    709635    mcdma_glue_irq_disable(sc->rxDmaChan);/*Disable receive ints*/
    710636    sc->rxInterrupts++;                 /* Rx int has occurred */
    711     rtems_bsdnet_event_send(sc->rxDaemonTid, INTERRUPT_EVENT);
     637    fec_send_event(sc->rxDaemonTid);
    712638  }
    713639}
     
    729655    sc->txInterrupts++; /* Tx int has occurred */
    730656
    731     rtems_bsdnet_event_send(sc->txDaemonTid, INTERRUPT_EVENT);
    732   }
    733 }
    734 
    735 
    736 
    737 
    738 
    739  /*
    740   * Function:       mcf548x_fec_retire_tbd
    741   *
    742   * Description:        Soak up buffer descriptors that have been sent.
    743   *
    744   * Returns:            void
    745   *
    746   * Notes:
    747   *
    748   */
    749 static void mcf548x_fec_retire_tbd(struct mcf548x_enet_struct *sc,
    750                                    bool force)
    751 {
    752   struct mbuf *n;
    753   /*
    754    * Clear already transmitted BDs first. Will not work calling same
    755    * from fecExceptionHandler(TFINT).
    756    */
    757 
    758   while ((sc->txBdActiveCount > 0) &&
    759          (force ||
    760           ((MCF548X_FEC_TBD_READY & GET_BD_STATUS(sc->txBd+sc->txBdTail))
    761            == 0x0))) {
    762     if (sc->txMbuf[sc->txBdTail] != NULL) {
    763       /*
    764        * NOTE: txMbuf can be NULL, if mbuf has been split into different BDs
    765        */
    766       MFREE (sc->txMbuf[sc->txBdTail],n);
    767       sc->txMbuf[sc->txBdTail] = NULL;
    768     }
    769     sc->txBdActiveCount--;
    770     if(++sc->txBdTail >= sc->txBdCount) {
    771       sc->txBdTail = 0;
    772     }
    773   }
    774 }
    775 
    776 
    777 static void mcf548x_fec_sendpacket(struct ifnet *ifp,struct mbuf *m) {
    778   struct mcf548x_enet_struct *sc = ifp->if_softc;
    779   struct mbuf *l = NULL;
    780   int nAdded;
    781   uint32_t status;
    782   rtems_event_set events;
    783   MCD_bufDescFec *thisBd;
    784   MCD_bufDescFec *firstBd = NULL;
    785   void *data_ptr;
    786   size_t data_len;
    787 
    788  /*
    789   * Free up buffer descriptors
    790   */
    791   mcf548x_fec_retire_tbd(sc,false);
    792 
    793  /*
    794   * Set up the transmit buffer descriptors.
    795   * No need to pad out short packets since the
    796   * hardware takes care of that automatically.
    797   * No need to copy the packet to a contiguous buffer
    798   * since the hardware is capable of scatter/gather DMA.
    799   */
    800   nAdded = 0;
    801 
    802   for(;;) {
    803 
    804    /*
    805     * Wait for buffer descriptor to become available.
    806     */
    807     if((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
    808 
    809       /*
    810        * Clear old events
    811        */
    812       MCDMA_CLR_PENDING(sc->txDmaChan);
    813       /*
    814        * Wait for buffer descriptor to become available.
    815        * Note that the buffer descriptors are checked
    816        * *before* * entering the wait loop -- this catches
    817        * the possibility that a buffer descriptor became
    818        * available between the `if' above, and the clearing
    819        * of the event register.
    820        * This is to catch the case where the transmitter
    821        * stops in the middle of a frame -- and only the
    822        * last buffer descriptor in a frame can generate
    823        * an interrupt.
    824        */
    825       mcf548x_fec_retire_tbd(sc,false);
    826 
    827       while((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
    828         mcdma_glue_irq_enable(sc->txDmaChan);
    829         rtems_bsdnet_event_receive(INTERRUPT_EVENT,
    830                                    RTEMS_WAIT | RTEMS_EVENT_ANY,
    831                                    RTEMS_NO_TIMEOUT, &events);
    832         mcf548x_fec_retire_tbd(sc,false);
    833       }
    834     }
    835 
    836     if(m->m_len == 0) {
    837       /*
    838        * Just toss empty mbufs
    839        */
    840       struct mbuf *n;
    841       MFREE(m, n);
    842       m = n;
    843       if(l != NULL) {
    844         l->m_next = m;
    845       }
    846     }
    847     else {
    848       /*
    849        * Flush the buffer for this descriptor
    850        */
    851       rtems_cache_flush_multiple_data_lines((const void *)mtod(m, void *),
    852                                             m->m_len);
    853       /*
    854        * Fill in the buffer descriptor,
    855        * set "end of frame" bit in status,
    856        * if last mbuf in chain
    857        */
    858       thisBd = sc->txBd + sc->txBdHead;
    859       /*
    860        * FIXME: do not send interrupt after every frame
    861        * doing this every quarter of BDs is much more efficent
    862        */
    863       status = (((m->m_next == NULL)
    864                  ? MCF548X_FEC_TBD_LAST | MCF548X_FEC_TBD_INT
    865                  : 0)
    866                 | ((sc->txBdHead == sc->txBdCount-1)
    867                    ? MCF548X_FEC_TBD_WRAP
    868                    :0 ));
    869       /*
    870        * Don't set the READY flag till the
    871        * whole packet has been readied.
    872        */
    873       if (firstBd != NULL) {
    874         status |= MCF548X_FEC_TBD_READY;
    875       }
    876       else {
    877         firstBd = thisBd;
    878       }
    879 
    880       data_ptr = mtod(m, void *);
    881       data_len = m->m_len;
    882       sc->txMbuf[sc->txBdHead] = m;
    883       /* go to next part in chain */
    884       l = m;
    885       m = m->m_next;
    886 
    887       SET_BD_BUFFER(thisBd, data_ptr);
    888       SET_BD_LENGTH(thisBd, data_len);
    889       SET_BD_STATUS(thisBd, status);
    890 
    891       nAdded++;
    892       if(++(sc->txBdHead) == sc->txBdCount) {
    893         sc->txBdHead = 0;
    894       }
    895     }
    896     /*
    897      * Set the transmit buffer status.
    898      * Break out of the loop if this mbuf is the last in the frame.
    899      */
    900     if(m == NULL) {
    901       if(nAdded) {
    902         SET_BD_STATUS(firstBd,
    903                       GET_BD_STATUS(firstBd) | MCF548X_FEC_TBD_READY);
    904         MCD_continDma(sc->txDmaChan);
    905         sc->txBdActiveCount += nAdded;
    906       }
    907       break;
    908     }
    909   } /* end of for(;;) */
    910 }
    911 
    912 
    913 /*
    914  * Driver transmit daemon
    915  */
    916 void mcf548x_fec_txDaemon(void *arg)
    917   {
    918   struct mcf548x_enet_struct *sc = (struct mcf548x_enet_struct *)arg;
    919   struct ifnet *ifp = &sc->arpcom.ac_if;
    920   struct mbuf *m;
    921   rtems_event_set events;
    922 
    923   for(;;) {
    924    /*
    925     * Wait for packet
    926     */
    927     mcdma_glue_irq_enable(sc->txDmaChan);
    928     rtems_bsdnet_event_receive(START_TRANSMIT_EVENT|INTERRUPT_EVENT,
    929                                RTEMS_EVENT_ANY | RTEMS_WAIT,
    930                                RTEMS_NO_TIMEOUT,
    931                                &events);
    932 
    933     /*
    934      * Send packets till queue is empty
    935      */
    936     for(;;)
    937       {
    938 
    939       /*
    940        * Get the next mbuf chain to transmit.
    941        */
    942       IF_DEQUEUE(&ifp->if_snd, m);
    943 
    944       if (!m)
    945         break;
    946 
    947       mcf548x_fec_sendpacket(ifp, m);
    948 
    949       }
    950 
    951     ifp->if_flags &= ~IFF_OACTIVE;
    952 
    953     }
    954 
    955   }
    956 
    957 
    958 /*
    959  * reader task
    960  */
    961 static void mcf548x_fec_rxDaemon(void *arg){
    962   struct mcf548x_enet_struct *sc = (struct mcf548x_enet_struct *)arg;
    963   struct ifnet *ifp = &sc->arpcom.ac_if;
    964   struct mbuf *m;
    965   struct ether_header *eh;
    966   int rxBdIndex;
    967   uint32_t status;
    968   size_t size;
    969   rtems_event_set events;
    970   size_t len = 1;
    971   MCD_bufDescFec *bd;
    972 
    973   /*
    974    * Input packet handling loop
    975    */
    976   rxBdIndex = 0;
    977 
    978   for (;;) {
    979     /*
    980      * Clear old events
    981      */
    982     MCDMA_CLR_PENDING(sc->rxDmaChan);
    983     /*
    984      * Get the first BD pointer and its length.
    985      */
    986     bd     = sc->rxBd + rxBdIndex;
    987     status = GET_BD_STATUS( bd );
    988     len    = GET_BD_LENGTH( bd );
    989 
    990     /*
    991      * Loop through BDs until we find an empty one. This indicates that
    992      * the DMA is still using it.
    993      */
    994     while( !(status & MCF548X_FEC_RBD_EMPTY) ) {
    995 
    996       /*
    997        * Remember the data pointer from this transfer.
    998        */
    999       GET_BD_BUFFER(bd);
    1000       m    = sc->rxMbuf[rxBdIndex];
    1001       m->m_len = m->m_pkthdr.len = (len
    1002                                     - sizeof(uint32_t)
    1003                                     - sizeof(struct ether_header));
    1004       eh = mtod(m, struct ether_header *);
    1005       m->m_data += sizeof(struct ether_header);
    1006       ether_input(ifp, eh, m);
    1007 
    1008       /*
    1009        * Done w/ the BD. Clean it.
    1010        */
    1011       sc->rxMbuf[rxBdIndex] = NULL;
    1012 
    1013       /*
    1014        * Add a new buffer to the ring.
    1015        */
    1016       MGETHDR (m, M_WAIT, MT_DATA);
    1017       MCLGET (m, M_WAIT);
    1018       m->m_pkthdr.rcvif = ifp;
    1019       size = ETHER_MAX_LEN;
    1020 
    1021       sc->rxMbuf[rxBdIndex] = m;
    1022       rtems_cache_invalidate_multiple_data_lines(mtod(m,const void *),
    1023                                                  size);
    1024 
    1025       SET_BD_BUFFER(bd,mtod(m, void *));
    1026       SET_BD_LENGTH(bd,size);
    1027       SET_BD_STATUS(bd,
    1028                     MCF548X_FEC_RBD_EMPTY
    1029                     |MCF548X_FEC_RBD_INT
    1030                     |((rxBdIndex == sc->rxBdCount-1)
    1031                       ? MCF548X_FEC_RBD_WRAP
    1032                       : 0)
    1033                     );
    1034 
    1035       /*
    1036        * advance to next BD
    1037        */
    1038       if (++rxBdIndex >= sc->rxBdCount) {
    1039         rxBdIndex = 0;
    1040       }
    1041       /*
    1042        * Get next BD pointer and its length.
    1043        */
    1044       bd     = sc->rxBd + rxBdIndex;
    1045       status = GET_BD_STATUS( bd );
    1046       len    = GET_BD_LENGTH( bd );
    1047     }
    1048     /*
    1049      * Unmask RXF (Full frame received) event
    1050      */
    1051     mcdma_glue_irq_enable(sc->rxDmaChan);
    1052 
    1053     rtems_bsdnet_event_receive (INTERRUPT_EVENT | FATAL_INT_EVENT,
    1054                                 RTEMS_WAIT | RTEMS_EVENT_ANY,
    1055                                 RTEMS_NO_TIMEOUT, &events);
    1056     if (events & FATAL_INT_EVENT) {
    1057       /*
    1058        * fatal interrupt ocurred, so reinit fec and restart mcdma tasks
    1059        */
    1060       mcf548x_fec_restart(sc);
    1061       rxBdIndex = 0;
    1062     }
    1063   }
    1064 }
    1065 
     657    fec_send_event(sc->txDaemonTid);
     658  }
     659}
    1066660
    1067661/*
     
    1137731   * Set transmit fifo watermark register (X_WMRK), default = 64
    1138732   */
    1139   MCF548X_FEC_FECTFAR(chan) = MCF548X_FEC_FECTFAR_ALARM(256);   /* 256 bytes */
    1140   MCF548X_FEC_FECTFWR(chan) = MCF548X_FEC_FECTFWR_X_WMRK_64;    /* 64 bytes */
     733  MCF548X_FEC_FECTFAR(chan) = MCF548X_FEC_FECTFAR_ALARM(128);
     734  MCF548X_FEC_FECTFWR(chan) = MCF548X_FEC_FECTFWR_X_WMRK_64;   /* 64 bytes */
    1141735
    1142736 /*
     
    1169763  ifp->if_flags |= IFF_OACTIVE;
    1170764
    1171   rtems_bsdnet_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT);
    1172 
    1173   }
    1174 
    1175 
    1176 /*
    1177  * start the DMA channel
    1178  */
    1179 static void mcf548x_fec_startDMA(struct mcf548x_enet_struct *sc)
     765  fec_send_event(sc->txDaemonTid);
     766
     767  }
     768
     769static void fec_start_dma_and_controller(struct mcf548x_enet_struct *sc)
    1180770{
    1181771  int chan = sc->chan;
     
    1232822        rtems_panic("FEC: cannot start tx DMA");
    1233823      }
    1234 }
     824
     825  /*
     826   * Enable FEC-Lite controller
     827   */
     828  MCF548X_FEC_ECR(chan) |= MCF548X_FEC_ECR_ETHER_EN;
     829}
     830
     831static void mcf548x_fec_restart(struct mcf548x_enet_struct *sc, rtems_id otherDaemon)
     832{
     833  if (sc->state == FEC_STATE_RESTART_1) {
     834    mcf548x_fec_initialize_hardware(sc);
     835    fec_start_dma_and_controller(sc);
     836    sc->state = FEC_STATE_NORMAL;
     837  } else {
     838    sc->state = FEC_STATE_RESTART_1;
     839  }
     840
     841  fec_send_event(otherDaemon);
     842  while (sc->state != FEC_STATE_NORMAL) {
     843    fec_wait_for_event();
     844  }
     845}
     846
     847static void fec_reset_bd_and_discard_tx_frames(
     848  int bdCount,
     849  MCD_bufDescFec *bdRing,
     850  struct mbuf **mbufs
     851)
     852{
     853  int bdIndex = 0;
     854
     855  for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) {
     856    bool bdIsLast = bdIndex == bdCount - 1;
     857    struct mbuf *m = mbufs[bdIndex];
     858
     859    bdRing[bdIndex].statCtrl = bdIsLast ? MCF548X_FEC_TBD_WRAP : 0;
     860
     861    if (m != NULL) {
     862      mbufs[bdIndex] = NULL;
     863      m_free(m);
     864    }
     865  }
     866}
     867
     868static void fec_reset_tx_dma(
     869  int dmaChan,
     870  int bdCount,
     871  MCD_bufDescFec *bdRing,
     872  struct mbuf **mbufs,
     873  struct mbuf *m
     874)
     875{
     876  if (m != NULL) {
     877    m_freem(m);
     878  }
     879
     880  MCD_killDma(dmaChan);
     881
     882  fec_reset_bd_and_discard_tx_frames(bdCount, bdRing, mbufs);
     883}
     884
     885static struct mbuf *fec_next_fragment(
     886  struct ifnet *ifp,
     887  struct mbuf *m,
     888  bool *isFirst
     889)
     890{
     891  struct mbuf *n = NULL;
     892
     893  *isFirst = false;
     894
     895  while (true) {
     896    if (m == NULL) {
     897      IF_DEQUEUE(&ifp->if_snd, m);
     898
     899      if (m != NULL) {
     900        *isFirst = true;
     901      } else {
     902        ifp->if_flags &= ~IFF_OACTIVE;
     903
     904        return NULL;
     905      }
     906    }
     907
     908    if (m->m_len > 0) {
     909      break;
     910    } else {
     911      m = m_free(m);
     912    }
     913  }
     914
     915  n = m->m_next;
     916  while (n != NULL && n->m_len <= 0) {
     917    n = m_free(n);
     918  }
     919  m->m_next = n;
     920
     921  return m;
     922}
     923
     924static bool fec_transmit(
     925  struct ifnet *ifp,
     926  int dmaChan,
     927  int bdCount,
     928  MCD_bufDescFec *bdRing,
     929  struct mbuf **mbufs,
     930  int *bdIndexPtr,
     931  struct mbuf **mPtr,
     932  MCD_bufDescFec **firstPtr
     933)
     934{
     935  bool bdShortage = false;
     936  int bdIndex = *bdIndexPtr;
     937  struct mbuf *m = *mPtr;
     938  MCD_bufDescFec *first = *firstPtr;
     939
     940  while (true) {
     941    MCD_bufDescFec *bd = &bdRing[bdIndex];
     942
     943    MCDMA_CLR_PENDING(dmaChan);
     944    if ((bd->statCtrl & MCF548X_FEC_TBD_READY) == 0) {
     945      struct mbuf *done = mbufs[bdIndex];
     946      bool isFirst = false;
     947
     948      if (done != NULL) {
     949        m_free(done);
     950        mbufs[bdIndex] = NULL;
     951      }
     952
     953      m = fec_next_fragment(ifp, m, &isFirst);
     954      if (m != NULL) {
     955        bool bdIsLast = bdIndex == bdCount - 1;
     956        u16 status = bdIsLast ? MCF548X_FEC_TBD_WRAP : 0;
     957
     958        bd->length = (u16) m->m_len;
     959        bd->dataPointer = mtod(m, u32);
     960
     961        mbufs[bdIndex] = m;
     962
     963        rtems_cache_flush_multiple_data_lines(mtod(m, void *), m->m_len);
     964
     965        if (isFirst) {
     966          first = bd;
     967        } else {
     968          status |= MCF548X_FEC_TBD_READY;
     969        }
     970
     971        if (m->m_next != NULL) {
     972          bd->statCtrl = status;
     973        } else {
     974          bd->statCtrl = status | MCF548X_FEC_TBD_INT | MCF548X_FEC_TBD_LAST;
     975          first->statCtrl |= MCF548X_FEC_TBD_READY;
     976          MCD_continDma(dmaChan);
     977        }
     978
     979        m = m->m_next;
     980      } else {
     981        break;
     982      }
     983    } else {
     984      bdShortage = true;
     985      break;
     986    }
     987
     988    if (bdIndex < bdCount - 1) {
     989      ++bdIndex;
     990    } else {
     991      bdIndex = 0;
     992    }
     993  }
     994
     995  *bdIndexPtr = bdIndex;
     996  *mPtr = m;
     997  *firstPtr = first;
     998
     999  return bdShortage;
     1000}
     1001
     1002static MCD_bufDescFec *fec_init_tx_dma(
     1003  MCD_bufDescFec *bdRing,
     1004  int bdCount
     1005)
     1006{
     1007  int bdIndex;
     1008
     1009  for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) {
     1010    bool bdIsLast = bdIndex == bdCount - 1;
     1011
     1012    bdRing[bdIndex].dataPointer = 0;
     1013    bdRing[bdIndex].length = 0;
     1014    bdRing[bdIndex].statCtrl = bdIsLast ? MCF548X_FEC_RBD_WRAP : 0;
     1015  }
     1016
     1017  return bdRing;
     1018}
     1019
     1020static void mcf548x_fec_txDaemon(void *arg)
     1021{
     1022  struct mcf548x_enet_struct *sc = arg;
     1023  struct ifnet *ifp = &sc->arpcom.ac_if;
     1024  int dmaChan = sc->txDmaChan;
     1025  int bdIndex = 0;
     1026  int bdCount = sc->txBdCount;
     1027  struct mbuf **mbufs = &sc->txMbuf[0];
     1028  struct mbuf *m = NULL;
     1029  MCD_bufDescFec *bdRing = fec_init_tx_dma(sc->txBd, bdCount);
     1030  MCD_bufDescFec *first = NULL;
     1031  bool bdShortage = false;
     1032
     1033  memset(mbufs, 0, bdCount * sizeof(*mbufs));
     1034
     1035  while (true) {
     1036    if (bdShortage) {
     1037      mcdma_glue_irq_enable(dmaChan);
     1038    }
     1039    fec_wait_for_event();
     1040
     1041    if (sc->state != FEC_STATE_NORMAL) {
     1042      fec_reset_tx_dma(dmaChan, bdCount, bdRing, mbufs, m);
     1043      mcf548x_fec_restart(sc, sc->rxDaemonTid);
     1044      bdIndex = 0;
     1045      m = NULL;
     1046      first = NULL;
     1047    }
     1048
     1049    bdShortage = fec_transmit(
     1050      ifp,
     1051      dmaChan,
     1052      bdCount,
     1053      bdRing,
     1054      mbufs,
     1055      &bdIndex,
     1056      &m,
     1057      &first
     1058    );
     1059  }
     1060}
     1061
     1062static struct mbuf *fec_add_mbuf(
     1063  int how,
     1064  struct ifnet *ifp,
     1065  MCD_bufDescFec *bd,
     1066  bool bdIsLast
     1067)
     1068{
     1069  struct mbuf *m;
     1070
     1071  MGETHDR(m, how, MT_DATA);
     1072  if (m != NULL) {
     1073    MCLGET(m, how);
     1074    if ((m->m_flags & M_EXT) != 0) {
     1075      m->m_pkthdr.rcvif = ifp;
     1076
     1077      rtems_cache_invalidate_multiple_data_lines(mtod(m, void *), ETHER_MAX_LEN);
     1078
     1079      bd->dataPointer = mtod(m, u32);
     1080      bd->length = ETHER_MAX_LEN;
     1081      bd->statCtrl = MCF548X_FEC_RBD_EMPTY
     1082        | MCF548X_FEC_RBD_INT
     1083        | (bdIsLast ? MCF548X_FEC_RBD_WRAP : 0);
     1084    } else {
     1085      m_free(m);
     1086    }
     1087  }
     1088
     1089  return m;
     1090}
     1091
     1092static MCD_bufDescFec *fec_init_rx_dma(
     1093  MCD_bufDescFec *bdRing,
     1094  struct ifnet *ifp,
     1095  int bdCount,
     1096  struct mbuf **mbufs
     1097)
     1098{
     1099  int bdIndex;
     1100
     1101  for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) {
     1102    bool bdIsLast = bdIndex == bdCount - 1;
     1103
     1104    mbufs[bdIndex] = fec_add_mbuf(M_WAIT, ifp, &bdRing[bdIndex], bdIsLast);
     1105  }
     1106
     1107  return bdRing;
     1108}
     1109
     1110static void fec_reset_rx_dma(
     1111  int dmaChan,
     1112  int bdCount,
     1113  MCD_bufDescFec *bdRing
     1114)
     1115{
     1116  int bdIndex;
     1117
     1118  MCD_killDma(dmaChan);
     1119
     1120  for (bdIndex = 0; bdIndex < bdCount - 1; ++bdIndex) {
     1121    bdRing[bdIndex].length = ETHER_MAX_LEN;
     1122    bdRing[bdIndex].statCtrl = MCF548X_FEC_RBD_EMPTY | MCF548X_FEC_RBD_INT;
     1123  }
     1124
     1125  bdRing[bdIndex].length = ETHER_MAX_LEN;
     1126  bdRing[bdIndex].statCtrl = MCF548X_FEC_RBD_EMPTY | MCF548X_FEC_RBD_INT | MCF548X_FEC_RBD_WRAP;
     1127}
     1128
     1129static int fec_ether_input(
     1130  struct ifnet *ifp,
     1131  int dmaChan,
     1132  int bdIndex,
     1133  int bdCount,
     1134  MCD_bufDescFec *bdRing,
     1135  struct mbuf **mbufs
     1136)
     1137{
     1138  while (true) {
     1139    bool bdIsLast = bdIndex == bdCount - 1;
     1140    MCD_bufDescFec *bd = &bdRing[bdIndex];
     1141    struct mbuf *m = mbufs[bdIndex];
     1142    struct mbuf *n;
     1143    u16 status;
     1144
     1145    MCDMA_CLR_PENDING(dmaChan);
     1146    status = bd->statCtrl;
     1147
     1148    if ((status & MCF548X_FEC_RBD_EMPTY) != 0) {
     1149      break;
     1150    }
     1151
     1152    n = fec_add_mbuf(0, ifp, bd, bdIsLast);
     1153    if (n != NULL) {
     1154      int len = bd->length - ETHER_HDR_LEN - ETHER_CRC_LEN;
     1155      struct ether_header *eh = mtod(m, struct ether_header *);
     1156
     1157      m->m_len = len;
     1158      m->m_pkthdr.len = len;
     1159      m->m_data = mtod(m, char *) + ETHER_HDR_LEN;
     1160
     1161      ether_input(ifp, eh, m);
     1162    } else {
     1163      n = m;
     1164    }
     1165
     1166    mbufs[bdIndex] = n;
     1167
     1168    if (bdIndex < bdCount - 1) {
     1169      ++bdIndex;
     1170    } else {
     1171      bdIndex = 0;
     1172    }
     1173  }
     1174
     1175  return bdIndex;
     1176}
     1177
     1178static void mcf548x_fec_rxDaemon(void *arg)
     1179{
     1180  struct mcf548x_enet_struct *sc = arg;
     1181  struct ifnet *ifp = &sc->arpcom.ac_if;
     1182  int dmaChan = sc->rxDmaChan;
     1183  int bdIndex = 0;
     1184  int bdCount = sc->rxBdCount;
     1185  struct mbuf **mbufs = &sc->rxMbuf[0];
     1186  MCD_bufDescFec *bdRing = fec_init_rx_dma(sc->rxBd, ifp, bdCount, mbufs);
     1187
     1188  while (true) {
     1189    mcdma_glue_irq_enable(dmaChan);
     1190    fec_wait_for_event();
     1191
     1192    bdIndex = fec_ether_input(ifp, dmaChan, bdIndex, bdCount, bdRing, mbufs);
     1193
     1194    if (sc->state != FEC_STATE_NORMAL) {
     1195      fec_reset_rx_dma(dmaChan, bdCount, bdRing);
     1196      mcf548x_fec_restart(sc, sc->txDaemonTid);
     1197      bdIndex = 0;
     1198    }
     1199  }
     1200}
     1201
    12351202/*
    12361203 * Initialize and start the device
     
    12931260
    12941261      MCF548X_FEC_EIMR(chan) = FEC_INTR_MASK_USED;
    1295       mcf548x_fec_rx_bd_init(sc);
    1296 
    1297       /*
    1298        * reset and Set up mcf548x FEC hardware
    1299        */
    1300       mcf548x_fec_initialize_hardware(sc);
    13011262
    13021263      /*
     
    13091270      sc->rxDaemonTid = rtems_bsdnet_newproc(rxTaskName, 4096,
    13101271                                             mcf548x_fec_rxDaemon, sc);
    1311       /*
    1312        * Clear SmartDMA task interrupt pending bits.
    1313        */
    1314       MCDMA_CLR_PENDING(sc->rxDmaChan );
    1315       MCDMA_CLR_PENDING(sc->txDmaChan );
    1316 
    1317       /*
    1318        * start the DMA channels
    1319        */
    1320       mcf548x_fec_startDMA(sc);
    1321       /*
    1322        * Enable FEC-Lite controller
    1323        */
    1324       MCF548X_FEC_ECR(chan) |= MCF548X_FEC_ECR_ETHER_EN;
    1325 
    1326 
    1327     }
     1272    }
     1273
     1274  mcf548x_fec_request_restart(sc);
    13281275
    13291276  /*
     
    13481295static void enet_stats (struct mcf548x_enet_struct *sc)
    13491296{
    1350   printf ("      Rx Interrupts:%-8lu", sc->rxInterrupts);
    1351   printf ("       Not First:%-8lu", sc->rxNotFirst);
    1352   printf ("        Not Last:%-8lu\n", sc->rxNotLast);
    1353   printf ("              Giant:%-8lu", sc->rxGiant);
    1354   printf ("       Non-octet:%-8lu\n", sc->rxNonOctet);
    1355   printf ("            Bad CRC:%-8lu", sc->rxBadCRC);
    1356   printf ("         Overrun:%-8lu", sc->rxOverrun);
    1357   printf ("       Collision:%-8lu\n", sc->rxCollision);
    1358 
    1359   printf ("      Tx Interrupts:%-8lu", sc->txInterrupts);
    1360   printf ("        Deferred:%-8lu", sc->txDeferred);
    1361   printf ("  Late Collision:%-8lu\n", sc->txLateCollision);
    1362   printf ("   Retransmit Limit:%-8lu", sc->txRetryLimit);
    1363   printf ("        Underrun:%-8lu", sc->txUnderrun);
    1364   printf ("      Misaligned:%-8lu\n", sc->txMisaligned);
    1365 
    1366 }
    1367 
    1368 /*
    1369  * restart the driver, reinit the fec
    1370  * this function is responsible to reinitialize the FEC in case a fatal
    1371  * error has ocurred. This is needed, wen a RxFIFO Overrun or a TxFIFO underrun
    1372  * has ocurred. In these cases, the FEC is automatically disabled, and
    1373  * both FIFOs must be reset and the BestComm tasks must be restarted
    1374  *
    1375  * Note: the daemon tasks will continue to run
    1376  * (in fact this function will be called in the context of the rx daemon task)
    1377  */
    1378 #define NEW_DMA_SETUP
    1379 
    1380 static void mcf548x_fec_restart(struct mcf548x_enet_struct *sc)
    1381 {
    1382   int chan = sc->chan;
    1383   /*
    1384    * FIXME: bring Tx Daemon into idle state
    1385    */
    1386 #ifdef NEW_DMA_SETUP
    1387   /*
    1388    * cleanup remaining receive mbufs
    1389    */
    1390   mcf548x_fec_rx_bd_cleanup(sc);
    1391 #endif
    1392   /*
    1393    * Stop DMA tasks
    1394    */
    1395   MCD_killDma (sc->rxDmaChan);
    1396   MCD_killDma (sc->txDmaChan);
    1397   /*
    1398    * FIXME: wait, until Tx Daemon is in idle state
    1399    */
    1400 
    1401   /*
    1402    * Disable transmit / receive interrupts
    1403    */
    1404   mcdma_glue_irq_disable(sc->txDmaChan);
    1405   mcdma_glue_irq_disable(sc->rxDmaChan);
    1406 #ifdef NEW_DMA_SETUP
    1407   /*
    1408    * recycle pending tx buffers
    1409    * FIXME: try to extract pending Tx buffers
    1410    */
    1411   mcf548x_fec_retire_tbd(sc,true);
    1412 #endif
    1413   /*
    1414    * re-initialize the FEC hardware
    1415    */
    1416   mcf548x_fec_initialize_hardware(sc);
    1417 
    1418 #ifdef NEW_DMA_SETUP
    1419 
    1420   /*
    1421    * reinit receive mbufs
    1422    */
    1423   mcf548x_fec_rx_bd_init(sc);
    1424 #endif
    1425   /*
    1426    * Clear SmartDMA task interrupt pending bits.
    1427    */
    1428   MCDMA_CLR_PENDING( sc->rxDmaChan );
    1429 
    1430   /*
    1431    * start the DMA channels again
    1432    */
    1433   mcf548x_fec_startDMA(sc);
    1434   /*
    1435    * reenable rx/tx interrupts
    1436    */
    1437   mcdma_glue_irq_enable(sc->rxDmaChan);
    1438   mcdma_glue_irq_enable(sc->txDmaChan);
    1439   /*
    1440    * (re-)init fec hardware
    1441    */
    1442   mcf548x_fec_initialize_hardware(sc);
    1443   /*
    1444    * reenable fec FIFO error interrupts
    1445    */
    1446   MCF548X_FEC_EIMR(chan) = FEC_INTR_MASK_USED;
    1447   /*
    1448    * Enable FEC-Lite controller
    1449    */
    1450   MCF548X_FEC_ECR(chan) |= MCF548X_FEC_ECR_ETHER_EN;
     1297  printf ("       Rx Interrupts:%-8lu", sc->rxInterrupts);
     1298  printf ("        Rx Not First:%-8lu", sc->rxNotFirst);
     1299  printf ("         Rx Not Last:%-8lu\n", sc->rxNotLast);
     1300  printf ("            Rx Giant:%-8lu", sc->rxGiant);
     1301  printf ("        Rx Non-octet:%-8lu", sc->rxNonOctet);
     1302  printf ("          Rx Bad CRC:%-8lu\n", sc->rxBadCRC);
     1303  printf ("       Rx FIFO Error:%-8lu", sc->rxFIFOError);
     1304  printf ("        Rx Collision:%-8lu", sc->rxCollision);
     1305
     1306  printf ("       Tx Interrupts:%-8lu\n", sc->txInterrupts);
     1307  printf ("         Tx Deferred:%-8lu", sc->txDeferred);
     1308  printf ("   Tx Late Collision:%-8lu", sc->txLateCollision);
     1309  printf (" Tx Retransmit Limit:%-8lu\n", sc->txRetryLimit);
     1310  printf ("         Tx Underrun:%-8lu", sc->txUnderrun);
     1311  printf ("       Tx FIFO Error:%-8lu", sc->txFIFOError);
     1312  printf ("       Tx Misaligned:%-8lu\n", sc->txMisaligned);
     1313
    14511314}
    14521315
Note: See TracChangeset for help on using the changeset viewer.