mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
hyperv: Use standard taskqueue instead of hv_work_queue
HyperV code was ported from Linux. There is an implementation of work queue called hv_work_queue. In FreeBSD, taskqueue could be used for the same purpose. Convert all the consumer of hv_work_queue to use taskqueue, and remove work queue implementation. Submitted by: Jun Su <junsu microsoft com> Reviewed by: adrian, Hongjiang Zhang <honzhan microsoft com> Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D4963
This commit is contained in:
parent
a7f84cedee
commit
f11ef33f0d
7 changed files with 101 additions and 291 deletions
|
|
@ -908,30 +908,6 @@ int hv_vmbus_channel_teardown_gpdal(
|
|||
|
||||
struct hv_vmbus_channel* vmbus_select_outgoing_channel(struct hv_vmbus_channel *promary);
|
||||
|
||||
/*
|
||||
* Work abstraction defines
|
||||
*/
|
||||
typedef struct hv_work_queue {
|
||||
struct taskqueue* queue;
|
||||
struct proc* proc;
|
||||
struct sema* work_sema;
|
||||
} hv_work_queue;
|
||||
|
||||
typedef struct hv_work_item {
|
||||
struct task work;
|
||||
void (*callback)(void *);
|
||||
void* context;
|
||||
hv_work_queue* wq;
|
||||
} hv_work_item;
|
||||
|
||||
struct hv_work_queue* hv_work_queue_create(char* name);
|
||||
|
||||
void hv_work_queue_close(struct hv_work_queue* wq);
|
||||
|
||||
int hv_queue_work_item(
|
||||
hv_work_queue* wq,
|
||||
void (*callback)(void *),
|
||||
void* context);
|
||||
/**
|
||||
* @brief Get physical address from virtual
|
||||
*/
|
||||
|
|
@ -952,8 +928,8 @@ typedef struct hv_vmbus_service {
|
|||
hv_guid guid; /* Hyper-V GUID */
|
||||
char *name; /* name of service */
|
||||
boolean_t enabled; /* service enabled */
|
||||
hv_work_queue *work_queue; /* background work queue */
|
||||
|
||||
void* context;
|
||||
struct task task;
|
||||
/*
|
||||
* function to initialize service
|
||||
*/
|
||||
|
|
@ -963,6 +939,11 @@ typedef struct hv_vmbus_service {
|
|||
* function to process Hyper-V messages
|
||||
*/
|
||||
void (*callback)(void *);
|
||||
|
||||
/*
|
||||
* function to uninitilize service
|
||||
*/
|
||||
int (*uninit)(struct hv_vmbus_service *);
|
||||
} hv_vmbus_service;
|
||||
|
||||
extern uint8_t* receive_buffer[];
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ static d_poll_t hv_kvp_dev_daemon_poll;
|
|||
static int hv_kvp_req_in_progress(void);
|
||||
static void hv_kvp_transaction_init(uint32_t, hv_vmbus_channel *, uint64_t, uint8_t *);
|
||||
static void hv_kvp_send_msg_to_daemon(void);
|
||||
static void hv_kvp_process_request(void *context);
|
||||
static void hv_kvp_process_request(void *context, int pending);
|
||||
|
||||
/* hv_kvp character device structure */
|
||||
static struct cdevsw hv_kvp_cdevsw =
|
||||
|
|
@ -123,9 +123,6 @@ static struct selinfo hv_kvp_selinfo;
|
|||
*/
|
||||
static struct {
|
||||
|
||||
/* Pre-allocated work item for queue */
|
||||
hv_work_item work_item;
|
||||
|
||||
/* Unless specified the pending mutex should be
|
||||
* used to alter the values of the following paramters:
|
||||
* 1. req_in_progress
|
||||
|
|
@ -642,7 +639,7 @@ hv_kvp_send_msg_to_daemon(void)
|
|||
* and interact with daemon
|
||||
*/
|
||||
static void
|
||||
hv_kvp_process_request(void *context)
|
||||
hv_kvp_process_request(void *context, int pending)
|
||||
{
|
||||
uint8_t *kvp_buf;
|
||||
hv_vmbus_channel *channel = context;
|
||||
|
|
@ -756,23 +753,18 @@ hv_kvp_callback(void *context)
|
|||
uint64_t pending_cnt = 0;
|
||||
|
||||
if (kvp_globals.register_done == false) {
|
||||
|
||||
kvp_globals.channelp = context;
|
||||
TASK_INIT(&service_table[HV_KVP].task, 0, hv_kvp_process_request, context);
|
||||
} else {
|
||||
|
||||
mtx_lock(&kvp_globals.pending_mutex);
|
||||
kvp_globals.pending_reqs = kvp_globals.pending_reqs + 1;
|
||||
pending_cnt = kvp_globals.pending_reqs;
|
||||
mtx_unlock(&kvp_globals.pending_mutex);
|
||||
if (pending_cnt == 1) {
|
||||
hv_kvp_log_info("%s: Queuing work item\n", __func__);
|
||||
hv_queue_work_item(
|
||||
service_table[HV_KVP].work_queue,
|
||||
hv_kvp_process_request,
|
||||
context
|
||||
);
|
||||
taskqueue_enqueue(taskqueue_thread, &service_table[HV_KVP].task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -977,26 +969,13 @@ int
|
|||
hv_kvp_init(hv_vmbus_service *srv)
|
||||
{
|
||||
int error = 0;
|
||||
hv_work_queue *work_queue = NULL;
|
||||
|
||||
memset(&kvp_globals, 0, sizeof(kvp_globals));
|
||||
|
||||
work_queue = hv_work_queue_create("KVP Service");
|
||||
if (work_queue == NULL) {
|
||||
hv_kvp_log_info("%s: Work queue alloc failed\n", __func__);
|
||||
error = ENOMEM;
|
||||
hv_kvp_log_error("%s: ENOMEM\n", __func__);
|
||||
goto Finish;
|
||||
}
|
||||
srv->work_queue = work_queue;
|
||||
memset(&kvp_globals, 0, sizeof(kvp_globals));
|
||||
|
||||
error = hv_kvp_dev_init();
|
||||
mtx_init(&kvp_globals.pending_mutex, "hv-kvp pending mutex",
|
||||
NULL, MTX_DEF);
|
||||
kvp_globals.pending_reqs = 0;
|
||||
NULL, MTX_DEF);
|
||||
|
||||
|
||||
Finish:
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ static void hv_heartbeat_cb(void *context);
|
|||
static void hv_timesync_cb(void *context);
|
||||
|
||||
static int hv_timesync_init(hv_vmbus_service *serv);
|
||||
static int hv_timesync_uninit(hv_vmbus_service *serv);
|
||||
static void hv_set_host_time(void *context, int pending);
|
||||
|
||||
/*
|
||||
* Note: GUID codes below are predefined by the host hypervisor
|
||||
|
|
@ -73,6 +75,7 @@ hv_vmbus_service service_table[] = {
|
|||
.enabled = TRUE,
|
||||
.init = hv_timesync_init,
|
||||
.callback = hv_timesync_cb,
|
||||
.uninit = hv_timesync_uninit,
|
||||
},
|
||||
|
||||
/* Heartbeat Service */
|
||||
|
|
@ -111,10 +114,16 @@ struct hv_ictimesync_data {
|
|||
static int
|
||||
hv_timesync_init(hv_vmbus_service *serv)
|
||||
{
|
||||
void *time_msg = malloc(sizeof(time_sync_data), M_DEVBUF, M_WAITOK);
|
||||
TASK_INIT(&serv->task, 1, hv_set_host_time, time_msg);
|
||||
return (0);
|
||||
}
|
||||
|
||||
serv->work_queue = hv_work_queue_create("Time Sync");
|
||||
if (serv->work_queue == NULL)
|
||||
return (ENOMEM);
|
||||
static int
|
||||
hv_timesync_uninit(hv_vmbus_service *serv)
|
||||
{
|
||||
taskqueue_drain(taskqueue_thread, &serv->task);
|
||||
free(serv->task.ta_context, M_DEVBUF);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
@ -152,9 +161,9 @@ hv_negotiate_version(
|
|||
* Set host time based on time sync message from host
|
||||
*/
|
||||
static void
|
||||
hv_set_host_time(void *context)
|
||||
hv_set_host_time(void *context, int pending)
|
||||
{
|
||||
time_sync_data* time_msg = (time_sync_data*) context;
|
||||
time_sync_data* time_msg = (time_sync_data*) context;
|
||||
uint64_t hosttime = time_msg->data;
|
||||
struct timespec guest_ts, host_ts;
|
||||
uint64_t host_tns;
|
||||
|
|
@ -166,7 +175,7 @@ hv_set_host_time(void *context)
|
|||
host_ts.tv_nsec = (long)(host_tns%HV_NANO_SEC_PER_SEC);
|
||||
|
||||
nanotime(&guest_ts);
|
||||
|
||||
|
||||
diff = (int64_t)host_ts.tv_sec - (int64_t)guest_ts.tv_sec;
|
||||
|
||||
/*
|
||||
|
|
@ -175,12 +184,7 @@ hv_set_host_time(void *context)
|
|||
if (diff > 5 || diff < -5) {
|
||||
error = kern_clock_settime(curthread, CLOCK_REALTIME,
|
||||
&host_ts);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the hosttime that was allocated in hv_adj_guesttime()
|
||||
*/
|
||||
free(time_msg, M_DEVBUF);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -197,23 +201,13 @@ hv_set_host_time(void *context)
|
|||
static inline
|
||||
void hv_adj_guesttime(uint64_t hosttime, uint8_t flags)
|
||||
{
|
||||
time_sync_data* time_msg;
|
||||
time_sync_data* time_msg = service_table[HV_TIME_SYNCH].task.ta_context;
|
||||
|
||||
time_msg = malloc(sizeof(time_sync_data), M_DEVBUF, M_NOWAIT);
|
||||
|
||||
if (time_msg == NULL)
|
||||
return;
|
||||
|
||||
time_msg->data = hosttime;
|
||||
|
||||
if ((flags & HV_ICTIMESYNCFLAG_SYNC) != 0) {
|
||||
hv_queue_work_item(service_table[HV_TIME_SYNCH].work_queue,
|
||||
hv_set_host_time, time_msg);
|
||||
} else if ((flags & HV_ICTIMESYNCFLAG_SAMPLE) != 0) {
|
||||
hv_queue_work_item(service_table[HV_TIME_SYNCH].work_queue,
|
||||
hv_set_host_time, time_msg);
|
||||
} else {
|
||||
free(time_msg, M_DEVBUF);
|
||||
if (((flags & HV_ICTIMESYNCFLAG_SYNC) != 0) ||
|
||||
((flags & HV_ICTIMESYNCFLAG_SAMPLE) != 0)) {
|
||||
taskqueue_enqueue(taskqueue_thread, &service_table[HV_TIME_SYNCH].task);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -452,19 +446,14 @@ hv_util_detach(device_t dev)
|
|||
service = device_get_softc(dev);
|
||||
receive_buffer_offset = service - &service_table[0];
|
||||
|
||||
if (service->work_queue != NULL)
|
||||
hv_work_queue_close(service->work_queue);
|
||||
if (service->uninit != NULL)
|
||||
service->uninit(service);
|
||||
|
||||
free(receive_buffer[receive_buffer_offset], M_DEVBUF);
|
||||
receive_buffer[receive_buffer_offset] = NULL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
hv_util_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
hv_util_modevent(module_t mod, int event, void *arg)
|
||||
{
|
||||
|
|
@ -495,6 +484,3 @@ static devclass_t util_devclass;
|
|||
DRIVER_MODULE(hv_utils, vmbus, util_driver, util_devclass, hv_util_modevent, 0);
|
||||
MODULE_VERSION(hv_utils, 1);
|
||||
MODULE_DEPEND(hv_utils, vmbus, 1, 1, 1);
|
||||
|
||||
SYSINIT(hv_util_initx, SI_SUB_KTHREAD_IDLE, SI_ORDER_MIDDLE + 1,
|
||||
hv_util_init, NULL);
|
||||
|
|
|
|||
|
|
@ -36,8 +36,10 @@
|
|||
*/
|
||||
|
||||
static void vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr);
|
||||
static void vmbus_channel_on_offer_internal(void* context);
|
||||
static void vmbus_channel_on_open_result(hv_vmbus_channel_msg_header* hdr);
|
||||
static void vmbus_channel_on_offer_rescind(hv_vmbus_channel_msg_header* hdr);
|
||||
static void vmbus_channel_on_offer_rescind_internal(void* context);
|
||||
static void vmbus_channel_on_gpadl_created(hv_vmbus_channel_msg_header* hdr);
|
||||
static void vmbus_channel_on_gpadl_torndown(hv_vmbus_channel_msg_header* hdr);
|
||||
static void vmbus_channel_on_offers_delivered(hv_vmbus_channel_msg_header* hdr);
|
||||
|
|
@ -49,41 +51,46 @@ static void vmbus_channel_on_version_response(hv_vmbus_channel_msg_header* hdr);
|
|||
hv_vmbus_channel_msg_table_entry
|
||||
g_channel_message_table[HV_CHANNEL_MESSAGE_COUNT] = {
|
||||
{ HV_CHANNEL_MESSAGE_INVALID,
|
||||
0, NULL },
|
||||
NULL },
|
||||
{ HV_CHANNEL_MESSAGE_OFFER_CHANNEL,
|
||||
0, vmbus_channel_on_offer },
|
||||
vmbus_channel_on_offer },
|
||||
{ HV_CHANNEL_MESSAGE_RESCIND_CHANNEL_OFFER,
|
||||
0, vmbus_channel_on_offer_rescind },
|
||||
vmbus_channel_on_offer_rescind },
|
||||
{ HV_CHANNEL_MESSAGE_REQUEST_OFFERS,
|
||||
0, NULL },
|
||||
NULL },
|
||||
{ HV_CHANNEL_MESSAGE_ALL_OFFERS_DELIVERED,
|
||||
1, vmbus_channel_on_offers_delivered },
|
||||
vmbus_channel_on_offers_delivered },
|
||||
{ HV_CHANNEL_MESSAGE_OPEN_CHANNEL,
|
||||
0, NULL },
|
||||
NULL },
|
||||
{ HV_CHANNEL_MESSAGE_OPEN_CHANNEL_RESULT,
|
||||
1, vmbus_channel_on_open_result },
|
||||
vmbus_channel_on_open_result },
|
||||
{ HV_CHANNEL_MESSAGE_CLOSE_CHANNEL,
|
||||
0, NULL },
|
||||
NULL },
|
||||
{ HV_CHANNEL_MESSAGEL_GPADL_HEADER,
|
||||
0, NULL },
|
||||
NULL },
|
||||
{ HV_CHANNEL_MESSAGE_GPADL_BODY,
|
||||
0, NULL },
|
||||
NULL },
|
||||
{ HV_CHANNEL_MESSAGE_GPADL_CREATED,
|
||||
1, vmbus_channel_on_gpadl_created },
|
||||
vmbus_channel_on_gpadl_created },
|
||||
{ HV_CHANNEL_MESSAGE_GPADL_TEARDOWN,
|
||||
0, NULL },
|
||||
NULL },
|
||||
{ HV_CHANNEL_MESSAGE_GPADL_TORNDOWN,
|
||||
1, vmbus_channel_on_gpadl_torndown },
|
||||
vmbus_channel_on_gpadl_torndown },
|
||||
{ HV_CHANNEL_MESSAGE_REL_ID_RELEASED,
|
||||
0, NULL },
|
||||
NULL },
|
||||
{ HV_CHANNEL_MESSAGE_INITIATED_CONTACT,
|
||||
0, NULL },
|
||||
NULL },
|
||||
{ HV_CHANNEL_MESSAGE_VERSION_RESPONSE,
|
||||
1, vmbus_channel_on_version_response },
|
||||
vmbus_channel_on_version_response },
|
||||
{ HV_CHANNEL_MESSAGE_UNLOAD,
|
||||
0, NULL }
|
||||
NULL }
|
||||
};
|
||||
|
||||
typedef struct hv_work_item {
|
||||
struct task work;
|
||||
void (*callback)(void *);
|
||||
void* context;
|
||||
} hv_work_item;
|
||||
|
||||
/**
|
||||
* Implementation of the work abstraction.
|
||||
|
|
@ -93,120 +100,30 @@ work_item_callback(void *work, int pending)
|
|||
{
|
||||
struct hv_work_item *w = (struct hv_work_item *)work;
|
||||
|
||||
/*
|
||||
* Serialize work execution.
|
||||
*/
|
||||
if (w->wq->work_sema != NULL) {
|
||||
sema_wait(w->wq->work_sema);
|
||||
}
|
||||
|
||||
w->callback(w->context);
|
||||
|
||||
if (w->wq->work_sema != NULL) {
|
||||
sema_post(w->wq->work_sema);
|
||||
}
|
||||
|
||||
free(w, M_DEVBUF);
|
||||
}
|
||||
|
||||
struct hv_work_queue*
|
||||
hv_work_queue_create(char* name)
|
||||
{
|
||||
static unsigned int qid = 0;
|
||||
char qname[64];
|
||||
int pri;
|
||||
struct hv_work_queue* wq;
|
||||
|
||||
wq = malloc(sizeof(struct hv_work_queue), M_DEVBUF, M_NOWAIT | M_ZERO);
|
||||
KASSERT(wq != NULL, ("Error VMBUS: Failed to allocate work_queue\n"));
|
||||
if (wq == NULL)
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* We use work abstraction to handle messages
|
||||
* coming from the host and these are typically offers.
|
||||
* Some FreeBsd drivers appear to have a concurrency issue
|
||||
* where probe/attach needs to be serialized. We ensure that
|
||||
* by having only one thread process work elements in a
|
||||
* specific queue by serializing work execution.
|
||||
*
|
||||
*/
|
||||
if (strcmp(name, "vmbusQ") == 0) {
|
||||
pri = PI_DISK;
|
||||
} else { /* control */
|
||||
pri = PI_NET;
|
||||
/*
|
||||
* Initialize semaphore for this queue by pointing
|
||||
* to the globale semaphore used for synchronizing all
|
||||
* control messages.
|
||||
*/
|
||||
wq->work_sema = &hv_vmbus_g_connection.control_sema;
|
||||
}
|
||||
|
||||
sprintf(qname, "hv_%s_%u", name, qid);
|
||||
|
||||
/*
|
||||
* Fixme: FreeBSD 8.2 has a different prototype for
|
||||
* taskqueue_create(), and for certain other taskqueue functions.
|
||||
* We need to research the implications of these changes.
|
||||
* Fixme: Not sure when the changes were introduced.
|
||||
*/
|
||||
wq->queue = taskqueue_create(qname, M_NOWAIT, taskqueue_thread_enqueue,
|
||||
&wq->queue
|
||||
#if __FreeBSD_version < 800000
|
||||
, &wq->proc
|
||||
#endif
|
||||
);
|
||||
|
||||
if (wq->queue == NULL) {
|
||||
free(wq, M_DEVBUF);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (taskqueue_start_threads(&wq->queue, 1, pri, "%s taskq", qname)) {
|
||||
taskqueue_free(wq->queue);
|
||||
free(wq, M_DEVBUF);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
qid++;
|
||||
|
||||
return (wq);
|
||||
}
|
||||
|
||||
void
|
||||
hv_work_queue_close(struct hv_work_queue *wq)
|
||||
{
|
||||
/*
|
||||
* KYS: Need to drain the taskqueue
|
||||
* before we close the hv_work_queue.
|
||||
*/
|
||||
/*KYS: taskqueue_drain(wq->tq, ); */
|
||||
taskqueue_free(wq->queue);
|
||||
free(wq, M_DEVBUF);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create work item
|
||||
*/
|
||||
int
|
||||
static int
|
||||
hv_queue_work_item(
|
||||
struct hv_work_queue *wq,
|
||||
void (*callback)(void *), void *context)
|
||||
{
|
||||
struct hv_work_item *w = malloc(sizeof(struct hv_work_item),
|
||||
M_DEVBUF, M_NOWAIT | M_ZERO);
|
||||
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;
|
||||
w->wq = wq;
|
||||
|
||||
TASK_INIT(&w->work, 0, work_item_callback, w);
|
||||
|
||||
return (taskqueue_enqueue(wq->queue, &w->work));
|
||||
return (taskqueue_enqueue(taskqueue_thread, &w->work));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -221,10 +138,7 @@ hv_vmbus_allocate_channel(void)
|
|||
channel = (hv_vmbus_channel*) malloc(
|
||||
sizeof(hv_vmbus_channel),
|
||||
M_DEVBUF,
|
||||
M_NOWAIT | M_ZERO);
|
||||
KASSERT(channel != NULL, ("Error VMBUS: Failed to allocate channel!"));
|
||||
if (channel == NULL)
|
||||
return (NULL);
|
||||
M_WAITOK | M_ZERO);
|
||||
|
||||
mtx_init(&channel->inbound_lock, "channel inbound", NULL, MTX_DEF);
|
||||
mtx_init(&channel->sc_lock, "vmbus multi channel", NULL, MTX_DEF);
|
||||
|
|
@ -234,16 +148,6 @@ hv_vmbus_allocate_channel(void)
|
|||
return (channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release the vmbus channel object itself
|
||||
*/
|
||||
static inline void
|
||||
ReleaseVmbusChannel(void *context)
|
||||
{
|
||||
hv_vmbus_channel* channel = (hv_vmbus_channel*) context;
|
||||
free(channel, M_DEVBUF);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release the resources used by the vmbus channel object
|
||||
*/
|
||||
|
|
@ -252,13 +156,8 @@ hv_vmbus_free_vmbus_channel(hv_vmbus_channel* channel)
|
|||
{
|
||||
mtx_destroy(&channel->sc_lock);
|
||||
mtx_destroy(&channel->inbound_lock);
|
||||
/*
|
||||
* We have to release the channel's workqueue/thread in
|
||||
* the vmbus's workqueue/thread context
|
||||
* ie we can't destroy ourselves
|
||||
*/
|
||||
hv_queue_work_item(hv_vmbus_g_connection.work_queue,
|
||||
ReleaseVmbusChannel, (void *) channel);
|
||||
|
||||
free(channel, M_DEVBUF);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -456,7 +355,7 @@ static void
|
|||
vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr)
|
||||
{
|
||||
hv_vmbus_channel_offer_channel* offer;
|
||||
hv_vmbus_channel* new_channel;
|
||||
hv_vmbus_channel_offer_channel* copied;
|
||||
|
||||
offer = (hv_vmbus_channel_offer_channel*) hdr;
|
||||
|
||||
|
|
@ -466,10 +365,25 @@ vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr)
|
|||
guidType = &offer->offer.interface_type;
|
||||
guidInstance = &offer->offer.interface_instance;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
static void
|
||||
vmbus_channel_on_offer_internal(void* context)
|
||||
{
|
||||
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();
|
||||
if (new_channel == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* By default we setup state to enable batched
|
||||
|
|
@ -509,6 +423,8 @@ vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr)
|
|||
new_channel->monitor_bit = (uint8_t) offer->monitor_id % 32;
|
||||
|
||||
vmbus_channel_process_offer(new_channel);
|
||||
|
||||
free(offer, M_DEVBUF);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -526,13 +442,20 @@ vmbus_channel_on_offer_rescind(hv_vmbus_channel_msg_header* hdr)
|
|||
rescind = (hv_vmbus_channel_rescind_offer*) hdr;
|
||||
|
||||
channel = hv_vmbus_g_connection.channels[rescind->child_rel_id];
|
||||
if (channel == NULL)
|
||||
if (channel == NULL)
|
||||
return;
|
||||
|
||||
hv_vmbus_child_device_unregister(channel->device);
|
||||
mtx_lock(&hv_vmbus_g_connection.channel_lock);
|
||||
hv_queue_work_item(vmbus_channel_on_offer_rescind_internal, channel);
|
||||
hv_vmbus_g_connection.channels[rescind->child_rel_id] = NULL;
|
||||
mtx_unlock(&hv_vmbus_g_connection.channel_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
vmbus_channel_on_offer_rescind_internal(void *context)
|
||||
{
|
||||
hv_vmbus_channel* channel;
|
||||
|
||||
channel = (hv_vmbus_channel*)context;
|
||||
hv_vmbus_child_device_unregister(channel->device);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -708,35 +631,6 @@ vmbus_channel_on_version_response(hv_vmbus_channel_msg_header* hdr)
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handler for channel protocol messages.
|
||||
*
|
||||
* This is invoked in the vmbus worker thread context.
|
||||
*/
|
||||
void
|
||||
hv_vmbus_on_channel_message(void *context)
|
||||
{
|
||||
hv_vmbus_message* msg;
|
||||
hv_vmbus_channel_msg_header* hdr;
|
||||
int size;
|
||||
|
||||
msg = (hv_vmbus_message*) context;
|
||||
hdr = (hv_vmbus_channel_msg_header*) msg->u.payload;
|
||||
size = msg->header.payload_size;
|
||||
|
||||
if (hdr->message_type >= HV_CHANNEL_MESSAGE_COUNT) {
|
||||
free(msg, M_DEVBUF);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_channel_message_table[hdr->message_type].messageHandler) {
|
||||
g_channel_message_table[hdr->message_type].messageHandler(hdr);
|
||||
}
|
||||
|
||||
/* Free the msg that was allocated in VmbusOnMsgDPC() */
|
||||
free(msg, M_DEVBUF);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send a request to get all our pending offers.
|
||||
*/
|
||||
|
|
@ -762,8 +656,7 @@ hv_vmbus_request_channel_offers(void)
|
|||
|
||||
ret = hv_vmbus_post_message(msg, sizeof(hv_vmbus_channel_msg_header));
|
||||
|
||||
if (msg_info)
|
||||
free(msg_info, M_DEVBUF);
|
||||
free(msg_info, M_DEVBUF);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,8 +164,6 @@ hv_vmbus_connect(void) {
|
|||
* Initialize the vmbus connection
|
||||
*/
|
||||
hv_vmbus_g_connection.connect_state = HV_CONNECTING;
|
||||
hv_vmbus_g_connection.work_queue = hv_work_queue_create("vmbusQ");
|
||||
sema_init(&hv_vmbus_g_connection.control_sema, 1, "control_sema");
|
||||
|
||||
TAILQ_INIT(&hv_vmbus_g_connection.channel_msg_anchor);
|
||||
mtx_init(&hv_vmbus_g_connection.channel_msg_lock, "vmbus channel msg",
|
||||
|
|
@ -269,8 +267,6 @@ hv_vmbus_connect(void) {
|
|||
|
||||
hv_vmbus_g_connection.connect_state = HV_DISCONNECTED;
|
||||
|
||||
hv_work_queue_close(hv_vmbus_g_connection.work_queue);
|
||||
sema_destroy(&hv_vmbus_g_connection.control_sema);
|
||||
mtx_destroy(&hv_vmbus_g_connection.channel_lock);
|
||||
mtx_destroy(&hv_vmbus_g_connection.channel_msg_lock);
|
||||
|
||||
|
|
@ -323,9 +319,6 @@ hv_vmbus_disconnect(void) {
|
|||
|
||||
mtx_destroy(&hv_vmbus_g_connection.channel_msg_lock);
|
||||
|
||||
hv_work_queue_close(hv_vmbus_g_connection.work_queue);
|
||||
sema_destroy(&hv_vmbus_g_connection.control_sema);
|
||||
|
||||
free(hv_vmbus_g_connection.channels, M_DEVBUF);
|
||||
hv_vmbus_g_connection.connect_state = HV_DISCONNECTED;
|
||||
|
||||
|
|
|
|||
|
|
@ -83,8 +83,6 @@ vmbus_msg_swintr(void *arg)
|
|||
hv_vmbus_channel_msg_table_entry *entry;
|
||||
hv_vmbus_channel_msg_type msg_type;
|
||||
hv_vmbus_message* msg;
|
||||
hv_vmbus_message* copied;
|
||||
static bool warned = false;
|
||||
|
||||
cpu = (int)(long)arg;
|
||||
KASSERT(cpu <= mp_maxid, ("VMBUS: vmbus_msg_swintr: "
|
||||
|
|
@ -100,31 +98,15 @@ vmbus_msg_swintr(void *arg)
|
|||
hdr = (hv_vmbus_channel_msg_header *)msg->u.payload;
|
||||
msg_type = hdr->message_type;
|
||||
|
||||
if (msg_type >= HV_CHANNEL_MESSAGE_COUNT && !warned) {
|
||||
warned = true;
|
||||
if (msg_type >= HV_CHANNEL_MESSAGE_COUNT) {
|
||||
printf("VMBUS: unknown message type = %d\n", msg_type);
|
||||
goto handled;
|
||||
}
|
||||
|
||||
entry = &g_channel_message_table[msg_type];
|
||||
|
||||
if (entry->handler_no_sleep)
|
||||
if (entry->messageHandler)
|
||||
entry->messageHandler(hdr);
|
||||
else {
|
||||
|
||||
copied = malloc(sizeof(hv_vmbus_message),
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
KASSERT(copied != NULL,
|
||||
("Error VMBUS: malloc failed to allocate"
|
||||
" hv_vmbus_message!"));
|
||||
if (copied == NULL)
|
||||
continue;
|
||||
|
||||
memcpy(copied, msg, sizeof(hv_vmbus_message));
|
||||
hv_queue_work_item(hv_vmbus_g_connection.work_queue,
|
||||
hv_vmbus_on_channel_message,
|
||||
copied);
|
||||
}
|
||||
handled:
|
||||
msg->header.message_type = HV_MESSAGE_TYPE_NONE;
|
||||
|
||||
|
|
|
|||
|
|
@ -362,10 +362,8 @@ typedef struct {
|
|||
|
||||
/**
|
||||
* channel table for fast lookup through id.
|
||||
*/
|
||||
*/
|
||||
hv_vmbus_channel **channels;
|
||||
hv_vmbus_handle work_queue;
|
||||
struct sema control_sema;
|
||||
} hv_vmbus_connection;
|
||||
|
||||
typedef union {
|
||||
|
|
@ -632,7 +630,6 @@ typedef void (*vmbus_msg_handler)(hv_vmbus_channel_msg_header *msg);
|
|||
typedef struct hv_vmbus_channel_msg_table_entry {
|
||||
hv_vmbus_channel_msg_type messageType;
|
||||
|
||||
bool handler_no_sleep; /* true: the handler doesn't sleep */
|
||||
vmbus_msg_handler messageHandler;
|
||||
} hv_vmbus_channel_msg_table_entry;
|
||||
|
||||
|
|
@ -682,7 +679,6 @@ uint32_t hv_ring_buffer_read_end(
|
|||
|
||||
hv_vmbus_channel* hv_vmbus_allocate_channel(void);
|
||||
void hv_vmbus_free_vmbus_channel(hv_vmbus_channel *channel);
|
||||
void hv_vmbus_on_channel_message(void *context);
|
||||
int hv_vmbus_request_channel_offers(void);
|
||||
void hv_vmbus_release_unattached_channels(void);
|
||||
int hv_vmbus_init(void);
|
||||
|
|
|
|||
Loading…
Reference in a new issue