svn commit: r307016 - in stable/10/sys/dev/hyperv: include vmbus
Sepherosa Ziehau
sephe at FreeBSD.org
Tue Oct 11 06:04:42 UTC 2016
Author: sephe
Date: Tue Oct 11 06:04:40 2016
New Revision: 307016
URL: https://svnweb.freebsd.org/changeset/base/307016
Log:
MFC 302543,302545,302547,302549,302554,302556,302557,302559,302606
302543
hyperv/vmbus: Use post message Hypercall APIs for channel request
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6831
302545
hyperv/vmbus: Function renaming.
And pass vmbus_softc to vmbus_doattach()
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6842
302547
hyperv/vmbus: Explicitly assign channel message process array.
While I'm here, remove the useless message type from message process
array, which is not used and serves no purposes at all.
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6858
302549
hyperv/vmbus: Add sysctl to expose vmbus version.
Requested by: Hongxiong Xian <v-hoxian microsoft com>
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6860
302554
hyperv/vmbus: Use post message Hypercall APIs for unload
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6861
302556
hyperv/vmbus: Create channel synchronously.
The device probe/attach has been move to a different thread, so the
reasons to create the channel asynchronously are no longer valid.
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6862
302557
hyperv/vmbus: Save vmbus softc to channels.
So that we don't need to access the global vmbus softc.
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6863
302559
hyperv/vmbus: Embed channel detach task in channel itself.
GC work queue stuffs.
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6864
302606
hyperv/vmbus: Reorganize vmbus scan process.
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6875
Modified:
stable/10/sys/dev/hyperv/include/hyperv.h
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_connection.c
stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
stable/10/sys/dev/hyperv/vmbus/vmbus.c
stable/10/sys/dev/hyperv/vmbus/vmbus_reg.h
stable/10/sys/dev/hyperv/vmbus/vmbus_var.h
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 05:47:52 2016 (r307015)
+++ stable/10/sys/dev/hyperv/include/hyperv.h Tue Oct 11 06:04:40 2016 (r307016)
@@ -713,6 +713,7 @@ typedef struct {
typedef struct hv_vmbus_channel {
TAILQ_ENTRY(hv_vmbus_channel) list_entry;
struct hv_device* device;
+ struct vmbus_softc *vmbus_sc;
hv_vmbus_channel_state state;
hv_vmbus_channel_offer_channel offer_msg;
/*
@@ -808,6 +809,8 @@ typedef struct hv_vmbus_channel {
void *hv_chan_priv1;
void *hv_chan_priv2;
void *hv_chan_priv3;
+
+ struct task ch_detach_task;
} hv_vmbus_channel;
#define HV_VMBUS_CHAN_ISPRIMARY(chan) ((chan)->primary_channel == NULL)
Modified: stable/10/sys/dev/hyperv/vmbus/hv_channel.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_channel.c Tue Oct 11 05:47:52 2016 (r307015)
+++ stable/10/sys/dev/hyperv/vmbus/hv_channel.c Tue Oct 11 06:04:40 2016 (r307016)
@@ -67,7 +67,7 @@ static void
vmbus_channel_set_event(hv_vmbus_channel *channel)
{
if (channel->offer_msg.monitor_allocated) {
- struct vmbus_softc *sc = vmbus_get_softc();
+ struct vmbus_softc *sc = channel->vmbus_sc;
hv_vmbus_monitor_page *monitor_page;
uint32_t chanid = channel->offer_msg.child_rel_id;
@@ -205,7 +205,7 @@ hv_vmbus_channel_open(
vmbus_on_channel_open(new_channel);
- new_channel->rxq = VMBUS_PCPU_GET(vmbus_get_softc(), event_tq,
+ new_channel->rxq = VMBUS_PCPU_GET(new_channel->vmbus_sc, event_tq,
new_channel->target_cpu);
TASK_INIT(&new_channel->channel_task, 0, VmbusProcessChannelEvent, new_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 05:47:52 2016 (r307015)
+++ stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c Tue Oct 11 06:04:40 2016 (r307016)
@@ -39,19 +39,13 @@ __FBSDID("$FreeBSD$");
#include <dev/hyperv/vmbus/vmbus_reg.h>
#include <dev/hyperv/vmbus/vmbus_var.h>
-/*
- * Internal functions
- */
+typedef void (*vmbus_chanmsg_proc_t)
+ (struct vmbus_softc *, const struct vmbus_message *);
-typedef struct hv_vmbus_channel_msg_table_entry {
- hv_vmbus_channel_msg_type messageType;
- void (*messageHandler)
- (struct vmbus_softc *sc,
- const struct vmbus_message *msg);
-} hv_vmbus_channel_msg_table_entry;
-
-static void vmbus_channel_on_offer_internal(void *context);
-static void vmbus_channel_on_offer_rescind_internal(void *context);
+static struct hv_vmbus_channel *hv_vmbus_allocate_channel(struct vmbus_softc *);
+static void vmbus_channel_on_offer_internal(struct vmbus_softc *,
+ const hv_vmbus_channel_offer_channel *offer);
+static void vmbus_chan_detach_task(void *, int);
static void vmbus_channel_on_offer(struct vmbus_softc *,
const struct vmbus_message *);
@@ -71,108 +65,38 @@ static void vmbus_channel_on_version_res
/**
* Channel message dispatch table
*/
-static const hv_vmbus_channel_msg_table_entry
- g_channel_message_table[HV_CHANNEL_MESSAGE_COUNT] = {
- { HV_CHANNEL_MESSAGE_INVALID,
- NULL },
- { HV_CHANNEL_MESSAGE_OFFER_CHANNEL,
- vmbus_channel_on_offer },
- { HV_CHANNEL_MESSAGE_RESCIND_CHANNEL_OFFER,
- vmbus_channel_on_offer_rescind },
- { HV_CHANNEL_MESSAGE_REQUEST_OFFERS,
- NULL },
- { HV_CHANNEL_MESSAGE_ALL_OFFERS_DELIVERED,
- vmbus_channel_on_offers_delivered },
- { HV_CHANNEL_MESSAGE_OPEN_CHANNEL,
- NULL },
- { HV_CHANNEL_MESSAGE_OPEN_CHANNEL_RESULT,
- vmbus_channel_on_open_result },
- { HV_CHANNEL_MESSAGE_CLOSE_CHANNEL,
- NULL },
- { HV_CHANNEL_MESSAGEL_GPADL_HEADER,
- NULL },
- { HV_CHANNEL_MESSAGE_GPADL_BODY,
- NULL },
- { HV_CHANNEL_MESSAGE_GPADL_CREATED,
- vmbus_channel_on_gpadl_created },
- { HV_CHANNEL_MESSAGE_GPADL_TEARDOWN,
- NULL },
- { HV_CHANNEL_MESSAGE_GPADL_TORNDOWN,
- vmbus_channel_on_gpadl_torndown },
- { HV_CHANNEL_MESSAGE_REL_ID_RELEASED,
- NULL },
- { HV_CHANNEL_MESSAGE_INITIATED_CONTACT,
- NULL },
- { HV_CHANNEL_MESSAGE_VERSION_RESPONSE,
- vmbus_channel_on_version_response },
- { HV_CHANNEL_MESSAGE_UNLOAD,
- NULL }
+static const vmbus_chanmsg_proc_t
+vmbus_chanmsg_process[HV_CHANNEL_MESSAGE_COUNT] = {
+ [HV_CHANNEL_MESSAGE_OFFER_CHANNEL] =
+ vmbus_channel_on_offer,
+ [HV_CHANNEL_MESSAGE_RESCIND_CHANNEL_OFFER] =
+ vmbus_channel_on_offer_rescind,
+ [HV_CHANNEL_MESSAGE_ALL_OFFERS_DELIVERED] =
+ vmbus_channel_on_offers_delivered,
+ [HV_CHANNEL_MESSAGE_OPEN_CHANNEL_RESULT] =
+ vmbus_channel_on_open_result,
+ [HV_CHANNEL_MESSAGE_GPADL_CREATED] =
+ vmbus_channel_on_gpadl_created,
+ [HV_CHANNEL_MESSAGE_GPADL_TORNDOWN] =
+ vmbus_channel_on_gpadl_torndown,
+ [HV_CHANNEL_MESSAGE_VERSION_RESPONSE] =
+ vmbus_channel_on_version_response
};
-typedef struct hv_work_item {
- struct task work;
- void (*callback)(void *);
- void* context;
-} hv_work_item;
-
-static struct mtx vmbus_chwait_lock;
-MTX_SYSINIT(vmbus_chwait_lk, &vmbus_chwait_lock, "vmbus primarych wait lock",
- MTX_DEF);
-static uint32_t vmbus_chancnt;
-static uint32_t vmbus_devcnt;
-
-#define VMBUS_CHANCNT_DONE 0x80000000
-
-/**
- * Implementation of the work abstraction.
- */
-static void
-work_item_callback(void *work, int pending)
-{
- struct hv_work_item *w = (struct hv_work_item *)work;
-
- w->callback(w->context);
-
- free(w, M_DEVBUF);
-}
-
-/**
- * @brief Create work item
- */
-static int
-hv_queue_work_item(
- void (*callback)(void *), void *context)
-{
- struct hv_work_item *w = malloc(sizeof(struct hv_work_item),
- M_DEVBUF, M_NOWAIT);
- KASSERT(w != NULL, ("Error VMBUS: Failed to allocate WorkItem\n"));
- if (w == NULL)
- return (ENOMEM);
-
- w->callback = callback;
- w->context = context;
-
- TASK_INIT(&w->work, 0, work_item_callback, w);
-
- return (taskqueue_enqueue(taskqueue_thread, &w->work));
-}
-
-
/**
* @brief Allocate and initialize a vmbus channel object
*/
-hv_vmbus_channel*
-hv_vmbus_allocate_channel(void)
+static struct hv_vmbus_channel *
+hv_vmbus_allocate_channel(struct vmbus_softc *sc)
{
- hv_vmbus_channel* channel;
+ struct hv_vmbus_channel *channel;
- channel = (hv_vmbus_channel*) malloc(
- sizeof(hv_vmbus_channel),
- M_DEVBUF,
- M_WAITOK | M_ZERO);
+ channel = malloc(sizeof(*channel), M_DEVBUF, M_WAITOK | M_ZERO);
+ channel->vmbus_sc = sc;
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);
return (channel);
}
@@ -195,7 +119,6 @@ static void
vmbus_channel_process_offer(hv_vmbus_channel *new_channel)
{
hv_vmbus_channel* channel;
- int ret;
uint32_t relid;
relid = new_channel->offer_msg.child_rel_id;
@@ -300,19 +223,8 @@ vmbus_channel_process_offer(hv_vmbus_cha
* binding which eventually invokes the device driver's AddDevice()
* method.
*/
- 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);
- mtx_unlock(&hv_vmbus_g_connection.channel_lock);
- hv_vmbus_free_vmbus_channel(new_channel);
- }
-
- mtx_lock(&vmbus_chwait_lock);
- vmbus_devcnt++;
- mtx_unlock(&vmbus_chwait_lock);
- wakeup(&vmbus_devcnt);
+ hv_vmbus_child_device_register(new_channel->vmbus_sc,
+ new_channel->device);
}
void
@@ -327,7 +239,7 @@ vmbus_channel_cpu_set(struct hv_vmbus_ch
}
chan->target_cpu = cpu;
- chan->target_vcpu = VMBUS_PCPU_GET(vmbus_get_softc(), vcpuid, cpu);
+ chan->target_vcpu = VMBUS_PCPU_GET(chan->vmbus_sc, vcpuid, cpu);
if (bootverbose) {
printf("vmbus_chan%u: assigned to cpu%u [vcpu%u]\n",
@@ -396,46 +308,28 @@ vmbus_channel_select_defcpu(struct hv_vm
/**
* @brief Handler for channel offers from Hyper-V/Azure
*
- * Handler for channel offers from vmbus in parent partition. We ignore
- * all offers except network and storage offers. For each network and storage
- * offers, we create a channel object and queue a work item to the channel
- * object to process the offer synchronously
+ * Handler for channel offers from vmbus in parent partition.
*/
static void
vmbus_channel_on_offer(struct vmbus_softc *sc, const struct vmbus_message *msg)
{
- const hv_vmbus_channel_msg_header *hdr =
- (const hv_vmbus_channel_msg_header *)msg->msg_data;
-
const hv_vmbus_channel_offer_channel *offer;
- hv_vmbus_channel_offer_channel *copied;
- offer = (const hv_vmbus_channel_offer_channel *)hdr;
+ /* New channel is offered by vmbus */
+ vmbus_scan_newchan(sc);
- // copy offer data
- copied = malloc(sizeof(*copied), M_DEVBUF, M_NOWAIT);
- if (copied == NULL) {
- printf("fail to allocate memory\n");
- return;
- }
-
- memcpy(copied, hdr, sizeof(*copied));
- hv_queue_work_item(vmbus_channel_on_offer_internal, copied);
-
- mtx_lock(&vmbus_chwait_lock);
- if ((vmbus_chancnt & VMBUS_CHANCNT_DONE) == 0)
- vmbus_chancnt++;
- mtx_unlock(&vmbus_chwait_lock);
+ offer = (const hv_vmbus_channel_offer_channel *)msg->msg_data;
+ vmbus_channel_on_offer_internal(sc, offer);
}
static void
-vmbus_channel_on_offer_internal(void* context)
+vmbus_channel_on_offer_internal(struct vmbus_softc *sc,
+ const hv_vmbus_channel_offer_channel *offer)
{
hv_vmbus_channel* new_channel;
- hv_vmbus_channel_offer_channel* offer = (hv_vmbus_channel_offer_channel*)context;
/* Allocate the channel object and save this offer */
- new_channel = hv_vmbus_allocate_channel();
+ new_channel = hv_vmbus_allocate_channel(sc);
/*
* By default we setup state to enable batched
@@ -472,45 +366,41 @@ vmbus_channel_on_offer_internal(void* co
vmbus_channel_select_defcpu(new_channel);
vmbus_channel_process_offer(new_channel);
-
- free(offer, M_DEVBUF);
}
/**
* @brief Rescind offer handler.
*
* We queue a work item to process this offer
- * synchronously
+ * synchronously.
+ *
+ * XXX pretty broken; need rework.
*/
static void
vmbus_channel_on_offer_rescind(struct vmbus_softc *sc,
const struct vmbus_message *msg)
{
- const hv_vmbus_channel_msg_header *hdr =
- (const hv_vmbus_channel_msg_header *)msg->msg_data;
-
const hv_vmbus_channel_rescind_offer *rescind;
hv_vmbus_channel* channel;
- rescind = (const hv_vmbus_channel_rescind_offer *)hdr;
+ rescind = (const hv_vmbus_channel_rescind_offer *)msg->msg_data;
channel = hv_vmbus_g_connection.channels[rescind->child_rel_id];
if (channel == NULL)
return;
-
- hv_queue_work_item(vmbus_channel_on_offer_rescind_internal, channel);
hv_vmbus_g_connection.channels[rescind->child_rel_id] = NULL;
+
+ taskqueue_enqueue(taskqueue_thread, &channel->ch_detach_task);
}
static void
-vmbus_channel_on_offer_rescind_internal(void *context)
+vmbus_chan_detach_task(void *xchan, int pending __unused)
{
- hv_vmbus_channel* channel;
+ struct hv_vmbus_channel *chan = xchan;
- channel = (hv_vmbus_channel*)context;
- if (HV_VMBUS_CHAN_ISPRIMARY(channel)) {
+ if (HV_VMBUS_CHAN_ISPRIMARY(chan)) {
/* Only primary channel owns the hv_device */
- hv_vmbus_child_device_unregister(channel->device);
+ hv_vmbus_child_device_unregister(chan->device);
}
}
@@ -519,14 +409,12 @@ vmbus_channel_on_offer_rescind_internal(
* @brief Invoked when all offers have been delivered.
*/
static void
-vmbus_channel_on_offers_delivered(struct vmbus_softc *sc __unused,
+vmbus_channel_on_offers_delivered(struct vmbus_softc *sc,
const struct vmbus_message *msg __unused)
{
- mtx_lock(&vmbus_chwait_lock);
- vmbus_chancnt |= VMBUS_CHANCNT_DONE;
- mtx_unlock(&vmbus_chwait_lock);
- wakeup(&vmbus_chancnt);
+ /* No more new channels for the channel request. */
+ vmbus_scan_done(sc);
}
/**
@@ -678,36 +566,6 @@ vmbus_channel_on_version_response(struct
}
/**
- * @brief Send a request to get all our pending offers.
- */
-int
-hv_vmbus_request_channel_offers(void)
-{
- int ret;
- hv_vmbus_channel_msg_header* msg;
- hv_vmbus_channel_msg_info* msg_info;
-
- msg_info = (hv_vmbus_channel_msg_info *)
- malloc(sizeof(hv_vmbus_channel_msg_info)
- + sizeof(hv_vmbus_channel_msg_header), M_DEVBUF, M_NOWAIT);
-
- if (msg_info == NULL) {
- if(bootverbose)
- printf("Error VMBUS: malloc failed for Request Offers\n");
- return (ENOMEM);
- }
-
- msg = (hv_vmbus_channel_msg_header*) msg_info->msg;
- msg->message_type = HV_CHANNEL_MESSAGE_REQUEST_OFFERS;
-
- ret = hv_vmbus_post_message(msg, sizeof(hv_vmbus_channel_msg_header));
-
- free(msg_info, M_DEVBUF);
-
- return (ret);
-}
-
-/**
* @brief Release channels that are unattached/unconnected (i.e., no drivers associated)
*/
void
@@ -760,7 +618,7 @@ vmbus_select_outgoing_channel(struct hv_
return outgoing_channel;
}
- cur_vcpu = VMBUS_PCPU_GET(vmbus_get_softc(), vcpuid, smp_pro_id);
+ 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){
@@ -789,21 +647,6 @@ vmbus_select_outgoing_channel(struct hv_
return(outgoing_channel);
}
-void
-vmbus_scan(void)
-{
- uint32_t chancnt;
-
- mtx_lock(&vmbus_chwait_lock);
- while ((vmbus_chancnt & VMBUS_CHANCNT_DONE) == 0)
- mtx_sleep(&vmbus_chancnt, &vmbus_chwait_lock, 0, "waitch", 0);
- chancnt = vmbus_chancnt & ~VMBUS_CHANCNT_DONE;
-
- while (vmbus_devcnt != chancnt)
- 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)
{
@@ -845,20 +688,17 @@ vmbus_rel_subchan(struct hv_vmbus_channe
void
vmbus_chan_msgproc(struct vmbus_softc *sc, const struct vmbus_message *msg)
{
- const hv_vmbus_channel_msg_table_entry *entry;
- const hv_vmbus_channel_msg_header *hdr;
- hv_vmbus_channel_msg_type msg_type;
-
- hdr = (const hv_vmbus_channel_msg_header *)msg->msg_data;
- msg_type = hdr->message_type;
+ vmbus_chanmsg_proc_t msg_proc;
+ uint32_t msg_type;
+ msg_type = ((const struct vmbus_chanmsg_hdr *)msg->msg_data)->chm_type;
if (msg_type >= HV_CHANNEL_MESSAGE_COUNT) {
device_printf(sc->vmbus_dev, "unknown message type 0x%x\n",
msg_type);
return;
}
- entry = &g_channel_message_table[msg_type];
- if (entry->messageHandler)
- entry->messageHandler(sc, msg);
+ msg_proc = vmbus_chanmsg_process[msg_type];
+ if (msg_proc != NULL)
+ msg_proc(sc, msg);
}
Modified: stable/10/sys/dev/hyperv/vmbus/hv_connection.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_connection.c Tue Oct 11 05:47:52 2016 (r307015)
+++ stable/10/sys/dev/hyperv/vmbus/hv_connection.c Tue Oct 11 06:04:40 2016 (r307016)
@@ -95,19 +95,13 @@ hv_vmbus_connect(struct vmbus_softc *sc)
int
hv_vmbus_disconnect(void)
{
- int ret = 0;
- hv_vmbus_channel_unload msg;
-
- msg.message_type = HV_CHANNEL_MESSAGE_UNLOAD;
-
- ret = hv_vmbus_post_message(&msg, sizeof(hv_vmbus_channel_unload));
mtx_destroy(&hv_vmbus_g_connection.channel_msg_lock);
free(hv_vmbus_g_connection.channels, M_DEVBUF);
hv_vmbus_g_connection.connect_state = HV_DISCONNECTED;
- return (ret);
+ return (0);
}
static __inline void
@@ -213,7 +207,7 @@ int hv_vmbus_post_message(void *buffer,
int
hv_vmbus_set_event(hv_vmbus_channel *channel)
{
- struct vmbus_softc *sc = vmbus_get_softc();
+ struct vmbus_softc *sc = channel->vmbus_sc;
int ret = 0;
uint32_t chanid = channel->offer_msg.child_rel_id;
@@ -231,7 +225,7 @@ vmbus_on_channel_open(const struct hv_vm
int flag_cnt;
flag_cnt = (chan->offer_msg.child_rel_id / VMBUS_EVTFLAG_LEN) + 1;
- flag_cnt_ptr = VMBUS_PCPU_PTR(vmbus_get_softc(), event_flags_cnt,
+ flag_cnt_ptr = VMBUS_PCPU_PTR(chan->vmbus_sc, event_flags_cnt,
chan->target_cpu);
for (;;) {
Modified: stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h Tue Oct 11 05:47:52 2016 (r307015)
+++ stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h Tue Oct 11 06:04:40 2016 (r307016)
@@ -395,9 +395,7 @@ void hv_ring_buffer_read_begin(
uint32_t hv_ring_buffer_read_end(
hv_vmbus_ring_buffer_info *ring_info);
-hv_vmbus_channel* hv_vmbus_allocate_channel(void);
void hv_vmbus_free_vmbus_channel(hv_vmbus_channel *channel);
-int hv_vmbus_request_channel_offers(void);
void hv_vmbus_release_unattached_channels(void);
uint16_t hv_vmbus_post_msg_via_msg_ipc(
@@ -413,7 +411,9 @@ struct hv_device* hv_vmbus_child_device_
hv_guid device_instance,
hv_vmbus_channel *channel);
-int hv_vmbus_child_device_register(
+struct vmbus_softc;
+
+void hv_vmbus_child_device_register(struct vmbus_softc *,
struct hv_device *child_dev);
int hv_vmbus_child_device_unregister(
struct hv_device *child_dev);
@@ -421,13 +421,9 @@ int hv_vmbus_child_device_unregister(
/**
* Connection interfaces
*/
-struct vmbus_softc;
int hv_vmbus_connect(struct vmbus_softc *);
int hv_vmbus_disconnect(void);
int hv_vmbus_post_message(void *buffer, size_t buf_size);
int hv_vmbus_set_event(hv_vmbus_channel *channel);
-/* Wait for device creation */
-void vmbus_scan(void);
-
#endif /* __HYPERV_PRIV_H__ */
Modified: stable/10/sys/dev/hyperv/vmbus/vmbus.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/vmbus.c Tue Oct 11 05:47:52 2016 (r307015)
+++ stable/10/sys/dev/hyperv/vmbus/vmbus.c Tue Oct 11 06:04:40 2016 (r307016)
@@ -98,6 +98,13 @@ struct vmbus_msghc_ctx {
static int vmbus_init(struct vmbus_softc *);
static int vmbus_init_contact(struct vmbus_softc *,
uint32_t);
+static int vmbus_req_channels(struct vmbus_softc *sc);
+static void vmbus_uninit(struct vmbus_softc *);
+static int vmbus_scan(struct vmbus_softc *);
+static void vmbus_scan_wait(struct vmbus_softc *);
+static void vmbus_scan_newdev(struct vmbus_softc *);
+
+static int vmbus_sysctl_version(SYSCTL_HANDLER_ARGS);
static struct vmbus_msghc_ctx *vmbus_msghc_ctx_create(bus_dma_tag_t);
static void vmbus_msghc_ctx_destroy(
@@ -418,6 +425,131 @@ vmbus_init(struct vmbus_softc *sc)
}
static void
+vmbus_uninit(struct vmbus_softc *sc)
+{
+ struct vmbus_chanmsg_unload *req;
+ struct vmbus_msghc *mh;
+ int error;
+
+ mh = vmbus_msghc_get(sc, sizeof(*req));
+ if (mh == NULL) {
+ device_printf(sc->vmbus_dev,
+ "can not get msg hypercall for unload\n");
+ return;
+ }
+
+ req = vmbus_msghc_dataptr(mh);
+ req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_UNLOAD;
+
+ error = vmbus_msghc_exec_noresult(mh);
+ vmbus_msghc_put(sc, mh);
+
+ if (error) {
+ device_printf(sc->vmbus_dev,
+ "unload msg hypercall failed\n");
+ }
+}
+
+static int
+vmbus_req_channels(struct vmbus_softc *sc)
+{
+ struct vmbus_chanmsg_channel_req *req;
+ struct vmbus_msghc *mh;
+ int error;
+
+ mh = vmbus_msghc_get(sc, sizeof(*req));
+ if (mh == NULL)
+ return ENXIO;
+
+ req = vmbus_msghc_dataptr(mh);
+ req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CHANNEL_REQ;
+
+ error = vmbus_msghc_exec_noresult(mh);
+ vmbus_msghc_put(sc, mh);
+
+ return error;
+}
+
+void
+vmbus_scan_newchan(struct vmbus_softc *sc)
+{
+ mtx_lock(&sc->vmbus_scan_lock);
+ if ((sc->vmbus_scan_chcnt & VMBUS_SCAN_CHCNT_DONE) == 0)
+ sc->vmbus_scan_chcnt++;
+ mtx_unlock(&sc->vmbus_scan_lock);
+}
+
+void
+vmbus_scan_done(struct vmbus_softc *sc)
+{
+ mtx_lock(&sc->vmbus_scan_lock);
+ sc->vmbus_scan_chcnt |= VMBUS_SCAN_CHCNT_DONE;
+ mtx_unlock(&sc->vmbus_scan_lock);
+ wakeup(&sc->vmbus_scan_chcnt);
+}
+
+static void
+vmbus_scan_newdev(struct vmbus_softc *sc)
+{
+ mtx_lock(&sc->vmbus_scan_lock);
+ sc->vmbus_scan_devcnt++;
+ mtx_unlock(&sc->vmbus_scan_lock);
+ wakeup(&sc->vmbus_scan_devcnt);
+}
+
+static void
+vmbus_scan_wait(struct vmbus_softc *sc)
+{
+ uint32_t chancnt;
+
+ mtx_lock(&sc->vmbus_scan_lock);
+ while ((sc->vmbus_scan_chcnt & VMBUS_SCAN_CHCNT_DONE) == 0) {
+ mtx_sleep(&sc->vmbus_scan_chcnt, &sc->vmbus_scan_lock, 0,
+ "waitch", 0);
+ }
+ chancnt = sc->vmbus_scan_chcnt & ~VMBUS_SCAN_CHCNT_DONE;
+
+ while (sc->vmbus_scan_devcnt != chancnt) {
+ mtx_sleep(&sc->vmbus_scan_devcnt, &sc->vmbus_scan_lock, 0,
+ "waitdev", 0);
+ }
+ mtx_unlock(&sc->vmbus_scan_lock);
+}
+
+static int
+vmbus_scan(struct vmbus_softc *sc)
+{
+ int error;
+
+ /*
+ * Start vmbus scanning.
+ */
+ error = vmbus_req_channels(sc);
+ if (error) {
+ device_printf(sc->vmbus_dev, "channel request failed: %d\n",
+ error);
+ return error;
+ }
+
+ /*
+ * Wait for all devices are added to vmbus.
+ */
+ vmbus_scan_wait(sc);
+
+ /*
+ * Identify, probe and attach.
+ */
+ bus_generic_probe(sc->vmbus_dev);
+ bus_generic_attach(sc->vmbus_dev);
+
+ if (bootverbose) {
+ device_printf(sc->vmbus_dev, "device scan, probe and attach "
+ "done\n");
+ }
+ return 0;
+}
+
+static void
vmbus_msg_task(void *xsc, int pending __unused)
{
struct vmbus_softc *sc = xsc;
@@ -972,12 +1104,13 @@ hv_vmbus_child_device_create(hv_guid typ
return (child_dev);
}
-int
-hv_vmbus_child_device_register(struct hv_device *child_dev)
+void
+hv_vmbus_child_device_register(struct vmbus_softc *sc,
+ struct hv_device *child_dev)
{
device_t child, parent;
- parent = vmbus_get_device();
+ parent = sc->vmbus_dev;
if (bootverbose) {
char name[HYPERV_GUID_STRLEN];
@@ -989,7 +1122,8 @@ hv_vmbus_child_device_register(struct hv
child_dev->device = child;
device_set_ivars(child, child_dev);
- return (0);
+ /* New device was added to vmbus */
+ vmbus_scan_newdev(sc);
}
int
@@ -1007,6 +1141,17 @@ hv_vmbus_child_device_unregister(struct
}
static int
+vmbus_sysctl_version(SYSCTL_HANDLER_ARGS)
+{
+ char verstr[16];
+
+ snprintf(verstr, sizeof(verstr), "%u.%u",
+ hv_vmbus_protocal_version >> 16,
+ hv_vmbus_protocal_version & 0xffff);
+ return sysctl_handle_string(oidp, verstr, sizeof(verstr), req);
+}
+
+static int
vmbus_probe(device_t dev)
{
char *id[] = { "VMBUS", NULL };
@@ -1034,15 +1179,18 @@ vmbus_probe(device_t dev)
* - retrieve the channel offers
*/
static int
-vmbus_bus_init(void)
+vmbus_doattach(struct vmbus_softc *sc)
{
- struct vmbus_softc *sc = vmbus_get_softc();
+ struct sysctl_oid_list *child;
+ struct sysctl_ctx_list *ctx;
int ret;
if (sc->vmbus_flags & VMBUS_FLAG_ATTACHED)
return (0);
sc->vmbus_flags |= VMBUS_FLAG_ATTACHED;
+ mtx_init(&sc->vmbus_scan_lock, "vmbus scan", NULL, MTX_DEF);
+
/*
* Create context for "post message" Hypercalls
*/
@@ -1092,11 +1240,15 @@ vmbus_bus_init(void)
else
sc->vmbus_event_proc = vmbus_event_proc;
- hv_vmbus_request_channel_offers();
+ ret = vmbus_scan(sc);
+ if (ret != 0)
+ goto cleanup;
- vmbus_scan();
- bus_generic_attach(sc->vmbus_dev);
- device_printf(sc->vmbus_dev, "device scan, probe and attach done\n");
+ ctx = device_get_sysctl_ctx(sc->vmbus_dev);
+ child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->vmbus_dev));
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "version",
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ vmbus_sysctl_version, "A", "vmbus version");
return (ret);
@@ -1107,6 +1259,7 @@ cleanup:
vmbus_msghc_ctx_destroy(sc->vmbus_msg_hc);
sc->vmbus_msg_hc = NULL;
}
+ mtx_destroy(&sc->vmbus_scan_lock);
return (ret);
}
@@ -1136,16 +1289,17 @@ vmbus_attach(device_t dev)
* initialization directly.
*/
if (!cold)
- vmbus_bus_init();
+ vmbus_doattach(vmbus_sc);
- bus_generic_probe(dev);
return (0);
}
static void
vmbus_sysinit(void *arg __unused)
{
- if (vm_guest != VM_GUEST_HV || vmbus_get_softc() == NULL)
+ struct vmbus_softc *sc = vmbus_get_softc();
+
+ if (vm_guest != VM_GUEST_HV || sc == NULL)
return;
/*
@@ -1155,7 +1309,7 @@ vmbus_sysinit(void *arg __unused)
* initialization directly.
*/
if (!cold)
- vmbus_bus_init();
+ vmbus_doattach(sc);
}
static int
@@ -1164,6 +1318,8 @@ vmbus_detach(device_t dev)
struct vmbus_softc *sc = device_get_softc(dev);
hv_vmbus_release_unattached_channels();
+
+ vmbus_uninit(sc);
hv_vmbus_disconnect();
if (sc->vmbus_flags & VMBUS_FLAG_SYNIC) {
@@ -1179,6 +1335,7 @@ vmbus_detach(device_t dev)
sc->vmbus_msg_hc = NULL;
}
+ mtx_destroy(&sc->vmbus_scan_lock);
return (0);
}
Modified: stable/10/sys/dev/hyperv/vmbus/vmbus_reg.h
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/vmbus_reg.h Tue Oct 11 05:47:52 2016 (r307015)
+++ stable/10/sys/dev/hyperv/vmbus/vmbus_reg.h Tue Oct 11 06:04:40 2016 (r307016)
@@ -83,8 +83,10 @@ CTASSERT(sizeof(struct vmbus_evtflags) =
* - Embedded in hypercall_postmsg_in.hc_data, e.g. request.
*/
+#define VMBUS_CHANMSG_TYPE_CHANNEL_REQ 3 /* REQ */
#define VMBUS_CHANMSG_TYPE_INIT_CONTACT 14 /* REQ */
#define VMBUS_CHANMSG_TYPE_VERSION_RESP 15 /* RESP */
+#define VMBUS_CHANMSG_TYPE_UNLOAD 16 /* REQ */
struct vmbus_chanmsg_hdr {
uint32_t chm_type; /* VMBUS_CHANMSG_TYPE_ */
@@ -107,4 +109,14 @@ struct vmbus_chanmsg_version_resp {
uint8_t chm_supp;
} __packed;
+/* VMBUS_CHANMSG_TYPE_CHANNEL_REQ */
+struct vmbus_chanmsg_channel_req {
+ struct vmbus_chanmsg_hdr chm_hdr;
+} __packed;
+
+/* VMBUS_CHANMSG_TYPE_UNLOAD */
+struct vmbus_chanmsg_unload {
+ struct vmbus_chanmsg_hdr chm_hdr;
+} __packed;
+
#endif /* !_VMBUS_REG_H_ */
Modified: stable/10/sys/dev/hyperv/vmbus/vmbus_var.h
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/vmbus_var.h Tue Oct 11 05:47:52 2016 (r307015)
+++ stable/10/sys/dev/hyperv/vmbus/vmbus_var.h Tue Oct 11 06:04:40 2016 (r307016)
@@ -83,6 +83,11 @@ struct vmbus_softc {
void *vmbus_mnf1; /* monitored by VM, unused */
struct hyperv_dma vmbus_mnf1_dma;
struct hyperv_dma vmbus_mnf2_dma;
+
+ struct mtx vmbus_scan_lock;
+ uint32_t vmbus_scan_chcnt;
+#define VMBUS_SCAN_CHCNT_DONE 0x80000000
+ uint32_t vmbus_scan_devcnt;
};
#define VMBUS_FLAG_ATTACHED 0x0001 /* vmbus was attached */
@@ -128,4 +133,7 @@ const struct vmbus_message *vmbus_msghc_
struct vmbus_msghc *);
void vmbus_msghc_wakeup(struct vmbus_softc *, const struct vmbus_message *);
+void vmbus_scan_done(struct vmbus_softc *);
+void vmbus_scan_newchan(struct vmbus_softc *);
+
#endif /* !_VMBUS_VAR_H_ */
More information about the svn-src-stable-10
mailing list