Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 08 Aug 2026 15:57:53 +0000
From:      Kevin Bowling <kbowling@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 66baeec9f8a4 - main - e1000: Program Tx descriptor control by family
Message-ID:  <6a775201.303c9.3554c0ce@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by kbowling:

URL: https://cgit.FreeBSD.org/src/commit/?id=66baeec9f8a4c4b1609d255b62e3572e0618747f

commit 66baeec9f8a4c4b1609d255b62e3572e0618747f
Author:     Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-08 11:48:43 +0000
Commit:     Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-08-08 15:29:05 +0000

    e1000: Program Tx descriptor control by family
    
    TXDCTL programming is family dependent.  82543 erratum 35 and
    82544 erratum 20 require WTHRESH to remain zero; a nonzero value
    can corrupt descriptor writebacks and hang the controller.  Leave all
    descriptor-control thresholds at their reset values on 82542, 82543,
    and 82544.
    
    On the remaining em controllers, retain the established PTHRESH=31,
    HTHRESH=1, WTHRESH=1, and descriptor granularity policy.  Several
    legacy specification updates identify full descriptor writeback as a
    workaround for transmit descriptor-queue errata.
    
    TXDCTL bit 22 is also family dependent.  It is COUNT_DESC on the
    82571 family and 80003ES2LAN.  Intel shared initialization explicitly
    sets raw bit 22 on both transmit queues of every supported ICH/PCH
    generation, although the integrated public documentation marks it
    reserved.  Preserve that required setting when iflib programs the
    thresholds, as DPDK does.  Clearing it caused a persistent I219
    transmit stall under descriptor pressure.
    
    The combined em/igb setup also wrote LWTHRESH=1 on every em
    controller.  The driver does not enable the TXD_LOW interrupt
    controlled by that field.  Enumerate every supported em MAC type and
    leave the unused low-water threshold disabled.
    
    This keeps the legacy descriptor-writeback safety policies separate
    from igb sparse-RS operation while programming only the fields
    appropriate to each family.
    
    MFC after:      2 weeks
---
 sys/dev/e1000/if_em.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++-----
 sys/dev/e1000/if_em.h |  3 ++
 2 files changed, 78 insertions(+), 8 deletions(-)

diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index 6ef36eb579b6..e7bc457ed1bd 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -4137,6 +4137,74 @@ em_if_queues_free(if_ctx_t ctx)
 	}
 }
 
+static u32
+em_legacy_txdctl(struct e1000_hw *hw)
+{
+	u32 txdctl;
+
+	/*
+	 * Start with the established full-descriptor writeback policy.
+	 * Several generations have descriptor-queue errata for which it is
+	 * a documented workaround.  The unsafe early controllers are
+	 * overridden below.
+	 */
+	txdctl = EM_TX_PTHRESH | (EM_TX_HTHRESH << 8) |
+	    (EM_TX_WTHRESH << 16) | E1000_TXDCTL_GRAN;
+
+	switch (hw->mac.type) {
+	case e1000_82571:
+	case e1000_82572:
+	case e1000_82573:
+	case e1000_82574:
+	case e1000_82583:
+	case e1000_80003es2lan:
+		/* Match the Intel shared-code policy for these families. */
+		txdctl |= E1000_TXDCTL_COUNT_DESC;
+		break;
+	case e1000_ich8lan:
+	case e1000_ich9lan:
+	case e1000_ich10lan:
+	case e1000_pchlan:
+	case e1000_pch2lan:
+	case e1000_pch_lpt:
+	case e1000_pch_spt:
+	case e1000_pch_cnp:
+	case e1000_pch_tgp:
+	case e1000_pch_adp:
+	case e1000_pch_mtp:
+	case e1000_pch_ptp:
+		/* Preserve the required bit set by the integrated shared code. */
+		txdctl |= (1U << 22);
+		break;
+	case e1000_82542:
+	case e1000_82543:
+	case e1000_82544:
+		/*
+		 * 82543 erratum 35 and 82544 erratum 20 require
+		 * WTHRESH=0.  Leave all descriptor-control thresholds at
+		 * their reset values on these early controllers.
+		 */
+		txdctl = 0;
+		break;
+	case e1000_82540:
+	case e1000_82545:
+	case e1000_82545_rev_3:
+	case e1000_82546:
+	case e1000_82546_rev_3:
+	case e1000_82541:
+	case e1000_82541_rev_2:
+	case e1000_82547:
+	case e1000_82547_rev_2:
+		break;
+	default:
+		KASSERT(0, ("%s: unsupported MAC type %d", __func__,
+		    hw->mac.type));
+		break;
+	}
+
+	return (txdctl);
+}
+
 /*********************************************************************
  *
  *  Enable transmit unit.
@@ -4187,16 +4255,15 @@ em_initialize_transmit_rings(if_ctx_t ctx)
 		    E1000_READ_REG(hw, E1000_TDBAL(qid)),
 		    E1000_READ_REG(hw, E1000_TDLEN(qid)));
 
-		txdctl = 0; /* clear txdctl */
-		txdctl |= 0x1f; /* PTHRESH */
-		txdctl |= 1 << 8; /* HTHRESH */
-		txdctl |= 1 << 16;/* WTHRESH */
 		if (hw->mac.type < igb_mac_min) {
-			txdctl |= 1 << 22; /* Reserved bit must always be 1 */
-			txdctl |= E1000_TXDCTL_GRAN;
-			txdctl |= 1 << 25; /* LWTHRESH */
-		} else
+			txdctl = em_legacy_txdctl(hw);
+		} else {
+			txdctl = 0;
+			txdctl |= 0x1f; /* PTHRESH */
+			txdctl |= 1 << 8; /* HTHRESH */
+			txdctl |= 1 << 16; /* WTHRESH */
 			txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
+		}
 
 		E1000_WRITE_REG(hw, E1000_TXDCTL(qid), txdctl);
 	}
diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h
index 6d3f312715d4..5f53f4074fcf 100644
--- a/sys/dev/e1000/if_em.h
+++ b/sys/dev/e1000/if_em.h
@@ -296,6 +296,9 @@ struct igb_vf_mac_filter;
 #define PCICFG_DESC_RING_STATUS	0xe4
 #define FLUSH_DESC_REQUIRED	0x100
 
+#define EM_TX_PTHRESH		31
+#define EM_TX_HTHRESH		1
+#define EM_TX_WTHRESH		1
 
 #define IGB_RX_PTHRESH	((hw->mac.type == e1000_i354) ? 12 : \
 			    ((hw->mac.type <= e1000_82576) ? 16 : 8))


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a775201.303c9.3554c0ce>