From nobody Tue Sep 15 02:06:40 2026 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 4hkQPL1HMWz6sMfH for ; Tue, 15 Sep 2026 02:06:46 +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 "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hkQPL11gsz4b1L for ; Tue, 15 Sep 2026 02:06:46 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789438006; 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=tmgHHED+sCOaH5o1zZfcnO+8078Kl562jVGm+4XNBFE=; b=H2FQirYXj8E2h7BT/5/vc8Mtxkq91cDqdidO+4/gl0qIY9j337Nlb2fq0xRNRqNK+84aEl DZx0KS0IvcblVT4lPsMmBGd6AxVy/qb7LMNGyqQnW8WljQ+TownNIyfPXr+8IStswXN2Ml 9TVBDeQNeoOlDWuNErApgYGZxUpJonN1aO7D1rjXCXvdJ132ReY06iQI1m7XIBqXudHpBA 0352fGxnUs2nBNRwSchmEAr2h6VcMWszQKD4H76GCz4lL+JiLePDWRXfpruNnuQeE2YGiS KJucjjK3qoM57ZogayNKbe1U2CGfcm4TA30NFCPMhHWq+6wtGdehFr5FGFsO+Q== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1789438006; b=YlqMpjH4kXc5vm0/iUDE7EXp843YFJ1uqu5MbpqCDjT+noaWElJkRjX6lZ4aLvlUBa1uG3 PEivPVVsdoaLlLMwGqpVJUdT/1uusL73SFFXIz1rUlIRMSScWy18fD3JK7IDPCccObN4Ad 0LugTRbRHEEG/tOYOpfn8DB6UxjUxht28bf70SyzpGtKOkU76R/OqbQ4bvY3i3ppnPl3j7 pnybgbu0qP8LZZyb5frLd56jrZ2mplRwJ4Qvbu4PH4GdEk4DY2Lphozv/QKmvbRE+PqvoR o1Tjs0wkGXXLio6IAV6akYS6JJA0ShpJfouq4LZ9xRYB+EAJlPn4ytVMN3spXQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789438006; 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=tmgHHED+sCOaH5o1zZfcnO+8078Kl562jVGm+4XNBFE=; b=YqaBLfypy/HzBn1xsEQ16S4iZPMRiJPZ0x5n1Qc61SGa8fAgNb7xcgeu/P267N6FA0pxi8 fcX91CFfEXLEo84VzzjlIS8fS7HBLAuv6weMX0PZXnKSEZz++FywSHaU0BUwBo1C0hS0K8 OzK6y+P53yvuZeOkKDQSmRC0bS9EnoOeTE5vdwEZVWHcPyZXohoLs/pdIIHzCFoTXIQk92 WOR6b0lD22TieNUMfK02NRbyPfCBd+ZLanEjdSAAKrHUvsbA2/NC9QE5apqiHwVzbXYbbK qAPzPM61tOpPvFSOUt7Ln1ZkirZfEeXzbh7qM50ZdqR4jPM1E7M2KY/+vdlZfw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hkQPL05FDzgb6 for ; Tue, 15 Sep 2026 02:06:46 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 262b3 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 15 Sep 2026 02:06:40 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: 9ea7beb173b8 - main - ixv: Add Hyper-V virtual function support 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: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@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: 9ea7beb173b8b5c77663ee0f86b32cc76f20357f Auto-Submitted: auto-generated Date: Tue, 15 Sep 2026 02:06:40 +0000 Message-Id: <6aa8a830.262b3.a980264@gitrepo.freebsd.org> The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=9ea7beb173b8b5c77663ee0f86b32cc76f20357f commit 9ea7beb173b8b5c77663ee0f86b32cc76f20357f Author: Kevin Bowling AuthorDate: 2026-09-07 03:34:50 +0000 Commit: Kevin Bowling CommitDate: 2026-09-15 02:05:00 +0000 ixv: Add Hyper-V virtual function support Hyper-V does not expose the normal Intel PF/VF mailbox. Import the Hyper-V operation overrides from DPDK and complete its reset callback with the configuration-space mechanism submitted by Microsoft. Route ixv operations through the operation table, use mailbox API 1.0, and limit this environment to one queue pair. Claim the 82599, X540, X550, X550EM-X, and X550EM-A Hyper-V device IDs listed by DPDK. Select the same path for the E610 Hyper-V subdevice identity defined there. For E610/Linkville, read the emulated VFLINKS-format status from PCI configuration space at offset 0x209. Older families retain the MMIO VFLINKS path. Treat receive-mode changes as host-owned no-ops and do not retry VLAN operations that Hyper-V permanently rejects. Limit the Hyper-V 82599 MTU to 1504 because its VF does not implement the X540 RLPML field. Use mailbox reset indications only to refresh cached Hyper-V link state. Hyper-V does not provide the mailbox handshake required to treat that indication as a request for an iflib reinitialization. Tested on 82599 and E610 (with a followup commit) with Windows Server 2025 Hyper-V. PR: 232472, 239849 Obtained from: DPDK (shared code) Sponsored by: BBOX.io Co-authored-by: Wei Hu --- share/man/man4/ixv.4 | 11 +- sys/conf/files | 2 + sys/dev/ixgbe/if_ixv.c | 134 ++++++++++++++------- sys/dev/ixgbe/ixgbe_hv_vf.c | 277 ++++++++++++++++++++++++++++++++++++++++++++ sys/dev/ixgbe/ixgbe_hv_vf.h | 12 ++ sys/dev/ixgbe/ixgbe_osdep.c | 8 +- sys/dev/ixgbe/ixgbe_osdep.h | 4 + sys/modules/ixv/Makefile | 1 + 8 files changed, 406 insertions(+), 43 deletions(-) diff --git a/share/man/man4/ixv.4 b/share/man/man4/ixv.4 index 6acc41737294..907ff30103ec 100644 --- a/share/man/man4/ixv.4 +++ b/share/man/man4/ixv.4 @@ -28,7 +28,7 @@ .\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS .\" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd August 15, 2026 +.Dd September 6, 2026 .Dt IXV 4 .Os .Sh NAME @@ -60,7 +60,8 @@ guest. .Pp The driver supports jumbo frames, MSI-X, receive-side scaling, TCP segmentation offload, checksum offload, and VLAN hardware offload. -The maximum supported MTU is 9710 bytes. +The maximum supported MTU is 9710 bytes, except that an 82599 VF on +Hyper-V is limited to 1504 bytes. .Pp The physical-function driver controls the resources and policy presented to the virtual function. @@ -70,6 +71,12 @@ MSI-X vectors. Requests to change the MAC address, VLAN membership, or receive mode may be rejected by physical-function policy. .Pp +On Hyper-V, the host provides reset and assigned-address information through +PCI configuration space instead of the Intel PF/VF mailbox. +The driver uses one queue pair in this environment. +MAC address, VLAN, multicast filter, and receive mode policies remain under +host control. +.Pp The virtual function cannot configure the physical media. Only automatic media selection is supported, and reported link state and speed are supplied by the physical function or virtual-function hardware. diff --git a/sys/conf/files b/sys/conf/files index a195d93cb169..c10592263caa 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2348,6 +2348,8 @@ dev/ixgbe/ixgbe_common.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_fw_logging.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" +dev/ixgbe/ixgbe_hv_vf.c optional ixv inet \ + compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_mbx.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_vf.c optional ix inet | ixv inet \ diff --git a/sys/dev/ixgbe/if_ixv.c b/sys/dev/ixgbe/if_ixv.c index 8405ac1aa8f9..a5e8a9b39de1 100644 --- a/sys/dev/ixgbe/if_ixv.c +++ b/sys/dev/ixgbe/if_ixv.c @@ -37,6 +37,7 @@ #include "opt_rss.h" #include "ixgbe.h" +#include "ixgbe_hv_vf.h" #include "ifdi_if.h" #include @@ -74,14 +75,27 @@ static const pci_vendor_info_t ixv_vendor_info_array[] = { PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_VF, "Intel(R) X520 82599 Virtual Function"), + PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_VF_HV, + "Intel(R) X520 82599 Hyper-V Virtual Function"), PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540_VF, "Intel(R) X540 Virtual Function"), + PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540_VF_HV, + "Intel(R) X540 Hyper-V Virtual Function"), PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550_VF, "Intel(R) X550 Virtual Function"), + PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550_VF_HV, + "Intel(R) X550 Hyper-V Virtual Function"), PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_VF, "Intel(R) X552 Virtual Function"), + PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_VF_HV, + "Intel(R) X552 Hyper-V Virtual Function"), PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_VF, "Intel(R) X553 Virtual Function"), + PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_VF_HV, + "Intel(R) X553 Hyper-V Virtual Function"), + PVID_OEM(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_E610_VF, 0, + IXGBE_SUBDEV_ID_E610_VF_HV, 0, + "Intel(R) E610 Hyper-V Virtual Function"), PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_E610_VF, "Intel(R) E610 Virtual Function"), /* required last entry */ @@ -92,7 +106,6 @@ static const pci_vendor_info_t ixv_vendor_info_array[] = * Function prototypes ************************************************************************/ static void *ixv_register(device_t); -static int ixv_probe(device_t); static int ixv_if_attach_pre(if_ctx_t); static int ixv_if_attach_post(if_ctx_t); static int ixv_if_detach(if_ctx_t); @@ -104,6 +117,7 @@ static int ixv_if_rx_queues_alloc(if_ctx_t, caddr_t *, uint64_t *, int, int); static void ixv_if_queues_free(if_ctx_t); static void ixv_identify_hardware(if_ctx_t); +static bool ixv_is_hyperv(const struct ixgbe_hw *); static void ixv_init_device_features(struct ixgbe_softc *); static int ixv_allocate_pci_resources(if_ctx_t); static void ixv_free_pci_resources(if_ctx_t); @@ -133,6 +147,7 @@ static void ixv_initialize_receive_units(if_ctx_t); static void ixv_initialize_rss_mapping(struct ixgbe_softc *); static void ixv_setup_vlan_support(if_ctx_t); +static bool ixv_vlan_error_retryable(s32); static void ixv_vlan_retry_add(struct ixgbe_softc *, u16); static void ixv_vlan_retry_clear(struct ixgbe_softc *, u16); static bool ixv_vlan_retry_pending(const struct ixgbe_softc *); @@ -168,7 +183,7 @@ static int ixv_msix_mbx(void *); static device_method_t ixv_methods[] = { /* Device interface */ DEVMETHOD(device_register, ixv_register), - DEVMETHOD(device_probe, ixv_probe), + DEVMETHOD(device_probe, iflib_device_probe), DEVMETHOD(device_attach, iflib_device_attach), DEVMETHOD(device_detach, iflib_device_detach), DEVMETHOD(device_shutdown, iflib_device_shutdown), @@ -257,16 +272,6 @@ ixv_register(device_t dev) return (&ixv_sctx_init); } -static int -ixv_probe(device_t dev) -{ - if (pci_get_device(dev) == IXGBE_DEV_ID_E610_VF && - pci_get_subdevice(dev) == IXGBE_SUBDEV_ID_E610_VF_HV) - return (ENXIO); - - return (iflib_device_probe(dev)); -} - /************************************************************************ * ixv_if_tx_queues_alloc ************************************************************************/ @@ -457,9 +462,12 @@ ixv_if_attach_pre(if_ctx_t ctx) sc->vf_link_poll_tick = device_get_unit(dev) % IXV_LINK_POLL_TICKS; /* Initialize the shared code */ - error = ixgbe_init_ops_vf(hw); + if (ixv_is_hyperv(hw)) + error = ixgbevf_hv_init_ops_vf(hw); + else + error = ixgbe_init_ops_vf(hw); if (error) { - device_printf(dev, "ixgbe_init_ops_vf() failed!\n"); + device_printf(dev, "VF shared-code initialization failed\n"); error = EIO; goto err_out; } @@ -603,10 +611,16 @@ ixv_if_mtu_set(if_ctx_t ctx, uint32_t mtu) { struct ixgbe_softc *sc = iflib_get_softc(ctx); if_t ifp = iflib_get_ifp(ctx); + uint32_t max_mtu; int error = 0; IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)"); - if (mtu > IXGBE_MAX_FRAME_SIZE - IXGBE_MTU_HDR) { + max_mtu = IXGBE_MAX_FRAME_SIZE - IXGBE_MTU_HDR; + /* The 82599 VF cannot enforce the X540 RLPML field. */ + if (ixv_is_hyperv(&sc->hw) && + sc->hw.mac.type == ixgbe_mac_82599_vf) + max_mtu = ETHERMTU + ETHER_CRC_LEN; + if (mtu > max_mtu) { error = EINVAL; } else { if_setmtu(ifp, mtu); @@ -1071,12 +1085,12 @@ ixv_negotiate_api(struct ixgbe_softc *sc) }; int i = 0; - if (hw->mac.type == ixgbe_mac_E610_vf && - ixgbevf_negotiate_api_version(hw, ixgbe_mbox_api_16) == 0) + if (hw->mac.type == ixgbe_mac_E610_vf && !ixv_is_hyperv(hw) && + hw->mac.ops.negotiate_api_version(hw, ixgbe_mbox_api_16) == 0) return (0); while (mbx_api[i] != ixgbe_mbox_api_unknown) { - if (ixgbevf_negotiate_api_version(hw, mbx_api[i]) == 0) + if (hw->mac.ops.negotiate_api_version(hw, mbx_api[i]) == 0) return (0); i++; } @@ -1097,22 +1111,26 @@ ixv_queue_limit(struct ixgbe_softc *sc, bool mailbox_ready) int admin_vectors, limit, msix_vectors; hw = &sc->hw; - /* Preserve the current family limit as the mailbox fallback. */ - switch (hw->mac.type) { - case ixgbe_mac_82599_vf: - case ixgbe_mac_X540_vf: - limit = 1; - break; - case ixgbe_mac_X550_vf: - case ixgbe_mac_X550EM_x_vf: - case ixgbe_mac_X550EM_a_vf: - limit = 2; - break; - case ixgbe_mac_E610_vf: + if (ixv_is_hyperv(hw)) { limit = 1; - break; - default: - return (1); + } else { + /* Preserve the current family limit as the mailbox fallback. */ + switch (hw->mac.type) { + case ixgbe_mac_82599_vf: + case ixgbe_mac_X540_vf: + limit = 1; + break; + case ixgbe_mac_X550_vf: + case ixgbe_mac_X550EM_x_vf: + case ixgbe_mac_X550EM_a_vf: + limit = 2; + break; + case ixgbe_mac_E610_vf: + limit = 1; + break; + default: + return (1); + } } /* Replace the fallback with the queue grant reported by the PF. */ @@ -1162,7 +1180,7 @@ ixv_update_xcast_mode(struct ixgbe_softc *sc, int flags) mode = IXGBEVF_XCAST_MODE_MULTI; else mode = IXGBEVF_XCAST_MODE_NONE; - return (ixgbevf_update_xcast_mode(&sc->hw, mode)); + return (sc->hw.mac.ops.update_xcast_mode(&sc->hw, mode)); } static int @@ -1306,7 +1324,13 @@ ixv_if_update_admin_status(if_ctx_t ctx) if (sc->hw.mac.type != ixgbe_mac_E610_vf || sc->hw.api_version != ixgbe_mbox_api_16) check_link = true; - reset_seen = ixgbe_check_for_rst(&sc->hw, 0) == IXGBE_SUCCESS; + /* + * Hyper-V uses this indication only to invalidate cached VFLINKS + * state; it does not expose the mailbox handshake needed to turn it + * into a driver reset. Its check_link operation samples the bit. + */ + reset_seen = !ixv_is_hyperv(&sc->hw) && + ixgbe_check_for_rst(&sc->hw, 0) == IXGBE_SUCCESS; if (reset_seen) sc->hw.mac.get_link_status = true; if (check_link) { @@ -1442,18 +1466,23 @@ ixv_identify_hardware(if_ctx_t ctx) /* A subset of set_mac_type */ switch (hw->device_id) { case IXGBE_DEV_ID_82599_VF: + case IXGBE_DEV_ID_82599_VF_HV: hw->mac.type = ixgbe_mac_82599_vf; break; case IXGBE_DEV_ID_X540_VF: + case IXGBE_DEV_ID_X540_VF_HV: hw->mac.type = ixgbe_mac_X540_vf; break; case IXGBE_DEV_ID_X550_VF: + case IXGBE_DEV_ID_X550_VF_HV: hw->mac.type = ixgbe_mac_X550_vf; break; case IXGBE_DEV_ID_X550EM_X_VF: + case IXGBE_DEV_ID_X550EM_X_VF_HV: hw->mac.type = ixgbe_mac_X550EM_x_vf; break; case IXGBE_DEV_ID_X550EM_A_VF: + case IXGBE_DEV_ID_X550EM_A_VF_HV: hw->mac.type = ixgbe_mac_X550EM_a_vf; break; case IXGBE_DEV_ID_E610_VF: @@ -1466,6 +1495,24 @@ ixv_identify_hardware(if_ctx_t ctx) } } /* ixv_identify_hardware */ +static bool +ixv_is_hyperv(const struct ixgbe_hw *hw) +{ + switch (hw->device_id) { + case IXGBE_DEV_ID_82599_VF_HV: + case IXGBE_DEV_ID_X540_VF_HV: + case IXGBE_DEV_ID_X550_VF_HV: + case IXGBE_DEV_ID_X550EM_X_VF_HV: + case IXGBE_DEV_ID_X550EM_A_VF_HV: + return (true); + case IXGBE_DEV_ID_E610_VF: + return (hw->subsystem_device_id == + IXGBE_SUBDEV_ID_E610_VF_HV); + default: + return (false); + } +} + /************************************************************************ * ixv_if_msix_intr_assign - Setup MSI-X Interrupt resources and handlers ************************************************************************/ @@ -1854,7 +1901,7 @@ ixv_initialize_receive_units(if_ctx_t ctx) IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, psrtype); /* Tell PF our max_frame size */ - if (ixgbevf_rlpml_set_vf(hw, sc->max_frame_size) != 0) { + if (hw->mac.ops.set_rlpml(hw, sc->max_frame_size) != 0) { device_printf(sc->dev, "There is a problem with the PF setup. It is likely the" " receive unit for this VF will not function correctly." @@ -1954,6 +2001,12 @@ ixv_initialize_receive_units(if_ctx_t ctx) /************************************************************************ * VF VLAN mailbox retry helpers ************************************************************************/ +static bool +ixv_vlan_error_retryable(s32 error) +{ + return (error != IXGBE_ERR_FEATURE_NOT_SUPPORTED); +} + static void ixv_vlan_retry_add(struct ixgbe_softc *sc, u16 vid) { @@ -2051,7 +2104,7 @@ ixv_vlan_retry_tick(struct ixgbe_softc *sc) attempts++; enable = (sc->shadow_vfta[vid >> 5] & bit) != 0; error = hw->mac.ops.set_vfta(hw, vid, 0, enable, false); - if (error != IXGBE_SUCCESS) + if (error != IXGBE_SUCCESS && ixv_vlan_error_retryable(error)) break; ixv_vlan_retry_clear(sc, vid); } @@ -2109,7 +2162,8 @@ ixv_setup_vlan_support(if_ctx_t ctx) false); else error = IXGBE_ERR_MBX; - if (error != IXGBE_SUCCESS) { + if (error != IXGBE_SUCCESS && + ixv_vlan_error_retryable(error)) { ixv_vlan_retry_add(sc, vid); restore_failures++; } else @@ -2150,7 +2204,7 @@ ixv_if_register_vlan(if_ctx_t ctx, u16 vtag) return; error = sc->hw.mac.ops.set_vfta(&sc->hw, vtag, 0, true, false); - if (error != IXGBE_SUCCESS) { + if (error != IXGBE_SUCCESS && ixv_vlan_error_retryable(error)) { ixv_vlan_retry_add(sc, vtag); if (!pending) device_printf(sc->dev, @@ -2184,7 +2238,7 @@ ixv_if_unregister_vlan(if_ctx_t ctx, u16 vtag) return; error = sc->hw.mac.ops.set_vfta(&sc->hw, vtag, 0, false, false); - if (error != IXGBE_SUCCESS) { + if (error != IXGBE_SUCCESS && ixv_vlan_error_retryable(error)) { ixv_vlan_retry_add(sc, vtag); if (!pending) device_printf(sc->dev, diff --git a/sys/dev/ixgbe/ixgbe_hv_vf.c b/sys/dev/ixgbe/ixgbe_hv_vf.c new file mode 100644 index 000000000000..6ce994ff06f1 --- /dev/null +++ b/sys/dev/ixgbe/ixgbe_hv_vf.c @@ -0,0 +1,277 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2001-2024 Intel Corporation + */ + +#include "ixgbe_common.h" +#include "ixgbe_vf.h" +#include "ixgbe_hv_vf.h" + +/* Reading these PCI configuration bytes resets a VF on Hyper-V. */ +#define IXGBE_HV_RESET_OFFSET 0x201 + +/* E610 exposes VFLINKS in four emulated PCI configuration bytes. */ +#define IXGBE_HV_LINK_STATUS_OFFSET 0x209 +#define IXGBE_HV_LINK_STATUS_SIZE 4 + +/** + * ixgbevf_hv_update_mc_addr_list_vf - Hyper-V variant - just a stub. + * @hw: unused + * @mc_addr_list: unused + * @mc_addr_count: unused + * @next: unused + * @clear: unused + */ +static s32 +ixgbevf_hv_update_mc_addr_list_vf(struct ixgbe_hw *hw, u8 *mc_addr_list, + u32 mc_addr_count, ixgbe_mc_addr_itr next, bool clear) +{ + UNREFERENCED_5PARAMETER(hw, mc_addr_list, mc_addr_count, next, clear); + + return (IXGBE_ERR_FEATURE_NOT_SUPPORTED); +} + +/** + * ixgbevf_hv_update_xcast_mode - Leave receive-mode policy to Hyper-V + * @hw: unused + * @xcast_mode: unused + */ +static s32 +ixgbevf_hv_update_xcast_mode(struct ixgbe_hw *hw, int xcast_mode) +{ + UNREFERENCED_2PARAMETER(hw, xcast_mode); + + return (IXGBE_SUCCESS); +} + +/** + * ixgbevf_hv_set_vfta_vf - Hyper-V variant - just a stub. + * @hw: unused + * @vlan: unused + * @vind: unused + * @vlan_on: unused + * @vlvf_bypass: unused + */ +static s32 +ixgbevf_hv_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind, + bool vlan_on, bool vlvf_bypass) +{ + UNREFERENCED_5PARAMETER(hw, vlan, vind, vlan_on, vlvf_bypass); + + return (IXGBE_ERR_FEATURE_NOT_SUPPORTED); +} + +static s32 +ixgbevf_hv_set_uc_addr_vf(struct ixgbe_hw *hw, u32 index, u8 *addr) +{ + UNREFERENCED_3PARAMETER(hw, index, addr); + + return (IXGBE_ERR_FEATURE_NOT_SUPPORTED); +} + +/** + * ixgbevf_hv_reset_hw_vf - Reset through the Hyper-V PCI side channel + * @hw: pointer to hardware structure + * + * Hyper-V returns the permanent VF address when the guest reads six bytes + * beginning at offset 0x201 in PCI configuration space. The reads also + * perform the host-side VF reset handshake. + */ +static s32 +ixgbevf_hv_reset_hw_vf(struct ixgbe_hw *hw) +{ + int i; + + hw->api_version = ixgbe_mbox_api_10; + for (i = 0; i < IXGBE_ETH_LENGTH_OF_ADDRESS; i++) + hw->mac.perm_addr[i] = IXGBE_READ_PCIE_BYTE(hw, + IXGBE_HV_RESET_OFFSET + i); + if (ixgbe_validate_mac_addr(hw->mac.perm_addr) != IXGBE_SUCCESS) + return (IXGBE_ERR_INVALID_MAC_ADDR); + + return (IXGBE_SUCCESS); +} + +/** + * ixgbevf_hv_set_rar_vf - Hyper-V variant - just a stub. + * @hw: unused + * @index: unused + * @addr: unused + * @vmdq: unused + * @enable_addr: unused + */ +static s32 +ixgbevf_hv_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, + u32 enable_addr) +{ + UNREFERENCED_5PARAMETER(hw, index, addr, vmdq, enable_addr); + + return (IXGBE_ERR_FEATURE_NOT_SUPPORTED); +} + +static u32 +ixgbevf_hv_read_links(struct ixgbe_hw *hw) +{ + u32 links_reg; + int i; + + if (hw->mac.type != ixgbe_mac_E610_vf) + return (IXGBE_READ_REG(hw, IXGBE_VFLINKS)); + + links_reg = 0; + for (i = 0; i < IXGBE_HV_LINK_STATUS_SIZE; i++) + links_reg |= (u32)IXGBE_READ_PCIE_BYTE(hw, + IXGBE_HV_LINK_STATUS_OFFSET + i) << (i * NBBY); + return (links_reg); +} + +/** + * ixgbevf_hv_check_mac_link_vf - Check link without mailbox communication + * @hw: pointer to hardware structure + * @speed: pointer to link speed + * @link_up: true is link is up, false otherwise + * @autoneg_wait_to_complete: unused + */ +static s32 +ixgbevf_hv_check_mac_link_vf(struct ixgbe_hw *hw, ixgbe_link_speed *speed, + bool *link_up, bool autoneg_wait_to_complete) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + struct ixgbe_mac_info *mac = &hw->mac; + u32 links_reg; + + UNREFERENCED_1PARAMETER(autoneg_wait_to_complete); + + /* If we were hit with a reset, drop the cached link state. */ + if (!mbx->ops[0].check_for_rst(hw, 0) || !mbx->timeout) + mac->get_link_status = true; + if (!mac->get_link_status) + goto out; + + links_reg = ixgbevf_hv_read_links(hw); + if (!(links_reg & IXGBE_LINKS_UP)) + goto out; + + /* Link status can take up to 500 usec to settle on 82599. */ + if (mac->type == ixgbe_mac_82599_vf) { + int i; + + for (i = 0; i < 5; i++) { + usec_delay(100); + links_reg = ixgbevf_hv_read_links(hw); + if (!(links_reg & IXGBE_LINKS_UP)) + goto out; + } + } + + switch (links_reg & IXGBE_LINKS_SPEED_82599) { + case IXGBE_LINKS_SPEED_10G_82599: + *speed = IXGBE_LINK_SPEED_10GB_FULL; + if (hw->mac.type >= ixgbe_mac_X550_vf && + (links_reg & IXGBE_LINKS_SPEED_NON_STD) != 0) + *speed = IXGBE_LINK_SPEED_2_5GB_FULL; + break; + case IXGBE_LINKS_SPEED_1G_82599: + *speed = IXGBE_LINK_SPEED_1GB_FULL; + break; + case IXGBE_LINKS_SPEED_100_82599: + *speed = IXGBE_LINK_SPEED_100_FULL; + if ((hw->mac.type == ixgbe_mac_X550_vf || + hw->mac.type == ixgbe_mac_E610_vf) && + (links_reg & IXGBE_LINKS_SPEED_NON_STD) != 0) + *speed = IXGBE_LINK_SPEED_5GB_FULL; + break; + case IXGBE_LINKS_SPEED_10_X550EM_A: + *speed = IXGBE_LINK_SPEED_UNKNOWN; + if (hw->mac.type >= ixgbe_mac_X550_vf) + *speed = IXGBE_LINK_SPEED_10_FULL; + break; + default: + *speed = IXGBE_LINK_SPEED_UNKNOWN; + } + + mac->get_link_status = false; + +out: + *link_up = !mac->get_link_status; + return (IXGBE_SUCCESS); +} + +/** + * ixgbevf_hv_get_link_state_vf - Hyper-V has no mailbox link policy + * @hw: unused + * @link_state: unused + */ +static s32 +ixgbevf_hv_get_link_state_vf(struct ixgbe_hw *hw, bool *link_state) +{ + UNREFERENCED_2PARAMETER(hw, link_state); + + return (IXGBE_ERR_FEATURE_NOT_SUPPORTED); +} + +/** + * ixgbevf_hv_set_rlpml_vf - Set the maximum receive packet length + * @hw: pointer to hardware structure + * @max_size: maximum frame size + */ +static s32 +ixgbevf_hv_set_rlpml_vf(struct ixgbe_hw *hw, u16 max_size) +{ + u32 reg; + + /* RLPML is not implemented by the 82599 VF. */ + if (hw->mac.type == ixgbe_mac_82599_vf) + return (IXGBE_SUCCESS); + + reg = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(0)); + reg &= ~IXGBE_RXDCTL_RLPMLMASK; + reg |= ((max_size + 4) & IXGBE_RXDCTL_RLPMLMASK) | + IXGBE_RXDCTL_RLPML_EN; + IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(0), reg); + + return (IXGBE_SUCCESS); +} + +/** + * ixgbevf_hv_negotiate_api_version_vf - Negotiate the Hyper-V API version + * @hw: pointer to hardware structure + * @api: requested API version + */ +static int +ixgbevf_hv_negotiate_api_version_vf(struct ixgbe_hw *hw, int api) +{ + if (api != ixgbe_mbox_api_10) + return (IXGBE_ERR_INVALID_ARGUMENT); + + hw->api_version = api; + return (IXGBE_SUCCESS); +} + +/** + * ixgbevf_hv_init_ops_vf - Initialize Hyper-V VF operations + * @hw: pointer to hardware structure + */ +s32 +ixgbevf_hv_init_ops_vf(struct ixgbe_hw *hw) +{ + s32 status; + + status = ixgbe_init_ops_vf(hw); + if (status != IXGBE_SUCCESS) + return (status); + + hw->mac.ops.reset_hw = ixgbevf_hv_reset_hw_vf; + hw->mac.ops.check_link = ixgbevf_hv_check_mac_link_vf; + hw->mac.ops.negotiate_api_version = + ixgbevf_hv_negotiate_api_version_vf; + hw->mac.ops.set_rar = ixgbevf_hv_set_rar_vf; + hw->mac.ops.update_mc_addr_list = + ixgbevf_hv_update_mc_addr_list_vf; + hw->mac.ops.update_xcast_mode = ixgbevf_hv_update_xcast_mode; + hw->mac.ops.get_link_state = ixgbevf_hv_get_link_state_vf; + hw->mac.ops.set_uc_addr = ixgbevf_hv_set_uc_addr_vf; + hw->mac.ops.set_vfta = ixgbevf_hv_set_vfta_vf; + hw->mac.ops.set_rlpml = ixgbevf_hv_set_rlpml_vf; + + return (IXGBE_SUCCESS); +} diff --git a/sys/dev/ixgbe/ixgbe_hv_vf.h b/sys/dev/ixgbe/ixgbe_hv_vf.h new file mode 100644 index 000000000000..dd2e1eee4e9c --- /dev/null +++ b/sys/dev/ixgbe/ixgbe_hv_vf.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2001-2020 Intel Corporation + */ + +#ifndef _IXGBE_HV_VF_H_ +#define _IXGBE_HV_VF_H_ + +#include "ixgbe_type.h" + +s32 ixgbevf_hv_init_ops_vf(struct ixgbe_hw *hw); + +#endif /* _IXGBE_HV_VF_H_ */ diff --git a/sys/dev/ixgbe/ixgbe_osdep.c b/sys/dev/ixgbe/ixgbe_osdep.c index d96e15f4f87f..00b7f27faead 100644 --- a/sys/dev/ixgbe/ixgbe_osdep.c +++ b/sys/dev/ixgbe/ixgbe_osdep.c @@ -39,10 +39,16 @@ ixgbe_dev_from_hw(struct ixgbe_hw *hw) return ((struct ixgbe_softc *)hw->back)->dev; } +inline u8 +ixgbe_read_pci_cfg_byte(struct ixgbe_hw *hw, u32 reg) +{ + return (pci_read_config(ixgbe_dev_from_hw(hw), reg, 1)); +} + inline u16 ixgbe_read_pci_cfg(struct ixgbe_hw *hw, u32 reg) { - return pci_read_config(((struct ixgbe_softc *)hw->back)->dev, reg, 2); + return (pci_read_config(ixgbe_dev_from_hw(hw), reg, 2)); } inline void diff --git a/sys/dev/ixgbe/ixgbe_osdep.h b/sys/dev/ixgbe/ixgbe_osdep.h index ec2b3274ec31..2066033ea174 100644 --- a/sys/dev/ixgbe/ixgbe_osdep.h +++ b/sys/dev/ixgbe/ixgbe_osdep.h @@ -126,6 +126,7 @@ enum { #define UNREFERENCED_2PARAMETER(_p, _q) #define UNREFERENCED_3PARAMETER(_p, _q, _r) #define UNREFERENCED_4PARAMETER(_p, _q, _r, _s) +#define UNREFERENCED_5PARAMETER(_p, _q, _r, _s, _t) #define IXGBE_NTOHL(_i) ntohl(_i) #define IXGBE_NTOHS(_i) ntohs(_i) @@ -208,6 +209,9 @@ struct ixgbe_hw; device_t ixgbe_dev_from_hw(struct ixgbe_hw *hw); /* These routines are needed by the shared code */ +extern u8 ixgbe_read_pci_cfg_byte(struct ixgbe_hw *, u32); +#define IXGBE_READ_PCIE_BYTE ixgbe_read_pci_cfg_byte + extern u16 ixgbe_read_pci_cfg(struct ixgbe_hw *, u32); #define IXGBE_READ_PCIE_WORD ixgbe_read_pci_cfg diff --git a/sys/modules/ixv/Makefile b/sys/modules/ixv/Makefile index 743b2b407a5e..c2b27a689f76 100644 --- a/sys/modules/ixv/Makefile +++ b/sys/modules/ixv/Makefile @@ -6,6 +6,7 @@ SRCS += opt_inet.h opt_inet6.h opt_rss.h SRCS += if_ixv.c if_fdir.c ix_txrx.c ixgbe_osdep.c # Shared source SRCS += ixgbe_common.c ixgbe_api.c ixgbe_phy.c ixgbe_mbx.c ixgbe_vf.c +SRCS += ixgbe_hv_vf.c SRCS += ixgbe_dcb.c ixgbe_dcb_82598.c ixgbe_dcb_82599.c SRCS += ixgbe_82598.c ixgbe_82599.c ixgbe_x540.c ixgbe_x550.c ixgbe_e610.c SRCS += ixgbe_fw_logging.c