aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWei Hu <whu@FreeBSD.org>2025-02-04 13:39:14 +0000
committerWei Hu <whu@FreeBSD.org>2025-02-04 13:39:14 +0000
commitda1deb784d9ad3a4015a3f91fa1a5ce394fd3fdb (patch)
tree18f03f79714360bc4d99eb74a0425639da7a13bf
parentff977fd34b4bb85cf27b55106131b4dd6594afab (diff)
Hyper-V: hn: rewrite hn rsc swtich to avoid sysctl hang
Changing the rsc_switch flag using sysctl to turn rsc on or off could hang. The orignal code sends request to host to get the mtu setting. Sometimes the host fails to reply, causing the thread to sleep forever waiting for the host response. Use existing cached mtu from hn device instead to avoid calling host. Reported by: whu Tested by: whu MFC after: 1 week
-rw-r--r--sys/dev/hyperv/netvsc/if_hn.c30
1 files changed, 14 insertions, 16 deletions
diff --git a/sys/dev/hyperv/netvsc/if_hn.c b/sys/dev/hyperv/netvsc/if_hn.c
index 212b6bc0ff57..ab7671025107 100644
--- a/sys/dev/hyperv/netvsc/if_hn.c
+++ b/sys/dev/hyperv/netvsc/if_hn.c
@@ -2355,7 +2355,7 @@ hn_attach(device_t dev)
}
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rsc_switch",
- CTLTYPE_UINT | CTLFLAG_RW, sc, 0, hn_rsc_sysctl, "A",
+ CTLTYPE_UINT | CTLFLAG_RW, sc, 0, hn_rsc_sysctl, "I",
"switch to rsc");
/*
@@ -4523,24 +4523,22 @@ static int
hn_rsc_sysctl(SYSCTL_HANDLER_ARGS)
{
struct hn_softc *sc = arg1;
- uint32_t mtu;
+ int rsc_ctrl, mtu;
int error;
- HN_LOCK(sc);
- error = hn_rndis_get_mtu(sc, &mtu);
- if (error) {
- if_printf(sc->hn_ifp, "failed to get mtu\n");
- goto back;
- }
- error = SYSCTL_OUT(req, &(sc->hn_rsc_ctrl), sizeof(sc->hn_rsc_ctrl));
+
+ rsc_ctrl = sc->hn_rsc_ctrl;
+ error = sysctl_handle_int(oidp, &rsc_ctrl, 0, req);
if (error || req->newptr == NULL)
- goto back;
+ return (error);
+
+ if (sc->hn_rsc_ctrl != rsc_ctrl) {
+ HN_LOCK(sc);
+ sc->hn_rsc_ctrl = rsc_ctrl;
+ mtu = if_getmtu(sc->hn_ifp);
+ error = hn_rndis_reconf_offload(sc, mtu);
+ HN_UNLOCK(sc);
+ }
- error = SYSCTL_IN(req, &(sc->hn_rsc_ctrl), sizeof(sc->hn_rsc_ctrl));
- if (error)
- goto back;
- error = hn_rndis_reconf_offload(sc, mtu);
-back:
- HN_UNLOCK(sc);
return (error);
}
#ifndef RSS