svn commit: r307453 - in stable/11/sys/dev/hyperv: include vmbus

Sepherosa Ziehau sephe at FreeBSD.org
Mon Oct 17 02:23:06 UTC 2016


Author: sephe
Date: Mon Oct 17 02:23:05 2016
New Revision: 307453
URL: https://svnweb.freebsd.org/changeset/base/307453

Log:
  MFC 302871,302872
  
  302871
      hyperv/vmbus: Add vmbus_chan_gpadl_connect, which takes GPA physaddr
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D7139
  
  302872
      hyperv/vmbus: Busdma-fy channel bufring.
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D7140

Modified:
  stable/11/sys/dev/hyperv/include/hyperv.h
  stable/11/sys/dev/hyperv/vmbus/hv_channel.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/hyperv/include/hyperv.h
==============================================================================
--- stable/11/sys/dev/hyperv/include/hyperv.h	Mon Oct 17 02:19:55 2016	(r307452)
+++ stable/11/sys/dev/hyperv/include/hyperv.h	Mon Oct 17 02:23:05 2016	(r307453)
@@ -257,13 +257,6 @@ typedef struct hv_vmbus_channel {
 	int				ch_montrig_idx;	/* MNF trig index */
 	uint32_t			ch_montrig_mask;/* MNF trig mask */
 
-	uint32_t			ring_buffer_gpadl_handle;
-	/*
-	 * Allocated memory for ring buffer
-	 */
-	void*				ring_buffer_pages;
-	unsigned long			ring_buffer_size;
-	uint32_t			ring_buffer_page_count;
 	/*
 	 * send to parent
 	 */
@@ -312,6 +305,10 @@ typedef struct hv_vmbus_channel {
 	void				*hv_chan_priv2;
 	void				*hv_chan_priv3;
 
+	void				*ch_bufring;	/* TX+RX bufrings */
+	struct hyperv_dma		ch_bufring_dma;
+	uint32_t			ch_bufring_gpadl;
+
 	struct task			ch_detach_task;
 	TAILQ_ENTRY(hv_vmbus_channel)	ch_prilink;	/* primary chan link */
 	uint32_t			ch_subidx;	/* subchan index */
@@ -409,6 +406,9 @@ int		hv_vmbus_channel_teardown_gpdal(
 				hv_vmbus_channel*	channel,
 				uint32_t		gpadl_handle);
 
+int		vmbus_chan_gpadl_connect(struct hv_vmbus_channel *chan,
+		    bus_addr_t paddr, int size, uint32_t *gpadl);
+
 struct hv_vmbus_channel* vmbus_select_outgoing_channel(struct hv_vmbus_channel *promary);
 
 void		vmbus_channel_cpu_set(struct hv_vmbus_channel *chan, int cpu);

Modified: stable/11/sys/dev/hyperv/vmbus/hv_channel.c
==============================================================================
--- stable/11/sys/dev/hyperv/vmbus/hv_channel.c	Mon Oct 17 02:19:55 2016	(r307452)
+++ stable/11/sys/dev/hyperv/vmbus/hv_channel.c	Mon Oct 17 02:23:05 2016	(r307453)
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_param.h>
 #include <vm/pmap.h>
 
+#include <dev/hyperv/include/hyperv_busdma.h>
 #include <dev/hyperv/vmbus/hv_vmbus_priv.h>
 #include <dev/hyperv/vmbus/hyperv_var.h>
 #include <dev/hyperv/vmbus/vmbus_reg.h>
@@ -202,7 +203,7 @@ hv_vmbus_channel_open(
 	struct vmbus_msghc *mh;
 	uint32_t status;
 	int ret = 0;
-	void *in, *out;
+	uint8_t *br;
 
 	if (user_data_len > VMBUS_CHANMSG_CHOPEN_UDATA_SIZE) {
 		device_printf(sc->vmbus_dev,
@@ -210,6 +211,10 @@ hv_vmbus_channel_open(
 		    user_data_len, new_channel->ch_id);
 		return EINVAL;
 	}
+	KASSERT((send_ring_buffer_size & PAGE_MASK) == 0,
+	    ("send bufring size is not multiple page"));
+	KASSERT((recv_ring_buffer_size & PAGE_MASK) == 0,
+	    ("recv bufring size is not multiple page"));
 
 	if (atomic_testandset_int(&new_channel->ch_stflags,
 	    VMBUS_CHAN_ST_OPENED_SHIFT))
@@ -230,46 +235,43 @@ hv_vmbus_channel_open(
 		    vmbus_chan_task_nobatch, new_channel);
 	}
 
-	/* Allocate the ring buffer */
-	out = contigmalloc((send_ring_buffer_size + recv_ring_buffer_size),
-	    M_DEVBUF, M_ZERO, 0UL, BUS_SPACE_MAXADDR, PAGE_SIZE, 0);
-	KASSERT(out != NULL,
-	    ("Error VMBUS: contigmalloc failed to allocate Ring Buffer!"));
-	if (out == NULL) {
+	/*
+	 * 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, send_ring_buffer_size + recv_ring_buffer_size,
+	    &new_channel->ch_bufring_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
+	if (br == NULL) {
+		device_printf(sc->vmbus_dev, "bufring allocation failed\n");
 		ret = ENOMEM;
 		goto failed;
 	}
+	new_channel->ch_bufring = br;
 
-	in = ((uint8_t *) out + send_ring_buffer_size);
-
-	new_channel->ring_buffer_pages = out;
-	new_channel->ring_buffer_page_count = (send_ring_buffer_size +
-	    recv_ring_buffer_size) >> PAGE_SHIFT;
-	new_channel->ring_buffer_size = send_ring_buffer_size +
-	    recv_ring_buffer_size;
-
-	hv_vmbus_ring_buffer_init(
-		&new_channel->outbound,
-		out,
-		send_ring_buffer_size);
-
-	hv_vmbus_ring_buffer_init(
-		&new_channel->inbound,
-		in,
-		recv_ring_buffer_size);
+	/* TX bufring comes first */
+	hv_vmbus_ring_buffer_init(&new_channel->outbound,
+	    br, send_ring_buffer_size);
+	/* RX bufring immediately follows TX bufring */
+	hv_vmbus_ring_buffer_init(&new_channel->inbound,
+	    br + send_ring_buffer_size, recv_ring_buffer_size);
 
 	/* Create sysctl tree for this channel */
 	vmbus_channel_sysctl_create(new_channel);
 
-	/**
-	 * Establish the gpadl for the ring buffer
+	/*
+	 * Connect the bufrings, both RX and TX, to this channel.
 	 */
-	new_channel->ring_buffer_gpadl_handle = 0;
-
-	ret = hv_vmbus_channel_establish_gpadl(new_channel,
-		new_channel->outbound.ring_buffer,
+	ret = vmbus_chan_gpadl_connect(new_channel,
+		new_channel->ch_bufring_dma.hv_paddr,
 		send_ring_buffer_size + recv_ring_buffer_size,
-		&new_channel->ring_buffer_gpadl_handle);
+		&new_channel->ch_bufring_gpadl);
+	if (ret != 0) {
+		device_printf(sc->vmbus_dev,
+		    "failed to connect bufring GPADL to chan%u\n",
+		    new_channel->ch_id);
+		goto failed;
+	}
 
 	/*
 	 * Open channel w/ the bufring GPADL on the target CPU.
@@ -287,7 +289,7 @@ hv_vmbus_channel_open(
 	req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CHOPEN;
 	req->chm_chanid = new_channel->ch_id;
 	req->chm_openid = new_channel->ch_id;
-	req->chm_gpadl = new_channel->ring_buffer_gpadl_handle;
+	req->chm_gpadl = new_channel->ch_bufring_gpadl;
 	req->chm_vcpuid = new_channel->target_vcpu;
 	req->chm_rxbr_pgofs = send_ring_buffer_size >> PAGE_SHIFT;
 	if (user_data_len)
@@ -321,6 +323,16 @@ hv_vmbus_channel_open(
 	ret = ENXIO;
 
 failed:
+	if (new_channel->ch_bufring_gpadl) {
+		hv_vmbus_channel_teardown_gpdal(new_channel,
+		    new_channel->ch_bufring_gpadl);
+		new_channel->ch_bufring_gpadl = 0;
+	}
+	if (new_channel->ch_bufring != NULL) {
+		hyperv_dmamem_free(&new_channel->ch_bufring_dma,
+		    new_channel->ch_bufring);
+		new_channel->ch_bufring = NULL;
+	}
 	atomic_clear_int(&new_channel->ch_stflags, VMBUS_CHAN_ST_OPENED);
 	return ret;
 }
@@ -330,26 +342,33 @@ failed:
  */
 int
 hv_vmbus_channel_establish_gpadl(struct hv_vmbus_channel *channel,
-    void *contig_buffer, uint32_t size, uint32_t *gpadl0)
+    void *contig_buffer, uint32_t size, uint32_t *gpadl)
 {
-	struct vmbus_softc *sc = channel->vmbus_sc;
+	return vmbus_chan_gpadl_connect(channel,
+	    hv_get_phys_addr(contig_buffer), size, gpadl);
+}
+
+int
+vmbus_chan_gpadl_connect(struct hv_vmbus_channel *chan, bus_addr_t paddr,
+    int size, uint32_t *gpadl0)
+{
+	struct vmbus_softc *sc = chan->vmbus_sc;
 	struct vmbus_msghc *mh;
 	struct vmbus_chanmsg_gpadl_conn *req;
 	const struct vmbus_message *msg;
 	size_t reqsz;
 	uint32_t gpadl, status;
 	int page_count, range_len, i, cnt, error;
-	uint64_t page_id, paddr;
+	uint64_t page_id;
 
 	/*
 	 * Preliminary checks.
 	 */
 
 	KASSERT((size & PAGE_MASK) == 0,
-	    ("invalid GPA size %u, not multiple page size", size));
+	    ("invalid GPA size %d, not multiple page size", size));
 	page_count = size >> PAGE_SHIFT;
 
-	paddr = hv_get_phys_addr(contig_buffer);
 	KASSERT((paddr & PAGE_MASK) == 0,
 	    ("GPA is not page aligned %jx", (uintmax_t)paddr));
 	page_id = paddr >> PAGE_SHIFT;
@@ -390,13 +409,13 @@ hv_vmbus_channel_establish_gpadl(struct 
 	if (mh == NULL) {
 		device_printf(sc->vmbus_dev,
 		    "can not get msg hypercall for gpadl->chan%u\n",
-		    channel->ch_id);
+		    chan->ch_id);
 		return EIO;
 	}
 
 	req = vmbus_msghc_dataptr(mh);
 	req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_GPADL_CONN;
-	req->chm_chanid = channel->ch_id;
+	req->chm_chanid = chan->ch_id;
 	req->chm_gpadl = gpadl;
 	req->chm_range_len = range_len;
 	req->chm_range_cnt = 1;
@@ -409,7 +428,7 @@ hv_vmbus_channel_establish_gpadl(struct 
 	if (error) {
 		device_printf(sc->vmbus_dev,
 		    "gpadl->chan%u msg hypercall exec failed: %d\n",
-		    channel->ch_id, error);
+		    chan->ch_id, error);
 		vmbus_msghc_put(sc, mh);
 		return error;
 	}
@@ -445,12 +464,12 @@ hv_vmbus_channel_establish_gpadl(struct 
 
 	if (status != 0) {
 		device_printf(sc->vmbus_dev, "gpadl->chan%u failed: "
-		    "status %u\n", channel->ch_id, status);
+		    "status %u\n", chan->ch_id, status);
 		return EIO;
 	} else {
 		if (bootverbose) {
 			device_printf(sc->vmbus_dev, "gpadl->chan%u "
-			    "succeeded\n", channel->ch_id);
+			    "succeeded\n", chan->ch_id);
 		}
 	}
 	return 0;
@@ -547,9 +566,10 @@ hv_vmbus_channel_close_internal(hv_vmbus
 	}
 
 	/* Tear down the gpadl for the channel's ring buffer */
-	if (channel->ring_buffer_gpadl_handle) {
+	if (channel->ch_bufring_gpadl) {
 		hv_vmbus_channel_teardown_gpdal(channel,
-			channel->ring_buffer_gpadl_handle);
+		    channel->ch_bufring_gpadl);
+		channel->ch_bufring_gpadl = 0;
 	}
 
 	/* TODO: Send a msg to release the childRelId */
@@ -558,8 +578,11 @@ hv_vmbus_channel_close_internal(hv_vmbus
 	hv_ring_buffer_cleanup(&channel->outbound);
 	hv_ring_buffer_cleanup(&channel->inbound);
 
-	contigfree(channel->ring_buffer_pages, channel->ring_buffer_size,
-	    M_DEVBUF);
+	if (channel->ch_bufring != NULL) {
+		hyperv_dmamem_free(&channel->ch_bufring_dma,
+		    channel->ch_bufring);
+		channel->ch_bufring = NULL;
+	}
 }
 
 /*


More information about the svn-src-all mailing list