svn commit: r310757 - stable/10/sys/dev/hyperv/netvsc
Sepherosa Ziehau
sephe at FreeBSD.org
Thu Dec 29 07:07:18 UTC 2016
Author: sephe
Date: Thu Dec 29 07:07:16 2016
New Revision: 310757
URL: https://svnweb.freebsd.org/changeset/base/310757
Log:
MFC 309226-309231,309235
309226
hyperv/hn: Utilize vmbus_chan_xact_wait
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D8612
309227
hyperv/hn: Fix detach error handling.
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D8613
309228
hyperv/hn: Fix multi-packet RNDIS message aggregation size setting.
Just in case that no chimney sending buffer can be used.
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D8619
309229
hyperv/hn: Fix attach error handling
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D8620
309230
hyperv/hn: Enable multi-packet RNDIS message support by default.
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D8621
309231
hyperv/hn: Fix vmbus_chan_subidx usage.
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D8629
309235
hyperv/hn: Simplify RSS indirect table fixup API
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D8630
Modified:
stable/10/sys/dev/hyperv/netvsc/hn_nvs.c
stable/10/sys/dev/hyperv/netvsc/hn_rndis.c
stable/10/sys/dev/hyperv/netvsc/if_hn.c
stable/10/sys/dev/hyperv/netvsc/if_hnvar.h
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/dev/hyperv/netvsc/hn_nvs.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hn_nvs.c Thu Dec 29 07:06:49 2016 (r310756)
+++ stable/10/sys/dev/hyperv/netvsc/hn_nvs.c Thu Dec 29 07:07:16 2016 (r310757)
@@ -62,8 +62,8 @@ __FBSDID("$FreeBSD$");
static int hn_nvs_conn_chim(struct hn_softc *);
static int hn_nvs_conn_rxbuf(struct hn_softc *);
-static int hn_nvs_disconn_chim(struct hn_softc *);
-static int hn_nvs_disconn_rxbuf(struct hn_softc *);
+static void hn_nvs_disconn_chim(struct hn_softc *);
+static void hn_nvs_disconn_rxbuf(struct hn_softc *);
static int hn_nvs_conf_ndis(struct hn_softc *, int);
static int hn_nvs_init_ndis(struct hn_softc *);
static int hn_nvs_doinit(struct hn_softc *, uint32_t);
@@ -109,10 +109,8 @@ hn_nvs_xact_execute(struct hn_softc *sc,
vmbus_xact_deactivate(xact);
return (NULL);
}
- if (HN_CAN_SLEEP(sc))
- hdr = vmbus_xact_wait(xact, &resplen);
- else
- hdr = vmbus_xact_busywait(xact, &resplen);
+ hdr = vmbus_chan_xact_wait(sc->hn_prichan, xact, &resplen,
+ HN_CAN_SLEEP(sc));
/*
* Check this NVS response message.
@@ -275,8 +273,14 @@ hn_nvs_conn_chim(struct hn_softc *sc)
goto cleanup;
}
if (sectsz == 0) {
+ /*
+ * Can't use chimney sending buffer; done!
+ */
if_printf(sc->hn_ifp, "zero chimney sending buffer "
"section size\n");
+ sc->hn_chim_szmax = 0;
+ sc->hn_chim_cnt = 0;
+ sc->hn_flags |= HN_FLAG_CHIM_CONNECTED;
return (0);
}
@@ -310,7 +314,7 @@ cleanup:
return (error);
}
-static int
+static void
hn_nvs_disconn_rxbuf(struct hn_softc *sc)
{
int error;
@@ -330,7 +334,12 @@ hn_nvs_disconn_rxbuf(struct hn_softc *sc
if (error) {
if_printf(sc->hn_ifp,
"send nvs rxbuf disconn failed: %d\n", error);
- return (error);
+ /*
+ * Fine for a revoked channel, since the hypervisor
+ * does not drain TX bufring for a revoked channel.
+ */
+ if (!vmbus_chan_is_revoked(sc->hn_prichan))
+ sc->hn_flags |= HN_FLAG_RXBUF_REF;
}
sc->hn_flags &= ~HN_FLAG_RXBUF_CONNECTED;
@@ -359,14 +368,13 @@ hn_nvs_disconn_rxbuf(struct hn_softc *sc
if (error) {
if_printf(sc->hn_ifp,
"rxbuf gpadl disconn failed: %d\n", error);
- return (error);
+ sc->hn_flags |= HN_FLAG_RXBUF_REF;
}
sc->hn_rxbuf_gpadl = 0;
}
- return (0);
}
-static int
+static void
hn_nvs_disconn_chim(struct hn_softc *sc)
{
int error;
@@ -386,7 +394,12 @@ hn_nvs_disconn_chim(struct hn_softc *sc)
if (error) {
if_printf(sc->hn_ifp,
"send nvs chim disconn failed: %d\n", error);
- return (error);
+ /*
+ * Fine for a revoked channel, since the hypervisor
+ * does not drain TX bufring for a revoked channel.
+ */
+ if (!vmbus_chan_is_revoked(sc->hn_prichan))
+ sc->hn_flags |= HN_FLAG_CHIM_REF;
}
sc->hn_flags &= ~HN_FLAG_CHIM_CONNECTED;
@@ -416,7 +429,7 @@ hn_nvs_disconn_chim(struct hn_softc *sc)
if (error) {
if_printf(sc->hn_ifp,
"chim gpadl disconn failed: %d\n", error);
- return (error);
+ sc->hn_flags |= HN_FLAG_CHIM_REF;
}
sc->hn_chim_gpadl = 0;
}
@@ -424,8 +437,8 @@ hn_nvs_disconn_chim(struct hn_softc *sc)
if (sc->hn_chim_bmap != NULL) {
free(sc->hn_chim_bmap, M_DEVBUF);
sc->hn_chim_bmap = NULL;
+ sc->hn_chim_bmap_cnt = 0;
}
- return (0);
}
static int
@@ -614,8 +627,10 @@ hn_nvs_attach(struct hn_softc *sc, int m
* Connect chimney sending buffer.
*/
error = hn_nvs_conn_chim(sc);
- if (error)
+ if (error) {
+ hn_nvs_disconn_rxbuf(sc);
return (error);
+ }
return (0);
}
Modified: stable/10/sys/dev/hyperv/netvsc/hn_rndis.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hn_rndis.c Thu Dec 29 07:06:49 2016 (r310756)
+++ stable/10/sys/dev/hyperv/netvsc/hn_rndis.c Thu Dec 29 07:07:16 2016 (r310757)
@@ -233,10 +233,8 @@ hn_rndis_xact_exec1(struct hn_softc *sc,
if_printf(sc->hn_ifp, "RNDIS ctrl send failed: %d\n", error);
return (NULL);
}
- if (HN_CAN_SLEEP(sc))
- return (vmbus_xact_wait(xact, comp_len));
- else
- return (vmbus_xact_busywait(xact, comp_len));
+ return (vmbus_chan_xact_wait(sc->hn_prichan, xact, comp_len,
+ HN_CAN_SLEEP(sc)));
}
static const void *
@@ -982,7 +980,6 @@ hn_rndis_attach(struct hn_softc *sc, int
/*
* Configure NDIS offload settings.
- * XXX no offloading, if error happened?
*/
hn_rndis_conf_offload(sc, mtu);
return (0);
Modified: stable/10/sys/dev/hyperv/netvsc/if_hn.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/if_hn.c Thu Dec 29 07:06:49 2016 (r310756)
+++ stable/10/sys/dev/hyperv/netvsc/if_hn.c Thu Dec 29 07:07:16 2016 (r310757)
@@ -299,6 +299,7 @@ static int hn_synth_attach(struct hn_s
static void hn_synth_detach(struct hn_softc *);
static int hn_synth_alloc_subchans(struct hn_softc *,
int *);
+static bool hn_synth_attachable(const struct hn_softc *);
static void hn_suspend(struct hn_softc *);
static void hn_suspend_data(struct hn_softc *);
static void hn_suspend_mgmt(struct hn_softc *);
@@ -321,7 +322,7 @@ static void hn_destroy_rx_data(struct
static int hn_check_iplen(const struct mbuf *, int);
static int hn_set_rxfilter(struct hn_softc *);
static int hn_rss_reconfig(struct hn_softc *);
-static void hn_rss_ind_fixup(struct hn_softc *, int);
+static void hn_rss_ind_fixup(struct hn_softc *);
static int hn_rxpkt(struct hn_rx_ring *, const void *,
int, const struct hn_rxinfo *);
@@ -467,7 +468,7 @@ SYSCTL_INT(_hw_hn, OID_AUTO, tx_agg_size
&hn_tx_agg_size, 0, "Packet transmission aggregation size limit");
/* Packet transmission aggregation count limit */
-static int hn_tx_agg_pkts = 0;
+static int hn_tx_agg_pkts = -1;
SYSCTL_INT(_hw_hn, OID_AUTO, tx_agg_pkts, CTLFLAG_RDTUN,
&hn_tx_agg_pkts, 0, "Packet transmission aggregation packet limit");
@@ -708,6 +709,10 @@ hn_set_txagg(struct hn_softc *sc)
if (sc->hn_rndis_agg_size < size)
size = sc->hn_rndis_agg_size;
+ /* NOTE: We only aggregate packets using chimney sending buffers. */
+ if (size > (uint32_t)sc->hn_chim_szmax)
+ size = sc->hn_chim_szmax;
+
if (size <= 2 * HN_PKTSIZE_MIN(sc->hn_rndis_agg_align)) {
/* Disable */
size = 0;
@@ -719,10 +724,6 @@ hn_set_txagg(struct hn_softc *sc)
if (size > INT_MAX)
size = INT_MAX;
- /* NOTE: We only aggregate packets using chimney sending buffers. */
- if (size > (uint32_t)sc->hn_chim_szmax)
- size = sc->hn_chim_szmax;
-
/*
* Setup aggregation packet count.
*/
@@ -819,11 +820,12 @@ hn_rss_reconfig(struct hn_softc *sc)
}
static void
-hn_rss_ind_fixup(struct hn_softc *sc, int nchan)
+hn_rss_ind_fixup(struct hn_softc *sc)
{
struct ndis_rssprm_toeplitz *rss = &sc->hn_rss;
- int i;
+ int i, nchan;
+ nchan = sc->hn_rx_ring_inuse;
KASSERT(nchan > 1, ("invalid # of channels %d", nchan));
/*
@@ -1545,7 +1547,7 @@ hn_txpkt_done(struct hn_nvs_sendctx *snd
txr = txd->txr;
KASSERT(txr->hn_chan == chan,
("channel mismatch, on chan%u, should be chan%u",
- vmbus_chan_subidx(chan), vmbus_chan_subidx(txr->hn_chan)));
+ vmbus_chan_id(chan), vmbus_chan_id(txr->hn_chan)));
txr->hn_has_txeof = 1;
hn_txdesc_put(txr, txd);
@@ -2968,7 +2970,7 @@ hn_rss_ind_sysctl(SYSCTL_HANDLER_ARGS)
goto back;
sc->hn_flags |= HN_FLAG_HAS_RSSIND;
- hn_rss_ind_fixup(sc, sc->hn_rx_ring_inuse);
+ hn_rss_ind_fixup(sc);
error = hn_rss_reconfig(sc);
back:
HN_UNLOCK(sc);
@@ -3275,7 +3277,10 @@ hn_destroy_rx_data(struct hn_softc *sc)
int i;
if (sc->hn_rxbuf != NULL) {
- hyperv_dmamem_free(&sc->hn_rxbuf_dma, sc->hn_rxbuf);
+ if ((sc->hn_flags & HN_FLAG_RXBUF_REF) == 0)
+ hyperv_dmamem_free(&sc->hn_rxbuf_dma, sc->hn_rxbuf);
+ else
+ device_printf(sc->hn_dev, "RXBUF is referenced\n");
sc->hn_rxbuf = NULL;
}
@@ -3287,7 +3292,12 @@ hn_destroy_rx_data(struct hn_softc *sc)
if (rxr->hn_br == NULL)
continue;
- hyperv_dmamem_free(&rxr->hn_br_dma, rxr->hn_br);
+ if ((rxr->hn_rx_flags & HN_RX_FLAG_BR_REF) == 0) {
+ hyperv_dmamem_free(&rxr->hn_br_dma, rxr->hn_br);
+ } else {
+ device_printf(sc->hn_dev,
+ "%dth channel bufring is referenced", i);
+ }
rxr->hn_br = NULL;
#if defined(INET) || defined(INET6)
@@ -3756,7 +3766,12 @@ hn_destroy_tx_data(struct hn_softc *sc)
int i;
if (sc->hn_chim != NULL) {
- hyperv_dmamem_free(&sc->hn_chim_dma, sc->hn_chim);
+ if ((sc->hn_flags & HN_FLAG_CHIM_REF) == 0) {
+ hyperv_dmamem_free(&sc->hn_chim_dma, sc->hn_chim);
+ } else {
+ device_printf(sc->hn_dev,
+ "chimney sending buffer is referenced");
+ }
sc->hn_chim = NULL;
}
@@ -4227,11 +4242,14 @@ hn_chan_attach(struct hn_softc *sc, stru
cbr.cbr_rxsz = HN_RXBR_SIZE;
error = vmbus_chan_open_br(chan, &cbr, NULL, 0, hn_chan_callback, rxr);
if (error) {
- if_printf(sc->hn_ifp, "open chan%u failed: %d\n",
- vmbus_chan_id(chan), error);
- rxr->hn_rx_flags &= ~HN_RX_FLAG_ATTACHED;
- if (txr != NULL)
- txr->hn_tx_flags &= ~HN_TX_FLAG_ATTACHED;
+ if (error == EISCONN) {
+ if_printf(sc->hn_ifp, "bufring is connected after "
+ "chan%u open failure\n", vmbus_chan_id(chan));
+ rxr->hn_rx_flags |= HN_RX_FLAG_BR_REF;
+ } else {
+ if_printf(sc->hn_ifp, "open chan%u failed: %d\n",
+ vmbus_chan_id(chan), error);
+ }
}
return (error);
}
@@ -4240,7 +4258,7 @@ static void
hn_chan_detach(struct hn_softc *sc, struct vmbus_channel *chan)
{
struct hn_rx_ring *rxr;
- int idx;
+ int idx, error;
idx = vmbus_chan_subidx(chan);
@@ -4269,7 +4287,15 @@ hn_chan_detach(struct hn_softc *sc, stru
* NOTE:
* Channel closing does _not_ destroy the target channel.
*/
- vmbus_chan_close(chan);
+ error = vmbus_chan_close_direct(chan);
+ if (error == EISCONN) {
+ if_printf(sc->hn_ifp, "chan%u bufring is connected "
+ "after being closed\n", vmbus_chan_id(chan));
+ rxr->hn_rx_flags |= HN_RX_FLAG_BR_REF;
+ } else if (error) {
+ if_printf(sc->hn_ifp, "chan%u close failed: %d\n",
+ vmbus_chan_id(chan), error);
+ }
}
static int
@@ -4279,15 +4305,18 @@ hn_attach_subchans(struct hn_softc *sc)
int subchan_cnt = sc->hn_rx_ring_inuse - 1;
int i, error = 0;
- if (subchan_cnt == 0)
- return (0);
+ KASSERT(subchan_cnt > 0, ("no sub-channels"));
/* Attach the sub-channels. */
subchans = vmbus_subchan_get(sc->hn_prichan, subchan_cnt);
for (i = 0; i < subchan_cnt; ++i) {
- error = hn_chan_attach(sc, subchans[i]);
- if (error)
- break;
+ int error1;
+
+ error1 = hn_chan_attach(sc, subchans[i]);
+ if (error1) {
+ error = error1;
+ /* Move on; all channels will be detached later. */
+ }
}
vmbus_subchan_rel(subchans, subchan_cnt);
@@ -4399,16 +4428,39 @@ hn_synth_alloc_subchans(struct hn_softc
return (0);
}
+static bool
+hn_synth_attachable(const struct hn_softc *sc)
+{
+ int i;
+
+ if (sc->hn_flags & HN_FLAG_ERRORS)
+ return (false);
+
+ for (i = 0; i < sc->hn_rx_ring_cnt; ++i) {
+ const struct hn_rx_ring *rxr = &sc->hn_rx_ring[i];
+
+ if (rxr->hn_rx_flags & HN_RX_FLAG_BR_REF)
+ return (false);
+ }
+ return (true);
+}
+
static int
hn_synth_attach(struct hn_softc *sc, int mtu)
{
+#define ATTACHED_NVS 0x0002
+#define ATTACHED_RNDIS 0x0004
+
struct ndis_rssprm_toeplitz *rss = &sc->hn_rss;
int error, nsubch, nchan, i;
- uint32_t old_caps;
+ uint32_t old_caps, attached = 0;
KASSERT((sc->hn_flags & HN_FLAG_SYNTH_ATTACHED) == 0,
("synthetic parts were attached"));
+ if (!hn_synth_attachable(sc))
+ return (ENXIO);
+
/* Save capabilities for later verification. */
old_caps = sc->hn_caps;
sc->hn_caps = 0;
@@ -4422,21 +4474,23 @@ hn_synth_attach(struct hn_softc *sc, int
*/
error = hn_chan_attach(sc, sc->hn_prichan);
if (error)
- return (error);
+ goto failed;
/*
* Attach NVS.
*/
error = hn_nvs_attach(sc, mtu);
if (error)
- return (error);
+ goto failed;
+ attached |= ATTACHED_NVS;
/*
* Attach RNDIS _after_ NVS is attached.
*/
error = hn_rndis_attach(sc, mtu);
if (error)
- return (error);
+ goto failed;
+ attached |= ATTACHED_RNDIS;
/*
* Make sure capabilities are not changed.
@@ -4444,9 +4498,8 @@ hn_synth_attach(struct hn_softc *sc, int
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;
+ error = ENXIO;
+ goto failed;
}
/*
@@ -4459,19 +4512,34 @@ hn_synth_attach(struct hn_softc *sc, int
nsubch = sc->hn_rx_ring_cnt - 1;
error = hn_synth_alloc_subchans(sc, &nsubch);
if (error)
- return (error);
+ goto failed;
+ /* NOTE: _Full_ synthetic parts detach is required now. */
+ sc->hn_flags |= HN_FLAG_SYNTH_ATTACHED;
+ /*
+ * Set the # of TX/RX rings that could be used according to
+ * the # of channels that NVS offered.
+ */
nchan = nsubch + 1;
+ hn_set_ring_inuse(sc, nchan);
if (nchan == 1) {
/* Only the primary channel can be used; done */
goto back;
}
/*
- * Configure RSS key and indirect table _after_ all sub-channels
- * are allocated.
+ * Attach the sub-channels.
+ *
+ * NOTE: hn_set_ring_inuse() _must_ have been called.
*/
+ error = hn_attach_subchans(sc);
+ if (error)
+ goto failed;
+ /*
+ * Configure RSS key and indirect table _after_ all sub-channels
+ * are attached.
+ */
if ((sc->hn_flags & HN_FLAG_HAS_RSSKEY) == 0) {
/*
* RSS key is not set yet; set it to the default RSS key.
@@ -4499,39 +4567,38 @@ hn_synth_attach(struct hn_softc *sc, int
* # of usable channels may be changed, so we have to
* make sure that all entries in RSS indirect table
* are valid.
+ *
+ * NOTE: hn_set_ring_inuse() _must_ have been called.
*/
- hn_rss_ind_fixup(sc, nchan);
+ hn_rss_ind_fixup(sc);
}
error = hn_rndis_conf_rss(sc, NDIS_RSS_FLAG_NONE);
- if (error) {
- /*
- * Failed to configure RSS key or indirect table; only
- * the primary channel can be used.
- */
- nchan = 1;
- }
-back:
- /*
- * Set the # of TX/RX rings that could be used according to
- * the # of channels that NVS offered.
- */
- hn_set_ring_inuse(sc, nchan);
-
- /*
- * Attach the sub-channels, if any.
- */
- error = hn_attach_subchans(sc);
if (error)
- return (error);
-
+ goto failed;
+back:
/*
* Fixup transmission aggregation setup.
*/
hn_set_txagg(sc);
-
- sc->hn_flags |= HN_FLAG_SYNTH_ATTACHED;
return (0);
+
+failed:
+ if (sc->hn_flags & HN_FLAG_SYNTH_ATTACHED) {
+ hn_synth_detach(sc);
+ } else {
+ if (attached & ATTACHED_RNDIS)
+ hn_rndis_detach(sc);
+ if (attached & ATTACHED_NVS)
+ hn_nvs_detach(sc);
+ hn_chan_detach(sc, sc->hn_prichan);
+ /* Restore old capabilities. */
+ sc->hn_caps = old_caps;
+ }
+ return (error);
+
+#undef ATTACHED_RNDIS
+#undef ATTACHED_NVS
}
/*
@@ -4542,7 +4609,6 @@ back:
static void
hn_synth_detach(struct hn_softc *sc)
{
- HN_LOCK_ASSERT(sc);
KASSERT(sc->hn_flags & HN_FLAG_SYNTH_ATTACHED,
("synthetic parts were not attached"));
Modified: stable/10/sys/dev/hyperv/netvsc/if_hnvar.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/if_hnvar.h Thu Dec 29 07:06:49 2016 (r310756)
+++ stable/10/sys/dev/hyperv/netvsc/if_hnvar.h Thu Dec 29 07:07:16 2016 (r310757)
@@ -91,7 +91,8 @@ struct hn_rx_ring {
#define HN_TRUST_HCSUM_TCP 0x0002
#define HN_TRUST_HCSUM_UDP 0x0004
-#define HN_RX_FLAG_ATTACHED 0x1
+#define HN_RX_FLAG_ATTACHED 0x0001
+#define HN_RX_FLAG_BR_REF 0x0002
struct hn_tx_ring {
#ifndef HN_USE_TXDESC_BUFRING
@@ -162,8 +163,8 @@ struct hn_tx_ring {
struct sysctl_oid *hn_tx_sysctl_tree;
} __aligned(CACHE_LINE_SIZE);
-#define HN_TX_FLAG_ATTACHED 0x1
-#define HN_TX_FLAG_HASHVAL 0x2 /* support HASHVAL pktinfo */
+#define HN_TX_FLAG_ATTACHED 0x0001
+#define HN_TX_FLAG_HASHVAL 0x0002 /* support HASHVAL pktinfo */
/*
* Device-specific softc structure
@@ -238,6 +239,10 @@ struct hn_softc {
#define HN_FLAG_HAS_RSSIND 0x0008
#define HN_FLAG_SYNTH_ATTACHED 0x0010
#define HN_FLAG_NO_SLEEPING 0x0020
+#define HN_FLAG_RXBUF_REF 0x0040
+#define HN_FLAG_CHIM_REF 0x0080
+
+#define HN_FLAG_ERRORS (HN_FLAG_RXBUF_REF | HN_FLAG_CHIM_REF)
#define HN_NO_SLEEPING(sc) \
do { \
More information about the svn-src-stable
mailing list