From owner-svn-src-stable@freebsd.org Mon Oct 17 02:44:29 2016 Return-Path: Delivered-To: svn-src-stable@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id D379DC13F13; Mon, 17 Oct 2016 02:44:29 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 943FE1CBE; Mon, 17 Oct 2016 02:44:29 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u9H2iSMm000830; Mon, 17 Oct 2016 02:44:28 GMT (envelope-from sephe@FreeBSD.org) Received: (from sephe@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u9H2iS9o000822; Mon, 17 Oct 2016 02:44:28 GMT (envelope-from sephe@FreeBSD.org) Message-Id: <201610170244.u9H2iS9o000822@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: sephe set sender to sephe@FreeBSD.org using -f From: Sepherosa Ziehau Date: Mon, 17 Oct 2016 02:44:28 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r307459 - in stable/11/sys/dev/hyperv: include netvsc storvsc utilities vmbus X-SVN-Group: stable-11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 17 Oct 2016 02:44:29 -0000 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 #include +#include #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 #include -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 ***