Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 01 Mar 2019 02:59:30 +0000
From:      bugzilla-noreply@freebsd.org
To:        bugs@FreeBSD.org
Subject:   [Bug 236119] Intel Ethernet 82547 device cannot transfer data
Message-ID:  <bug-236119-227@https.bugs.freebsd.org/bugzilla/>

next in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D236119

            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@FreeBSD.org
          Reporter: jgibbons@protogate.com

When upgrading some of my machines from FreeBSD 11 to FreeBSD 12, I found t=
hat
some of them could not transfer data via Ethernet after the upgrade.  ifcon=
fig
seemed to work normally, including showing "status: active", but that inter=
face
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 ch=
ips,
which look like this in "pciconf -lv":

em0@pci0:1:1:0: class=3D0x020000 card=3D0x10758086 chip=3D0x10758086 rev=3D=
0x00
hdr=3D0x00
    vendor     =3D 'Intel Corporation'
    device     =3D '82547GI Gigabit Ethernet Controller'
    class      =3D network
    subclass   =3D 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 wh=
ich
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 Ethern=
et
chips work:

root@prod:~ # svn diff /usr/src/sys/dev/e1000/if_em.c
Index: /usr/src/sys/dev/e1000/if_em.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- /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_mi=
n)
+                                 //   is true for 82547GI and below
 #define igb_mac_min e1000_82575

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

 /*********************************************************************
  *  PCI Device ID Table
@@ -2476,6 +2479,24 @@
        case e1000_i211:
                pba =3D 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 =3D E1000_PBA_22K; /* 22K for Rx, 18K for Tx */
+               else
+                       pba =3D E1000_PBA_30K; /* 30K for Rx, 10K for Tx */
+
+               // jag; the following would be needed for plain 82547 (befo=
re
GI)
+               // and would also require adding the elements set here to
+               // struct adapter in if_em.h:
+               // adapter->tx_fifo_head =3D 0;
+               // adapter->tx_head_addr =3D pba << EM_TX_HEAD_ADDR_SHIFT;
+               // adapter->tx_fifo_size =3D
+               //     (E1000_PBA_40K - pba) << EM_PBA_BYTES_SHIFT;
+
+               break;
        default:
                if (adapter->hw.mac.max_frame_size > 8192)
                        pba =3D E1000_PBA_40K; /* 40K for Rx, 24K for Tx */
root@prod:~ #

With that change, my interfaces all now work fine, and my systems don't han=
g (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 a=
lso
seem to need some workarounds for special cases (like jumbo frames which cr=
oss
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 ha=
ve
not tested that).

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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-236119-227>