svn commit: r307247 - in stable/10/sys/dev/hyperv: include netvsc vmbus

Sepherosa Ziehau sephe at FreeBSD.org
Fri Oct 14 02:34:05 UTC 2016


Author: sephe
Date: Fri Oct 14 02:34:03 2016
New Revision: 307247
URL: https://svnweb.freebsd.org/changeset/base/307247

Log:
  MFC 306072-306074,306076
  
  306072
      hyperv/vmbus: Allow bufrings preallocation.
  
      The assumption that the channel is only opened upon synthetic device
      attach time no longer holds, e.g. Hyper-V network device MTU changes.
      We have to allow device drivers to preallocate bufrings, e.g. in
      attach DEVMETHOD, to prevent bufring allocation failure once the
      system memory is fragmented after running for a while.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7960
  
  306073
      hyperv/hn: Allocate bufrings in attach DEVMETHOD.
  
      So that reinitialization, e.g. MTU change, will not fail when the system
      memory is excessively fragmented.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7961
  
  306074
      hyperv/vmbus: Assert that the bufring address is page aligned.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7962
  
  306076
      hyperv/hn: Put debug messages under bootverbose
  
      While I'm here, strip blank line.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7963

Modified:
  stable/10/sys/dev/hyperv/include/vmbus.h
  stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h
  stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
  stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/hyperv/include/vmbus.h
==============================================================================
--- stable/10/sys/dev/hyperv/include/vmbus.h	Fri Oct 14 02:27:19 2016	(r307246)
+++ stable/10/sys/dev/hyperv/include/vmbus.h	Fri Oct 14 02:34:03 2016	(r307247)
@@ -109,6 +109,13 @@ struct vmbus_chanpkt_rxbuf {
 	struct vmbus_rxbuf_desc cp_rxbuf[];
 } __packed;
 
+struct vmbus_chan_br {
+	void		*cbr;
+	bus_addr_t	cbr_paddr;
+	int		cbr_txsz;
+	int		cbr_rxsz;
+};
+
 struct vmbus_channel;
 struct hyperv_guid;
 
@@ -123,6 +130,9 @@ vmbus_get_channel(device_t dev)
 int		vmbus_chan_open(struct vmbus_channel *chan,
 		    int txbr_size, int rxbr_size, const void *udata, int udlen,
 		    vmbus_chan_callback_t cb, void *cbarg);
+int		vmbus_chan_open_br(struct vmbus_channel *chan,
+		    const struct vmbus_chan_br *cbr, const void *udata,
+		    int udlen, vmbus_chan_callback_t cb, void *cbarg);
 void		vmbus_chan_close(struct vmbus_channel *chan);
 
 int		vmbus_chan_gpadl_connect(struct vmbus_channel *chan,

Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h	Fri Oct 14 02:27:19 2016	(r307246)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h	Fri Oct 14 02:34:03 2016	(r307247)
@@ -136,6 +136,9 @@ struct hn_rx_ring {
 	/* Rarely used stuffs */
 	struct sysctl_oid *hn_rx_sysctl_tree;
 	int		hn_rx_flags;
+
+	void		*hn_br;		/* TX/RX bufring */
+	struct hyperv_dma hn_br_dma;
 } __aligned(CACHE_LINE_SIZE);
 
 #define HN_TRUST_HCSUM_IP	0x0001

Modified: stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Fri Oct 14 02:27:19 2016	(r307246)
+++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Fri Oct 14 02:34:03 2016	(r307247)
@@ -2378,7 +2378,8 @@ hn_create_rx_data(struct hn_softc *sc, i
 	lroent_cnt = hn_lro_entry_count;
 	if (lroent_cnt < TCP_LRO_ENTRIES)
 		lroent_cnt = TCP_LRO_ENTRIES;
-	device_printf(dev, "LRO: entry count %d\n", lroent_cnt);
+	if (bootverbose)
+		device_printf(dev, "LRO: entry count %d\n", lroent_cnt);
 #endif
 #endif	/* INET || INET6 */
 
@@ -2392,6 +2393,16 @@ hn_create_rx_data(struct hn_softc *sc, i
 	for (i = 0; i < sc->hn_rx_ring_cnt; ++i) {
 		struct hn_rx_ring *rxr = &sc->hn_rx_ring[i];
 
+		rxr->hn_br = hyperv_dmamem_alloc(bus_get_dma_tag(dev),
+		    PAGE_SIZE, 0,
+		    NETVSC_DEVICE_RING_BUFFER_SIZE +
+		    NETVSC_DEVICE_RING_BUFFER_SIZE,
+		    &rxr->hn_br_dma, BUS_DMA_WAITOK);
+		if (rxr->hn_br == NULL) {
+			device_printf(dev, "allocate bufring failed\n");
+			return (ENOMEM);
+		}
+
 		if (hn_trust_hosttcp)
 			rxr->hn_trust_hcsum |= HN_TRUST_HCSUM_TCP;
 		if (hn_trust_hostudp)
@@ -2540,6 +2551,11 @@ hn_destroy_rx_data(struct hn_softc *sc)
 	for (i = 0; i < sc->hn_rx_ring_cnt; ++i) {
 		struct hn_rx_ring *rxr = &sc->hn_rx_ring[i];
 
+		if (rxr->hn_br == NULL)
+			continue;
+		hyperv_dmamem_free(&rxr->hn_br_dma, rxr->hn_br);
+		rxr->hn_br = NULL;
+
 #if defined(INET) || defined(INET6)
 		tcp_lro_free(&rxr->hn_lro);
 #endif
@@ -3145,6 +3161,7 @@ hn_xmit_txeof_taskfunc(void *xtxr, int p
 static int
 hn_chan_attach(struct hn_softc *sc, struct vmbus_channel *chan)
 {
+	struct vmbus_chan_br cbr;
 	struct hn_rx_ring *rxr;
 	struct hn_tx_ring *txr = NULL;
 	int idx, error;
@@ -3183,9 +3200,14 @@ hn_chan_attach(struct hn_softc *sc, stru
 	/* Bind this channel to a proper CPU. */
 	vmbus_chan_cpu_set(chan, (sc->hn_cpu + idx) % mp_ncpus);
 
-	/* Open this channel */
-	error = vmbus_chan_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE,
-	    NETVSC_DEVICE_RING_BUFFER_SIZE, NULL, 0, hn_chan_callback, rxr);
+	/*
+	 * Open this channel
+	 */
+	cbr.cbr = rxr->hn_br;
+	cbr.cbr_paddr = rxr->hn_br_dma.hv_paddr;
+	cbr.cbr_txsz = NETVSC_DEVICE_RING_BUFFER_SIZE;
+	cbr.cbr_rxsz = NETVSC_DEVICE_RING_BUFFER_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);
@@ -3328,8 +3350,10 @@ hn_synth_alloc_subchans(struct hn_softc 
 		*nsubch = 0;
 		return (0);
 	}
-	if_printf(sc->hn_ifp, "RX rings offered %u, requested %d\n",
-	    rxr_cnt, nchan);
+	if (bootverbose) {
+		if_printf(sc->hn_ifp, "RX rings offered %u, requested %d\n",
+		    rxr_cnt, nchan);
+	}
 
 	if (nchan > rxr_cnt)
 		nchan = rxr_cnt;
@@ -3338,7 +3362,7 @@ hn_synth_alloc_subchans(struct hn_softc 
 		*nsubch = 0;
 		return (0);
 	}
-	
+
 	/*
 	 * Allocate sub-channels from NVS.
 	 */

Modified: stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c	Fri Oct 14 02:27:19 2016	(r307246)
+++ stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c	Fri Oct 14 02:34:03 2016	(r307247)
@@ -196,13 +196,45 @@ int
 vmbus_chan_open(struct vmbus_channel *chan, int txbr_size, int rxbr_size,
     const void *udata, int udlen, vmbus_chan_callback_t cb, void *cbarg)
 {
+	struct vmbus_chan_br cbr;
+	int error;
+
+	/*
+	 * Allocate the TX+RX bufrings.
+	 */
+	KASSERT(chan->ch_bufring == NULL, ("bufrings are allocated"));
+	chan->ch_bufring = hyperv_dmamem_alloc(bus_get_dma_tag(chan->ch_dev),
+	    PAGE_SIZE, 0, txbr_size + rxbr_size, &chan->ch_bufring_dma,
+	    BUS_DMA_WAITOK);
+	if (chan->ch_bufring == NULL) {
+		device_printf(chan->ch_dev, "bufring allocation failed\n");
+		return (ENOMEM);
+	}
+
+	cbr.cbr = chan->ch_bufring;
+	cbr.cbr_paddr = chan->ch_bufring_dma.hv_paddr;
+	cbr.cbr_txsz = txbr_size;
+	cbr.cbr_rxsz = rxbr_size;
+
+	error = vmbus_chan_open_br(chan, &cbr, udata, udlen, cb, cbarg);
+	if (error) {
+		hyperv_dmamem_free(&chan->ch_bufring_dma, chan->ch_bufring);
+		chan->ch_bufring = NULL;
+	}
+	return (error);
+}
+
+int
+vmbus_chan_open_br(struct vmbus_channel *chan, const struct vmbus_chan_br *cbr,
+    const void *udata, int udlen, vmbus_chan_callback_t cb, void *cbarg)
+{
 	struct vmbus_softc *sc = chan->ch_vmbus;
 	const struct vmbus_chanmsg_chopen_resp *resp;
 	const struct vmbus_message *msg;
 	struct vmbus_chanmsg_chopen *req;
 	struct vmbus_msghc *mh;
 	uint32_t status;
-	int error;
+	int error, txbr_size, rxbr_size;
 	uint8_t *br;
 
 	if (udlen > VMBUS_CHANMSG_CHOPEN_UDATA_SIZE) {
@@ -210,10 +242,21 @@ vmbus_chan_open(struct vmbus_channel *ch
 		    "invalid udata len %d for chan%u\n", udlen, chan->ch_id);
 		return EINVAL;
 	}
+
+	br = cbr->cbr;
+	txbr_size = cbr->cbr_txsz;
+	rxbr_size = cbr->cbr_rxsz;
 	KASSERT((txbr_size & PAGE_MASK) == 0,
 	    ("send bufring size is not multiple page"));
 	KASSERT((rxbr_size & PAGE_MASK) == 0,
 	    ("recv bufring size is not multiple page"));
+	KASSERT((cbr->cbr_paddr & PAGE_MASK) == 0,
+	    ("bufring is not page aligned"));
+
+	/*
+	 * Zero out the TX/RX bufrings, in case that they were used before.
+	 */
+	memset(br, 0, txbr_size + rxbr_size);
 
 	if (atomic_testandset_int(&chan->ch_stflags,
 	    VMBUS_CHAN_ST_OPENED_SHIFT))
@@ -230,20 +273,6 @@ vmbus_chan_open(struct vmbus_channel *ch
 	else
 		TASK_INIT(&chan->ch_task, 0, vmbus_chan_task_nobatch, chan);
 
-	/*
-	 * Allocate the TX+RX bufrings.
-	 * XXX should use ch_dev dtag
-	 */
-	br = hyperv_dmamem_alloc(bus_get_dma_tag(sc->vmbus_dev),
-	    PAGE_SIZE, 0, txbr_size + rxbr_size, &chan->ch_bufring_dma,
-	    BUS_DMA_WAITOK | BUS_DMA_ZERO);
-	if (br == NULL) {
-		device_printf(sc->vmbus_dev, "bufring allocation failed\n");
-		error = ENOMEM;
-		goto failed;
-	}
-	chan->ch_bufring = br;
-
 	/* TX bufring comes first */
 	vmbus_txbr_setup(&chan->ch_txbr, br, txbr_size);
 	/* RX bufring immediately follows TX bufring */
@@ -255,7 +284,7 @@ vmbus_chan_open(struct vmbus_channel *ch
 	/*
 	 * Connect the bufrings, both RX and TX, to this channel.
 	 */
-	error = vmbus_chan_gpadl_connect(chan, chan->ch_bufring_dma.hv_paddr,
+	error = vmbus_chan_gpadl_connect(chan, cbr->cbr_paddr,
 	    txbr_size + rxbr_size, &chan->ch_bufring_gpadl);
 	if (error) {
 		device_printf(sc->vmbus_dev,
@@ -316,10 +345,6 @@ failed:
 		vmbus_chan_gpadl_disconnect(chan, chan->ch_bufring_gpadl);
 		chan->ch_bufring_gpadl = 0;
 	}
-	if (chan->ch_bufring != NULL) {
-		hyperv_dmamem_free(&chan->ch_bufring_dma, chan->ch_bufring);
-		chan->ch_bufring = NULL;
-	}
 	atomic_clear_int(&chan->ch_stflags, VMBUS_CHAN_ST_OPENED);
 	return error;
 }


More information about the svn-src-all mailing list