From owner-svn-src-stable@freebsd.org Thu Dec 29 07:07:18 2016 Return-Path: Delivered-To: svn-src-stable@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 2E91AC94219; Thu, 29 Dec 2016 07:07:18 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id F12B011EF; Thu, 29 Dec 2016 07:07:17 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id uBT77HKw055117; Thu, 29 Dec 2016 07:07:17 GMT (envelope-from sephe@FreeBSD.org) Received: (from sephe@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id uBT77GBK055113; Thu, 29 Dec 2016 07:07:16 GMT (envelope-from sephe@FreeBSD.org) Message-Id: <201612290707.uBT77GBK055113@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: sephe set sender to sephe@FreeBSD.org using -f From: Sepherosa Ziehau Date: Thu, 29 Dec 2016 07:07:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r310757 - stable/10/sys/dev/hyperv/netvsc X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 29 Dec 2016 07:07:18 -0000 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 { \