From owner-svn-src-head@freebsd.org Tue Jul 19 05:46:17 2016 Return-Path: Delivered-To: svn-src-head@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 0C2CFB9D771; Tue, 19 Jul 2016 05:46:17 +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 D84B61F34; Tue, 19 Jul 2016 05:46:16 +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 u6J5kGW1019114; Tue, 19 Jul 2016 05:46:16 GMT (envelope-from sephe@FreeBSD.org) Received: (from sephe@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u6J5kFT7019109; Tue, 19 Jul 2016 05:46:15 GMT (envelope-from sephe@FreeBSD.org) Message-Id: <201607190546.u6J5kFT7019109@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: sephe set sender to sephe@FreeBSD.org using -f From: Sepherosa Ziehau Date: Tue, 19 Jul 2016 05:46:15 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r303020 - in head/sys/dev/hyperv: include storvsc vmbus X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 19 Jul 2016 05:46:17 -0000 Author: sephe Date: Tue Jul 19 05:46:15 2016 New Revision: 303020 URL: https://svnweb.freebsd.org/changeset/base/303020 Log: hyperv/vmbus: Cleanup cpu based channel selection. And create cpu to channel map at device attach time for storvsc(4). MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D7229 Modified: head/sys/dev/hyperv/include/hyperv.h head/sys/dev/hyperv/include/vmbus.h head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c head/sys/dev/hyperv/vmbus/hv_channel.c Modified: head/sys/dev/hyperv/include/hyperv.h ============================================================================== --- head/sys/dev/hyperv/include/hyperv.h Tue Jul 19 05:36:21 2016 (r303019) +++ head/sys/dev/hyperv/include/hyperv.h Tue Jul 19 05:46:15 2016 (r303020) @@ -281,8 +281,6 @@ int hv_vmbus_channel_open(struct hv_vmb vmbus_chan_callback_t cb, void *cbarg); void hv_vmbus_channel_close(hv_vmbus_channel *channel); -struct hv_vmbus_channel* vmbus_select_outgoing_channel(struct hv_vmbus_channel *promary); - /** * @brief Get physical address from virtual */ Modified: head/sys/dev/hyperv/include/vmbus.h ============================================================================== --- head/sys/dev/hyperv/include/vmbus.h Tue Jul 19 05:36:21 2016 (r303019) +++ head/sys/dev/hyperv/include/vmbus.h Tue Jul 19 05:46:15 2016 (r303020) @@ -96,13 +96,14 @@ int vmbus_chan_gpadl_disconnect(struct h 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); 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: head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c ============================================================================== --- head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c Tue Jul 19 05:36:21 2016 (r303019) +++ head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c Tue Jul 19 05:46:15 2016 (r303020) @@ -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]; }; @@ -664,7 +666,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) { @@ -870,6 +872,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 * @@ -967,6 +983,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 Modified: head/sys/dev/hyperv/vmbus/hv_channel.c ============================================================================== --- head/sys/dev/hyperv/vmbus/hv_channel.c Tue Jul 19 05:36:21 2016 (r303019) +++ head/sys/dev/hyperv/vmbus/hv_channel.c Tue Jul 19 05:46:15 2016 (r303020) @@ -1250,61 +1250,63 @@ 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; \ + sel_dist = CHAN_VCPU_DIST(ch, vcpu); \ +} while (0) + + CHAN_SELECT(prichan); - old_cpu_distance = ((outgoing_channel->ch_vcpuid > cur_vcpu) ? - (outgoing_channel->ch_vcpuid - cur_vcpu) : - (cur_vcpu - outgoing_channel->ch_vcpuid)); - - new_cpu_distance = ((new_channel->ch_vcpuid > cur_vcpu) ? - (new_channel->ch_vcpuid - cur_vcpu) : - (cur_vcpu - new_channel->ch_vcpuid)); + mtx_lock(&prichan->ch_subchan_lock); + TAILQ_FOREACH(chan, &prichan->ch_subchans, ch_sublink) { + uint32_t dist; - if (old_cpu_distance < new_cpu_distance) { + KASSERT(chan->ch_stflags & VMBUS_CHAN_ST_OPENED, + ("chan%u is not opened", chan->ch_id)); + + if (chan->ch_vcpuid == vcpu) { + /* Exact match; done */ + CHAN_SELECT(chan); + break; + } + + dist = CHAN_VCPU_DIST(chan, vcpu); + if (sel_dist <= dist) { + /* Far or same distance; skip */ continue; } - outgoing_channel = new_channel; + /* Select the closer channel. */ + CHAN_SELECT(chan); } + mtx_unlock(&prichan->ch_subchan_lock); + +#undef CHAN_SELECT +#undef CHAN_VCPU_DIST - return(outgoing_channel); + return sel; } struct hv_vmbus_channel **