[Bug 236119] Intel Ethernet 82547 device cannot transfer data

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Fri Mar 1 02:59:32 UTC 2019


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236119

            Bug ID: 236119
           Summary: Intel Ethernet 82547 device cannot transfer data
           Product: Base System
           Version: 12.0-STABLE
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: kern
          Assignee: bugs at FreeBSD.org
          Reporter: jgibbons at protogate.com

When upgrading some of my machines from FreeBSD 11 to FreeBSD 12, I found that
some of them could not transfer data via Ethernet after the upgrade.  ifconfig
seemed to work normally, including showing "status: active", but that interface
could neither send nor receive data packets, no matter what I tried.  And a few
minutes after booting my systems, they would silently hang, with no response
whatsoever, even on a serial console.

I eventually narrowed down the problem to my machines with Intel 82547GI chips,
which look like this in "pciconf -lv":

em0 at pci0:1:1:0: class=0x020000 card=0x10758086 chip=0x10758086 rev=0x00
hdr=0x00
    vendor     = 'Intel Corporation'
    device     = '82547GI Gigabit Ethernet Controller'
    class      = network
    subclass   = ethernet

By comparing the FreeBSD 11 code (which I knew worked) with the FreeBSD 12 code
which had the problem, I found the solution: the 82547 is an "edge" case which
slipped through the cracks when the Intel em driver was modified for FreeBSD
12.  Here is what I had to change in if_em.c to make the Intel 82547 Ethernet
chips work:

root at prod:~ # svn diff /usr/src/sys/dev/e1000/if_em.c
Index: /usr/src/sys/dev/e1000/if_em.c
===================================================================
--- /usr/src/sys/dev/e1000/if_em.c      (revision 344229)
+++ /usr/src/sys/dev/e1000/if_em.c      (working copy)
@@ -31,13 +31,16 @@
 #include <sys/sbuf.h>
 #include <machine/_inttypes.h>

-#define em_mac_min e1000_82547
+// jagwas: #define em_mac_min e1000_82547
+#define em_mac_min e1000_82571   // jag; 25feb2019;
+                                 //   so (adapter->hw.mac.type < em_mac_min)
+                                 //   is true for 82547GI and below
 #define igb_mac_min e1000_82575

 /*********************************************************************
  *  Driver version:
  *********************************************************************/
-char em_driver_version[] = "7.6.1-k";
+char em_driver_version[] = "7.6.1-k+jag3";

 /*********************************************************************
  *  PCI Device ID Table
@@ -2476,6 +2479,24 @@
        case e1000_i211:
                pba = E1000_PBA_34K;
                break;
+                        // jag; 26feb2019 added this case section; adapted
from
+                        //      FreeBSD 11 /usr/src/sys/dev/e1000/if_lem.c
+       case e1000_82547:
+       case e1000_82547_rev_2: /* 82547: Total Packet Buffer is 40K */
+               if (adapter->hw.mac.max_frame_size > 8192)
+                       pba = E1000_PBA_22K; /* 22K for Rx, 18K for Tx */
+               else
+                       pba = E1000_PBA_30K; /* 30K for Rx, 10K for Tx */
+
+               // jag; the following would be needed for plain 82547 (before
GI)
+               // and would also require adding the elements set here to
+               // struct adapter in if_em.h:
+               // adapter->tx_fifo_head = 0;
+               // adapter->tx_head_addr = pba << EM_TX_HEAD_ADDR_SHIFT;
+               // adapter->tx_fifo_size =
+               //     (E1000_PBA_40K - pba) << EM_PBA_BYTES_SHIFT;
+
+               break;
        default:
                if (adapter->hw.mac.max_frame_size > 8192)
                        pba = E1000_PBA_40K; /* 40K for Rx, 24K for Tx */
root at prod:~ #

With that change, my interfaces all now work fine, and my systems don't hang (I
think the hanging problem was because the pre-change if_em.c was assigning more
packet buffer space than the 82547GI actually has).

I believe this change will also help some of the other 82547 models to work,
but I don't have any of those chips and so cannot test them.  Those chips also
seem to need some workarounds for special cases (like jumbo frames which cross
buffer boundaries); those workarounds are implemented in FreeBSD 11 but not in
FreeBSD 12, and I didn't implement them as part of this change because my
82547GI chip doesn't need them.  (For example, see the
lem_82547_fifo_workaround() function; search for "82547" in the
/usr/src/sys/dev/e1000/if_lem.c file in FreeBSD 11 to see other workarounds).

This problem seems to exist on CURRENT, too (from looking at the code; I have
not tested that).

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-bugs mailing list