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]

Re: ethernet driver problem when line reconnected


Damir Salantic wrote:
> 
> 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.

You're probably not going to like this :-), but this was already fixed in
the anonymous CVS repository with this change:

2001-10-29  Hugo Tyson  <hmt@redhat.com>

        * src/sys/net/if_ethersubr.c (ether_output): [CASE 106613] Even if
        the queue is full, and we are dropping the packet, try to start
        the interface anyway, to give it a chance to empty the queue if
        the device has recovered from whatever made the queue fill up in
        the first place - being unplugged from the network for example.
        This change is belt & braces with a similar policy in the periodic
        tickle function in the logical ether driver in io/eth/... ; this
        change will recover the situation immediately if the application
        continues trying to send despite ENOBUFS.


You mustn't have this fix as it is the same as your own!

Jifl
 
> 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

-- 
Red Hat, Rustat House, Clifton Road, Cambridge, UK. Tel: +44 (1223) 271062
Maybe this world is another planet's Hell -Aldous Huxley || Opinions==mine


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