git: 66baeec9f8a4 - main - e1000: Program Tx descriptor control by family
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 08 Aug 2026 15:57:53 UTC
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))