This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

ethernet driver problem when line reconnected


Hi.

We are experiencing following problem with ethernet driver using our MIPS
based board.

Once the board is disconnected from the LAN, the number of buffers increases
with a rate of 4 for each retry (approx. 2 sec.) up
to 104/106. It takes approx. 50 sec. to reach this limit. If I reconnect the
LAN just at this moment the communication restarts. If I try
again but I wait just a little more nothing happens.

After some debug outputs we found the cause of the problem.

The focal point is in if_ethersubr.c in function ether_output():
....................
    /*
     * Queue message on interface, and start output if interface
     * not yet active.
     */
    if (IF_QFULL(&ifp->if_snd)) {
       IF_DROP(&ifp->if_snd);
       splx(s);
       senderr(ENOBUFS);
    }
    ifp->if_obytes += m->m_pkthdr.len;
    IF_ENQUEUE(&ifp->if_snd, m);
    if (m->m_flags & M_MCAST)
        ifp->if_omcasts++;
    if ((ifp->if_flags & IFF_OACTIVE) == 0)
        (*ifp->if_start)(ifp);
    splx(s);
    return (error);
 .....................

System is sending packets and is disconnected from the LAN.
The low level can_send() returns FALSE, so packets are queued and
*ifp->if_start (points to: eth_drv_send()) is called but
low level send() is not. When the queue is full (IF_QFULL), then the
eth_drv_send() is no more called.
Once the LAN is reconnected what should happen? Low level driver is not
waiting for a TX event so no TX interrupt occurs and the engine hangs on.
It's a little confusing that the interface restarts only if somebody try to
send something.
Newer requests are aborted because the queue is full, but nobody retry to
send packets already in queue.......


This fixing will try to restart transmission of the queue every time there
is a packet to be sent and queue is full.
.........
   if (IF_QFULL(&ifp->if_snd)) {
      IF_DROP(&ifp->if_snd);
//fix start
      if ((ifp->if_flags & IFF_OACTIVE) == 0)   //try anyway to restart the
interface
         (*ifp->if_start)(ifp);
//fix end
      splx(s);
      senderr(ENOBUFS);
   }
............


We tried the fixing and it worked, but we are not really sure that it is the
proper solution.
Please advice.

Thanks
Damir



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]