Date: Tue, 11 Oct 2016 08:14:11 +0000 (UTC) From: Sepherosa Ziehau <sephe@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r307027 - in stable/10/sys/dev/hyperv: include netvsc vmbus Message-ID: <201610110814.u9B8EBnw026673@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sephe Date: Tue Oct 11 08:14:11 2016 New Revision: 307027 URL: https://svnweb.freebsd.org/changeset/base/307027 Log: MFC 302808-302815 302808 hyperv/vmbus: Alloc/Free monitor param in vmbus channel alloc/free. Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D7101 302809 hyperv/vmbus: Move device register and channel free to the caller. This paves the way for more cleanup/disentangle. Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D7102 302810 hyperv/vmbus: Move new channel scan notification to device register And nuke now unnecessary function indirection. Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D7103 302811 hyperv/vmbus: Cleanup vmbus_chan_msgproc_choffer Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D7104 302812 hyperv/vmbus: Nuke the channel open state. Channel is either opened or not-opened. Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D7105 302813 hyperv/vmbus: Cleanup vmbus_chan_add() Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D7106 302814 hyperv/vmbus: Use sub-channel index to detect primary channel In case that VMBUS_CHAN_ISPRIMARY is needed in the early place of channel setup. Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D7108 302815 hyperv/vmbus: Only add primary channels to vmbus channel list - Make the vmbus_chan_add more straightforward. - Partially fix the hv_vmbus_release_unattached_channels(). Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D7109 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_netvsc_drv_freebsd.c stable/10/sys/dev/hyperv/vmbus/hv_channel.c stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h stable/10/sys/dev/hyperv/vmbus/vmbus.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 Oct 11 08:01:43 2016 (r307026) +++ stable/10/sys/dev/hyperv/include/hyperv.h Tue Oct 11 08:14:11 2016 (r307027) @@ -244,18 +244,9 @@ typedef struct { typedef void (*hv_vmbus_pfn_channel_callback)(void *context); -typedef enum { - HV_CHANNEL_OFFER_STATE, - HV_CHANNEL_OPENING_STATE, - HV_CHANNEL_OPEN_STATE, - HV_CHANNEL_OPENED_STATE, - HV_CHANNEL_CLOSING_NONDESTRUCTIVE_STATE, -} hv_vmbus_channel_state; - typedef struct hv_vmbus_channel { device_t ch_dev; struct vmbus_softc *vmbus_sc; - hv_vmbus_channel_state state; uint32_t ch_flags; /* VMBUS_CHAN_FLAG_ */ uint32_t ch_id; /* channel id */ @@ -337,14 +328,15 @@ typedef struct hv_vmbus_channel { struct task ch_detach_task; TAILQ_ENTRY(hv_vmbus_channel) ch_link; uint32_t ch_subidx; /* subchan index */ - + volatile uint32_t ch_stflags; /* atomic-op */ + /* VMBUS_CHAN_ST_ */ struct hyperv_guid ch_guid_type; struct hyperv_guid ch_guid_inst; struct sysctl_ctx_list ch_sysctl_ctx; } hv_vmbus_channel; -#define HV_VMBUS_CHAN_ISPRIMARY(chan) ((chan)->primary_channel == NULL) +#define VMBUS_CHAN_ISPRIMARY(chan) ((chan)->ch_subidx == 0) #define VMBUS_CHAN_FLAG_HASMNF 0x0001 /* @@ -357,6 +349,9 @@ typedef struct hv_vmbus_channel { */ #define VMBUS_CHAN_FLAG_BATCHREAD 0x0002 +#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) { Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c Tue Oct 11 08:01:43 2016 (r307026) +++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c Tue Oct 11 08:14:11 2016 (r307027) @@ -718,11 +718,6 @@ hv_nv_on_device_remove(struct hn_softc * /* Now, we can close the channel safely */ - if (!destroy_channel) { - sc->hn_prichan->state = - HV_CHANNEL_CLOSING_NONDESTRUCTIVE_STATE; - } - free(sc->hn_prichan->hv_chan_rdbuf, M_NETVSC); hv_vmbus_channel_close(sc->hn_prichan); Modified: stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Tue Oct 11 08:01:43 2016 (r307026) +++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Tue Oct 11 08:14:11 2016 (r307027) @@ -3013,7 +3013,7 @@ static void hn_subchan_attach(struct hn_softc *sc, struct hv_vmbus_channel *chan) { - KASSERT(!HV_VMBUS_CHAN_ISPRIMARY(chan), + KASSERT(!VMBUS_CHAN_ISPRIMARY(chan), ("subchannel callback on primary channel")); KASSERT(chan->ch_subidx > 0, ("invalid channel subidx %u", Modified: stable/10/sys/dev/hyperv/vmbus/hv_channel.c ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/hv_channel.c Tue Oct 11 08:01:43 2016 (r307026) +++ stable/10/sys/dev/hyperv/vmbus/hv_channel.c Tue Oct 11 08:14:11 2016 (r307027) @@ -191,17 +191,9 @@ hv_vmbus_channel_open( return EINVAL; } - mtx_lock(&new_channel->sc_lock); - if (new_channel->state == HV_CHANNEL_OPEN_STATE) { - new_channel->state = HV_CHANNEL_OPENING_STATE; - } else { - mtx_unlock(&new_channel->sc_lock); - if(bootverbose) - printf("VMBUS: Trying to open channel <%p> which in " - "%d state.\n", new_channel, new_channel->state); - return (EINVAL); - } - mtx_unlock(&new_channel->sc_lock); + if (atomic_testandset_int(&new_channel->ch_stflags, + VMBUS_CHAN_ST_OPENED_SHIFT)) + panic("double-open chan%u", new_channel->ch_id); new_channel->on_channel_callback = pfn_on_channel_callback; new_channel->channel_callback_context = context; @@ -223,8 +215,10 @@ hv_vmbus_channel_open( M_DEVBUF, M_ZERO, 0UL, BUS_SPACE_MAXADDR, PAGE_SIZE, 0); KASSERT(out != NULL, ("Error VMBUS: contigmalloc failed to allocate Ring Buffer!")); - if (out == NULL) - return (ENOMEM); + if (out == NULL) { + ret = ENOMEM; + goto failed; + } in = ((uint8_t *) out + send_ring_buffer_size); @@ -265,7 +259,8 @@ hv_vmbus_channel_open( device_printf(sc->vmbus_dev, "can not get msg hypercall for chopen(chan%u)\n", new_channel->ch_id); - return ENXIO; + ret = ENXIO; + goto failed; } req = vmbus_msghc_dataptr(mh); @@ -284,7 +279,7 @@ hv_vmbus_channel_open( "chopen(chan%u) msg hypercall exec failed: %d\n", new_channel->ch_id, ret); vmbus_msghc_put(sc, mh); - return ret; + goto failed; } msg = vmbus_msghc_wait_result(sc, mh); @@ -294,17 +289,20 @@ hv_vmbus_channel_open( vmbus_msghc_put(sc, mh); if (status == 0) { - new_channel->state = HV_CHANNEL_OPENED_STATE; if (bootverbose) { device_printf(sc->vmbus_dev, "chan%u opened\n", new_channel->ch_id); } - } else { - device_printf(sc->vmbus_dev, "failed to open chan%u\n", - new_channel->ch_id); - ret = ENXIO; + return 0; } - return (ret); + + device_printf(sc->vmbus_dev, "failed to open chan%u\n", + new_channel->ch_id); + ret = ENXIO; + +failed: + atomic_clear_int(&new_channel->ch_stflags, VMBUS_CHAN_ST_OPENED); + return ret; } /** @@ -487,7 +485,9 @@ hv_vmbus_channel_close_internal(hv_vmbus struct taskqueue *rxq = channel->rxq; int error; - channel->state = HV_CHANNEL_OPEN_STATE; + /* TODO: stringent check */ + atomic_clear_int(&channel->ch_stflags, VMBUS_CHAN_ST_OPENED); + sysctl_ctx_free(&channel->ch_sysctl_ctx); /* @@ -563,7 +563,7 @@ hv_vmbus_channel_close(hv_vmbus_channel */ TAILQ_FOREACH(sub_channel, &channel->sc_list_anchor, sc_list_entry) { - if (sub_channel->state != HV_CHANNEL_OPENED_STATE) + if ((sub_channel->ch_stflags & VMBUS_CHAN_ST_OPENED) == 0) continue; hv_vmbus_channel_close_internal(sub_channel); } Modified: stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c Tue Oct 11 08:01:43 2016 (r307026) +++ stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c Tue Oct 11 08:14:11 2016 (r307027) @@ -43,15 +43,12 @@ __FBSDID("$FreeBSD$"); typedef void (*vmbus_chanmsg_proc_t) (struct vmbus_softc *, const struct vmbus_message *); -static struct hv_vmbus_channel *hv_vmbus_allocate_channel(struct vmbus_softc *); -static void vmbus_channel_on_offer_internal(struct vmbus_softc *, - const struct vmbus_chanmsg_choffer *); static void vmbus_chan_detach_task(void *, int); -static void vmbus_channel_on_offer(struct vmbus_softc *, - const struct vmbus_message *); static void vmbus_channel_on_offers_delivered(struct vmbus_softc *, const struct vmbus_message *); +static void vmbus_chan_msgproc_choffer(struct vmbus_softc *, + const struct vmbus_message *); static void vmbus_chan_msgproc_chrescind(struct vmbus_softc *, const struct vmbus_message *); @@ -66,7 +63,7 @@ static void vmbus_chan_msgproc_chrescind static const vmbus_chanmsg_proc_t vmbus_chanmsg_process[VMBUS_CHANMSG_TYPE_MAX] = { - VMBUS_CHANMSG_PROC(CHOFFER, vmbus_channel_on_offer), + VMBUS_CHANMSG_PROC(CHOFFER, vmbus_chan_msgproc_choffer), VMBUS_CHANMSG_PROC(CHRESCIND, vmbus_chan_msgproc_chrescind), VMBUS_CHANMSG_PROC(CHOFFER_DONE,vmbus_channel_on_offers_delivered), @@ -79,146 +76,125 @@ vmbus_chanmsg_process[VMBUS_CHANMSG_TYPE #undef VMBUS_CHANMSG_PROC_WAKEUP #undef VMBUS_CHANMSG_PROC -/** - * @brief Allocate and initialize a vmbus channel object - */ static struct hv_vmbus_channel * -hv_vmbus_allocate_channel(struct vmbus_softc *sc) +vmbus_chan_alloc(struct vmbus_softc *sc) { - struct hv_vmbus_channel *channel; + struct hv_vmbus_channel *chan; - channel = malloc(sizeof(*channel), M_DEVBUF, M_WAITOK | M_ZERO); - channel->vmbus_sc = sc; + chan = malloc(sizeof(*chan), M_DEVBUF, M_WAITOK | M_ZERO); - mtx_init(&channel->sc_lock, "vmbus multi channel", NULL, MTX_DEF); - TAILQ_INIT(&channel->sc_list_anchor); - TASK_INIT(&channel->ch_detach_task, 0, vmbus_chan_detach_task, channel); + chan->ch_monprm = hyperv_dmamem_alloc(bus_get_dma_tag(sc->vmbus_dev), + HYPERCALL_PARAM_ALIGN, 0, sizeof(struct hyperv_mon_param), + &chan->ch_monprm_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO); + if (chan->ch_monprm == NULL) { + device_printf(sc->vmbus_dev, "monprm alloc failed\n"); + free(chan, M_DEVBUF); + return NULL; + } - return (channel); + chan->vmbus_sc = sc; + mtx_init(&chan->sc_lock, "vmbus multi channel", NULL, MTX_DEF); + TAILQ_INIT(&chan->sc_list_anchor); + TASK_INIT(&chan->ch_detach_task, 0, vmbus_chan_detach_task, chan); + + return chan; } -/** - * @brief Release the resources used by the vmbus channel object - */ -void -hv_vmbus_free_vmbus_channel(hv_vmbus_channel* channel) +static void +vmbus_chan_free(struct hv_vmbus_channel *chan) { - mtx_destroy(&channel->sc_lock); - free(channel, M_DEVBUF); + /* TODO: assert sub-channel list is empty */ + /* TODO: asset no longer on the primary channel's sub-channel list */ + /* TODO: asset no longer on the vmbus channel list */ + hyperv_dmamem_free(&chan->ch_monprm_dma, chan->ch_monprm); + mtx_destroy(&chan->sc_lock); + free(chan, M_DEVBUF); } -/** - * @brief Process the offer by creating a channel/device - * associated with this offer - */ -static void -vmbus_channel_process_offer(hv_vmbus_channel *new_channel) +static int +vmbus_chan_add(struct hv_vmbus_channel *newchan) { - struct vmbus_softc *sc = new_channel->vmbus_sc; - hv_vmbus_channel* channel; + struct vmbus_softc *sc = newchan->vmbus_sc; + struct hv_vmbus_channel *prichan; - /* - * Make sure this is a new offer - */ - mtx_lock(&sc->vmbus_chlist_lock); - if (new_channel->ch_id == 0) { + if (newchan->ch_id == 0) { /* - * XXX channel0 will not be processed; skip it. + * XXX + * Chan0 will neither be processed nor should be offered; + * skip it. */ - printf("VMBUS: got channel0 offer\n"); - } else { - sc->vmbus_chmap[new_channel->ch_id] = new_channel; + device_printf(sc->vmbus_dev, "got chan0 offer, discard\n"); + return EINVAL; + } else if (newchan->ch_id >= VMBUS_CHAN_MAX) { + device_printf(sc->vmbus_dev, "invalid chan%u offer\n", + newchan->ch_id); + return EINVAL; } + sc->vmbus_chmap[newchan->ch_id] = newchan; - TAILQ_FOREACH(channel, &sc->vmbus_chlist, ch_link) { - if (memcmp(&channel->ch_guid_type, &new_channel->ch_guid_type, + if (bootverbose) { + device_printf(sc->vmbus_dev, "chan%u subidx%u offer\n", + newchan->ch_id, newchan->ch_subidx); + } + + mtx_lock(&sc->vmbus_chlist_lock); + TAILQ_FOREACH(prichan, &sc->vmbus_chlist, ch_link) { + if (memcmp(&prichan->ch_guid_type, &newchan->ch_guid_type, sizeof(struct hyperv_guid)) == 0 && - memcmp(&channel->ch_guid_inst, &new_channel->ch_guid_inst, + memcmp(&prichan->ch_guid_inst, &newchan->ch_guid_inst, sizeof(struct hyperv_guid)) == 0) break; } - - if (channel == NULL) { - /* Install the new primary channel */ - TAILQ_INSERT_TAIL(&sc->vmbus_chlist, new_channel, ch_link); - } - mtx_unlock(&sc->vmbus_chlist_lock); - - if (bootverbose) { - char logstr[64]; - - logstr[0] = '\0'; - if (channel != NULL) { - snprintf(logstr, sizeof(logstr), ", primary chan%u", - channel->ch_id); + if (VMBUS_CHAN_ISPRIMARY(newchan)) { + if (prichan == NULL) { + /* Install the new primary channel */ + TAILQ_INSERT_TAIL(&sc->vmbus_chlist, newchan, ch_link); + mtx_unlock(&sc->vmbus_chlist_lock); + return 0; + } else { + mtx_unlock(&sc->vmbus_chlist_lock); + device_printf(sc->vmbus_dev, "duplicated primary " + "chan%u\n", newchan->ch_id); + return EINVAL; } - device_printf(sc->vmbus_dev, "chan%u subchanid%u offer%s\n", - new_channel->ch_id, - new_channel->ch_subidx, logstr); - } - - if (channel != NULL) { - /* - * Check if this is a sub channel. - */ - if (new_channel->ch_subidx != 0) { - /* - * It is a sub channel offer, process it. - */ - new_channel->primary_channel = channel; - new_channel->ch_dev = channel->ch_dev; - mtx_lock(&channel->sc_lock); - TAILQ_INSERT_TAIL(&channel->sc_list_anchor, - new_channel, sc_list_entry); - mtx_unlock(&channel->sc_lock); - - /* - * Insert the new channel to the end of the global - * channel list. - * - * NOTE: - * The new sub-channel MUST be inserted AFTER it's - * primary channel, so that the primary channel will - * be found in the above loop for its baby siblings. - */ - mtx_lock(&sc->vmbus_chlist_lock); - TAILQ_INSERT_TAIL(&sc->vmbus_chlist, new_channel, - ch_link); + } else { /* Sub-channel */ + if (prichan == NULL) { mtx_unlock(&sc->vmbus_chlist_lock); - - new_channel->state = HV_CHANNEL_OPEN_STATE; - - /* - * 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; + device_printf(sc->vmbus_dev, "no primary chan for " + "chan%u\n", newchan->ch_id); + return EINVAL; } - - printf("VMBUS: duplicated primary channel%u\n", - new_channel->ch_id); - hv_vmbus_free_vmbus_channel(new_channel); - return; + /* + * Found the primary channel for this sub-channel and + * move on. + * + * XXX refcnt prichan + */ } + mtx_unlock(&sc->vmbus_chlist_lock); + + /* + * This is a sub-channel; link it with the primary channel. + */ + KASSERT(!VMBUS_CHAN_ISPRIMARY(newchan), + ("new channel is not sub-channel")); + KASSERT(prichan != NULL, ("no primary channel")); - new_channel->state = HV_CHANNEL_OPEN_STATE; + newchan->primary_channel = prichan; + newchan->ch_dev = prichan->ch_dev; + mtx_lock(&prichan->sc_lock); + TAILQ_INSERT_TAIL(&prichan->sc_list_anchor, newchan, sc_list_entry); /* - * Add the new device to the bus. This will kick off device-driver - * binding which eventually invokes the device driver's AddDevice() - * method. - * - * NOTE: - * Error is ignored here; don't have much to do if error really - * happens. + * Bump up sub-channel count and notify anyone that is + * interested in this sub-channel, after this sub-channel + * is setup. */ - hv_vmbus_child_device_register(new_channel); + prichan->subchan_cnt++; + mtx_unlock(&prichan->sc_lock); + wakeup(prichan); + + return 0; } void @@ -253,7 +229,7 @@ vmbus_channel_cpu_rr(struct hv_vmbus_cha } static void -vmbus_channel_select_defcpu(struct hv_vmbus_channel *chan) +vmbus_chan_cpu_default(struct hv_vmbus_channel *chan) { /* * By default, pin the channel to cpu0. Devices having @@ -263,69 +239,68 @@ vmbus_channel_select_defcpu(struct hv_vm vmbus_channel_cpu_set(chan, 0); } -/** - * @brief Handler for channel offers from Hyper-V/Azure - * - * Handler for channel offers from vmbus in parent partition. - */ static void -vmbus_channel_on_offer(struct vmbus_softc *sc, const struct vmbus_message *msg) +vmbus_chan_msgproc_choffer(struct vmbus_softc *sc, + const struct vmbus_message *msg) { - /* New channel is offered by vmbus */ - vmbus_scan_newchan(sc); + const struct vmbus_chanmsg_choffer *offer; + struct hv_vmbus_channel *chan; + int error; - vmbus_channel_on_offer_internal(sc, - (const struct vmbus_chanmsg_choffer *)msg->msg_data); -} + offer = (const struct vmbus_chanmsg_choffer *)msg->msg_data; -static void -vmbus_channel_on_offer_internal(struct vmbus_softc *sc, - const struct vmbus_chanmsg_choffer *offer) -{ - hv_vmbus_channel* new_channel; + chan = vmbus_chan_alloc(sc); + if (chan == NULL) { + device_printf(sc->vmbus_dev, "allocate chan%u failed\n", + offer->chm_chanid); + return; + } - /* - * Allocate the channel object and save this offer - */ - new_channel = hv_vmbus_allocate_channel(sc); - new_channel->ch_id = offer->chm_chanid; - new_channel->ch_subidx = offer->chm_subidx; - new_channel->ch_guid_type = offer->chm_chtype; - new_channel->ch_guid_inst = offer->chm_chinst; + chan->ch_id = offer->chm_chanid; + chan->ch_subidx = offer->chm_subidx; + chan->ch_guid_type = offer->chm_chtype; + chan->ch_guid_inst = offer->chm_chinst; /* Batch reading is on by default */ - new_channel->ch_flags |= VMBUS_CHAN_FLAG_BATCHREAD; - if (offer->chm_flags1 & VMBUS_CHOFFER_FLAG1_HASMNF) - new_channel->ch_flags |= VMBUS_CHAN_FLAG_HASMNF; + chan->ch_flags |= VMBUS_CHAN_FLAG_BATCHREAD; - new_channel->ch_monprm = hyperv_dmamem_alloc( - bus_get_dma_tag(sc->vmbus_dev), - HYPERCALL_PARAM_ALIGN, 0, sizeof(struct hyperv_mon_param), - &new_channel->ch_monprm_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO); - if (new_channel->ch_monprm == NULL) { - device_printf(sc->vmbus_dev, "monprm alloc failed\n"); - /* XXX */ - mtx_destroy(&new_channel->sc_lock); - free(new_channel, M_DEVBUF); - return; - } - new_channel->ch_monprm->mp_connid = VMBUS_CONNID_EVENT; + chan->ch_monprm->mp_connid = VMBUS_CONNID_EVENT; if (sc->vmbus_version != VMBUS_VERSION_WS2008) - new_channel->ch_monprm->mp_connid = offer->chm_connid; + chan->ch_monprm->mp_connid = offer->chm_connid; - if (new_channel->ch_flags & VMBUS_CHAN_FLAG_HASMNF) { - new_channel->ch_montrig_idx = - offer->chm_montrig / VMBUS_MONTRIG_LEN; - if (new_channel->ch_montrig_idx >= VMBUS_MONTRIGS_MAX) + if (offer->chm_flags1 & VMBUS_CHOFFER_FLAG1_HASMNF) { + /* + * Setup MNF stuffs. + */ + chan->ch_flags |= VMBUS_CHAN_FLAG_HASMNF; + chan->ch_montrig_idx = offer->chm_montrig / VMBUS_MONTRIG_LEN; + if (chan->ch_montrig_idx >= VMBUS_MONTRIGS_MAX) panic("invalid monitor trigger %u", offer->chm_montrig); - new_channel->ch_montrig_mask = + chan->ch_montrig_mask = 1 << (offer->chm_montrig % VMBUS_MONTRIG_LEN); } /* Select default cpu for this channel. */ - vmbus_channel_select_defcpu(new_channel); + vmbus_chan_cpu_default(chan); - vmbus_channel_process_offer(new_channel); + error = vmbus_chan_add(chan); + if (error) { + device_printf(sc->vmbus_dev, "add chan%u failed: %d\n", + chan->ch_id, error); + vmbus_chan_free(chan); + return; + } + + if (VMBUS_CHAN_ISPRIMARY(chan)) { + /* + * Add device for this primary channel. + * + * NOTE: + * Error is ignored here; don't have much to do if error + * really happens. + */ + hv_vmbus_child_device_register(chan); + } } /* @@ -363,7 +338,7 @@ vmbus_chan_detach_task(void *xchan, int { struct hv_vmbus_channel *chan = xchan; - if (HV_VMBUS_CHAN_ISPRIMARY(chan)) { + if (VMBUS_CHAN_ISPRIMARY(chan)) { /* Only primary channel owns the device */ hv_vmbus_child_device_unregister(chan); /* NOTE: DO NOT free primary channel for now */ @@ -401,10 +376,6 @@ vmbus_chan_detach_task(void *xchan, int } } remove: - mtx_lock(&sc->vmbus_chlist_lock); - TAILQ_REMOVE(&sc->vmbus_chlist, chan, ch_link); - mtx_unlock(&sc->vmbus_chlist_lock); - mtx_lock(&pri_chan->sc_lock); TAILQ_REMOVE(&pri_chan->sc_list_anchor, chan, sc_list_entry); KASSERT(pri_chan->subchan_cnt > 0, @@ -413,7 +384,7 @@ remove: mtx_unlock(&pri_chan->sc_lock); wakeup(pri_chan); - hv_vmbus_free_vmbus_channel(chan); + vmbus_chan_free(chan); } } @@ -442,13 +413,11 @@ hv_vmbus_release_unattached_channels(str while (!TAILQ_EMPTY(&sc->vmbus_chlist)) { channel = TAILQ_FIRST(&sc->vmbus_chlist); + KASSERT(VMBUS_CHAN_ISPRIMARY(channel), ("not primary channel")); TAILQ_REMOVE(&sc->vmbus_chlist, channel, ch_link); - if (HV_VMBUS_CHAN_ISPRIMARY(channel)) { - /* Only primary channel owns the device */ - hv_vmbus_child_device_unregister(channel); - } - hv_vmbus_free_vmbus_channel(channel); + hv_vmbus_child_device_unregister(channel); + vmbus_chan_free(channel); } bzero(sc->vmbus_chmap, sizeof(struct hv_vmbus_channel *) * VMBUS_CHAN_MAX); @@ -486,7 +455,7 @@ vmbus_select_outgoing_channel(struct hv_ cur_vcpu = VMBUS_PCPU_GET(primary->vmbus_sc, vcpuid, smp_pro_id); TAILQ_FOREACH(new_channel, &primary->sc_list_anchor, sc_list_entry) { - if (new_channel->state != HV_CHANNEL_OPENED_STATE){ + if ((new_channel->ch_stflags & VMBUS_CHAN_ST_OPENED) == 0) { continue; } Modified: stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h Tue Oct 11 08:01:43 2016 (r307026) +++ stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h Tue Oct 11 08:14:11 2016 (r307027) @@ -55,7 +55,6 @@ typedef struct { typedef struct { uint32_t rel_id; - hv_vmbus_channel_state state; struct hyperv_guid interface_type; struct hyperv_guid interface_instance; uint32_t monitor_id; @@ -147,7 +146,6 @@ void hv_ring_buffer_read_begin( uint32_t hv_ring_buffer_read_end( hv_vmbus_ring_buffer_info *ring_info); -void hv_vmbus_free_vmbus_channel(hv_vmbus_channel *channel); void hv_vmbus_release_unattached_channels( struct vmbus_softc *); Modified: stable/10/sys/dev/hyperv/vmbus/vmbus.c ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/vmbus.c Tue Oct 11 08:01:43 2016 (r307026) +++ stable/10/sys/dev/hyperv/vmbus/vmbus.c Tue Oct 11 08:14:11 2016 (r307027) @@ -1074,6 +1074,9 @@ hv_vmbus_child_device_register(struct hv device_t parent = sc->vmbus_dev; int error = 0; + /* New channel has been offered */ + vmbus_scan_newchan(sc); + chan->ch_dev = device_add_child(parent, NULL, -1); if (chan->ch_dev == NULL) { device_printf(parent, "device_add_child for chan%u failed\n",
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201610110814.u9B8EBnw026673>