From owner-svn-src-stable@freebsd.org Tue Jun 21 06:18:43 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 9FB48A7B3CB; Tue, 21 Jun 2016 06:18:43 +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 6B27E1DB3; Tue, 21 Jun 2016 06:18:43 +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 u5L6IgqH013047; Tue, 21 Jun 2016 06:18:42 GMT (envelope-from sephe@FreeBSD.org) Received: (from sephe@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u5L6IfA0013039; Tue, 21 Jun 2016 06:18:41 GMT (envelope-from sephe@FreeBSD.org) Message-Id: <201606210618.u5L6IfA0013039@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: sephe set sender to sephe@FreeBSD.org using -f From: Sepherosa Ziehau Date: Tue, 21 Jun 2016 06:18:41 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r302048 - in stable/10/sys/dev/hyperv: include netvsc storvsc vmbus X-SVN-Group: stable-10 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.22 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: Tue, 21 Jun 2016 06:18:43 -0000 Author: sephe Date: Tue Jun 21 06:18:41 2016 New Revision: 302048 URL: https://svnweb.freebsd.org/changeset/base/302048 Log: MFC 298569,298570,298571,298572,298574,298575,298613,298614,298615,298616,298617 298569 hyperv/channel: Remove the unnecessary 'new' flag MFC after: 1 week Sponsored by: Microsoft OSTC 298570 hyperv/channel: Minor style changes; no functional changes. MFC after: 1 week Sponsored by: Microsoft OSTC 298571 hyperv/channel: Remove unapplied comment MFC after: 1 week Sponsored by: Microsoft OSTC 298572 hyperv/channel: Log a warning about duplicated primary channel offer MFC after: 1 week Sponsored by: Microsoft OSTC 298574 hyperv/channel: Add functions to synchronize sub-channel offers MFC after: 1 week Sponsored by: Microsoft OSTC 298575 hyperv/hn: Synchronize sub-channel offers MFC after: 1 week Sponsored by: Microsoft OSTC 298613 hyperv/stor: Remove the useless hs_open_multi_channel This fixes the sub-channel offer race after Hyper-V device probe/attach is moved to vmbus SYSINIT/attach. MFC after: 1 week Sponsored by: Microsoft OSTC 298614 hyperv/stor: Synchronize sub-channel offers MFC after: 1 week Sponsored by: Microsoft OSTC 298615 hyperv/hn: Avoid sub-channel creation callback. Since the sub-channel offers are synchronized, we can do our own channel setup without using the sub-channel creation callback. This paves the way to whack the sub-channel creation callback. MFC after: 1 week Sponsored by: Microsoft OSTC 298616 hyperv/stor: Avoid sub-channel creation callback. Since the sub-channel offers are synchronized, we can do our own channel setup without using the sub-channel creation callback. This paves the way to whack the sub-channel creation callback. MFC after: 1 week Sponsored by: Microsoft OSTC 298617 hyperv/channel: Git rid of the sub-channel creation callback It is no longer used. MFC after: 1 week Sponsored by: Microsoft OSTC Modified: stable/10/sys/dev/hyperv/include/hyperv.h stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c stable/10/sys/dev/hyperv/netvsc/hv_rndis.h stable/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c stable/10/sys/dev/hyperv/vmbus/hv_channel.c stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/dev/hyperv/include/hyperv.h ============================================================================== --- stable/10/sys/dev/hyperv/include/hyperv.h Tue Jun 21 05:49:07 2016 (r302047) +++ stable/10/sys/dev/hyperv/include/hyperv.h Tue Jun 21 06:18:41 2016 (r302048) @@ -691,7 +691,6 @@ typedef struct { } hv_vmbus_ring_buffer_info; typedef void (*hv_vmbus_pfn_channel_callback)(void *context); -typedef void (*hv_vmbus_sc_creation_callback)(void *context); typedef enum { HV_CHANNEL_OFFER_STATE, @@ -804,13 +803,6 @@ typedef struct hv_vmbus_channel { * response on the same channel. */ - /* - * Multi-channel creation callback. This callback will be called in - * process context when a Multi-channel offer is received from the host. - * The guest can open the Multi-channel in the context of this callback. - */ - hv_vmbus_sc_creation_callback sc_creation_callback; - struct mtx sc_lock; /* @@ -818,6 +810,7 @@ typedef struct hv_vmbus_channel { */ TAILQ_HEAD(, hv_vmbus_channel) sc_list_anchor; TAILQ_ENTRY(hv_vmbus_channel) sc_list_entry; + int subchan_cnt; /* * The primary channel this sub-channle belongs to. @@ -914,6 +907,9 @@ int hv_vmbus_channel_teardown_gpdal( 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); +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); /** * @brief Get physical address from virtual Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c Tue Jun 21 05:49:07 2016 (r302047) +++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c Tue Jun 21 06:18:41 2016 (r302048) @@ -660,30 +660,12 @@ hv_nv_disconnect_from_vsp(netvsc_dev *ne hv_nv_destroy_send_buffer(net_dev); } -/* - * Callback handler for subchannel offer - * @@param context new subchannel - */ -static void -hv_nv_subchan_callback(void *xchan) +void +hv_nv_subchan_attach(struct hv_vmbus_channel *chan) { - struct hv_vmbus_channel *chan = xchan; - netvsc_dev *net_dev; - uint16_t chn_index = chan->offer_msg.offer.sub_channel_index; - struct hv_device *device = chan->device; - hn_softc_t *sc = device_get_softc(device->device); - int ret; - - net_dev = sc->net_dev; - - if (chn_index >= net_dev->num_channel) { - /* Would this ever happen? */ - return; - } - netvsc_subchan_callback(sc, chan); chan->hv_chan_rdbuf = malloc(NETVSC_PACKET_SIZE, M_NETVSC, M_WAITOK); - ret = hv_vmbus_channel_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE, + hv_vmbus_channel_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE, NETVSC_DEVICE_RING_BUFFER_SIZE, NULL, 0, hv_nv_on_channel_callback, chan); } @@ -720,7 +702,6 @@ hv_nv_on_device_add(struct hv_device *de free(chan->hv_chan_rdbuf, M_NETVSC); goto cleanup; } - chan->sc_creation_callback = hv_nv_subchan_callback; /* * Connect with the NetVsp Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h Tue Jun 21 05:49:07 2016 (r302047) +++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h Tue Jun 21 06:18:41 2016 (r302048) @@ -1267,6 +1267,7 @@ int hv_nv_on_device_remove(struct hv_dev boolean_t destroy_channel); int hv_nv_on_send(struct hv_vmbus_channel *chan, netvsc_packet *pkt); int hv_nv_get_next_send_section(netvsc_dev *net_dev); +void hv_nv_subchan_attach(struct hv_vmbus_channel *chan); #endif /* __HV_NET_VSC_H__ */ Modified: stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Tue Jun 21 05:49:07 2016 (r302047) +++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Tue Jun 21 06:18:41 2016 (r302048) @@ -336,6 +336,7 @@ static void hn_create_rx_data(struct hn_ static void hn_destroy_rx_data(struct hn_softc *sc); static void hn_set_tx_chimney_size(struct hn_softc *, int); static void hn_channel_attach(struct hn_softc *, struct hv_vmbus_channel *); +static void hn_subchan_attach(struct hn_softc *, struct hv_vmbus_channel *); static int hn_transmit(struct ifnet *, struct mbuf *); static void hn_xmit_qflush(struct ifnet *); @@ -438,7 +439,7 @@ static int netvsc_attach(device_t dev) { struct hv_device *device_ctx = vmbus_get_devctx(dev); - struct hv_vmbus_channel *chan; + struct hv_vmbus_channel *pri_chan; netvsc_device_info device_info; hn_softc_t *sc; int unit = device_get_unit(dev); @@ -518,12 +519,12 @@ netvsc_attach(device_t dev) /* * Associate the first TX/RX ring w/ the primary channel. */ - chan = device_ctx->channel; - KASSERT(HV_VMBUS_CHAN_ISPRIMARY(chan), ("not primary channel")); - KASSERT(chan->offer_msg.offer.sub_channel_index == 0, + pri_chan = device_ctx->channel; + KASSERT(HV_VMBUS_CHAN_ISPRIMARY(pri_chan), ("not primary channel")); + KASSERT(pri_chan->offer_msg.offer.sub_channel_index == 0, ("primary channel subidx %u", - chan->offer_msg.offer.sub_channel_index)); - hn_channel_attach(sc, chan); + pri_chan->offer_msg.offer.sub_channel_index)); + hn_channel_attach(sc, pri_chan); ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = hn_ioctl; @@ -578,6 +579,26 @@ netvsc_attach(device_t dev) device_printf(dev, "%d TX ring, %d RX ring\n", sc->hn_tx_ring_inuse, sc->hn_rx_ring_inuse); + if (sc->net_dev->num_channel > 1) { + struct hv_vmbus_channel **subchan; + int subchan_cnt = sc->net_dev->num_channel - 1; + int i; + + /* Wait for sub-channels setup to complete. */ + subchan = vmbus_get_subchan(pri_chan, subchan_cnt); + + /* Attach the sub-channels. */ + for (i = 0; i < subchan_cnt; ++i) { + /* NOTE: Calling order is critical. */ + hn_subchan_attach(sc, subchan[i]); + hv_nv_subchan_attach(subchan[i]); + } + + /* Release the sub-channels */ + vmbus_rel_subchan(subchan, subchan_cnt); + device_printf(dev, "%d sub-channels setup done\n", subchan_cnt); + } + #if __FreeBSD_version >= 1100099 if (sc->hn_rx_ring_inuse > 1) { /* @@ -2910,8 +2931,8 @@ hn_channel_attach(struct hn_softc *sc, s vmbus_channel_cpu_set(chan, (sc->hn_cpu + idx) % mp_ncpus); } -void -netvsc_subchan_callback(struct hn_softc *sc, struct hv_vmbus_channel *chan) +static void +hn_subchan_attach(struct hn_softc *sc, struct hv_vmbus_channel *chan) { KASSERT(!HV_VMBUS_CHAN_ISPRIMARY(chan), Modified: stable/10/sys/dev/hyperv/netvsc/hv_rndis.h ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/hv_rndis.h Tue Jun 21 05:49:07 2016 (r302047) +++ stable/10/sys/dev/hyperv/netvsc/hv_rndis.h Tue Jun 21 06:18:41 2016 (r302048) @@ -1068,8 +1068,6 @@ struct hv_vmbus_channel; int netvsc_recv(struct hv_vmbus_channel *chan, netvsc_packet *packet, rndis_tcp_ip_csum_info *csum_info); void netvsc_channel_rollup(struct hv_vmbus_channel *chan); -void netvsc_subchan_callback(struct hn_softc *sc, - struct hv_vmbus_channel *chan); void* hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size, Modified: stable/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c ============================================================================== --- stable/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c Tue Jun 21 05:49:07 2016 (r302047) +++ stable/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c Tue Jun 21 06:18:41 2016 (r302048) @@ -134,7 +134,6 @@ struct storvsc_softc { uint32_t hs_num_out_reqs; boolean_t hs_destroy; boolean_t hs_drain_notify; - boolean_t hs_open_multi_channel; struct sema hs_drain_sema; struct hv_storvsc_request hs_init_req; struct hv_storvsc_request hs_reset_req; @@ -347,29 +346,19 @@ get_stor_device(struct hv_device *device return sc; } -/** - * @brief Callback handler, will be invoked when receive mutil-channel offer - * - * @param context new multi-channel - */ static void -storvsc_handle_sc_creation(void *context) +storvsc_subchan_attach(struct hv_vmbus_channel *new_channel) { - hv_vmbus_channel *new_channel; struct hv_device *device; struct storvsc_softc *sc; struct vmstor_chan_props props; int ret = 0; - new_channel = (hv_vmbus_channel *)context; device = new_channel->device; sc = get_stor_device(device, TRUE); if (sc == NULL) return; - if (FALSE == sc->hs_open_multi_channel) - return; - memset(&props, 0, sizeof(props)); ret = hv_vmbus_channel_open(new_channel, @@ -392,11 +381,12 @@ storvsc_handle_sc_creation(void *context static void storvsc_send_multichannel_request(struct hv_device *dev, int max_chans) { + struct hv_vmbus_channel **subchan; struct storvsc_softc *sc; struct hv_storvsc_request *request; struct vstor_packet *vstor_packet; int request_channels_cnt = 0; - int ret; + int ret, i; /* get multichannels count that need to create */ request_channels_cnt = MIN(max_chans, mp_ncpus); @@ -410,9 +400,6 @@ storvsc_send_multichannel_request(struct request = &sc->hs_init_req; - /* Establish a handler for multi-channel */ - dev->channel->sc_creation_callback = storvsc_handle_sc_creation; - /* request the host to create multi-channel */ memset(request, 0, sizeof(struct hv_storvsc_request)); @@ -448,7 +435,15 @@ storvsc_send_multichannel_request(struct return; } - sc->hs_open_multi_channel = TRUE; + /* Wait for sub-channels setup to complete. */ + subchan = vmbus_get_subchan(dev->channel, request_channels_cnt); + + /* Attach the sub-channels. */ + for (i = 0; i < request_channels_cnt; ++i) + storvsc_subchan_attach(subchan[i]); + + /* Release the sub-channels. */ + vmbus_rel_subchan(subchan, request_channels_cnt); if (bootverbose) printf("Storvsc create multi-channel success!\n"); @@ -1067,7 +1062,6 @@ storvsc_attach(device_t dev) sc->hs_destroy = FALSE; sc->hs_drain_notify = FALSE; - sc->hs_open_multi_channel = FALSE; sema_init(&sc->hs_drain_sema, 0, "Store Drain Sema"); ret = hv_storvsc_connect_vsp(hv_dev); Modified: stable/10/sys/dev/hyperv/vmbus/hv_channel.c ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/hv_channel.c Tue Jun 21 05:49:07 2016 (r302047) +++ stable/10/sys/dev/hyperv/vmbus/hv_channel.c Tue Jun 21 06:18:41 2016 (r302048) @@ -618,7 +618,6 @@ hv_vmbus_channel_close_internal(hv_vmbus hv_vmbus_channel_msg_info* info; channel->state = HV_CHANNEL_OPEN_STATE; - channel->sc_creation_callback = NULL; /* * set rxq to NULL to avoid more requests be scheduled Modified: stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c Tue Jun 21 05:49:07 2016 (r302047) +++ stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c Tue Jun 21 06:18:41 2016 (r302048) @@ -177,13 +177,10 @@ hv_vmbus_free_vmbus_channel(hv_vmbus_cha static void vmbus_channel_process_offer(hv_vmbus_channel *new_channel) { - boolean_t f_new; hv_vmbus_channel* channel; int ret; uint32_t relid; - f_new = TRUE; - channel = NULL; relid = new_channel->offer_msg.child_rel_id; /* * Make sure this is a new offer @@ -192,31 +189,24 @@ vmbus_channel_process_offer(hv_vmbus_cha hv_vmbus_g_connection.channels[relid] = new_channel; TAILQ_FOREACH(channel, &hv_vmbus_g_connection.channel_anchor, - list_entry) - { + list_entry) { if (memcmp(&channel->offer_msg.offer.interface_type, &new_channel->offer_msg.offer.interface_type, sizeof(hv_guid)) == 0 && memcmp(&channel->offer_msg.offer.interface_instance, &new_channel->offer_msg.offer.interface_instance, - sizeof(hv_guid)) == 0) { - f_new = FALSE; + sizeof(hv_guid)) == 0) break; - } } - if (f_new) { - /* Insert at tail */ - TAILQ_INSERT_TAIL( - &hv_vmbus_g_connection.channel_anchor, - new_channel, - list_entry); + if (channel == NULL) { + /* Install the new primary channel */ + TAILQ_INSERT_TAIL(&hv_vmbus_g_connection.channel_anchor, + new_channel, list_entry); } mtx_unlock(&hv_vmbus_g_connection.channel_lock); - /*XXX add new channel to percpu_list */ - - if (!f_new) { + if (channel != NULL) { /* * Check if this is a sub channel. */ @@ -227,10 +217,8 @@ vmbus_channel_process_offer(hv_vmbus_cha new_channel->primary_channel = channel; new_channel->device = channel->device; mtx_lock(&channel->sc_lock); - TAILQ_INSERT_TAIL( - &channel->sc_list_anchor, - new_channel, - sc_list_entry); + TAILQ_INSERT_TAIL(&channel->sc_list_anchor, + new_channel, sc_list_entry); mtx_unlock(&channel->sc_lock); if (bootverbose) { @@ -251,17 +239,25 @@ vmbus_channel_process_offer(hv_vmbus_cha "its primary channel is <%p>.\n", new_channel, new_channel->primary_channel); - /*XXX add it to percpu_list */ - new_channel->state = HV_CHANNEL_OPEN_STATE; - if (channel->sc_creation_callback != NULL) { - channel->sc_creation_callback(new_channel); - } + + /* + * Bump up sub-channel count and notify anyone that is + * interested in this sub-channel, after this sub-channel + * is setup. + */ + mtx_lock(&channel->sc_lock); + channel->subchan_cnt++; + mtx_unlock(&channel->sc_lock); + wakeup(channel); + return; } - hv_vmbus_free_vmbus_channel(new_channel); - return; + printf("VMBUS: duplicated primary channel%u\n", + new_channel->offer_msg.child_rel_id); + hv_vmbus_free_vmbus_channel(new_channel); + return; } new_channel->state = HV_CHANNEL_OPEN_STATE; @@ -283,10 +279,8 @@ vmbus_channel_process_offer(hv_vmbus_cha ret = hv_vmbus_child_device_register(new_channel->device); if (ret != 0) { mtx_lock(&hv_vmbus_g_connection.channel_lock); - TAILQ_REMOVE( - &hv_vmbus_g_connection.channel_anchor, - new_channel, - list_entry); + TAILQ_REMOVE(&hv_vmbus_g_connection.channel_anchor, + new_channel, list_entry); mtx_unlock(&hv_vmbus_g_connection.channel_lock); hv_vmbus_free_vmbus_channel(new_channel); } @@ -793,3 +787,41 @@ vmbus_scan(void) mtx_sleep(&vmbus_devcnt, &vmbus_chwait_lock, 0, "waitdev", 0); mtx_unlock(&vmbus_chwait_lock); } + +struct hv_vmbus_channel ** +vmbus_get_subchan(struct hv_vmbus_channel *pri_chan, int subchan_cnt) +{ + struct hv_vmbus_channel **ret, *chan; + int i; + + ret = malloc(subchan_cnt * sizeof(struct hv_vmbus_channel *), M_TEMP, + M_WAITOK); + + mtx_lock(&pri_chan->sc_lock); + + while (pri_chan->subchan_cnt < subchan_cnt) + mtx_sleep(pri_chan, &pri_chan->sc_lock, 0, "subch", 0); + + i = 0; + TAILQ_FOREACH(chan, &pri_chan->sc_list_anchor, sc_list_entry) { + /* TODO: refcnt chan */ + ret[i] = chan; + + ++i; + if (i == subchan_cnt) + break; + } + KASSERT(i == subchan_cnt, ("invalid subchan count %d, should be %d", + pri_chan->subchan_cnt, subchan_cnt)); + + mtx_unlock(&pri_chan->sc_lock); + + return ret; +} + +void +vmbus_rel_subchan(struct hv_vmbus_channel **subchan, int subchan_cnt __unused) +{ + + free(subchan, M_TEMP); +}