git: 66baeec9f8a4 - main - e1000: Program Tx descriptor control by family

Kevin Bowling <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.src
Message-ID <6a775201.303c9.3554c0ce__31697.1380192385$1786204866$gmane$org@gitrepo.freebsd.org>
The branch main has been updated by kbowling:

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

commit 66baeec9f8a4c4b1609d255b62e3572e0618747f
Author:     Kevin Bowling <[email protected]>
AuthorDate: 2026-08-08 11:48:43 +0000
Commit:     Kevin Bowling <[email protected]>
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))
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.