From nobody Wed Feb 08 19:30:44 2023 X-Original-To: dev-commits-src-main@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 4PBqps1tJjz3nrXD; Wed, 8 Feb 2023 19:30:45 +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 4PBqps1R3mz4d2D; Wed, 8 Feb 2023 19:30:45 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1675884645; 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=Z6vQ1qOkzKX4Utrme5S5oNyW0TNyeM9QaeqDPqcCHP0=; b=c5q/SDgvlplZSSc/3rE4xAK3Oma8/cVmSFgY/+eKFf1qkGKUaTMCSPDPrq++Tt4QriWnpF YKLvEF5yJIxcgGGytSjilL4OZdPxoKz2zXqpi7a1Exaa+6RacWD/NzxCRqM6ZmUa0sRCrH JAim01OX6ay6I7gLCkPu9MPFJ0P45I5fy+T72WzmXyTo1urlRjOo+Ihwh6aaQH3jFq32y3 bVwEedW8Yopek7q7uTgUpUCbFonwi2er11hoEWA0IlWifTbbY+XQB2NwwTPG4keP+2sXE3 5LcFUOa7Kk0dvcbiN8BdDRXkwCyTEaByGe2oJbxkqORXCU0Ana3rvnLBqXA/kA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1675884645; 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=Z6vQ1qOkzKX4Utrme5S5oNyW0TNyeM9QaeqDPqcCHP0=; b=k7ivGfCt1dZFH4lxweRdHBKNcWmL0+syGa51lMSknXWT3Ycmfnr9Xoh3+4ksER0Zu5irLY ltMdV0bcl9OZWjN7zuhvqg1ATATe1BE3P6qkAlZl17BGXe1z6izivZOxQLGjxjvhULo39X 5kjhlLg6hV31i2/Ytc6b4UI1sUIfqI4xyOAVRu20KZFRIUl8nkBRReryq8W5xJQqw2TP0S eCNm0uhP48uqBPzWDGVby+WmxQ7S6IMFvyhQOmZE/OLZqTQVBWdrGEineIS7a0SX50DdiK +XO86Ju6ZxFpa39KeXFK646B/lZfM1idszbFYomjpKO7Jrt9cilC9ahhzAzMpg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1675884645; a=rsa-sha256; cv=none; b=MyeHzMgXw+xrprCYLv4825sffcS0Y0znV0skoHlhAqQFtF+RWFoAB9EPwNhqRW2gXKRdaA tEfM354/N5AeJPDuDxpHSWNwRqITJvQyQDWmeIYm55R6eKTc1Vu1byOxaNssFtLX6I/L4A Iea/59E4mcsoKkkJ796GdrDeY1pagHlrYhnrUg+V/gIUyes2yMYF1fQCpfaMNZuy2eBaBm hTLfTGdicS05znbNLu4hSHMyBUek5buCzZDleBoPKSB7ettmh/kCSrNCT2X48pazYqgkay xLKh8AD1sgQL8IdNkqs4K1qjSVYqL54QlQeQiO2G/5fYMxlJIFxU+CpGB/2ibg== 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 4PBqps0VLbz18BS; Wed, 8 Feb 2023 19:30:45 +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 318JUivQ036535; Wed, 8 Feb 2023 19:30:44 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 318JUicp036534; Wed, 8 Feb 2023 19:30:44 GMT (envelope-from git) Date: Wed, 8 Feb 2023 19:30:44 GMT Message-Id: <202302081930.318JUicp036534@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: ae1dca798e0f - main - e1000: fix I219 hang on reset List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@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/main X-Git-Reftype: branch X-Git-Commit: ae1dca798e0f826de46f4ec11914ba4c91928d7a Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by kbowling (ports committer): URL: https://cgit.FreeBSD.org/src/commit/?id=ae1dca798e0f826de46f4ec11914ba4c91928d7a commit ae1dca798e0f826de46f4ec11914ba4c91928d7a Author: Kevin Bowling AuthorDate: 2023-02-08 19:21:45 +0000 Commit: Kevin Bowling CommitDate: 2023-02-08 19:30:34 +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 MFC after: 2 weeks Sponsored by: BBOX.io Pull Request: https://github.com/freebsd/freebsd-src/pull/540 --- 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 7135f273fd94..6442b5f3f41e 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -351,6 +351,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 *); /********************************************************************* @@ -1913,6 +1914,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); @@ -1978,8 +1983,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); @@ -2467,6 +2471,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); +} + /********************************************************************* * @@ -2698,6 +2809,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) {