5.2-RC oerrs and collisions on dc0

Don Lewis truckman at FreeBSD.org
Sun Jan 4 15:44:27 PST 2004

On  5 Jan, Dejan Lesjak wrote:
> On Sunday 04 of January 2004 22:51, Don Lewis wrote:
>> I just took a closer look at the busdma diff, and this change to
>> dc_txeof() looks very suspicious:
>> @@ -2663,7 +2809,7 @@
>>                 if (txstat & DC_TXSTAT_OWN)
>>                         break;
>> -               if (!(cur_tx->dc_ctl & DC_TXCTL_LASTFRAG) ||
>> +               if (!(cur_tx->dc_ctl & DC_TXCTL_FIRSTFRAG) ||
>>                     cur_tx->dc_ctl & DC_TXCTL_SETUP) {
>>                         if (cur_tx->dc_ctl & DC_TXCTL_SETUP) {
>>                                 /*
>> The code in the "if" block ends with a "continue" which will cause the
>> error handling code to be skipped if the "if" condition is true.  I'm
>> pretty sure that the error status bits are only set in the last
>> descriptor for the frame, so we want to execute the "continue" unless
>> the DC_TXCTL_LASTFRAG bit is set.
>> Try reverting this part of the busdma change.
> I tried this; although I'm now getting watchdog timeouts, I don't see any 
> collisions and the few output errors probably come from timeouts. So I guess 
> this is in the right direction. Could it be that we still need to do these 
> lines:
> sc->dc_cdata.dc_tx_cnt--;
> unless DC_TXCTL_FIRSTFRAG is set? I'll try playing with this now and see how 
> it goes...

These two statements need to be executed for each iteration of the outer
"while" loop unless DC_TXSTAT_OWN is set.  Since these two statements
are at the end of the "while" block, they have to be duplicated in the
"if" block so that these actions are taken before executing the
"continue" statement, which will skip these statements at the end of the

I don't know where this particular change came from, but it is not
related to the busdma change.

BTW, when testing the FIRSTFRAG flag instead of the LASTFRAG flag, you
should not see any errors when only sending small packets (that fit in
one mbuf).  The reason is that in this case both the FIRSTFRAG and
LASTFRAG bits will be set at the same time.

The other errors might have caused dc_init() to be called frequently
enough to mask the cause of the watchdog timeouts.

More information about the freebsd-current mailing list