From nobody Wed Feb 22 00:48:40 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 4PLyFh6vkBz3tjqP; Wed, 22 Feb 2023 00:48:40 +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 4PLyFh5tV3z3F42; Wed, 22 Feb 2023 00:48:40 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1677026920; 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=j/973yX4zx8s/qCLRs3g0dgug/+UoNt0gLhsYqDZrnM=; b=l8S6GN/V3C7iYWD9pnMk4K6ag/uG3mThV6ALBJLCEEVGkEhaDNb5ImDNORzyclZEdDv6Rv PwQ6DjZ9znuXVY9AmLZOit7rjrWopMueNCyS6YgFmh8CC53/bdtVFa2xiY5QVe4ZNxdsTh 18s0kG9ssiPoE4H4meDhBDNIxpSXD0S0Hfs93UYegoH9WUjeC+3HEKVp/0VYT/Yw4+pq19 BSxAEeUmOyLH+bYU9wRJnB86mKx98FJ/9vmzezLBEjggYAOFbiJN+1Ms3KhaCe3uXNDG+P G45mD26qvU7eJiEhqro90LmCN+Iha0VApqTeOnI20DUM83dy6jrdIIj4a4T94A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1677026920; 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=j/973yX4zx8s/qCLRs3g0dgug/+UoNt0gLhsYqDZrnM=; b=m0N3WkjEdSxSjbP9hWUO/yt7yvPMWXHPswI6Oi18PlQsfJvPRX8MCDrWwfTKupLEhIDx/O vfsaDVlcLhBxyA88gCt9JDXkomzaWlSjCuYTvLyRZqO7Ku/mcW5W+6pdyz/sUAvoDnF0oS 988fTgAFgjcQcsTiZr9T6CkHuE1JJqh9ptknGlnQf+Bim1t3S8B8KLiykhVAJbpq5LTmyF hb/ZqsfMD7R5uGmPitA8KBuXS3tTrbd0N9PWGPC3ZimgBBtZVVTap5DJjyVTMfTSRq3TFa PfU//LJGJM4ltRRsfCwTCpqk+Jofponio4lzM+3xeCTK9ETsbgT+oR1XGo5+Jg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1677026920; a=rsa-sha256; cv=none; b=SzuZMF95zjQRE1N+kDoa2n+sWBY7MGIsnbcot9xU0k5ZO71xG6t3Uyy2QMWMcJQsTkjQt4 Xl4t7ymwT33NzIyQqERS7FXosT+HNWCvkQyonbICqw6ZDqvTgbD62JB3HFjypjxAcDdZMr N5Kr2LyImtFpXtuDF4zaUuU6ZZVGW0lyRRswSeHQdvdmd0He2UcZN0YdxqrYkih+etwhnr aNnB5asmb9lskR/hXHkxSGg96QAHqjJuvqkCmOZWup4koOYXB0DLzEdIPzU/I7w0iTUcUY sS12q34dio324VkTlHaPZkCQGQKjiBXRrTmOkutX/eDoRG6B3xqs472X1ohHdA== 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 4PLyFh4x3jzh55; Wed, 22 Feb 2023 00:48:40 +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 31M0meJh040984; Wed, 22 Feb 2023 00:48:40 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 31M0meXw040983; Wed, 22 Feb 2023 00:48:40 GMT (envelope-from git) Date: Wed, 22 Feb 2023 00:48:40 GMT Message-Id: <202302220048.31M0meXw040983@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: 17d1b8eef7d1 - stable/13 - 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/13 X-Git-Reftype: branch X-Git-Commit: 17d1b8eef7d18ad6093c5024bd25a9bca7c3febe Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=17d1b8eef7d18ad6093c5024bd25a9bca7c3febe commit 17d1b8eef7d18ad6093c5024bd25a9bca7c3febe Author: Kevin Bowling AuthorDate: 2023-02-08 19:21:45 +0000 Commit: Kevin Bowling CommitDate: 2023-02-22 00:48:25 +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 c17714dbd566..80a3bbee7814 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 *); /********************************************************************* @@ -1907,6 +1908,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); @@ -1972,8 +1977,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); @@ -2461,6 +2465,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); +} + /********************************************************************* * @@ -2692,6 +2803,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) {