From nobody Tue Aug 11 20:10:43 2026 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 4hKN6D2741z6pG04 for ; Tue, 11 Aug 2026 20:10:44 +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 "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hKN6D0WnNz3wYb for ; Tue, 11 Aug 2026 20:10:44 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1786479044; 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=ozh3p2ObpXCZa4eMg+XuhX1U4ERRc/bZyn23bVBVzKo=; b=nLXsDho7B4mELRXkLcWooTNa2IkrbqnTY09Tg6wpYHVEB9Pba40CbuCgigPa8fRw5ghfF4 DY05fGduAhN2AbqpFxIJZ2eKDenh2itm+KaJ1nOomlj6W+3I4p/DW933pMZnkydG2DpeNo cr9/oUX3IIaYs0NIUfT4o+cqWTFudBPY6RI1hJJnPAifm+G90cBRT+5ZJIXCVs7LnnYKhV 8g0PeQeRwC0X0nmpsodKt5Ar/zvLfBUcuni6fOEkZCe+WGoaxAuFY9KHeLqifL+OD2QdRP x1wZKd4x6d1WL0tnaeOnUKXudIesAqhormZAjCP+avBroGKy6BuIIwA0F3GUDQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1786479044; a=rsa-sha256; cv=none; b=MO96K2fhP+sugI9SiV6wygDdig06zzLmYfSHIs0qHwt3kBVIrW0/PUllBTZ1u2S4j+QZzz PKNvLcsDOPwFUxD9Jq0XQSBKZUQcJLL3SzFeK4gqCQQf+yZomLDjyGCvICT+B21sSkwX5y xaVsF6QL6spgKR8M4EKFhBO/5BKoG99v9GzGPSaDzbaVp8m8wLEb3c7CMFWqNa4A1RvHNI C8M1D55v7CYJUwRVeza5krIVIWURApArRyw6e4iFSiBuRZ+jSJrB0OpkxkRrvzCK27zc/c LOK3qmIKbQWOm6dQbjQYEAnOJP8C83IBCd5Hr3kiBwj3IHnKfbkCkybMjLQjqw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1786479044; 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=ozh3p2ObpXCZa4eMg+XuhX1U4ERRc/bZyn23bVBVzKo=; b=kzZ46K/49JYmgIPlwKe5bLao7/SivVqcG8WKcyo+vd5e8eIJnkljYPZZNKNwgdIppX7391 ZcAhyoZo9/kwykMAgsWOGUsW5/TPkJc5krsXGp+9RnkTHpqckn4AjtsUVpoVGzYuEPmAdv E2BwK6nCl0BJWXv2T/WJ5hYiTcIiSkGTzQZ/HEC4HkeJqjaorEzBDrb83m6kp710WyeQqb l1AfRZ6B8HCeSB5ADF+1kv8MluHDD4Pf1hE5hlAfUuMCJUKKfo6HdqsSoP3i5XCwOwy5fk xiwFX1tExsV3jrzVXMMReOttNNOknxnFrg8fKu5hm+ZB/ZOcevpYQJeG0FSprA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hKN6C6802z18TR for ; Tue, 11 Aug 2026 20:10:43 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 31774 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 11 Aug 2026 20:10:43 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: 262519268925 - main - e1000: Separate hardware semaphore policies by family 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: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list 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: 26251926892585e0746c2b65227e56cf9b2fed58 Auto-Submitted: auto-generated Date: Tue, 11 Aug 2026 20:10:43 +0000 Message-Id: <6a7b81c3.31774.1f28e774@gitrepo.freebsd.org> The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=26251926892585e0746c2b65227e56cf9b2fed58 commit 26251926892585e0746c2b65227e56cf9b2fed58 Author: Kevin Bowling AuthorDate: 2026-08-11 18:58:17 +0000 Commit: Kevin Bowling CommitDate: 2026-08-11 20:08:43 +0000 e1000: Separate hardware semaphore policies by family The shared semaphore helper accesses both the 82571 retry counter and the I210 one-time-clear flag. Those fields occupy overlapping members of the device-specific union. On 82571, incrementing the counter thus enables the I210 recovery and clears SMBI after the first timeout. Give 82571, generic 80003/82575, and I210/I211 users distinct acquire paths. Preserve the legacy peer-driver policy on 82571 and one-time recovery on I210. The separation follows the Intel e1000 base code in DPDK. MFC after: 2 weeks --- sys/dev/e1000/e1000_82571.c | 62 ++++++++++++++++++++-- sys/dev/e1000/e1000_82575.c | 5 +- sys/dev/e1000/e1000_i210.c | 126 +++++++++++++++++++++++++++++++++++++++++++- sys/dev/e1000/e1000_i210.h | 2 + sys/dev/e1000/e1000_mac.c | 51 ++++-------------- sys/dev/e1000/e1000_mac.h | 2 +- 6 files changed, 201 insertions(+), 47 deletions(-) diff --git a/sys/dev/e1000/e1000_82571.c b/sys/dev/e1000/e1000_82571.c index 650169663f56..a0a183e326ca 100644 --- a/sys/dev/e1000/e1000_82571.c +++ b/sys/dev/e1000/e1000_82571.c @@ -72,6 +72,7 @@ static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data); static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw); static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw); static s32 e1000_get_phy_id_82571(struct e1000_hw *hw); +static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw); static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw); static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw); static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, @@ -122,7 +123,7 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) phy->ops.get_cable_length = e1000_get_cable_length_igp_2; phy->ops.read_reg = e1000_read_phy_reg_igp; phy->ops.write_reg = e1000_write_phy_reg_igp; - phy->ops.acquire = e1000_get_hw_semaphore; + phy->ops.acquire = e1000_get_hw_semaphore_82571; phy->ops.release = e1000_put_hw_semaphore; break; case e1000_82573: @@ -135,7 +136,7 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) phy->ops.get_cable_length = e1000_get_cable_length_m88; phy->ops.read_reg = e1000_read_phy_reg_m88; phy->ops.write_reg = e1000_write_phy_reg_m88; - phy->ops.acquire = e1000_get_hw_semaphore; + phy->ops.acquire = e1000_get_hw_semaphore_82571; phy->ops.release = e1000_put_hw_semaphore; break; case e1000_82574: @@ -615,6 +616,61 @@ static s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active) return E1000_SUCCESS; } +/** + * e1000_get_hw_semaphore_82571 - Acquire hardware semaphore + * @hw: pointer to the HW structure + * + * Acquire the hardware semaphore while preserving the 82571 inter-port + * compatibility policy. + **/ +static s32 +e1000_get_hw_semaphore_82571(struct e1000_hw *hw) +{ + u32 swsm; + s32 sw_timeout = hw->nvm.word_size + 1; + s32 fw_timeout = hw->nvm.word_size + 1; + s32 i = 0; + + DEBUGFUNC("e1000_get_hw_semaphore_82571"); + + /* + * After three SMBI timeouts, minimize interference with an older + * peer driver which may not release the inter-port semaphore. + */ + if (hw->dev_spec._82571.smb_counter > 2) + sw_timeout = 1; + + while (i < sw_timeout) { + swsm = E1000_READ_REG(hw, E1000_SWSM); + if (!(swsm & E1000_SWSM_SMBI)) + break; + usec_delay(50); + i++; + } + + if (i == sw_timeout) { + DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); + hw->dev_spec._82571.smb_counter++; + } + + for (i = 0; i < fw_timeout; i++) { + swsm = E1000_READ_REG(hw, E1000_SWSM); + E1000_WRITE_REG(hw, E1000_SWSM, + swsm | E1000_SWSM_SWESMBI); + if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI) + break; + usec_delay(50); + } + + if (i == fw_timeout) { + e1000_put_hw_semaphore(hw); + DEBUGOUT("Driver can't access the NVM\n"); + return -E1000_ERR_NVM; + } + + return E1000_SUCCESS; +} + /** * e1000_acquire_nvm_82571 - Request for access to the EEPROM * @hw: pointer to the HW structure @@ -630,7 +686,7 @@ static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw) DEBUGFUNC("e1000_acquire_nvm_82571"); - ret_val = e1000_get_hw_semaphore(hw); + ret_val = e1000_get_hw_semaphore_82571(hw); if (ret_val) return ret_val; diff --git a/sys/dev/e1000/e1000_82575.c b/sys/dev/e1000/e1000_82575.c index d0aebbce74d8..f8b512266acf 100644 --- a/sys/dev/e1000/e1000_82575.c +++ b/sys/dev/e1000/e1000_82575.c @@ -426,6 +426,10 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync; /* release SW_FW sync */ mac->ops.release_swfw_sync = e1000_release_swfw_sync; + if (mac->type == e1000_i210 || mac->type == e1000_i211) { + mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_i210; + mac->ops.release_swfw_sync = e1000_release_swfw_sync_i210; + } /* set lan id for port to determine which phy lock to use */ hw->mac.ops.set_lan_id(hw); @@ -3532,4 +3536,3 @@ void e1000_i2c_bus_clear(struct e1000_hw *hw) /* Put the i2c bus back to default state */ e1000_i2c_stop(hw); } - diff --git a/sys/dev/e1000/e1000_i210.c b/sys/dev/e1000/e1000_i210.c index 4005034d7d31..a38e1c10ab67 100644 --- a/sys/dev/e1000/e1000_i210.c +++ b/sys/dev/e1000/e1000_i210.c @@ -37,6 +37,7 @@ static s32 e1000_acquire_nvm_i210(struct e1000_hw *hw); static void e1000_release_nvm_i210(struct e1000_hw *hw); +static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw); static s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); static s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw); @@ -57,7 +58,7 @@ static s32 e1000_acquire_nvm_i210(struct e1000_hw *hw) DEBUGFUNC("e1000_acquire_nvm_i210"); - ret_val = e1000_acquire_swfw_sync(hw, E1000_SWFW_EEP_SM); + ret_val = e1000_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); return ret_val; } @@ -73,7 +74,128 @@ static void e1000_release_nvm_i210(struct e1000_hw *hw) { DEBUGFUNC("e1000_release_nvm_i210"); - e1000_release_swfw_sync(hw, E1000_SWFW_EEP_SM); + e1000_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); +} + +/** + * e1000_acquire_swfw_sync_i210 - Acquire SW/FW semaphore + * @hw: pointer to the HW structure + * @mask: specifies which semaphore to acquire + **/ +s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask) +{ + u32 swfw_sync; + u32 swmask = mask; + u32 fwmask = mask << 16; + s32 ret_val = E1000_SUCCESS; + s32 i = 0, timeout = 200; + + DEBUGFUNC("e1000_acquire_swfw_sync_i210"); + ASSERT_NO_LOCKS(); + + while (i < timeout) { + if (e1000_get_hw_semaphore_i210(hw)) { + ret_val = -E1000_ERR_SWFW_SYNC; + goto out; + } + + swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); + if (!(swfw_sync & (fwmask | swmask))) + break; + + e1000_put_hw_semaphore(hw); + msec_delay_irq(5); + i++; + } + + if (i == timeout) { + DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); + ret_val = -E1000_ERR_SWFW_SYNC; + goto out; + } + + swfw_sync |= swmask; + E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); + e1000_put_hw_semaphore(hw); + +out: + return ret_val; +} + +/** + * e1000_release_swfw_sync_i210 - Release SW/FW semaphore + * @hw: pointer to the HW structure + * @mask: specifies which semaphore to release + **/ +void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask) +{ + u32 swfw_sync; + + DEBUGFUNC("e1000_release_swfw_sync_i210"); + + while (e1000_get_hw_semaphore_i210(hw) != E1000_SUCCESS) + ; /* Empty */ + + swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); + swfw_sync &= (u32)~mask; + E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); + e1000_put_hw_semaphore(hw); +} + +/** + * e1000_get_hw_semaphore_i210 - Acquire hardware semaphore + * @hw: pointer to the HW structure + **/ +static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw) +{ + u32 swsm; + s32 timeout = hw->nvm.word_size + 1; + s32 i = 0; + + DEBUGFUNC("e1000_get_hw_semaphore_i210"); + + while (i < timeout) { + swsm = E1000_READ_REG(hw, E1000_SWSM); + if (!(swsm & E1000_SWSM_SMBI)) + break; + usec_delay(50); + i++; + } + + if (i == timeout) { + /* Clear an unintentionally retained semaphore once. */ + if (hw->dev_spec._82575.clear_semaphore_once) { + hw->dev_spec._82575.clear_semaphore_once = false; + e1000_put_hw_semaphore(hw); + for (i = 0; i < timeout; i++) { + swsm = E1000_READ_REG(hw, E1000_SWSM); + if (!(swsm & E1000_SWSM_SMBI)) + break; + usec_delay(50); + } + } + if (i == timeout) { + DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); + return -E1000_ERR_NVM; + } + } + + for (i = 0; i < timeout; i++) { + swsm = E1000_READ_REG(hw, E1000_SWSM); + E1000_WRITE_REG(hw, E1000_SWSM, + swsm | E1000_SWSM_SWESMBI); + if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI) + break; + usec_delay(50); + } + + if (i == timeout) { + e1000_put_hw_semaphore(hw); + DEBUGOUT("Driver can't access the NVM\n"); + return -E1000_ERR_NVM; + } + + return E1000_SUCCESS; } /** diff --git a/sys/dev/e1000/e1000_i210.h b/sys/dev/e1000/e1000_i210.h index 6f82462246e0..1d648ce41261 100644 --- a/sys/dev/e1000/e1000_i210.h +++ b/sys/dev/e1000/e1000_i210.h @@ -46,6 +46,8 @@ s32 e1000_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, s32 e1000_read_invm_version(struct e1000_hw *hw, struct e1000_fw_version *invm_ver); s32 e1000_init_hw_i210(struct e1000_hw *hw); +s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask); +void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask); #define E1000_STM_OPCODE 0xDB00 #define E1000_EEPROM_FLASH_SIZE_WORD 0x11 diff --git a/sys/dev/e1000/e1000_mac.c b/sys/dev/e1000/e1000_mac.c index dcebd9cf1eb9..a2e05498c681 100644 --- a/sys/dev/e1000/e1000_mac.c +++ b/sys/dev/e1000/e1000_mac.c @@ -2190,34 +2190,21 @@ s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg, } /** - * e1000_get_hw_semaphore - Acquire hardware semaphore + * e1000_get_hw_semaphore_generic - Acquire hardware semaphore * @hw: pointer to the HW structure * * Acquire the HW semaphore to access the PHY or NVM **/ -s32 e1000_get_hw_semaphore(struct e1000_hw *hw) +s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw) { u32 swsm; - s32 fw_timeout = hw->nvm.word_size + 1; - s32 sw_timeout = hw->nvm.word_size + 1; + s32 timeout = hw->nvm.word_size + 1; s32 i = 0; - DEBUGFUNC("e1000_get_hw_semaphore"); - - /* _82571 */ - /* If we have timedout 3 times on trying to acquire - * the inter-port SMBI semaphore, there is old code - * operating on the other port, and it is not - * releasing SMBI. Modify the number of times that - * we try for the semaphore to interwork with this - * older code. - */ - if (hw->dev_spec._82571.smb_counter > 2) - sw_timeout = 1; - + DEBUGFUNC("e1000_get_hw_semaphore_generic"); /* Get the SW semaphore */ - while (i < sw_timeout) { + while (i < timeout) { swsm = E1000_READ_REG(hw, E1000_SWSM); if (!(swsm & E1000_SWSM_SMBI)) break; @@ -2226,28 +2213,13 @@ s32 e1000_get_hw_semaphore(struct e1000_hw *hw) i++; } - if (i == sw_timeout) { + if (i == timeout) { DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); - hw->dev_spec._82571.smb_counter++; + return -E1000_ERR_NVM; } - /* In rare circumstances, the SW semaphore may already be held - * unintentionally. Clear the semaphore once before giving up. - */ - if (hw->dev_spec._82575.clear_semaphore_once) { - hw->dev_spec._82575.clear_semaphore_once = false; - e1000_put_hw_semaphore(hw); - for (i = 0; i < fw_timeout; i++) { - swsm = E1000_READ_REG(hw, E1000_SWSM); - if (!(swsm & E1000_SWSM_SMBI)) - break; - - usec_delay(50); - } - } - /* Get the FW semaphore. */ - for (i = 0; i < fw_timeout; i++) { + for (i = 0; i < timeout; i++) { swsm = E1000_READ_REG(hw, E1000_SWSM); E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI); @@ -2258,7 +2230,7 @@ s32 e1000_get_hw_semaphore(struct e1000_hw *hw) usec_delay(50); } - if (i == fw_timeout) { + if (i == timeout) { /* Release semaphores */ e1000_put_hw_semaphore(hw); DEBUGOUT("Driver can't access the NVM\n"); @@ -2308,7 +2280,7 @@ e1000_acquire_swfw_sync(struct e1000_hw *hw, u16 mask) DEBUGFUNC("e1000_acquire_swfw_sync"); ASSERT_NO_LOCKS(); while (i < timeout) { - if (e1000_get_hw_semaphore(hw)) { + if (e1000_get_hw_semaphore_generic(hw)) { ret_val = -E1000_ERR_SWFW_SYNC; goto out; } @@ -2356,7 +2328,7 @@ e1000_release_swfw_sync(struct e1000_hw *hw, u16 mask) DEBUGFUNC("e1000_release_swfw_sync"); - while (e1000_get_hw_semaphore(hw) != E1000_SUCCESS) + while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS) ; /* Empty */ swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); @@ -2365,4 +2337,3 @@ e1000_release_swfw_sync(struct e1000_hw *hw, u16 mask) e1000_put_hw_semaphore(hw); } - diff --git a/sys/dev/e1000/e1000_mac.h b/sys/dev/e1000/e1000_mac.h index a0d609e311d9..a08e64c4b23e 100644 --- a/sys/dev/e1000/e1000_mac.h +++ b/sys/dev/e1000/e1000_mac.h @@ -91,7 +91,7 @@ void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop); void e1000_update_adaptive_generic(struct e1000_hw *hw); void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); -s32 e1000_get_hw_semaphore(struct e1000_hw *hw); +s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw); void e1000_put_hw_semaphore(struct e1000_hw *hw); s32 e1000_acquire_swfw_sync(struct e1000_hw *hw, u16 mask); void e1000_release_swfw_sync(struct e1000_hw *hw, u16 mask);