diff --git a/sys/dev/hyperv/netvsc/hn_rndis.c b/sys/dev/hyperv/netvsc/hn_rndis.c index 108950aa3f9b1..58167312c9f32 100644 --- a/sys/dev/hyperv/netvsc/hn_rndis.c +++ b/sys/dev/hyperv/netvsc/hn_rndis.c @@ -579,6 +579,12 @@ hn_rndis_set(struct hn_softc *sc, uint32_t oid, const void *data, size_t dlen) return (error); } +int +hn_rndis_reconf_offload(struct hn_softc *sc, int mtu) +{ + return(hn_rndis_conf_offload(sc, mtu)); +} + static int hn_rndis_conf_offload(struct hn_softc *sc, int mtu) { @@ -725,7 +731,8 @@ hn_rndis_conf_offload(struct hn_softc *sc, int mtu) /* RSC offload */ if (hwcaps.ndis_hdr.ndis_rev >= NDIS_OFFLOAD_PARAMS_REV_3) { - if (hwcaps.ndis_rsc.ndis_ip4 && hwcaps.ndis_rsc.ndis_ip6) { + if (hwcaps.ndis_rsc.ndis_ip4 && hwcaps.ndis_rsc.ndis_ip6 && + sc->hn_rsc_ctrl) { params.ndis_rsc_ip4 = NDIS_OFFLOAD_RSC_ON; params.ndis_rsc_ip6 = NDIS_OFFLOAD_RSC_ON; } else { diff --git a/sys/dev/hyperv/netvsc/hn_rndis.h b/sys/dev/hyperv/netvsc/hn_rndis.h index 4610d5a105265..6e4db9b0bb30b 100644 --- a/sys/dev/hyperv/netvsc/hn_rndis.h +++ b/sys/dev/hyperv/netvsc/hn_rndis.h @@ -46,5 +46,6 @@ int hn_rndis_get_mtu(struct hn_softc *sc, uint32_t *mtu); int hn_rndis_set_rxfilter(struct hn_softc *sc, uint32_t filter); void hn_rndis_rx_ctrl(struct hn_softc *sc, const void *data, int dlen); +int hn_rndis_reconf_offload(struct hn_softc *sc, int mtu); #endif /* !_HN_RNDIS_H_ */ diff --git a/sys/dev/hyperv/netvsc/if_hn.c b/sys/dev/hyperv/netvsc/if_hn.c index 3d13bd696c948..95f62902fe6b2 100644 --- a/sys/dev/hyperv/netvsc/if_hn.c +++ b/sys/dev/hyperv/netvsc/if_hn.c @@ -454,6 +454,8 @@ static void hn_start_txeof(struct hn_tx_ring *); static void hn_start_txeof_taskfunc(void *, int); #endif +static int hn_rsc_sysctl(SYSCTL_HANDLER_ARGS); + SYSCTL_NODE(_hw, OID_AUTO, hn, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Hyper-V network interface"); @@ -2370,6 +2372,10 @@ hn_attach(device_t dev) "Accurate BPF for transparent VF"); } + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rsc_switch", + CTLTYPE_UINT | CTLFLAG_RW, sc, 0, hn_rsc_sysctl, "A", + "switch to rsc"); + /* * Setup the ifmedia, which has been initialized earlier. */ @@ -4567,6 +4573,30 @@ hn_rxfilter_sysctl(SYSCTL_HANDLER_ARGS) return sysctl_handle_string(oidp, filter_str, sizeof(filter_str), req); } +static int +hn_rsc_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct hn_softc *sc = arg1; + uint32_t 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)); + if (error || req->newptr == NULL) + goto back; + + 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 static int diff --git a/sys/dev/hyperv/netvsc/if_hnvar.h b/sys/dev/hyperv/netvsc/if_hnvar.h index 27d93db5395ea..7b23f0ec7cbff 100644 --- a/sys/dev/hyperv/netvsc/if_hnvar.h +++ b/sys/dev/hyperv/netvsc/if_hnvar.h @@ -282,6 +282,11 @@ struct hn_softc { u_int hn_saved_tsomax; u_int hn_saved_tsosegcnt; u_int hn_saved_tsosegsz; + + /* + * RSC switch, default off + */ + u_int hn_rsc_ctrl; }; #define HN_FLAG_RXBUF_CONNECTED 0x0001