kern/101000: I may have found a subtle bug in the "em" driver in relase 6.1 - duplex/collision mismatch

Doug Havir rally at
Fri Jul 28 20:30:34 UTC 2006

>Number:         101000
>Category:       kern
>Synopsis:       I may have found a subtle bug in the "em" driver in relase 6.1 - duplex/collision mismatch
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jul 28 20:30:25 GMT 2006
>Originator:     Doug Havir
>Release:        i386 release 6.1
National Bankcard Services, Inc.
FreeBSD bsd.nbs 6.1-RELEASE FreeBSD 6.1-RELEASE #2: Mon Jul 10 09:56:35 CDT 2006     user at bsd.nbs:/usr/obj/usr/src/sys/QNXKERNEL  i386
In the file dev/em/if_em_hw.h, which is part of the Intel 825xx ethernet driver, the defines for DUPLEX are as follows:
#define HALF_DUPLEX 1
#define FULL_DUPLEX 2

In the file dev/em/if_em.c the message printed at the end of the em_attach() call is:
printf("em%d:  Speed:%d Mbps  Duplex:%s\n", adapter->unit, adapter->link_speed,
              adapter->link_duplex == FULL_DUPLEX ? "Full" : "Half");

Given that the code reads right, and nobody has complained about the message being wrong, one might assume the definitions for FULL and HALF duplex are correct.  BUT THEN,

In the file dev/em/if_em.c, function em_initialize_transmit_unit(struct adapter * adapter),
line 2396-2400:
if (adapter->link_duplex == 1) {
    reg_tctl |= E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT;
} else {
    reg_tctl |= E1000_HDX_COLLISION_DISTANCE << E1000_COLD_SHIFT;

Correct me if I'm wrong, but what that really says is if link_duplex == HALF_DUPLEX then set the collision distance to the full duplex setting.  At least one of the two usages are incorrect.

I figured I'd point it out just in case it actually has a meaningful impact.  Could it possibly explain some of the half duplex workaround stuff in here?  One can only hope....
Lookie at the source code.
1) Use the define for FULL_DUPLEX or HALF_DUPLEX instead of "1"
2) Make sure the effects of the if/else match whichever duplex definition you choose
3) Spend copious free time seeing if it has any effect on performance or reliability :-)

Best regards,


More information about the freebsd-bugs mailing list