svn commit: r307459 - in stable/11/sys/dev/hyperv: include netvsc storvsc utilities vmbus
Sepherosa Ziehau
sephe at FreeBSD.org
Mon Oct 17 02:44:29 UTC 2016
Author: sephe
Date: Mon Oct 17 02:44:27 2016
New Revision: 307459
URL: https://svnweb.freebsd.org/changeset/base/307459
Log:
MFC 302888-302892,302986,303020-303022
302888
hyperv/hn: Busdma-fy rxbuf and chimney sending buffer
Nuke unused channel GPADL API.
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D7211
302889
hyperv/vmbus: Back out r302888 temporarily
Committed by accident w/ duplicated commit log
Sponsored by: Microsoft OSTC
302890
hyperv/vmbus: Function rename
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D7212
302891
hyperv/vmbus: Cosmetic vmbus channel close cleanup
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D7213
302892
hyperv/vmbus: Cleanup channel sysctl tree creation
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D7214
302986
hyperv/vmbus: Cosmetic vmbus channel open cleanup
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D7217
303020
hyperv/vmbus: Cleanup cpu based channel selection.
And create cpu to channel map at device attach time for storvsc(4).
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D7229
303021
hyperv/vmbus: Function rename
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D7230
303022
hyperv/vmbus: Temp/internal variable/function rename
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D7231
Modified:
stable/11/sys/dev/hyperv/include/hyperv.h
stable/11/sys/dev/hyperv/include/vmbus.h
stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c
stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
stable/11/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
stable/11/sys/dev/hyperv/utilities/hv_util.c
stable/11/sys/dev/hyperv/vmbus/hv_channel.c
stable/11/sys/dev/hyperv/vmbus/vmbus_reg.h
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:38:44 2016 (r307458)
+++ stable/11/sys/dev/hyperv/include/hyperv.h Mon Oct 17 02:44:27 2016 (r307459)
@@ -267,42 +267,6 @@ typedef struct hv_vmbus_channel {
#define VMBUS_CHAN_ST_OPENED_SHIFT 0
#define VMBUS_CHAN_ST_OPENED (1 << VMBUS_CHAN_ST_OPENED_SHIFT)
-static inline void
-hv_set_channel_read_state(hv_vmbus_channel* channel, boolean_t on)
-{
- if (!on)
- channel->ch_flags &= ~VMBUS_CHAN_FLAG_BATCHREAD;
- else
- channel->ch_flags |= VMBUS_CHAN_FLAG_BATCHREAD;
-}
-
-int hv_vmbus_channel_open(
- hv_vmbus_channel* channel,
- uint32_t send_ring_buffer_size,
- uint32_t recv_ring_buffer_size,
- void* user_data,
- uint32_t user_data_len,
- vmbus_chan_callback_t cb,
- void *cbarg);
-
-void hv_vmbus_channel_close(hv_vmbus_channel *channel);
-
-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);
-void vmbus_channel_cpu_rr(struct hv_vmbus_channel *chan);
-struct hv_vmbus_channel **
- vmbus_get_subchan(struct hv_vmbus_channel *pri_chan, int subchan_cnt);
-void vmbus_rel_subchan(struct hv_vmbus_channel **subchan, int subchan_cnt);
-void vmbus_drain_subchan(struct hv_vmbus_channel *pri_chan);
-
/**
* @brief Get physical address from virtual
*/
Modified: stable/11/sys/dev/hyperv/include/vmbus.h
==============================================================================
--- stable/11/sys/dev/hyperv/include/vmbus.h Mon Oct 17 02:38:44 2016 (r307458)
+++ stable/11/sys/dev/hyperv/include/vmbus.h Mon Oct 17 02:44:27 2016 (r307459)
@@ -89,6 +89,27 @@ struct vmbus_chanpkt_rxbuf {
struct hv_vmbus_channel;
+int vmbus_chan_open(struct hv_vmbus_channel *chan,
+ int txbr_size, int rxbr_size, const void *udata, int udlen,
+ vmbus_chan_callback_t cb, void *cbarg);
+void vmbus_chan_close(struct hv_vmbus_channel *chan);
+
+int vmbus_chan_gpadl_connect(struct hv_vmbus_channel *chan,
+ bus_addr_t paddr, int size, uint32_t *gpadl);
+int vmbus_chan_gpadl_disconnect(struct hv_vmbus_channel *chan,
+ uint32_t gpadl);
+
+void vmbus_chan_cpu_set(struct hv_vmbus_channel *chan, int cpu);
+void vmbus_chan_cpu_rr(struct hv_vmbus_channel *chan);
+struct hv_vmbus_channel *
+ vmbus_chan_cpu2chan(struct hv_vmbus_channel *chan, int cpu);
+void vmbus_chan_set_readbatch(struct hv_vmbus_channel *chan, bool on);
+
+struct hv_vmbus_channel **
+ vmbus_subchan_get(struct hv_vmbus_channel *pri_chan, int subchan_cnt);
+void vmbus_subchan_rel(struct hv_vmbus_channel **subchan, int subchan_cnt);
+void vmbus_subchan_drain(struct hv_vmbus_channel *pri_chan);
+
int vmbus_chan_recv(struct hv_vmbus_channel *chan, void *data, int *dlen,
uint64_t *xactid);
int vmbus_chan_recv_pkt(struct hv_vmbus_channel *chan,
Modified: stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c Mon Oct 17 02:38:44 2016 (r307458)
+++ stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c Mon Oct 17 02:44:27 2016 (r307459)
@@ -363,7 +363,7 @@ hv_nv_destroy_rx_buffer(netvsc_dev *net_
/* Tear down the gpadl on the vsp end */
if (net_dev->rx_buf_gpadl_handle) {
- ret = hv_vmbus_channel_teardown_gpdal(net_dev->sc->hn_prichan,
+ ret = vmbus_chan_gpadl_disconnect(net_dev->sc->hn_prichan,
net_dev->rx_buf_gpadl_handle);
/*
* If we failed here, we might as well return and have a leak
@@ -430,7 +430,7 @@ hv_nv_destroy_send_buffer(netvsc_dev *ne
/* Tear down the gpadl on the vsp end */
if (net_dev->send_buf_gpadl_handle) {
- ret = hv_vmbus_channel_teardown_gpdal(net_dev->sc->hn_prichan,
+ ret = vmbus_chan_gpadl_disconnect(net_dev->sc->hn_prichan,
net_dev->send_buf_gpadl_handle);
/*
@@ -645,7 +645,7 @@ hv_nv_subchan_attach(struct hv_vmbus_cha
{
chan->hv_chan_rdbuf = malloc(NETVSC_PACKET_SIZE, M_NETVSC, M_WAITOK);
- hv_vmbus_channel_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE,
+ vmbus_chan_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE,
NETVSC_DEVICE_RING_BUFFER_SIZE, NULL, 0,
hv_nv_on_channel_callback, chan);
}
@@ -675,7 +675,7 @@ hv_nv_on_device_add(struct hn_softc *sc,
/*
* Open the channel
*/
- ret = hv_vmbus_channel_open(chan,
+ ret = vmbus_chan_open(chan,
NETVSC_DEVICE_RING_BUFFER_SIZE, NETVSC_DEVICE_RING_BUFFER_SIZE,
NULL, 0, hv_nv_on_channel_callback, chan);
if (ret != 0) {
@@ -695,7 +695,7 @@ hv_nv_on_device_add(struct hn_softc *sc,
close:
/* Now, we can close the channel safely */
free(chan->hv_chan_rdbuf, M_NETVSC);
- hv_vmbus_channel_close(chan);
+ vmbus_chan_close(chan);
cleanup:
/*
@@ -726,7 +726,7 @@ hv_nv_on_device_remove(struct hn_softc *
/* Now, we can close the channel safely */
free(sc->hn_prichan->hv_chan_rdbuf, M_NETVSC);
- hv_vmbus_channel_close(sc->hn_prichan);
+ vmbus_chan_close(sc->hn_prichan);
sema_destroy(&net_dev->channel_init_sema);
free(net_dev, M_NETVSC);
Modified: stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Mon Oct 17 02:38:44 2016 (r307458)
+++ stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Mon Oct 17 02:44:27 2016 (r307459)
@@ -1586,7 +1586,7 @@ hn_ioctl(struct ifnet *ifp, u_long cmd,
}
/* Wait for subchannels to be destroyed */
- vmbus_drain_subchan(sc->hn_prichan);
+ vmbus_subchan_drain(sc->hn_prichan);
error = hv_rf_on_device_add(sc, &device_info,
sc->hn_rx_ring_inuse);
@@ -2950,7 +2950,7 @@ hn_channel_attach(struct hn_softc *sc, s
}
/* Bind channel to a proper CPU */
- vmbus_channel_cpu_set(chan, (sc->hn_cpu + idx) % mp_ncpus);
+ vmbus_chan_cpu_set(chan, (sc->hn_cpu + idx) % mp_ncpus);
}
static void
@@ -2973,7 +2973,7 @@ hn_subchan_setup(struct hn_softc *sc)
int i;
/* Wait for sub-channels setup to complete. */
- subchan = vmbus_get_subchan(sc->hn_prichan, subchan_cnt);
+ subchan = vmbus_subchan_get(sc->hn_prichan, subchan_cnt);
/* Attach the sub-channels. */
for (i = 0; i < subchan_cnt; ++i) {
@@ -2983,7 +2983,7 @@ hn_subchan_setup(struct hn_softc *sc)
}
/* Release the sub-channels */
- vmbus_rel_subchan(subchan, subchan_cnt);
+ vmbus_subchan_rel(subchan, subchan_cnt);
if_printf(sc->hn_ifp, "%d sub-channels setup done\n", subchan_cnt);
}
Modified: stable/11/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
==============================================================================
--- stable/11/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c Mon Oct 17 02:38:44 2016 (r307458)
+++ stable/11/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c Mon Oct 17 02:44:27 2016 (r307459)
@@ -147,6 +147,8 @@ struct storvsc_softc {
struct hv_storvsc_request hs_init_req;
struct hv_storvsc_request hs_reset_req;
device_t hs_dev;
+
+ struct hv_vmbus_channel *hs_cpu2chan[MAXCPU];
};
@@ -315,8 +317,8 @@ storvsc_subchan_attach(struct storvsc_so
memset(&props, 0, sizeof(props));
new_channel->hv_chan_priv1 = sc;
- vmbus_channel_cpu_rr(new_channel);
- ret = hv_vmbus_channel_open(new_channel,
+ vmbus_chan_cpu_rr(new_channel);
+ ret = vmbus_chan_open(new_channel,
sc->hs_drv_props->drv_ringbuffer_size,
sc->hs_drv_props->drv_ringbuffer_size,
(void *)&props,
@@ -377,14 +379,14 @@ storvsc_send_multichannel_request(struct
}
/* Wait for sub-channels setup to complete. */
- subchan = vmbus_get_subchan(sc->hs_chan, request_channels_cnt);
+ subchan = vmbus_subchan_get(sc->hs_chan, request_channels_cnt);
/* Attach the sub-channels. */
for (i = 0; i < request_channels_cnt; ++i)
storvsc_subchan_attach(sc, subchan[i]);
/* Release the sub-channels. */
- vmbus_rel_subchan(subchan, request_channels_cnt);
+ vmbus_subchan_rel(subchan, request_channels_cnt);
if (bootverbose)
printf("Storvsc create multi-channel success!\n");
@@ -574,8 +576,8 @@ hv_storvsc_connect_vsp(struct storvsc_so
* Open the channel
*/
KASSERT(sc->hs_chan->hv_chan_priv1 == sc, ("invalid chan priv1"));
- vmbus_channel_cpu_rr(sc->hs_chan);
- ret = hv_vmbus_channel_open(
+ vmbus_chan_cpu_rr(sc->hs_chan);
+ ret = vmbus_chan_open(
sc->hs_chan,
sc->hs_drv_props->drv_ringbuffer_size,
sc->hs_drv_props->drv_ringbuffer_size,
@@ -665,7 +667,7 @@ hv_storvsc_io_request(struct storvsc_sof
vstor_packet->operation = VSTOR_OPERATION_EXECUTESRB;
- outgoing_channel = vmbus_select_outgoing_channel(sc->hs_chan);
+ outgoing_channel = sc->hs_cpu2chan[curcpu];
mtx_unlock(&request->softc->hs_lock);
if (request->prp_list.gpa_range.gpa_len) {
@@ -872,6 +874,20 @@ storvsc_probe(device_t dev)
return (ret);
}
+static void
+storvsc_create_cpu2chan(struct storvsc_softc *sc)
+{
+ int cpu;
+
+ CPU_FOREACH(cpu) {
+ sc->hs_cpu2chan[cpu] = vmbus_chan_cpu2chan(sc->hs_chan, cpu);
+ if (bootverbose) {
+ device_printf(sc->hs_dev, "cpu%d -> chan%u\n",
+ cpu, sc->hs_cpu2chan[cpu]->ch_id);
+ }
+ }
+}
+
/**
* @brief StorVSC attach function
*
@@ -969,6 +985,9 @@ storvsc_attach(device_t dev)
goto cleanup;
}
+ /* Construct cpu to channel mapping */
+ storvsc_create_cpu2chan(sc);
+
/*
* Create the device queue.
* Hyper-V maps each target to one SCSI HBA
@@ -1083,7 +1102,7 @@ storvsc_detach(device_t dev)
* under the protection of the incoming channel lock.
*/
- hv_vmbus_channel_close(sc->hs_chan);
+ vmbus_chan_close(sc->hs_chan);
mtx_lock(&sc->hs_lock);
while (!LIST_EMPTY(&sc->hs_free_list)) {
Modified: stable/11/sys/dev/hyperv/utilities/hv_util.c
==============================================================================
--- stable/11/sys/dev/hyperv/utilities/hv_util.c Mon Oct 17 02:38:44 2016 (r307458)
+++ stable/11/sys/dev/hyperv/utilities/hv_util.c Mon Oct 17 02:44:27 2016 (r307459)
@@ -40,6 +40,7 @@
#include <sys/syscallsubr.h>
#include <dev/hyperv/include/hyperv.h>
+#include <dev/hyperv/include/vmbus.h>
#include "hv_util.h"
void
@@ -89,9 +90,9 @@ hv_util_attach(device_t dev)
* Turn off batched reading for all util drivers before we open the
* channel.
*/
- hv_set_channel_read_state(softc->channel, FALSE);
+ vmbus_chan_set_readbatch(softc->channel, false);
- ret = hv_vmbus_channel_open(softc->channel, 4 * PAGE_SIZE,
+ ret = vmbus_chan_open(softc->channel, 4 * PAGE_SIZE,
4 * PAGE_SIZE, NULL, 0,
softc->callback, softc);
@@ -110,7 +111,7 @@ hv_util_detach(device_t dev)
{
struct hv_util_sc *sc = device_get_softc(dev);
- hv_vmbus_channel_close(sc->channel);
+ vmbus_chan_close(sc->channel);
free(sc->receive_buffer, M_DEVBUF);
return (0);
Modified: stable/11/sys/dev/hyperv/vmbus/hv_channel.c
==============================================================================
--- stable/11/sys/dev/hyperv/vmbus/hv_channel.c Mon Oct 17 02:38:44 2016 (r307458)
+++ stable/11/sys/dev/hyperv/vmbus/hv_channel.c Mon Oct 17 02:44:27 2016 (r307459)
@@ -51,7 +51,7 @@ __FBSDID("$FreeBSD$");
#include <dev/hyperv/vmbus/vmbus_reg.h>
#include <dev/hyperv/vmbus/vmbus_var.h>
-static void vmbus_chan_send_event(hv_vmbus_channel* channel);
+static void vmbus_chan_signal_tx(struct hv_vmbus_channel *chan);
static void vmbus_chan_update_evtflagcnt(struct vmbus_softc *,
const struct hv_vmbus_channel *);
@@ -81,195 +81,194 @@ vmbus_chan_msgprocs[VMBUS_CHANMSG_TYPE_M
* @brief Trigger an event notification on the specified channel
*/
static void
-vmbus_chan_send_event(hv_vmbus_channel *channel)
+vmbus_chan_signal_tx(struct hv_vmbus_channel *chan)
{
- struct vmbus_softc *sc = channel->vmbus_sc;
- uint32_t chanid = channel->ch_id;
+ struct vmbus_softc *sc = chan->vmbus_sc;
+ uint32_t chanid = chan->ch_id;
atomic_set_long(&sc->vmbus_tx_evtflags[chanid >> VMBUS_EVTFLAG_SHIFT],
1UL << (chanid & VMBUS_EVTFLAG_MASK));
- if (channel->ch_flags & VMBUS_CHAN_FLAG_HASMNF) {
+ if (chan->ch_flags & VMBUS_CHAN_FLAG_HASMNF) {
atomic_set_int(
- &sc->vmbus_mnf2->mnf_trigs[channel->ch_montrig_idx].mt_pending,
- channel->ch_montrig_mask);
+ &sc->vmbus_mnf2->mnf_trigs[chan->ch_montrig_idx].mt_pending,
+ chan->ch_montrig_mask);
} else {
- hypercall_signal_event(channel->ch_monprm_dma.hv_paddr);
+ hypercall_signal_event(chan->ch_monprm_dma.hv_paddr);
}
}
static int
-vmbus_channel_sysctl_monalloc(SYSCTL_HANDLER_ARGS)
+vmbus_chan_sysctl_mnf(SYSCTL_HANDLER_ARGS)
{
struct hv_vmbus_channel *chan = arg1;
- int alloc = 0;
+ int mnf = 0;
if (chan->ch_flags & VMBUS_CHAN_FLAG_HASMNF)
- alloc = 1;
- return sysctl_handle_int(oidp, &alloc, 0, req);
+ mnf = 1;
+ return sysctl_handle_int(oidp, &mnf, 0, req);
}
static void
-vmbus_channel_sysctl_create(hv_vmbus_channel* channel)
+vmbus_chan_sysctl_create(struct hv_vmbus_channel *chan)
{
- device_t dev;
- struct sysctl_oid *devch_sysctl;
- struct sysctl_oid *devch_id_sysctl, *devch_sub_sysctl;
- struct sysctl_oid *devch_id_in_sysctl, *devch_id_out_sysctl;
+ struct sysctl_oid *ch_tree, *chid_tree, *br_tree;
struct sysctl_ctx_list *ctx;
uint32_t ch_id;
- uint16_t sub_ch_id;
char name[16];
-
- hv_vmbus_channel* primary_ch = channel->ch_prichan;
- if (primary_ch == NULL) {
- dev = channel->ch_dev;
- ch_id = channel->ch_id;
- } else {
- dev = primary_ch->ch_dev;
- ch_id = primary_ch->ch_id;
- sub_ch_id = channel->ch_subidx;
- }
- ctx = &channel->ch_sysctl_ctx;
+ /*
+ * Add sysctl nodes related to this channel to this
+ * channel's sysctl ctx, so that they can be destroyed
+ * independently upon close of this channel, which can
+ * happen even if the device is not detached.
+ */
+ ctx = &chan->ch_sysctl_ctx;
sysctl_ctx_init(ctx);
- /* This creates dev.DEVNAME.DEVUNIT.channel tree */
- devch_sysctl = SYSCTL_ADD_NODE(ctx,
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "channel", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
- /* This creates dev.DEVNAME.DEVUNIT.channel.CHANID tree */
+
+ /*
+ * Create dev.NAME.UNIT.channel tree.
+ */
+ ch_tree = SYSCTL_ADD_NODE(ctx,
+ SYSCTL_CHILDREN(device_get_sysctl_tree(chan->ch_dev)),
+ OID_AUTO, "channel", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
+ if (ch_tree == NULL)
+ return;
+
+ /*
+ * Create dev.NAME.UNIT.channel.CHANID tree.
+ */
+ if (VMBUS_CHAN_ISPRIMARY(chan))
+ ch_id = chan->ch_id;
+ else
+ ch_id = chan->ch_prichan->ch_id;
snprintf(name, sizeof(name), "%d", ch_id);
- devch_id_sysctl = SYSCTL_ADD_NODE(ctx,
- SYSCTL_CHILDREN(devch_sysctl),
- OID_AUTO, name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
-
- if (primary_ch != NULL) {
- devch_sub_sysctl = SYSCTL_ADD_NODE(ctx,
- SYSCTL_CHILDREN(devch_id_sysctl),
- OID_AUTO, "sub", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
- snprintf(name, sizeof(name), "%d", sub_ch_id);
- devch_id_sysctl = SYSCTL_ADD_NODE(ctx,
- SYSCTL_CHILDREN(devch_sub_sysctl),
- OID_AUTO, name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
-
- SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(devch_id_sysctl),
- OID_AUTO, "chanid", CTLFLAG_RD,
- &channel->ch_id, 0, "channel id");
- }
- SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(devch_id_sysctl), OID_AUTO,
- "cpu", CTLFLAG_RD, &channel->ch_cpuid, 0, "owner CPU id");
- SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(devch_id_sysctl), OID_AUTO,
- "monitor_allocated", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
- channel, 0, vmbus_channel_sysctl_monalloc, "I",
- "is monitor allocated to this channel");
-
- devch_id_in_sysctl = SYSCTL_ADD_NODE(ctx,
- SYSCTL_CHILDREN(devch_id_sysctl),
- OID_AUTO,
- "in",
- CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
- devch_id_out_sysctl = SYSCTL_ADD_NODE(ctx,
- SYSCTL_CHILDREN(devch_id_sysctl),
- OID_AUTO,
- "out",
- CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
- hv_ring_buffer_stat(ctx,
- SYSCTL_CHILDREN(devch_id_in_sysctl),
- &(channel->inbound),
- "inbound ring buffer stats");
- hv_ring_buffer_stat(ctx,
- SYSCTL_CHILDREN(devch_id_out_sysctl),
- &(channel->outbound),
- "outbound ring buffer stats");
+ chid_tree = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(ch_tree),
+ OID_AUTO, name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
+ if (chid_tree == NULL)
+ return;
+
+ if (!VMBUS_CHAN_ISPRIMARY(chan)) {
+ /*
+ * Create dev.NAME.UNIT.channel.CHANID.sub tree.
+ */
+ ch_tree = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(chid_tree),
+ OID_AUTO, "sub", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
+ if (ch_tree == NULL)
+ return;
+
+ /*
+ * Create dev.NAME.UNIT.channel.CHANID.sub.SUBIDX tree.
+ *
+ * NOTE:
+ * chid_tree is changed to this new sysctl tree.
+ */
+ snprintf(name, sizeof(name), "%d", chan->ch_subidx);
+ chid_tree = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(ch_tree),
+ OID_AUTO, name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
+ if (chid_tree == NULL)
+ return;
+
+ SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
+ "chanid", CTLFLAG_RD, &chan->ch_id, 0, "channel id");
+ }
+
+ SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
+ "cpu", CTLFLAG_RD, &chan->ch_cpuid, 0, "owner CPU id");
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
+ "mnf", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ chan, 0, vmbus_chan_sysctl_mnf, "I",
+ "has monitor notification facilities");
+
+ /*
+ * Create sysctl tree for RX bufring.
+ */
+ br_tree = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
+ "in", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
+ if (br_tree != NULL) {
+ hv_ring_buffer_stat(ctx, SYSCTL_CHILDREN(br_tree),
+ &chan->inbound, "inbound ring buffer stats");
+ }
+
+ /*
+ * Create sysctl tree for TX bufring.
+ */
+ br_tree = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
+ "out", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
+ if (br_tree != NULL) {
+ hv_ring_buffer_stat(ctx, SYSCTL_CHILDREN(br_tree),
+ &chan->outbound, "outbound ring buffer stats");
+ }
}
-/**
- * @brief Open the specified channel
- */
int
-hv_vmbus_channel_open(
- hv_vmbus_channel* new_channel,
- uint32_t send_ring_buffer_size,
- uint32_t recv_ring_buffer_size,
- void* user_data,
- uint32_t user_data_len,
- vmbus_chan_callback_t cb,
- void *cbarg)
+vmbus_chan_open(struct hv_vmbus_channel *chan, int txbr_size, int rxbr_size,
+ const void *udata, int udlen, vmbus_chan_callback_t cb, void *cbarg)
{
- struct vmbus_softc *sc = new_channel->vmbus_sc;
+ struct vmbus_softc *sc = chan->vmbus_sc;
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 ret = 0;
+ int error;
uint8_t *br;
- if (user_data_len > VMBUS_CHANMSG_CHOPEN_UDATA_SIZE) {
+ if (udlen > VMBUS_CHANMSG_CHOPEN_UDATA_SIZE) {
device_printf(sc->vmbus_dev,
- "invalid udata len %u for chan%u\n",
- user_data_len, new_channel->ch_id);
+ "invalid udata len %d for chan%u\n", udlen, chan->ch_id);
return EINVAL;
}
- KASSERT((send_ring_buffer_size & PAGE_MASK) == 0,
+ KASSERT((txbr_size & PAGE_MASK) == 0,
("send bufring size is not multiple page"));
- KASSERT((recv_ring_buffer_size & PAGE_MASK) == 0,
+ KASSERT((rxbr_size & PAGE_MASK) == 0,
("recv bufring size is not multiple page"));
- if (atomic_testandset_int(&new_channel->ch_stflags,
+ if (atomic_testandset_int(&chan->ch_stflags,
VMBUS_CHAN_ST_OPENED_SHIFT))
- panic("double-open chan%u", new_channel->ch_id);
+ panic("double-open chan%u", chan->ch_id);
- new_channel->ch_cb = cb;
- new_channel->ch_cbarg = cbarg;
+ chan->ch_cb = cb;
+ chan->ch_cbarg = cbarg;
- vmbus_chan_update_evtflagcnt(sc, new_channel);
+ vmbus_chan_update_evtflagcnt(sc, chan);
- new_channel->ch_tq = VMBUS_PCPU_GET(new_channel->vmbus_sc, event_tq,
- new_channel->ch_cpuid);
- if (new_channel->ch_flags & VMBUS_CHAN_FLAG_BATCHREAD) {
- TASK_INIT(&new_channel->ch_task, 0, vmbus_chan_task,
- new_channel);
- } else {
- TASK_INIT(&new_channel->ch_task, 0, vmbus_chan_task_nobatch,
- new_channel);
- }
+ chan->ch_tq = VMBUS_PCPU_GET(chan->vmbus_sc, event_tq, chan->ch_cpuid);
+ if (chan->ch_flags & VMBUS_CHAN_FLAG_BATCHREAD)
+ TASK_INIT(&chan->ch_task, 0, vmbus_chan_task, chan);
+ 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, send_ring_buffer_size + recv_ring_buffer_size,
- &new_channel->ch_bufring_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
+ 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");
- ret = ENOMEM;
+ error = ENOMEM;
goto failed;
}
- new_channel->ch_bufring = br;
+ chan->ch_bufring = br;
/* TX bufring comes first */
- hv_vmbus_ring_buffer_init(&new_channel->outbound,
- br, send_ring_buffer_size);
+ hv_vmbus_ring_buffer_init(&chan->outbound, br, txbr_size);
/* RX bufring immediately follows TX bufring */
- hv_vmbus_ring_buffer_init(&new_channel->inbound,
- br + send_ring_buffer_size, recv_ring_buffer_size);
+ hv_vmbus_ring_buffer_init(&chan->inbound, br + txbr_size, rxbr_size);
/* Create sysctl tree for this channel */
- vmbus_channel_sysctl_create(new_channel);
+ vmbus_chan_sysctl_create(chan);
/*
* Connect the bufrings, both RX and TX, to this channel.
*/
- ret = vmbus_chan_gpadl_connect(new_channel,
- new_channel->ch_bufring_dma.hv_paddr,
- send_ring_buffer_size + recv_ring_buffer_size,
- &new_channel->ch_bufring_gpadl);
- if (ret != 0) {
+ error = vmbus_chan_gpadl_connect(chan, chan->ch_bufring_dma.hv_paddr,
+ txbr_size + rxbr_size, &chan->ch_bufring_gpadl);
+ if (error) {
device_printf(sc->vmbus_dev,
- "failed to connect bufring GPADL to chan%u\n",
- new_channel->ch_id);
+ "failed to connect bufring GPADL to chan%u\n", chan->ch_id);
goto failed;
}
@@ -280,26 +279,26 @@ hv_vmbus_channel_open(
if (mh == NULL) {
device_printf(sc->vmbus_dev,
"can not get msg hypercall for chopen(chan%u)\n",
- new_channel->ch_id);
- ret = ENXIO;
+ chan->ch_id);
+ error = ENXIO;
goto failed;
}
req = vmbus_msghc_dataptr(mh);
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->ch_bufring_gpadl;
- req->chm_vcpuid = new_channel->ch_vcpuid;
- req->chm_rxbr_pgofs = send_ring_buffer_size >> PAGE_SHIFT;
- if (user_data_len)
- memcpy(req->chm_udata, user_data, user_data_len);
+ req->chm_chanid = chan->ch_id;
+ req->chm_openid = chan->ch_id;
+ req->chm_gpadl = chan->ch_bufring_gpadl;
+ req->chm_vcpuid = chan->ch_vcpuid;
+ req->chm_txbr_pgcnt = txbr_size >> PAGE_SHIFT;
+ if (udlen > 0)
+ memcpy(req->chm_udata, udata, udlen);
- ret = vmbus_msghc_exec(sc, mh);
- if (ret != 0) {
+ error = vmbus_msghc_exec(sc, mh);
+ if (error) {
device_printf(sc->vmbus_dev,
"chopen(chan%u) msg hypercall exec failed: %d\n",
- new_channel->ch_id, ret);
+ chan->ch_id, error);
vmbus_msghc_put(sc, mh);
goto failed;
}
@@ -313,28 +312,25 @@ hv_vmbus_channel_open(
if (status == 0) {
if (bootverbose) {
device_printf(sc->vmbus_dev, "chan%u opened\n",
- new_channel->ch_id);
+ chan->ch_id);
}
return 0;
}
- device_printf(sc->vmbus_dev, "failed to open chan%u\n",
- new_channel->ch_id);
- ret = ENXIO;
+ device_printf(sc->vmbus_dev, "failed to open chan%u\n", chan->ch_id);
+ error = 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;
+ if (chan->ch_bufring_gpadl) {
+ 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(&new_channel->ch_stflags, VMBUS_CHAN_ST_OPENED);
- return ret;
+ atomic_clear_int(&chan->ch_stflags, VMBUS_CHAN_ST_OPENED);
+ return error;
}
int
@@ -468,7 +464,7 @@ vmbus_chan_gpadl_connect(struct hv_vmbus
* Disconnect the GPA from the target channel
*/
int
-hv_vmbus_channel_teardown_gpdal(struct hv_vmbus_channel *chan, uint32_t gpadl)
+vmbus_chan_gpadl_disconnect(struct hv_vmbus_channel *chan, uint32_t gpadl)
{
struct vmbus_softc *sc = chan->vmbus_sc;
struct vmbus_msghc *mh;
@@ -505,41 +501,45 @@ hv_vmbus_channel_teardown_gpdal(struct h
}
static void
-hv_vmbus_channel_close_internal(hv_vmbus_channel *channel)
+vmbus_chan_close_internal(struct hv_vmbus_channel *chan)
{
- struct vmbus_softc *sc = channel->vmbus_sc;
+ struct vmbus_softc *sc = chan->vmbus_sc;
struct vmbus_msghc *mh;
struct vmbus_chanmsg_chclose *req;
- struct taskqueue *tq = channel->ch_tq;
+ struct taskqueue *tq = chan->ch_tq;
int error;
/* TODO: stringent check */
- atomic_clear_int(&channel->ch_stflags, VMBUS_CHAN_ST_OPENED);
-
- sysctl_ctx_free(&channel->ch_sysctl_ctx);
+ atomic_clear_int(&chan->ch_stflags, VMBUS_CHAN_ST_OPENED);
/*
- * Set ch_tq to NULL to avoid more requests be scheduled
+ * Free this channel's sysctl tree attached to its device's
+ * sysctl tree.
*/
- channel->ch_tq = NULL;
- taskqueue_drain(tq, &channel->ch_task);
- channel->ch_cb = NULL;
+ sysctl_ctx_free(&chan->ch_sysctl_ctx);
- /**
- * Send a closing message
+ /*
+ * Set ch_tq to NULL to avoid more requests be scheduled.
+ * XXX pretty broken; need rework.
*/
+ chan->ch_tq = NULL;
+ taskqueue_drain(tq, &chan->ch_task);
+ chan->ch_cb = NULL;
+ /*
+ * Close this channel.
+ */
mh = vmbus_msghc_get(sc, sizeof(*req));
if (mh == NULL) {
device_printf(sc->vmbus_dev,
"can not get msg hypercall for chclose(chan%u)\n",
- channel->ch_id);
+ chan->ch_id);
return;
}
req = vmbus_msghc_dataptr(mh);
req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CHCLOSE;
- req->chm_chanid = channel->ch_id;
+ req->chm_chanid = chan->ch_id;
error = vmbus_msghc_exec_noresult(mh);
vmbus_msghc_put(sc, mh);
@@ -547,30 +547,28 @@ hv_vmbus_channel_close_internal(hv_vmbus
if (error) {
device_printf(sc->vmbus_dev,
"chclose(chan%u) msg hypercall exec failed: %d\n",
- channel->ch_id, error);
+ chan->ch_id, error);
return;
} else if (bootverbose) {
- device_printf(sc->vmbus_dev, "close chan%u\n",
- channel->ch_id);
+ device_printf(sc->vmbus_dev, "close chan%u\n", chan->ch_id);
}
- /* Tear down the gpadl for the channel's ring buffer */
- if (channel->ch_bufring_gpadl) {
- hv_vmbus_channel_teardown_gpdal(channel,
- channel->ch_bufring_gpadl);
- channel->ch_bufring_gpadl = 0;
+ /*
+ * Disconnect the TX+RX bufrings from this channel.
+ */
+ if (chan->ch_bufring_gpadl) {
+ vmbus_chan_gpadl_disconnect(chan, chan->ch_bufring_gpadl);
+ chan->ch_bufring_gpadl = 0;
}
- /* TODO: Send a msg to release the childRelId */
-
- /* cleanup the ring buffers for this channel */
- hv_ring_buffer_cleanup(&channel->outbound);
- hv_ring_buffer_cleanup(&channel->inbound);
-
- if (channel->ch_bufring != NULL) {
- hyperv_dmamem_free(&channel->ch_bufring_dma,
- channel->ch_bufring);
- channel->ch_bufring = NULL;
+ /*
+ * Destroy the TX+RX bufrings.
+ */
+ hv_ring_buffer_cleanup(&chan->outbound);
+ hv_ring_buffer_cleanup(&chan->inbound);
+ if (chan->ch_bufring != NULL) {
+ hyperv_dmamem_free(&chan->ch_bufring_dma, chan->ch_bufring);
+ chan->ch_bufring = NULL;
}
}
@@ -580,7 +578,7 @@ hv_vmbus_channel_close_internal(hv_vmbus
* are not being opened.
*/
void
-hv_vmbus_channel_close(struct hv_vmbus_channel *chan)
+vmbus_chan_close(struct hv_vmbus_channel *chan)
{
int subchan_cnt;
@@ -600,14 +598,14 @@ hv_vmbus_channel_close(struct hv_vmbus_c
struct hv_vmbus_channel **subchan;
int i;
- subchan = vmbus_get_subchan(chan, subchan_cnt);
+ subchan = vmbus_subchan_get(chan, subchan_cnt);
for (i = 0; i < subchan_cnt; ++i)
- hv_vmbus_channel_close_internal(subchan[i]);
- vmbus_rel_subchan(subchan, subchan_cnt);
+ vmbus_chan_close_internal(subchan[i]);
+ vmbus_subchan_rel(subchan, subchan_cnt);
}
/* Then close the primary channel. */
- hv_vmbus_channel_close_internal(chan);
+ vmbus_chan_close_internal(chan);
}
int
@@ -639,7 +637,7 @@ vmbus_chan_send(struct hv_vmbus_channel
error = hv_ring_buffer_write(&chan->outbound, iov, 3, &send_evt);
if (!error && send_evt)
- vmbus_chan_send_event(chan);
+ vmbus_chan_signal_tx(chan);
return error;
}
@@ -679,7 +677,7 @@ vmbus_chan_send_sglist(struct hv_vmbus_c
error = hv_ring_buffer_write(&chan->outbound, iov, 4, &send_evt);
if (!error && send_evt)
- vmbus_chan_send_event(chan);
+ vmbus_chan_signal_tx(chan);
return error;
}
@@ -721,7 +719,7 @@ vmbus_chan_send_prplist(struct hv_vmbus_
error = hv_ring_buffer_write(&chan->outbound, iov, 4, &send_evt);
if (!error && send_evt)
- vmbus_chan_send_event(chan);
+ vmbus_chan_signal_tx(chan);
return error;
}
@@ -840,20 +838,20 @@ vmbus_event_flags_proc(struct vmbus_soft
chid_base = f << VMBUS_EVTFLAG_SHIFT;
while ((chid_ofs = ffsl(flags)) != 0) {
- struct hv_vmbus_channel *channel;
+ struct hv_vmbus_channel *chan;
--chid_ofs; /* NOTE: ffsl is 1-based */
flags &= ~(1UL << chid_ofs);
- channel = sc->vmbus_chmap[chid_base + chid_ofs];
+ chan = sc->vmbus_chmap[chid_base + chid_ofs];
/* if channel is closed or closing */
- if (channel == NULL || channel->ch_tq == NULL)
+ if (chan == NULL || chan->ch_tq == NULL)
continue;
- if (channel->ch_flags & VMBUS_CHAN_FLAG_BATCHREAD)
- hv_ring_buffer_read_begin(&channel->inbound);
- taskqueue_enqueue(channel->ch_tq, &channel->ch_task);
+ if (chan->ch_flags & VMBUS_CHAN_FLAG_BATCHREAD)
+ hv_ring_buffer_read_begin(&chan->inbound);
+ taskqueue_enqueue(chan->ch_tq, &chan->ch_task);
}
}
}
@@ -1038,7 +1036,7 @@ vmbus_chan_add(struct hv_vmbus_channel *
}
void
-vmbus_channel_cpu_set(struct hv_vmbus_channel *chan, int cpu)
+vmbus_chan_cpu_set(struct hv_vmbus_channel *chan, int cpu)
{
KASSERT(cpu >= 0 && cpu < mp_ncpus, ("invalid cpu %d", cpu));
@@ -1058,13 +1056,13 @@ vmbus_channel_cpu_set(struct hv_vmbus_ch
}
void
-vmbus_channel_cpu_rr(struct hv_vmbus_channel *chan)
+vmbus_chan_cpu_rr(struct hv_vmbus_channel *chan)
{
static uint32_t vmbus_chan_nextcpu;
int cpu;
cpu = atomic_fetchadd_int(&vmbus_chan_nextcpu, 1) % mp_ncpus;
- vmbus_channel_cpu_set(chan, cpu);
+ vmbus_chan_cpu_set(chan, cpu);
}
static void
@@ -1073,9 +1071,9 @@ vmbus_chan_cpu_default(struct hv_vmbus_c
/*
* By default, pin the channel to cpu0. Devices having
* special channel-cpu mapping requirement should call
- * vmbus_channel_cpu_{set,rr}().
+ * vmbus_chan_cpu_{set,rr}().
*/
- vmbus_channel_cpu_set(chan, 0);
+ vmbus_chan_cpu_set(chan, 0);
}
static void
@@ -1251,65 +1249,67 @@ vmbus_chan_destroy_all(struct vmbus_soft
mtx_unlock(&sc->vmbus_prichan_lock);
}
-/**
- * @brief Select the best outgoing channel
- *
+/*
* The channel whose vcpu binding is closest to the currect vcpu will
* be selected.
- * If no multi-channel, always select primary channel
- *
- * @param primary - primary channel
+ * If no multi-channel, always select primary channel.
*/
struct hv_vmbus_channel *
-vmbus_select_outgoing_channel(struct hv_vmbus_channel *primary)
+vmbus_chan_cpu2chan(struct hv_vmbus_channel *prichan, int cpu)
{
- hv_vmbus_channel *new_channel = NULL;
- hv_vmbus_channel *outgoing_channel = primary;
- int old_cpu_distance = 0;
- int new_cpu_distance = 0;
- int cur_vcpu = 0;
- int smp_pro_id = PCPU_GET(cpuid);
+ struct hv_vmbus_channel *sel, *chan;
+ uint32_t vcpu, sel_dist;
- if (TAILQ_EMPTY(&primary->ch_subchans)) {
- return outgoing_channel;
- }
+ KASSERT(cpu >= 0 && cpu < mp_ncpus, ("invalid cpuid %d", cpu));
+ if (TAILQ_EMPTY(&prichan->ch_subchans))
+ return prichan;
- if (smp_pro_id >= MAXCPU) {
- return outgoing_channel;
- }
+ vcpu = VMBUS_PCPU_GET(prichan->vmbus_sc, vcpuid, cpu);
- cur_vcpu = VMBUS_PCPU_GET(primary->vmbus_sc, vcpuid, smp_pro_id);
-
- /* XXX need lock */
- TAILQ_FOREACH(new_channel, &primary->ch_subchans, ch_sublink) {
- if ((new_channel->ch_stflags & VMBUS_CHAN_ST_OPENED) == 0) {
- continue;
- }
+#define CHAN_VCPU_DIST(ch, vcpu) \
+ (((ch)->ch_vcpuid > (vcpu)) ? \
+ ((ch)->ch_vcpuid - (vcpu)) : ((vcpu) - (ch)->ch_vcpuid))
- if (new_channel->ch_vcpuid == cur_vcpu){
- return new_channel;
- }
+#define CHAN_SELECT(ch) \
+do { \
+ sel = ch; \
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable
mailing list