Date: Thu, 30 Jul 2026 05:07:28 +0000 From: Kevin Bowling <kbowling@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 350211ab1782 - main - igb: Update only changed IOV multicast hashes Message-ID: <6a6adc10.32ef8.5247bc68@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=350211ab1782a68190754dcbdbcc7c9169ce22cb commit 350211ab1782a68190754dcbdbcc7c9169ce22cb Author: Kevin Bowling <kbowling@FreeBSD.org> AuthorDate: 2026-07-29 07:59:53 +0000 Commit: Kevin Bowling <kbowling@FreeBSD.org> CommitDate: 2026-07-30 05:06:33 +0000 igb: Update only changed IOV multicast hashes Build the aggregate PF/VF multicast bitmap in software and compare it with the e1000 MTA shadow. Write only registers whose desired value changed, while forcing a complete write after PF reset invalidates the hardware table. This bounds alternating VF multicast updates without NACKing them. Linux igbvf and DPDK ignore multicast reply status, so a command-rate limiter could otherwise acknowledge configuration while leaving hardware state stale. Sponsored by: BBOX.io --- sys/dev/e1000/if_em.c | 3 ++- sys/dev/e1000/if_em.h | 1 + sys/dev/e1000/if_igb_iov.c | 37 +++++++++++++++++++++++++++++-------- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index 0f60178ae3c8..4612653cf1bc 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -2554,7 +2554,8 @@ em_if_multi_set(if_ctx_t ctx) return; } - if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) + if (mcnt < MAX_NUM_MULTICAST_ADDRESSES && + !igb_iov_enabled(sc)) e1000_update_mc_addr_list(&sc->hw, mta, mcnt); reg_rctl = E1000_READ_REG(&sc->hw, E1000_RCTL); diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h index 93ddf0bfc25a..1692fdf41295 100644 --- a/sys/dev/e1000/if_em.h +++ b/sys/dev/e1000/if_em.h @@ -611,6 +611,7 @@ struct e1000_softc { u16 num_vf_mac_filters; u16 pool; bool iov_hw_active; + bool iov_mta_valid; bool iov_mbx_retry_initialized; bool iov_pf_mdd_blocked; bool iov_pf_vlan_promisc; diff --git a/sys/dev/e1000/if_igb_iov.c b/sys/dev/e1000/if_igb_iov.c index 1f66f9084e1a..8b8dfcd0a8f6 100644 --- a/sys/dev/e1000/if_igb_iov.c +++ b/sys/dev/e1000/if_igb_iov.c @@ -557,6 +557,7 @@ igb_iov_reset_prepare(struct e1000_softc *sc) sc->iov_hw_active = false; if (sc->iov_mbx_retry_initialized) callout_stop(&sc->iov_mbx_retry); + sc->iov_mta_valid = false; sc->iov_vfta_valid = false; atomic_readandclear_32(&sc->iov_mdd_cause); atomic_readandclear_32(&sc->iov_pending); @@ -568,8 +569,10 @@ igb_iov_rebuild_mta(struct e1000_softc *sc) { struct e1000_hw *hw; struct igb_vf *vf; - u32 mta; + u32 hash_bit, hash_reg, hash_value; + u32 mta[MAX_MTA_REG] = {}; u16 hash; + bool changed; int i, j, mcnt; if (!igb_iov_enabled(sc)) @@ -580,22 +583,38 @@ igb_iov_rebuild_mta(struct e1000_softc *sc) ETHER_ADDR_LEN * MAX_NUM_MULTICAST_ADDRESSES); mcnt = if_foreach_llmaddr(iflib_get_ifp(sc->ctx), igb_iov_copy_maddr, sc->mta); - e1000_update_mc_addr_list(hw, sc->mta, - min(mcnt, MAX_NUM_MULTICAST_ADDRESSES)); + mcnt = min(mcnt, MAX_NUM_MULTICAST_ADDRESSES); + for (i = 0; i < mcnt; i++) { + hash_value = e1000_hash_mc_addr(hw, + &sc->mta[i * ETHER_ADDR_LEN]); + hash_reg = (hash_value >> 5) & + (hw->mac.mta_reg_count - 1); + hash_bit = hash_value & 0x1f; + mta[hash_reg] |= 1U << hash_bit; + } for (i = 0; i < sc->num_vfs; i++) { vf = &sc->vfs[i]; if (!(vf->flags & IGB_VF_ACTIVE)) continue; for (j = 0; j < vf->mc_count; j++) { hash = vf->mc_hashes[j] & 0xfff; - mta = E1000_READ_REG_ARRAY(hw, E1000_MTA, - (hash >> 5) & 0x7f); - mta |= 1U << (hash & 0x1f); - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, - (hash >> 5) & 0x7f, mta); + mta[(hash >> 5) & (hw->mac.mta_reg_count - 1)] |= + 1U << (hash & 0x1f); } igb_iov_configure_vmolr(sc, vf); } + + changed = false; + for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) { + if (sc->iov_mta_valid && hw->mac.mta_shadow[i] == mta[i]) + continue; + hw->mac.mta_shadow[i] = mta[i]; + E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, mta[i]); + changed = true; + } + if (changed) + E1000_WRITE_FLUSH(hw); + sc->iov_mta_valid = true; } static int @@ -1641,6 +1660,7 @@ igb_if_iov_init(if_ctx_t ctx, u16 num_vfs, const nvlist_t *config) for (i = 0; i < sc->num_vf_mac_filters; i++) sc->vf_mac_filters[i].rar_index = i + 1; sc->pool = num_vfs; + sc->iov_mta_valid = false; sc->iov_pf_mdd_blocked = false; sc->tx_queues[0].txr.me = sc->pool; sc->rx_queues[0].rxr.me = sc->pool; @@ -1717,6 +1737,7 @@ igb_if_iov_uninit(if_ctx_t ctx) sc->num_vfs = 0; sc->num_vf_mac_filters = 0; sc->pool = 0; + sc->iov_mta_valid = false; sc->iov_pf_mdd_blocked = false; sc->iov_pf_vlan_promisc = false; sc->iov_vfta_valid = false;home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a6adc10.32ef8.5247bc68>
