svn commit: r307032 - in stable/10/sys/dev/hyperv: include vmbus
Sepherosa Ziehau
sephe at FreeBSD.org
Tue Oct 11 08:52:28 UTC 2016
Author: sephe
Date: Tue Oct 11 08:52:27 2016
New Revision: 307032
URL: https://svnweb.freebsd.org/changeset/base/307032
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/10/sys/dev/hyperv/include/hyperv.h
stable/10/sys/dev/hyperv/vmbus/hv_channel.c
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/dev/hyperv/include/hyperv.h
==============================================================================
--- stable/10/sys/dev/hyperv/include/hyperv.h Tue Oct 11 08:48:36 2016 (r307031)
+++ stable/10/sys/dev/hyperv/include/hyperv.h Tue Oct 11 08:52:27 2016 (r307032)
@@ -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/10/sys/dev/hyperv/vmbus/hv_channel.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_channel.c Tue Oct 11 08:48:36 2016 (r307031)
+++ stable/10/sys/dev/hyperv/vmbus/hv_channel.c Tue Oct 11 08:52:27 2016 (r307032)
@@ -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