[PATCH net-next v11 12/12] enic: re-establish V2 VF admin channel and PF registration after reset
From: Satish Kharat <satishkh@cisco.com>
Date: 2026-07-03 18:09:25
Also in:
lkml
Subsystem:
cisco vic ethernet nic driver, networking drivers, the rest · Maintainers:
Satish Kharat, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
The reset paths (enic_reset/enic_tx_hang_reset) tore down and re-opened the V2 admin/MBOX channel only for the PF: the close/reopen was gated on enic_sriov_enabled() && vf_type == ENIC_VF_TYPE_V2, which is never true on a VF (vf_type is set only on the PF; VFs are identified by enic_is_sriov_vf_v2()). A VF-initiated reset therefore left the VF admin QP wiped by the reset but never re-opened, and the VF never re-registered with the PF, so VF<->PF MBOX traffic (link state, MAC, packet filter) stopped working until the VF was re-probed. Factor the decision into enic_has_admin_chan() (true for a V2 PF while SR-IOV is enabled and for every V2 VF) and the reopen sequence into enic_admin_chan_reopen(). For a VF the helper additionally re-runs the probe-time handshake (enic_mbox_vf_capability_check() + enic_mbox_vf_register()) so the PF learns about the VF again; for a PF it re-pushes the current link state as before. Signed-off-by: Satish Kharat <satishkh@cisco.com> --- drivers/net/ethernet/cisco/enic/enic_main.c | 105 +++++++++++++++++----------- 1 file changed, 65 insertions(+), 40 deletions(-)
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 99c06a049800..be3ae0a57af3 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c@@ -2171,6 +2171,57 @@ static void enic_set_api_busy(struct enic *enic, bool busy) spin_unlock(&enic->enic_api_lock); } +/* The admin/MBOX channel exists on a V2 PF while SR-IOV is enabled and on + * every V2 VF. A reset wipes the admin WQ/RQ/CQ, so such devices must tear + * the channel down before the reset and re-establish it afterwards. + */ +static bool enic_has_admin_chan(struct enic *enic) +{ + return enic_is_sriov_vf_v2(enic) || + (enic_sriov_enabled(enic) && enic->vf_type == ENIC_VF_TYPE_V2); +} + +/* Re-establish the admin/MBOX channel after a reset has re-created the data + * path. Mirrors the relevant part of the probe / SR-IOV-enable sequence: + * reopen the channel and reinitialise MBOX, then for a VF re-run the PF + * handshake (its admin QP and PF-side registration were torn down by the + * reset), or for a PF re-push the current link state to registered VFs. + */ +static void enic_admin_chan_reopen(struct enic *enic) +{ + int err; + + err = enic_admin_channel_open(enic); + if (err) { + netdev_err(enic->netdev, + "admin channel reopen after reset failed: %d\n", err); + return; + } + + enic_mbox_init(enic); + + if (enic_is_sriov_vf_v2(enic)) { + err = enic_mbox_vf_capability_check(enic); + if (err) { + netdev_err(enic->netdev, + "MBOX capability check after reset failed: %d\n", + err); + return; + } + err = enic_mbox_vf_register(enic); + if (err) + netdev_err(enic->netdev, + "MBOX VF re-registration after reset failed: %d\n", + err); + } else { + /* The link came back up during enic_open() above while MBOX + * sends were still disabled (channel not yet reopened), so that + * link-notify was dropped. Re-push current link state now. + */ + schedule_work(&enic->link_notify_work); + } +} + static void enic_reset(struct work_struct *work) { struct enic *enic = container_of(work, struct enic, reset);
@@ -2189,8 +2240,7 @@ static void enic_reset(struct work_struct *work) * DMAs from the about-to-be-reset rings) and frees the admin resources * so they are cleanly re-allocated afterwards. */ - if (enic_sriov_enabled(enic) && - enic->vf_type == ENIC_VF_TYPE_V2) + if (enic_has_admin_chan(enic)) enic_admin_channel_close(enic); enic_stop(enic->netdev);
@@ -2204,25 +2254,13 @@ static void enic_reset(struct work_struct *work) enic_open(enic->netdev); - /* Re-establish the admin/MBOX channel after the data path is back up, - * mirroring the SR-IOV enable path (channel open + mbox init). The - * channel was fully torn down by enic_admin_channel_close() above. + /* Re-establish the admin/MBOX channel after the data path is back up. + * It was fully torn down by enic_admin_channel_close() above; + * enic_admin_chan_reopen() reopens it and, for a PF re-pushes link + * state, or for a VF re-runs the probe-time PF handshake. */ - if (enic_sriov_enabled(enic) && - enic->vf_type == ENIC_VF_TYPE_V2) { - if (enic_admin_channel_open(enic)) { - netdev_err(enic->netdev, - "admin channel reopen after reset failed\n"); - } else { - enic_mbox_init(enic); - /* The link came back up during enic_open() above - * while MBOX sends were still disabled (channel not - * yet reopened), so that link-notify was dropped. - * Re-push current link state to registered VFs now. - */ - schedule_work(&enic->link_notify_work); - } - } + if (enic_has_admin_chan(enic)) + enic_admin_chan_reopen(enic); /* Allow infiniband to fiddle with the device again */ enic_set_api_busy(enic, false);
@@ -2245,8 +2283,7 @@ static void enic_tx_hang_reset(struct work_struct *work) * the same reason as the soft reset path: stop the admin QP and free * the admin resources before the hardware queues are wiped. */ - if (enic_sriov_enabled(enic) && - enic->vf_type == ENIC_VF_TYPE_V2) + if (enic_has_admin_chan(enic)) enic_admin_channel_close(enic); enic_dev_hang_notify(enic);
@@ -2261,25 +2298,13 @@ static void enic_tx_hang_reset(struct work_struct *work) enic_open(enic->netdev); - /* Re-establish the admin/MBOX channel after the data path is back up, - * mirroring the SR-IOV enable path (channel open + mbox init). The - * channel was fully torn down by enic_admin_channel_close() above. + /* Re-establish the admin/MBOX channel after the data path is back up. + * It was fully torn down by enic_admin_channel_close() above; + * enic_admin_chan_reopen() reopens it and, for a PF re-pushes link + * state, or for a VF re-runs the probe-time PF handshake. */ - if (enic_sriov_enabled(enic) && - enic->vf_type == ENIC_VF_TYPE_V2) { - if (enic_admin_channel_open(enic)) { - netdev_err(enic->netdev, - "admin channel reopen after reset failed\n"); - } else { - enic_mbox_init(enic); - /* The link came back up during enic_open() above - * while MBOX sends were still disabled (channel not - * yet reopened), so that link-notify was dropped. - * Re-push current link state to registered VFs now. - */ - schedule_work(&enic->link_notify_work); - } - } + if (enic_has_admin_chan(enic)) + enic_admin_chan_reopen(enic); /* Allow infiniband to fiddle with the device again */ enic_set_api_busy(enic, false);
--
2.43.0