Date: Mon, 17 Oct 2016 02:23:05 +0000 (UTC) From: Sepherosa Ziehau <sephe@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r307453 - in stable/11/sys/dev/hyperv: include vmbus Message-ID: <201610170223.u9H2N5TW092484@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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; + } } /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201610170223.u9H2N5TW092484>