svn commit: r307027 - in stable/10/sys/dev/hyperv: include netvsc vmbus
Sepherosa Ziehau
sephe at FreeBSD.org
Tue Oct 11 08:14:13 UTC 2016
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",
More information about the svn-src-all
mailing list