From nobody Thu Oct 29 06:40:10 2026 X-Original-To: dev-commits-src-branches@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 4jFZNV56Y4z6xtrD for ; Thu, 29 Oct 2026 06:40:10 +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) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 4jFZNV23ztz3JhW for ; Thu, 29 Oct 2026 06:40:10 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1793256010; 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=AgqFu5qdNH7x4WgrXF4B0TuxW60RRy41IGKO4l8KbXc=; b=mAcGe/Wc4hhfyIpKSuM5Feo48IzamLUvFw94gY0Re4aD1PkPd2n2+M7JLKwRgUnmfXstuR OGqOn8Jjt7q6LGlUxb2tsDN96fbF7LrZDnd4mYn1iwX33mgXDYw6dXvVqm+koTZ1f0sg48 gO8adxLLyKcxK+/sJsiSJnIhUEkaNDDyQG/QmWXkIB5skagImAFBRw792rIv+3dDIB9Bo1 PkcABkI8emStj6flwkaM0kx8r1C02UwP/oPzjG/dsRzfzdVeOZEH5psHX/Z4vKfIq7a3Jp LGFjVIjhYWAe+gyb2OaI8pc45gnMs/r7kUfnfYMzCZ00gkUuFaNueTcHaBCexA== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1793256010; b=QpoURG6JyWhCXQZ5ZgwT8WL3kogD513B5Nq2D6yLsnO6phWToaUoRTSdpVvjPTfqqhiRF/ i73u0ZfoUTfw7ILwUitjsKHxAj4AJNLfhl98DepwXdH6oyWEVHnACBY3H6Lho7I+kACv8f TqRjUajYqDOXGNrbdVeMUmrJ99mRD3a6nJk3iuV5HlMGgVZZ2CZl6S/u6kuBp2sKrfK81K pMUEjrrO3d5TH4eCqAmcC7ch8/V8nUavem+zK1PcW2bQ2naKErhq61gucGycXQ97RuJEJV kMrHOLQyjfTwdfUeGY0RlCBv54Dc/14vfvSuW/4XbPMen79KtExRV3pbBNPS2A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1793256010; 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=AgqFu5qdNH7x4WgrXF4B0TuxW60RRy41IGKO4l8KbXc=; b=qTjeOJhVX9IkGqnDpH1RWtAr6wCgM302xU+ms00SrfMEQ66rfxUASNAVoyKXZtdzNCVuCD YGu+8JtAMMqCcAhP35QDuL+RvMPMfpFpyKz3wL2cwtCOc3VkFyUx+Ftm6nLxvuq8aHgPou W392SrFFJiUYnQnChbjRadwhs2KK298PQTw/skkepoCUEhECV5MR56fj9EiQd/YMdcbvdV TShuXXjFFHbkjWDpauNuLDn+928d8B9vcxOGu0meEYxiAUITKVI/4hGIDHZ0V0e3BscHc/ Lfp+lKwQ5UfD8LK7hlqfVw7yRtcci/kMDoTMxYZEhLWZcGDtLw8/WEHWzw9bOQ== 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 4jFZNV1jSlzRkv for ; Thu, 29 Oct 2026 06:40:10 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3e80a by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 29 Oct 2026 06:40:10 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kevin Bowling Subject: git: dfd72f6349b3 - stable/15 - ice: Make VF VLAN requests idempotent List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org List-Id: Commits to the stable branches of the FreeBSD src repository 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/stable/15 X-Git-Reftype: branch X-Git-Commit: dfd72f6349b368cc117d877e4e62244eaea80ca1 Auto-Submitted: auto-generated Date: Thu, 29 Oct 2026 06:40:10 +0000 Message-Id: <6ae2ea4a.3e80a.5ac2a4e4@gitrepo.freebsd.org> The branch stable/15 has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=dfd72f6349b368cc117d877e4e62244eaea80ca1 commit dfd72f6349b368cc117d877e4e62244eaea80ca1 Author: Kevin Bowling AuthorDate: 2026-08-18 10:44:24 +0000 Commit: Kevin Bowling CommitDate: 2026-10-29 06:39:23 +0000 ice: Make VF VLAN requests idempotent VF drivers replay their VLAN filters after a reset and may retry a request whose reply was lost. The PF tracked only a count and sent every requested ID back to the switch. After PF reset replay had already restored the filters, duplicate VID 0 failed with ICE_ERR_ALREADY_EXISTS and NACKed the entire VF batch. Track exact VLAN membership for each VF. Compact requests to unique IDs whose membership changes, enforce the configured limit against those IDs, and update membership after each hardware operation so partial failures cannot undercount filters. Treat already-present adds and already-absent deletes as successful reconciliation and suppress their misleading low-level error dump. Validated on an E810-XXV with a host-attached iavf VF. A three-filter limit was filled with VIDs 0, 1, and 4094. PF and CORE resets replayed all three without a duplicate warning or ADD_VLAN NACK, and DTrace confirmed a three-VID replay reached the PF. A fourth unique VID was rejected without changing the count; deleting an absent VID was a no-op; deleting and replacing a present VID updated the count exactly. A 128 four-queue VF create/destroy cycle also completed cleanly, and a newly recreated VF started with an empty membership map. Sponsored by: BBOX.io Differential Revision: https://reviews.freebsd.org/D58909 (cherry picked from commit 2231e505d1d40441b80cfacb5a92111d1408a935) --- sys/dev/ice/ice_iov.c | 107 +++++++++++++++++++++++++++++++++++++++----------- sys/dev/ice/ice_iov.h | 3 ++ sys/dev/ice/ice_lib.c | 4 +- 3 files changed, 89 insertions(+), 25 deletions(-) diff --git a/sys/dev/ice/ice_iov.c b/sys/dev/ice/ice_iov.c index 869fe43a9411..61f53aad89b9 100644 --- a/sys/dev/ice/ice_iov.c +++ b/sys/dev/ice/ice_iov.c @@ -79,6 +79,8 @@ static void ice_vc_add_vlan_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf); static void ice_vc_del_vlan_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf); +static int ice_vc_select_vlans(struct ice_vf *vf, u16 *vids, u16 count, + bool add, u16 *selected_count); static enum virtchnl_status_code ice_iov_err_to_virt_err(int ice_err); static int ice_vf_validate_mac(struct ice_vf *vf, const uint8_t *addr); @@ -959,6 +961,43 @@ ice_vc_del_eth_addr_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) v_status, NULL, 0, NULL); } +/** + * ice_vc_select_vlans - Compact a VF VLAN request in place + * @vf: VF tracking structure + * @vids: VLAN IDs supplied by the VF + * @count: number of VLAN IDs in the request + * @add: select absent VLANs for add, or present VLANs for delete + * @selected_count: returned number of VLAN IDs requiring a hardware change + * + * A VF may replay its entire VLAN configuration after a reset or retry a + * request whose reply was lost. Select only unique IDs whose membership + * actually changes so those requests remain idempotent and filter accounting + * continues to enforce the configured limit. + */ +static int +ice_vc_select_vlans(struct ice_vf *vf, u16 *vids, u16 count, bool add, + u16 *selected_count) +{ + bitstr_t bit_decl(seen, ICE_VF_VLAN_MAP_LEN); + u16 selected, vid; + + bzero(seen, sizeof(seen)); + selected = 0; + for (u16 i = 0; i < count; i++) { + vid = vids[i]; + if (vid > EVL_VLID_MASK) + return (EINVAL); + if (bit_test(seen, vid)) + continue; + bit_set(seen, vid); + if (bit_test(vf->vlans_map, vid) == add) + continue; + vids[selected++] = vid; + } + *selected_count = selected; + return (0); +} + /** * ice_vc_add_vlan_msg - Handle VIRTCHNL_OP_ADD_VLAN msg from VF * @sc: PF's softc structure @@ -972,6 +1011,7 @@ ice_vc_add_vlan_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) { struct ice_hw *hw = &sc->hw; struct virtchnl_vlan_filter_list *vlan_list; + u16 selected; int status = 0; enum virtchnl_status_code v_status = VIRTCHNL_STATUS_SUCCESS; struct ice_vsi *vsi = vf->vsi; @@ -986,23 +1026,34 @@ ice_vc_add_vlan_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) goto done; } - if (vlan_list->num_elements > (vf->vlan_limit - vf->vlan_cnt)) { - v_status = VIRTCHNL_STATUS_ERR_NO_MEMORY; + status = ice_vc_select_vlans(vf, vlan_list->vlan_id, + vlan_list->num_elements, true, &selected); + if (status != 0) { + v_status = VIRTCHNL_STATUS_ERR_PARAM; goto done; } - status = ice_add_vlan_hw_filters(vsi, vlan_list->vlan_id, - vlan_list->num_elements); - if (status) { - device_printf(sc->dev, - "VF-%d: Failure adding VLANs to VSI %d, err %s aq_err %s\n", - vf->vf_num, vsi->idx, ice_status_str(status), - ice_aq_str(sc->hw.adminq.sq_last_status)); - v_status = ice_iov_err_to_virt_err(status); + if ((u32)vf->vlan_cnt + selected > vf->vlan_limit) { + v_status = VIRTCHNL_STATUS_ERR_NO_MEMORY; goto done; } + if (selected == 0) + goto done; - vf->vlan_cnt += vlan_list->num_elements; + for (u16 i = 0; i < selected; i++) { + status = ice_add_vlan_hw_filter(vsi, vlan_list->vlan_id[i]); + if (status != 0 && status != ICE_ERR_ALREADY_EXISTS) { + device_printf(sc->dev, + "VF-%d: Failure adding VLAN %d to VSI %d, err %s aq_err %s\n", + vf->vf_num, vlan_list->vlan_id[i], vsi->idx, + ice_status_str(status), + ice_aq_str(sc->hw.adminq.sq_last_status)); + v_status = ice_iov_err_to_virt_err(status); + goto done; + } + bit_set(vf->vlans_map, vlan_list->vlan_id[i]); + vf->vlan_cnt++; + } done: ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_ADD_VLAN, @@ -1022,6 +1073,7 @@ ice_vc_del_vlan_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) { struct ice_hw *hw = &sc->hw; struct virtchnl_vlan_filter_list *vlan_list; + u16 selected; int status = 0; enum virtchnl_status_code v_status = VIRTCHNL_STATUS_SUCCESS; struct ice_vsi *vsi = vf->vsi; @@ -1036,21 +1088,30 @@ ice_vc_del_vlan_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) goto done; } - status = ice_remove_vlan_hw_filters(vsi, vlan_list->vlan_id, - vlan_list->num_elements); - if (status) { - device_printf(sc->dev, - "VF-%d: Failure deleting VLANs from VSI %d, err %s aq_err %s\n", - vf->vf_num, vsi->idx, ice_status_str(status), - ice_aq_str(sc->hw.adminq.sq_last_status)); - v_status = ice_iov_err_to_virt_err(status); + status = ice_vc_select_vlans(vf, vlan_list->vlan_id, + vlan_list->num_elements, false, &selected); + if (status != 0) { + v_status = VIRTCHNL_STATUS_ERR_PARAM; goto done; } + if (selected == 0) + goto done; - if (vlan_list->num_elements >= vf->vlan_cnt) - vf->vlan_cnt = 0; - else - vf->vlan_cnt -= vlan_list->num_elements; + for (u16 i = 0; i < selected; i++) { + status = ice_remove_vlan_hw_filter(vsi, vlan_list->vlan_id[i]); + if (status != 0 && status != ICE_ERR_DOES_NOT_EXIST) { + device_printf(sc->dev, + "VF-%d: Failure deleting VLAN %d from VSI %d, err %s aq_err %s\n", + vf->vf_num, vlan_list->vlan_id[i], vsi->idx, + ice_status_str(status), + ice_aq_str(sc->hw.adminq.sq_last_status)); + v_status = ice_iov_err_to_virt_err(status); + goto done; + } + bit_clear(vf->vlans_map, vlan_list->vlan_id[i]); + MPASS(vf->vlan_cnt > 0); + vf->vlan_cnt--; + } done: ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_DEL_VLAN, diff --git a/sys/dev/ice/ice_iov.h b/sys/dev/ice/ice_iov.h index 7d6d7fdb1211..0ebd1b1c0555 100644 --- a/sys/dev/ice/ice_iov.h +++ b/sys/dev/ice/ice_iov.h @@ -41,6 +41,7 @@ #define _ICE_IOV_H_ #include +#include #include #include #include @@ -91,6 +92,8 @@ struct ice_vf { u16 mac_filter_cnt; u16 vlan_limit; u16 vlan_cnt; +#define ICE_VF_VLAN_MAP_LEN (EVL_VLID_MASK + 1) + bitstr_t bit_decl(vlans_map, ICE_VF_VLAN_MAP_LEN); u16 num_irq_vectors; u16 *vf_imap; diff --git a/sys/dev/ice/ice_lib.c b/sys/dev/ice/ice_lib.c index 56a3ce0e465f..22fe1196838a 100644 --- a/sys/dev/ice/ice_lib.c +++ b/sys/dev/ice/ice_lib.c @@ -5592,7 +5592,7 @@ ice_add_vlan_hw_filters(struct ice_vsi *vsi, u16 *vid, u16 length) } status = ice_add_vlan(hw, &vlan_list); - if (!status) + if (!status || status == ICE_ERR_ALREADY_EXISTS) goto done; device_printf(vsi->sc->dev, "Failed to add VLAN filters:\n"); @@ -5657,7 +5657,7 @@ ice_remove_vlan_hw_filters(struct ice_vsi *vsi, u16 *vid, u16 length) } status = ice_remove_vlan(hw, &vlan_list); - if (!status) + if (!status || status == ICE_ERR_DOES_NOT_EXIST) goto done; device_printf(vsi->sc->dev, "Failed to remove VLAN filters:\n");