From nobody Wed Feb 22 00:49:43 2023 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4PLyGv61jWz3tjqb; Wed, 22 Feb 2023 00:49:43 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4PLyGv5Wfdz3FLd; Wed, 22 Feb 2023 00:49:43 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1677026983; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=bEQLuDaKY6KNRAZb7ALNkSD+n3vLGVVxERKBI8BoEBM=; b=axIirnf6Fo9GDHLuRzP3WV6qAFEpS/QBTeUQMCQfJOdIctnLClmI8xmhViK/MitYUSBL/1 F3R4rFpQaaZpe4eQRZZChlA4LslBGI7+Eps2mfG9bO12VICd87l4bHM07mXxg0hLf3yu9f XptsFJg6z4QyjgiiYneQ8v/ybSDzDZGLaOkQFXcViV0kxDtsdpPCBop+2vcXVfDYwkZqww wUlxKjsErTFSoStEckoYBDVn3/ho3oBlPR4xjSQ9tXVEQT7aSCQtL9YOVeXmXIvMi1Z7sm UBARuoMOcs85UN/Wf9ecSeYiAJbz94TzdMTX8W9f/B+ZX1kUivPsJZr4XDrtYA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1677026983; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=bEQLuDaKY6KNRAZb7ALNkSD+n3vLGVVxERKBI8BoEBM=; b=AnVgKyBT8wq6x/3BYTh3D+9ibJBkpxTF3vN/W/xLAuUbYasFixMjT+Xhoy/u/QV/gORavV vfo1Is7y1lXqj+5bRuJR9AAs1cWRdJ2FA5jpWehLBzpySoofTW4DX4edJ+kf4+Khawq/Ze OW2VIawrAo8jEZHAUbYfDh6gfSM6QevS4ReiP1QQksXPckaGfjGmw6VDzoM6eEtJXpS/pq YzQc5UpMcts0TNn1KG/vSX/rXN19F05ZwuEGi0QYjsaCwHxyoWqPgY38WnUBq7HihPYrPo iR8gIWF3s08iBP9pQRXt1fbwPC3x9wA8KfMop5rivOLd9nnnXAqf0RmXWhYI7g== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1677026983; a=rsa-sha256; cv=none; b=ZdbfDubKr/DPDuWUSZqXJcvnDUz3fNUymD/18n3exLTz/yw8MpUxI78LnXDWJDFfMqUw05 AhT/+5l25NtDM4b54F/sffppLJ8dEHjK1h/rlrnF9DFEHH/qrgmuHnHsiMZJ0TC6nu0MQy Y9S14GRRcL/ORiXnHKTWmiv8G2I9Jmvcp2R5zpLnra6izbaMfvf0MJWS2/hweiYbfXCQw8 5oraf+UnBUb/aRjmPNu/eCxwmhMHhvrMOTX7t6aUzgiPxgVbHHzXUhjpXB9t8vLcWjYenJ 3jY0K3dM+o1T81mZHA0xrmSMe2DAFx9VKn0CXn/PSTRdqsi9cAIZM3O6UjYiSg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4PLyGv4bnjzh7M; Wed, 22 Feb 2023 00:49:43 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 31M0nhZd041208; Wed, 22 Feb 2023 00:49:43 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 31M0nhMg041207; Wed, 22 Feb 2023 00:49:43 GMT (envelope-from git) Date: Wed, 22 Feb 2023 00:49:43 GMT Message-Id: <202302220049.31M0nhMg041207@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kevin Bowling Subject: git: e646dced5931 - stable/12 - e1000: fix I219 hang on reset List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kbowling X-Git-Repository: src X-Git-Refname: refs/heads/stable/12 X-Git-Reftype: branch X-Git-Commit: e646dced5931a1e51177688d0bd8f1ace90711e5 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch stable/12 has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=e646dced5931a1e51177688d0bd8f1ace90711e5 commit e646dced5931a1e51177688d0bd8f1ace90711e5 Author: Kevin Bowling AuthorDate: 2023-02-08 19:21:45 +0000 Commit: Kevin Bowling CommitDate: 2023-02-22 00:49:29 +0000 e1000: fix I219 hang on reset Clear the rings before reset to avoid a HW hang. Inspired by em-7.7.8 and DPDK (1fc9701238edcf0541289b9ae15565b6d9d7ab30) Reviewed by: erj Sponsored by: BBOX.io Pull Request: https://github.com/freebsd/freebsd-src/pull/540 (cherry picked from commit ae1dca798e0f826de46f4ec11914ba4c91928d7a) --- sys/dev/e1000/if_em.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 2 deletions(-) diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index a9ab2fb21535..3f6087404f36 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -343,6 +343,7 @@ static int em_get_regs(SYSCTL_HANDLER_ARGS); static void lem_smartspeed(struct e1000_softc *); static void igb_configure_queues(struct e1000_softc *); +static void em_flush_desc_rings(struct e1000_softc *); /********************************************************************* @@ -1895,6 +1896,10 @@ em_if_stop(if_ctx_t ctx) INIT_DEBUGOUT("em_if_stop: begin"); + /* I219 needs special flushing to avoid hangs */ + if (sc->hw.mac.type >= e1000_pch_spt && sc->hw.mac.type < igb_mac_min) + em_flush_desc_rings(sc); + e1000_reset_hw(&sc->hw); if (sc->hw.mac.type >= e1000_82544) E1000_WRITE_REG(&sc->hw, E1000_WUFC, 0); @@ -1960,8 +1965,7 @@ em_allocate_pci_resources(if_ctx_t ctx) sc->hw.hw_addr = (u8 *)&sc->osdep.mem_bus_space_handle; /* Only older adapters use IO mapping */ - if (sc->hw.mac.type < em_mac_min && - sc->hw.mac.type > e1000_82543) { + if (sc->hw.mac.type < em_mac_min && sc->hw.mac.type > e1000_82543) { /* Figure our where our IO BAR is ? */ for (rid = PCIR_BAR(0); rid < PCIR_CIS;) { val = pci_read_config(dev, rid, 4); @@ -2449,6 +2453,113 @@ igb_init_dmac(struct e1000_softc *sc, u32 pba) E1000_WRITE_REG(hw, E1000_DMACR, 0); } } +/********************************************************************* + * The 3 following flush routines are used as a workaround in the + * I219 client parts and only for them. + * + * em_flush_tx_ring - remove all descriptors from the tx_ring + * + * We want to clear all pending descriptors from the TX ring. + * zeroing happens when the HW reads the regs. We assign the ring itself as + * the data of the next descriptor. We don't care about the data we are about + * to reset the HW. + **********************************************************************/ +static void +em_flush_tx_ring(struct e1000_softc *sc) +{ + struct e1000_hw *hw = &sc->hw; + struct tx_ring *txr = &sc->tx_queues->txr; + struct e1000_tx_desc *txd; + u32 tctl, txd_lower = E1000_TXD_CMD_IFCS; + u16 size = 512; + + tctl = E1000_READ_REG(hw, E1000_TCTL); + E1000_WRITE_REG(hw, E1000_TCTL, tctl | E1000_TCTL_EN); + + txd = &txr->tx_base[txr->tx_cidx_processed]; + + /* Just use the ring as a dummy buffer addr */ + txd->buffer_addr = txr->tx_paddr; + txd->lower.data = htole32(txd_lower | size); + txd->upper.data = 0; + + /* flush descriptors to memory before notifying the HW */ + wmb(); + + E1000_WRITE_REG(hw, E1000_TDT(0), txr->tx_cidx_processed); + mb(); + usec_delay(250); +} + +/********************************************************************* + * em_flush_rx_ring - remove all descriptors from the rx_ring + * + * Mark all descriptors in the RX ring as consumed and disable the rx ring + **********************************************************************/ +static void +em_flush_rx_ring(struct e1000_softc *sc) +{ + struct e1000_hw *hw = &sc->hw; + u32 rctl, rxdctl; + + rctl = E1000_READ_REG(hw, E1000_RCTL); + E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); + E1000_WRITE_FLUSH(hw); + usec_delay(150); + + rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(0)); + /* zero the lower 14 bits (prefetch and host thresholds) */ + rxdctl &= 0xffffc000; + /* + * update thresholds: prefetch threshold to 31, host threshold to 1 + * and make sure the granularity is "descriptors" and not "cache lines" + */ + rxdctl |= (0x1F | (1 << 8) | E1000_RXDCTL_THRESH_UNIT_DESC); + E1000_WRITE_REG(hw, E1000_RXDCTL(0), rxdctl); + + /* momentarily enable the RX ring for the changes to take effect */ + E1000_WRITE_REG(hw, E1000_RCTL, rctl | E1000_RCTL_EN); + E1000_WRITE_FLUSH(hw); + usec_delay(150); + E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); +} + +/********************************************************************* + * em_flush_desc_rings - remove all descriptors from the descriptor rings + * + * In I219, the descriptor rings must be emptied before resetting the HW + * or before changing the device state to D3 during runtime (runtime PM). + * + * Failure to do this will cause the HW to enter a unit hang state which can + * only be released by PCI reset on the device + * + **********************************************************************/ +static void +em_flush_desc_rings(struct e1000_softc *sc) +{ + struct e1000_hw *hw = &sc->hw; + device_t dev = sc->dev; + u16 hang_state; + u32 fext_nvm11, tdlen; + + /* First, disable MULR fix in FEXTNVM11 */ + fext_nvm11 = E1000_READ_REG(hw, E1000_FEXTNVM11); + fext_nvm11 |= E1000_FEXTNVM11_DISABLE_MULR_FIX; + E1000_WRITE_REG(hw, E1000_FEXTNVM11, fext_nvm11); + + /* do nothing if we're not in faulty state, or if the queue is empty */ + tdlen = E1000_READ_REG(hw, E1000_TDLEN(0)); + hang_state = pci_read_config(dev, PCICFG_DESC_RING_STATUS, 2); + if (!(hang_state & FLUSH_DESC_REQUIRED) || !tdlen) + return; + em_flush_tx_ring(sc); + + /* recheck, maybe the fault is caused by the rx ring */ + hang_state = pci_read_config(dev, PCICFG_DESC_RING_STATUS, 2); + if (hang_state & FLUSH_DESC_REQUIRED) + em_flush_rx_ring(sc); +} + /********************************************************************* * @@ -2680,6 +2791,10 @@ em_reset(if_ctx_t ctx) break; } + /* I219 needs some special flushing to avoid hangs */ + if (sc->hw.mac.type >= e1000_pch_spt && sc->hw.mac.type < igb_mac_min) + em_flush_desc_rings(sc); + /* Issue a global reset */ e1000_reset_hw(hw); if (hw->mac.type >= igb_mac_min) {