Waiting for mbufs

gregory.menke at gsfc.nasa.gov gregory.menke at gsfc.nasa.gov
Wed Mar 12 22:08:19 UTC 2003


I've been working on upgrading the dec21140 driver to support multiple
units, making it more efficient and support shared interrupts.  That
part is working OK, but I'm having some trouble with getting packets
thru the stack.

The symptom resembles a deadlock.  Its occuring on the receive side,
the rx daemon gets stuck in MCLGET (m, M_WAIT), waiting for an mbuf,
printing its message every 30 seconds.  This seems to occur when
traffic arrives on both ports.  

My current version of the rx daemon is below.  It serves all dec
units, accepting rx events from each.  Note I define 1 event for each
unit, so rx events from unit1 are separate from unit2, thus I only
manipulate ports that need service.  

Is there a task-id sensitivity built into the stack?  When I had 2
daemons per unit, the mbuf problem didn't occur.  I'm kind of
wondering if it could be some kind of effect related to
event_receive/semaphore timing.  Calling
rtems_bsdnet_show_mbuf_stats() shows 400+ mbufs free.  Any hints are
appreciated.

Thanks,

Gregm



static void
dec21140_rxDaemon (void *arg)
{
   volatile unsigned int *tbase;
   volatile struct MD    *rmd;
   struct dec21140_softc *sc;
   volatile struct ifnet *ifp;
   struct ether_header   *eh;
   struct mbuf           *m;
   unsigned int          i,len;
   rtems_event_set       events;

   for (;;)
   {

      rtems_bsdnet_event_receive( RTEMS_ALL_EVENTS, /* INTERRUPT_EVENT, */
                                  RTEMS_WAIT|RTEMS_EVENT_ANY,
                                  RTEMS_NO_TIMEOUT,
                                  &events);

      ++rxwakeup;

      for(i=0; i< NDECDRIVER; i++ )
      {
         ++spins;

         sc = &dec21140_softc[i];
         if( sc->base )
         {
            if( events & sc->ioevent )
            {
               ifp   = &sc->arpcom.ac_if;
               tbase = sc->base;
               rmd   = sc->nextRxMD;

               /*
               ** Read off all the packets we've received on this unit
               */
               while((rmd->status & 0x80000000) == 0)
               {
                  /* printk("unit %i rx\n", ifp->if_unit ); */
               
                  /* pass on the packet in the mbuf */
                  len = (rmd->status >> 16) & 0x7ff;
                  m = (struct mbuf *)(rmd->m);
                  m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header);
                  eh = mtod (m, struct ether_header *);
                  m->m_data += sizeof(struct ether_header);

                  ++etherin;
                  ether_input (ifp, eh, m);
                  ++etherout;

                  /* get a new mbuf for the 21140 */
                  MGETHDR (m, M_WAIT, MT_DATA);
                  ++newmbufhdr;
                  MCLGET (m, M_WAIT);
                  ++newmbufget;
                  m->m_pkthdr.rcvif = ifp;
                  rmd->m = m;
                  rmd->buf1 = phys_to_bus(mtod(m, void *));

                  /* mark the descriptor as ready to receive */
                  rmd->status = 0x80000000;
      
                  rmd=rmd->next;
               }

               sc->nextRxMD = rmd;
            }
         }
      }

      ++rxsleep;
   }
}




More information about the users mailing list