hyperv/hn: Save capabilities for later use.

And don't allow capability changes during reinitialization, which
breaks too much static configuration.

MFC after:	1 week
Sponsored by:	Microsoft
Differential Revision:	https://reviews.freebsd.org/D7922
This commit is contained in:
Sepherosa Ziehau 2016-09-19 07:17:43 +00:00
parent 34ccb11831
commit ae75f7ee26
4 changed files with 74 additions and 7 deletions

View File

@ -467,9 +467,15 @@ hn_nvs_conf_ndis(struct hn_softc *sc, int mtu)
/* NOTE: No response. */
error = hn_nvs_req_send(sc, &conf, sizeof(conf));
if (error)
if (error) {
if_printf(sc->hn_ifp, "send nvs ndis conf failed: %d\n", error);
return (error);
return (error);
}
if (bootverbose)
if_printf(sc->hn_ifp, "nvs ndis conf done\n");
sc->hn_caps |= HN_CAP_MTU | HN_CAP_VLAN;
return (0);
}
static int

View File

@ -228,7 +228,8 @@ struct hn_softc {
struct vmbus_xact_ctx *hn_xact;
uint32_t hn_nvs_ver;
uint32_t hn_flags;
uint32_t hn_caps; /* HN_CAP_ */
uint32_t hn_flags; /* HN_FLAG_ */
void *hn_rxbuf;
uint32_t hn_rxbuf_gpadl;
struct hyperv_dma hn_rxbuf_dma;
@ -245,6 +246,16 @@ struct hn_softc {
#define HN_FLAG_RXBUF_CONNECTED 0x0001
#define HN_FLAG_CHIM_CONNECTED 0x0002
#define HN_CAP_VLAN 0x0001
#define HN_CAP_MTU 0x0002
#define HN_CAP_IPCS 0x0004
#define HN_CAP_TCP4CS 0x0008
#define HN_CAP_TCP6CS 0x0010
#define HN_CAP_UDP4CS 0x0020
#define HN_CAP_UDP6CS 0x0040
#define HN_CAP_TSO4 0x0080
#define HN_CAP_TSO6 0x0100
/*
* Externs
*/

View File

@ -325,6 +325,7 @@ static int hn_rx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS);
static int hn_tx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS);
static int hn_tx_conf_int_sysctl(SYSCTL_HANDLER_ARGS);
static int hn_ndis_version_sysctl(SYSCTL_HANDLER_ARGS);
static int hn_caps_sysctl(SYSCTL_HANDLER_ARGS);
static int hn_rss_key_sysctl(SYSCTL_HANDLER_ARGS);
static int hn_rss_ind_sysctl(SYSCTL_HANDLER_ARGS);
static int hn_check_iplen(const struct mbuf *, int);
@ -641,6 +642,9 @@ netvsc_attach(device_t dev)
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "ndis_version",
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
hn_ndis_version_sysctl, "A", "NDIS version");
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "caps",
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
hn_caps_sysctl, "A", "capabilities");
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rss_key",
CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, 0,
hn_rss_key_sysctl, "IU", "RSS key");
@ -2094,6 +2098,30 @@ hn_ndis_version_sysctl(SYSCTL_HANDLER_ARGS)
return sysctl_handle_string(oidp, verstr, sizeof(verstr), req);
}
static int
hn_caps_sysctl(SYSCTL_HANDLER_ARGS)
{
struct hn_softc *sc = arg1;
char caps_str[128];
uint32_t caps;
HN_LOCK(sc);
caps = sc->hn_caps;
HN_UNLOCK(sc);
snprintf(caps_str, sizeof(caps_str), "%b", caps,
"\020"
"\001VLAN"
"\002MTU"
"\003IPCS"
"\004TCP4CS"
"\005TCP6CS"
"\006UDP4CS"
"\007UDP6CS"
"\010TSO4"
"\011TSO6");
return sysctl_handle_string(oidp, caps_str, sizeof(caps_str), req);
}
static int
hn_rss_key_sysctl(SYSCTL_HANDLER_ARGS)
{
@ -3223,6 +3251,11 @@ hn_synth_attach(struct hn_softc *sc, int mtu)
{
struct ndis_rssprm_toeplitz *rss = &sc->hn_rss;
int error, nsubch, nchan, i;
uint32_t old_caps;
/* Save capabilities for later verification. */
old_caps = sc->hn_caps;
sc->hn_caps = 0;
/*
* Attach the primary channel _before_ attaching NVS and RNDIS.
@ -3245,6 +3278,17 @@ hn_synth_attach(struct hn_softc *sc, int mtu)
if (error)
return (error);
/*
* Make sure capabilities are not changed.
*/
if (device_is_attached(sc->hn_dev) && old_caps != sc->hn_caps) {
if_printf(sc->hn_ifp, "caps mismatch old 0x%08x, new 0x%08x\n",
old_caps, sc->hn_caps);
/* Restore old capabilities and abort. */
sc->hn_caps = old_caps;
return ENXIO;
}
/*
* Allocate sub-channels for multi-TX/RX rings.
*

View File

@ -800,6 +800,7 @@ static int
hn_rndis_conf_offload(struct hn_softc *sc)
{
struct ndis_offload_params params;
uint32_t caps;
size_t paramsz;
int error;
@ -816,24 +817,29 @@ hn_rndis_conf_offload(struct hn_softc *sc)
}
params.ndis_hdr.ndis_size = paramsz;
caps = HN_CAP_IPCS | HN_CAP_TCP4CS | HN_CAP_TCP6CS;
params.ndis_ip4csum = NDIS_OFFLOAD_PARAM_TXRX;
params.ndis_tcp4csum = NDIS_OFFLOAD_PARAM_TXRX;
params.ndis_tcp6csum = NDIS_OFFLOAD_PARAM_TXRX;
if (sc->hn_ndis_ver >= HN_NDIS_VERSION_6_30) {
caps |= HN_CAP_UDP4CS | HN_CAP_UDP6CS;
params.ndis_udp4csum = NDIS_OFFLOAD_PARAM_TXRX;
params.ndis_udp6csum = NDIS_OFFLOAD_PARAM_TXRX;
}
caps |= HN_CAP_TSO4;
params.ndis_lsov2_ip4 = NDIS_OFFLOAD_LSOV2_ON;
/* XXX ndis_lsov2_ip6 = NDIS_OFFLOAD_LSOV2_ON */
error = hn_rndis_set(sc, OID_TCP_OFFLOAD_PARAMETERS, &params, paramsz);
if (error) {
if_printf(sc->hn_ifp, "offload config failed: %d\n", error);
} else {
if (bootverbose)
if_printf(sc->hn_ifp, "offload config done\n");
return (error);
}
return (error);
if (bootverbose)
if_printf(sc->hn_ifp, "offload config done\n");
sc->hn_caps |= caps;
return (0);
}
int