svn commit: r307084 - in stable/10/sys/dev/hyperv: include netvsc storvsc utilities vmbus

Sepherosa Ziehau sephe at FreeBSD.org
Wed Oct 12 02:45:32 UTC 2016


Author: sephe
Date: Wed Oct 12 02:45:30 2016
New Revision: 307084
URL: https://svnweb.freebsd.org/changeset/base/307084

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/10/sys/dev/hyperv/include/hyperv.h
  stable/10/sys/dev/hyperv/include/vmbus.h
  stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
  stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
  stable/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
  stable/10/sys/dev/hyperv/utilities/hv_util.c
  stable/10/sys/dev/hyperv/vmbus/hv_channel.c
  stable/10/sys/dev/hyperv/vmbus/vmbus_reg.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/hyperv/include/hyperv.h
==============================================================================
--- stable/10/sys/dev/hyperv/include/hyperv.h	Wed Oct 12 02:30:33 2016	(r307083)
+++ stable/10/sys/dev/hyperv/include/hyperv.h	Wed Oct 12 02:45:30 2016	(r307084)
@@ -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/10/sys/dev/hyperv/include/vmbus.h
==============================================================================
--- stable/10/sys/dev/hyperv/include/vmbus.h	Wed Oct 12 02:30:33 2016	(r307083)
+++ stable/10/sys/dev/hyperv/include/vmbus.h	Wed Oct 12 02:45:30 2016	(r307084)
@@ -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/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c	Wed Oct 12 02:30:33 2016	(r307083)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c	Wed Oct 12 02:45:30 2016	(r307084)
@@ -362,7 +362,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 
@@ -429,7 +429,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);
 
 		/*
@@ -644,7 +644,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);
 }
@@ -674,7 +674,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) {
@@ -694,7 +694,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:
 	/*
@@ -725,7 +725,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/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Wed Oct 12 02:30:33 2016	(r307083)
+++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Wed Oct 12 02:45:30 2016	(r307084)
@@ -1603,7 +1603,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);
@@ -3006,7 +3006,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
@@ -3029,7 +3029,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) {
@@ -3039,7 +3039,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/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c	Wed Oct 12 02:30:33 2016	(r307083)
+++ stable/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c	Wed Oct 12 02:45:30 2016	(r307084)
@@ -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/10/sys/dev/hyperv/utilities/hv_util.c
==============================================================================
--- stable/10/sys/dev/hyperv/utilities/hv_util.c	Wed Oct 12 02:30:33 2016	(r307083)
+++ stable/10/sys/dev/hyperv/utilities/hv_util.c	Wed Oct 12 02:45:30 2016	(r307084)
@@ -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/10/sys/dev/hyperv/vmbus/hv_channel.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_channel.c	Wed Oct 12 02:30:33 2016	(r307083)
+++ stable/10/sys/dev/hyperv/vmbus/hv_channel.c	Wed Oct 12 02:45:30 2016	(r307084)
@@ -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-all mailing list