svn commit: r308519 - stable/11/sys/dev/hyperv/netvsc

Sepherosa Ziehau sephe at FreeBSD.org
Fri Nov 11 08:52:25 UTC 2016


Author: sephe
Date: Fri Nov 11 08:52:23 2016
New Revision: 308519
URL: https://svnweb.freebsd.org/changeset/base/308519

Log:
  MFC 307838,307839
  
  307838
      hyperv/hn: Move chimney buffer index and size to txdesc.
  
      All RNDIS control messages have used SG list for a while.  This makes
      the send context suitable for further refactoring.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D8308
  
  307839
      hyperv/hn: Fix chimney sending buffer leakage upon NVS sending failure.
  
      This will not happen in real world, since TX consumption of the vmbus
      TX bufring is limitted.  Better safe than sorry.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D8309

Modified:
  stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c
  stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h
  stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
  stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.c
  stable/11/sys/dev/hyperv/netvsc/if_hnvar.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c	Fri Nov 11 08:49:28 2016	(r308518)
+++ stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c	Fri Nov 11 08:52:23 2016	(r308519)
@@ -117,7 +117,7 @@ hn_nvs_xact_execute(struct hn_softc *sc,
 	/*
 	 * Execute the xact setup by the caller.
 	 */
-	hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact);
+	hn_send_ctx_init(&sndc, hn_nvs_sent_xact, xact);
 
 	vmbus_xact_activate(xact);
 	error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC,
@@ -669,34 +669,6 @@ hn_chim_free(struct hn_softc *sc, uint32
 	atomic_clear_long(&sc->hn_chim_bmap[idx], mask);
 }
 
-/*
- * Net VSC on send
- * Sends a packet on the specified Hyper-V device.
- * Returns 0 on success, non-zero on failure.
- */
-int
-hv_nv_on_send(struct vmbus_channel *chan, uint32_t rndis_mtype,
-    struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt)
-{
-	struct hn_nvs_rndis rndis;
-	int ret;
-
-	rndis.nvs_type = HN_NVS_TYPE_RNDIS;
-	rndis.nvs_rndis_mtype = rndis_mtype;
-	rndis.nvs_chim_idx = sndc->hn_chim_idx;
-	rndis.nvs_chim_sz = sndc->hn_chim_sz;
-
-	if (gpa_cnt) {
-		ret = hn_nvs_send_sglist(chan, gpa, gpa_cnt,
-		    &rndis, sizeof(rndis), sndc);
-	} else {
-		ret = hn_nvs_send(chan, VMBUS_CHANPKT_FLAG_RC,
-		    &rndis, sizeof(rndis), sndc);
-	}
-
-	return (ret);
-}
-
 int
 hn_nvs_alloc_subchans(struct hn_softc *sc, int *nsubch0)
 {

Modified: stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h	Fri Nov 11 08:49:28 2016	(r308518)
+++ stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h	Fri Nov 11 08:52:23 2016	(r308519)
@@ -104,8 +104,8 @@ struct vmbus_channel;
 #define HN_XACT_REQ_SIZE		(HN_XACT_REQ_PGCNT * PAGE_SIZE)
 #define HN_XACT_RESP_SIZE		(HN_XACT_RESP_PGCNT * PAGE_SIZE)
 
-#ifndef HN_USE_TXDESC_BUFRING
 struct hn_txdesc;
+#ifndef HN_USE_TXDESC_BUFRING
 SLIST_HEAD(hn_txdesc_list, hn_txdesc);
 #else
 struct buf_ring;
@@ -179,6 +179,7 @@ struct hn_tx_ring {
 	bus_dma_tag_t	hn_tx_data_dtag;
 	uint64_t	hn_csum_assist;
 
+	int		(*hn_sendpkt)(struct hn_tx_ring *, struct hn_txdesc *);
 	int		hn_suspended;
 	int		hn_gpa_cnt;
 	struct vmbus_gpa hn_gpa[NETVSC_PACKET_MAXPAGE];
@@ -276,13 +277,5 @@ struct hn_softc {
 #define HN_LINK_FLAG_LINKUP		0x0001
 #define HN_LINK_FLAG_NETCHG		0x0002
 
-/*
- * Externs
- */
-struct hn_send_ctx;
-
-int hv_nv_on_send(struct vmbus_channel *chan, uint32_t rndis_mtype,
-	struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt);
-
 #endif  /* __HV_NET_VSC_H__ */
 

Modified: stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Fri Nov 11 08:49:28 2016	(r308518)
+++ stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Fri Nov 11 08:52:23 2016	(r308519)
@@ -169,6 +169,8 @@ struct hn_txdesc {
 	int		refs;
 	uint32_t	flags;		/* HN_TXD_FLAG_ */
 	struct hn_send_ctx send_ctx;
+	uint32_t	chim_index;
+	int		chim_size;
 
 	bus_dmamap_t	data_dmap;
 
@@ -363,6 +365,8 @@ static void hn_tx_resume(struct hn_softc
 static void hn_tx_ring_qflush(struct hn_tx_ring *);
 static int netvsc_detach(device_t dev);
 static void hn_link_status(struct hn_softc *);
+static int hn_sendpkt_rndis_sglist(struct hn_tx_ring *, struct hn_txdesc *);
+static int hn_sendpkt_rndis_chim(struct hn_tx_ring *, struct hn_txdesc *);
 
 static void hn_nvs_handle_notify(struct hn_softc *sc,
 		const struct vmbus_chanpkt_hdr *pkt);
@@ -399,6 +403,57 @@ hn_set_lro_lenlim(struct hn_softc *sc, i
 }
 #endif
 
+static __inline int
+hn_nvs_send_rndis_sglist1(struct vmbus_channel *chan, uint32_t rndis_mtype,
+    struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt)
+{
+	struct hn_nvs_rndis rndis;
+
+	rndis.nvs_type = HN_NVS_TYPE_RNDIS;
+	rndis.nvs_rndis_mtype = rndis_mtype;
+	rndis.nvs_chim_idx = HN_NVS_CHIM_IDX_INVALID;
+	rndis.nvs_chim_sz = 0;
+
+	return (hn_nvs_send_sglist(chan, gpa, gpa_cnt,
+	    &rndis, sizeof(rndis), sndc));
+}
+
+int
+hn_nvs_send_rndis_ctrl(struct vmbus_channel *chan,
+    struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt)
+{
+
+	return hn_nvs_send_rndis_sglist1(chan, HN_NVS_RNDIS_MTYPE_CTRL,
+	    sndc, gpa, gpa_cnt);
+}
+
+static int
+hn_sendpkt_rndis_sglist(struct hn_tx_ring *txr, struct hn_txdesc *txd)
+{
+
+	KASSERT(txd->chim_index == HN_NVS_CHIM_IDX_INVALID &&
+	    txd->chim_size == 0, ("invalid rndis sglist txd"));
+	return (hn_nvs_send_rndis_sglist1(txr->hn_chan, HN_NVS_RNDIS_MTYPE_DATA,
+	    &txd->send_ctx, txr->hn_gpa, txr->hn_gpa_cnt));
+}
+
+static int
+hn_sendpkt_rndis_chim(struct hn_tx_ring *txr, struct hn_txdesc *txd)
+{
+	struct hn_nvs_rndis rndis;
+
+	KASSERT(txd->chim_index != HN_NVS_CHIM_IDX_INVALID &&
+	    txd->chim_size > 0, ("invalid rndis chim txd"));
+
+	rndis.nvs_type = HN_NVS_TYPE_RNDIS;
+	rndis.nvs_rndis_mtype = HN_NVS_RNDIS_MTYPE_DATA;
+	rndis.nvs_chim_idx = txd->chim_index;
+	rndis.nvs_chim_sz = txd->chim_size;
+
+	return (hn_nvs_send(txr->hn_chan, VMBUS_CHANPKT_FLAG_RC,
+	    &rndis, sizeof(rndis), &txd->send_ctx));
+}
+
 static int
 hn_get_txswq_depth(const struct hn_tx_ring *txr)
 {
@@ -896,6 +951,8 @@ hn_txdesc_dmamap_load(struct hn_tx_ring 
 	struct mbuf *m = *m_head;
 	int error;
 
+	KASSERT(txd->chim_index == HN_NVS_CHIM_IDX_INVALID, ("txd uses chim"));
+
 	error = bus_dmamap_load_mbuf_sg(txr->hn_tx_data_dtag, txd->data_dmap,
 	    m, segs, nsegs, BUS_DMA_NOWAIT);
 	if (error == EFBIG) {
@@ -919,19 +976,6 @@ hn_txdesc_dmamap_load(struct hn_tx_ring 
 	return error;
 }
 
-static __inline void
-hn_txdesc_dmamap_unload(struct hn_tx_ring *txr, struct hn_txdesc *txd)
-{
-
-	if (txd->flags & HN_TXD_FLAG_DMAMAP) {
-		bus_dmamap_sync(txr->hn_tx_data_dtag,
-		    txd->data_dmap, BUS_DMASYNC_POSTWRITE);
-		bus_dmamap_unload(txr->hn_tx_data_dtag,
-		    txd->data_dmap);
-		txd->flags &= ~HN_TXD_FLAG_DMAMAP;
-	}
-}
-
 static __inline int
 hn_txdesc_put(struct hn_tx_ring *txr, struct hn_txdesc *txd)
 {
@@ -943,14 +987,25 @@ hn_txdesc_put(struct hn_tx_ring *txr, st
 	if (atomic_fetchadd_int(&txd->refs, -1) != 1)
 		return 0;
 
-	hn_txdesc_dmamap_unload(txr, txd);
+	if (txd->chim_index != HN_NVS_CHIM_IDX_INVALID) {
+		KASSERT((txd->flags & HN_TXD_FLAG_DMAMAP) == 0,
+		    ("chim txd uses dmamap"));
+		hn_chim_free(txr->hn_sc, txd->chim_index);
+		txd->chim_index = HN_NVS_CHIM_IDX_INVALID;
+	} else if (txd->flags & HN_TXD_FLAG_DMAMAP) {
+		bus_dmamap_sync(txr->hn_tx_data_dtag,
+		    txd->data_dmap, BUS_DMASYNC_POSTWRITE);
+		bus_dmamap_unload(txr->hn_tx_data_dtag,
+		    txd->data_dmap);
+		txd->flags &= ~HN_TXD_FLAG_DMAMAP;
+	}
+
 	if (txd->m != NULL) {
 		m_freem(txd->m);
 		txd->m = NULL;
 	}
 
 	txd->flags |= HN_TXD_FLAG_ONLIST;
-
 #ifndef HN_USE_TXDESC_BUFRING
 	mtx_lock_spin(&txr->hn_txlist_spin);
 	KASSERT(txr->hn_txdesc_avail >= 0 &&
@@ -991,7 +1046,9 @@ hn_txdesc_get(struct hn_tx_ring *txr)
 		atomic_subtract_int(&txr->hn_txdesc_avail, 1);
 #endif
 		KASSERT(txd->m == NULL && txd->refs == 0 &&
-		    (txd->flags & HN_TXD_FLAG_ONLIST), ("invalid txd"));
+		    txd->chim_index == HN_NVS_CHIM_IDX_INVALID &&
+		    (txd->flags & HN_TXD_FLAG_ONLIST) &&
+		    (txd->flags & HN_TXD_FLAG_DMAMAP) == 0, ("invalid txd"));
 		txd->flags &= ~HN_TXD_FLAG_ONLIST;
 		txd->refs = 1;
 	}
@@ -1038,9 +1095,6 @@ hn_tx_done(struct hn_send_ctx *sndc, str
 	struct hn_txdesc *txd = sndc->hn_cbarg;
 	struct hn_tx_ring *txr;
 
-	if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID)
-		hn_chim_free(sc, sndc->hn_chim_idx);
-
 	txr = txd->txr;
 	KASSERT(txr->hn_chan == chan,
 	    ("channel mismatch, on chan%u, should be chan%u",
@@ -1096,9 +1150,8 @@ hn_encap(struct hn_tx_ring *txr, struct 
 	int error, nsegs, i;
 	struct mbuf *m_head = *m_head0;
 	struct rndis_packet_msg *pkt;
-	uint32_t send_buf_section_idx;
-	int send_buf_section_size, pktlen;
 	uint32_t *pi_data;
+	int pktlen;
 
 	/*
 	 * extension points to the area reserved for the
@@ -1211,18 +1264,19 @@ hn_encap(struct hn_tx_ring *txr, struct 
 	 */
 	if (pkt->rm_len < txr->hn_chim_size) {
 		txr->hn_tx_chimney_tried++;
-		send_buf_section_idx = hn_chim_alloc(txr->hn_sc);
-		if (send_buf_section_idx != HN_NVS_CHIM_IDX_INVALID) {
+		txd->chim_index = hn_chim_alloc(txr->hn_sc);
+		if (txd->chim_index != HN_NVS_CHIM_IDX_INVALID) {
 			uint8_t *dest = txr->hn_sc->hn_chim +
-			    (send_buf_section_idx * txr->hn_sc->hn_chim_szmax);
+			    (txd->chim_index * txr->hn_sc->hn_chim_szmax);
 
 			memcpy(dest, pkt, pktlen);
 			dest += pktlen;
 			m_copydata(m_head, 0, m_head->m_pkthdr.len, dest);
 
-			send_buf_section_size = pkt->rm_len;
+			txd->chim_size = pkt->rm_len;
 			txr->hn_gpa_cnt = 0;
 			txr->hn_tx_chimney++;
+			txr->hn_sendpkt = hn_sendpkt_rndis_chim;
 			goto done;
 		}
 	}
@@ -1267,14 +1321,14 @@ hn_encap(struct hn_tx_ring *txr, struct 
 		gpa->gpa_len = segs[i].ds_len;
 	}
 
-	send_buf_section_idx = HN_NVS_CHIM_IDX_INVALID;
-	send_buf_section_size = 0;
+	txd->chim_index = HN_NVS_CHIM_IDX_INVALID;
+	txd->chim_size = 0;
+	txr->hn_sendpkt = hn_sendpkt_rndis_sglist;
 done:
 	txd->m = m_head;
 
 	/* Set the completion routine */
-	hn_send_ctx_init(&txd->send_ctx, hn_tx_done, txd,
-	    send_buf_section_idx, send_buf_section_size);
+	hn_send_ctx_init(&txd->send_ctx, hn_tx_done, txd);
 
 	return 0;
 }
@@ -1294,8 +1348,7 @@ again:
 	 * Make sure that txd is not freed before ETHER_BPF_MTAP.
 	 */
 	hn_txdesc_hold(txd);
-	error = hv_nv_on_send(txr->hn_chan, HN_NVS_RNDIS_MTYPE_DATA,
-	    &txd->send_ctx, txr->hn_gpa, txr->hn_gpa_cnt);
+	error = txr->hn_sendpkt(txr, txd);
 	if (!error) {
 		ETHER_BPF_MTAP(ifp, txd->m);
 		if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
@@ -2766,6 +2819,7 @@ hn_create_tx_ring(struct hn_softc *sc, i
 		struct hn_txdesc *txd = &txr->hn_txdesc[i];
 
 		txd->txr = txr;
+		txd->chim_index = HN_NVS_CHIM_IDX_INVALID;
 
 		/*
 		 * Allocate and load RNDIS packet message.

Modified: stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Fri Nov 11 08:49:28 2016	(r308518)
+++ stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Fri Nov 11 08:52:23 2016	(r308519)
@@ -585,8 +585,7 @@ hn_rndis_xact_exec1(struct hn_softc *sc,
 	 * message.
 	 */
 	vmbus_xact_activate(xact);
-	error = hv_nv_on_send(sc->hn_prichan, HN_NVS_RNDIS_MTYPE_CTRL, sndc,
-	    gpa, gpa_cnt);
+	error = hn_nvs_send_rndis_ctrl(sc->hn_prichan, sndc, gpa, gpa_cnt);
 	if (error) {
 		vmbus_xact_deactivate(xact);
 		if_printf(sc->hn_ifp, "RNDIS ctrl send failed: %d\n", error);
@@ -1165,7 +1164,7 @@ hn_rndis_halt(struct hn_softc *sc)
 	halt->rm_rid = hn_rndis_rid(sc);
 
 	/* No RNDIS completion; rely on NVS message send completion */
-	hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact);
+	hn_send_ctx_init(&sndc, hn_nvs_sent_xact, xact);
 	hn_rndis_xact_exec1(sc, xact, sizeof(*halt), &sndc, &comp_len);
 
 	vmbus_xact_put(xact);

Modified: stable/11/sys/dev/hyperv/netvsc/if_hnvar.h
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/if_hnvar.h	Fri Nov 11 08:49:28 2016	(r308518)
+++ stable/11/sys/dev/hyperv/netvsc/if_hnvar.h	Fri Nov 11 08:52:23 2016	(r308519)
@@ -46,8 +46,6 @@ typedef void		(*hn_sent_callback_t)
 struct hn_send_ctx {
 	hn_sent_callback_t	hn_cb;
 	void			*hn_cbarg;
-	uint32_t		hn_chim_idx;
-	int			hn_chim_sz;
 };
 
 struct rndis_hash_info;
@@ -66,31 +64,18 @@ struct hn_recvinfo {
 	uint32_t			hash_value;
 };
 
-#define HN_SEND_CTX_INITIALIZER(cb, cbarg)		\
-{							\
-	.hn_cb		= cb,				\
-	.hn_cbarg	= cbarg,			\
-	.hn_chim_idx	= HN_NVS_CHIM_IDX_INVALID,	\
-	.hn_chim_sz	= 0				\
+#define HN_SEND_CTX_INITIALIZER(cb, cbarg)	\
+{						\
+	.hn_cb		= cb,			\
+	.hn_cbarg	= cbarg			\
 }
 
 static __inline void
-hn_send_ctx_init(struct hn_send_ctx *sndc, hn_sent_callback_t cb,
-    void *cbarg, uint32_t chim_idx, int chim_sz)
+hn_send_ctx_init(struct hn_send_ctx *sndc, hn_sent_callback_t cb, void *cbarg)
 {
 
 	sndc->hn_cb = cb;
 	sndc->hn_cbarg = cbarg;
-	sndc->hn_chim_idx = chim_idx;
-	sndc->hn_chim_sz = chim_sz;
-}
-
-static __inline void
-hn_send_ctx_init_simple(struct hn_send_ctx *sndc, hn_sent_callback_t cb,
-    void *cbarg)
-{
-
-	hn_send_ctx_init(sndc, cb, cbarg, HN_NVS_CHIM_IDX_INVALID, 0);
 }
 
 static __inline int
@@ -134,6 +119,9 @@ void		hn_nvs_detach(struct hn_softc *sc)
 int		hn_nvs_alloc_subchans(struct hn_softc *sc, int *nsubch);
 void		hn_nvs_sent_xact(struct hn_send_ctx *sndc, struct hn_softc *sc,
 		    struct vmbus_channel *chan, const void *data, int dlen);
+int		hn_nvs_send_rndis_ctrl(struct vmbus_channel *chan,
+		    struct hn_send_ctx *sndc, struct vmbus_gpa *gpa,
+		    int gpa_cnt);
 
 int		hn_rxpkt(struct hn_rx_ring *rxr, const void *data, int dlen,
 		    const struct hn_recvinfo *info);


More information about the svn-src-all mailing list