Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 13 Jun 2016 06:38:47 +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: r301859 - in stable/10/sys/dev/hyperv: include netvsc utilities vmbus
Message-ID:  <201606130638.u5D6clMh066204@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Mon Jun 13 06:38:46 2016
New Revision: 301859
URL: https://svnweb.freebsd.org/changeset/base/301859

Log:
  MFC 295307,295308,295309,295606
  
  295307
      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
  
  295308
      hyperv: Use WAITOK in the places where we can wait
  
      And convert rndis non-hot path spinlock to mutex.
  
      Submitted by:       Jun Su <junsu microsoft com>
      Reviewed by:        adrian, sephe
      Approved by:        adrian (mentor)
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5081
  
  295309
      hyperv: Use malloc for page allocation.
  
      We will eventually convert them to use busdma.
  
      Submitted by:       Jun Su <junsu microsoft com>
      Reviewed by:        adrian, sephe, Dexuan Cui <decui microsoft com>
      Approved by:        adrian (mentor)
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5087
  
  295606
      hyperv/hn: Fix typo in comment
  
      Noticed by: avos
      Reviewed by:        adrian, avos, Hongjiang Zhang <honzhan microsoft com>
      Approved by:        adrian
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5199

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/netvsc/hv_rndis_filter.c
  stable/10/sys/dev/hyperv/utilities/hv_kvp.c
  stable/10/sys/dev/hyperv/utilities/hv_util.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_connection.c
  stable/10/sys/dev/hyperv/vmbus/hv_hv.c
  stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
  stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/hyperv/include/hyperv.h
==============================================================================
--- stable/10/sys/dev/hyperv/include/hyperv.h	Mon Jun 13 06:24:41 2016	(r301858)
+++ stable/10/sys/dev/hyperv/include/hyperv.h	Mon Jun 13 06:38:46 2016	(r301859)
@@ -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[];

Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c	Mon Jun 13 06:24:41 2016	(r301858)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c	Mon Jun 13 06:38:46 2016	(r301859)
@@ -73,10 +73,7 @@ hv_nv_alloc_net_device(struct hv_device 
 	netvsc_dev *net_dev;
 	hn_softc_t *sc = device_get_softc(device->device);
 
-	net_dev = malloc(sizeof(netvsc_dev), M_NETVSC, M_NOWAIT | M_ZERO);
-	if (net_dev == NULL) {
-		return (NULL);
-	}
+	net_dev = malloc(sizeof(netvsc_dev), M_NETVSC, M_WAITOK | M_ZERO);
 
 	net_dev->dev = device;
 	net_dev->destroy = FALSE;
@@ -223,11 +220,7 @@ hv_nv_init_rx_buffer_with_net_vsp(struct
 	    init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.num_sections;
 
 	net_dev->rx_sections = malloc(net_dev->rx_section_count *
-	    sizeof(nvsp_1_rx_buf_section), M_NETVSC, M_NOWAIT);
-	if (net_dev->rx_sections == NULL) {
-		ret = EINVAL;
-		goto cleanup;
-	}
+	    sizeof(nvsp_1_rx_buf_section), M_NETVSC, M_WAITOK);
 	memcpy(net_dev->rx_sections, 
 	    init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.sections,
 	    net_dev->rx_section_count * sizeof(nvsp_1_rx_buf_section));
@@ -325,11 +318,7 @@ hv_nv_init_send_buffer_with_net_vsp(stru
 	    BITS_PER_LONG);
 	net_dev->send_section_bitsmap =
 	    malloc(net_dev->bitsmap_words * sizeof(long), M_NETVSC,
-	    M_NOWAIT | M_ZERO);
-	if (NULL == net_dev->send_section_bitsmap) {
-		ret = ENOMEM;
-		goto cleanup;
-	}
+	    M_WAITOK | M_ZERO);
 
 	goto exit;
 

Modified: stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Mon Jun 13 06:24:41 2016	(r301858)
+++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Mon Jun 13 06:38:46 2016	(r301859)
@@ -787,7 +787,7 @@ netvsc_channel_rollup(struct hv_device *
 
 /*
  * NOTE:
- * This this function fails, then both txd and m_head0 will be freed
+ * If this function fails, then both txd and m_head0 will be freed.
  */
 static int
 hn_encap(struct hn_softc *sc, struct hn_txdesc *txd, struct mbuf **m_head0)

Modified: stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Mon Jun 13 06:24:41 2016	(r301858)
+++ stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Mon Jun 13 06:38:46 2016	(r301859)
@@ -136,12 +136,9 @@ hv_get_rndis_device(void)
 {
 	rndis_device *device;
 
-	device = malloc(sizeof(rndis_device), M_NETVSC, M_NOWAIT | M_ZERO);
-	if (device == NULL) {
-		return (NULL);
-	}
+	device = malloc(sizeof(rndis_device), M_NETVSC, M_WAITOK | M_ZERO);
 
-	mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_SPIN | MTX_RECURSE);
+	mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_DEF);
 
 	/* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */
 	STAILQ_INIT(&device->myrequest_list);
@@ -172,10 +169,7 @@ hv_rndis_request(rndis_device *device, u
 	rndis_msg *rndis_mesg;
 	rndis_set_request *set;
 
-	request = malloc(sizeof(rndis_request), M_NETVSC, M_NOWAIT | M_ZERO);
-	if (request == NULL) {
-		return (NULL);
-	}
+	request = malloc(sizeof(rndis_request), M_NETVSC, M_WAITOK | M_ZERO);
 
 	sema_init(&request->wait_sema, 0, "rndis sema");
 	
@@ -194,9 +188,9 @@ hv_rndis_request(rndis_device *device, u
 	set->request_id += 1;
 
 	/* Add to the request list */
-	mtx_lock_spin(&device->req_lock);
+	mtx_lock(&device->req_lock);
 	STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry);
-	mtx_unlock_spin(&device->req_lock);
+	mtx_unlock(&device->req_lock);
 
 	return (request);
 }
@@ -207,14 +201,14 @@ hv_rndis_request(rndis_device *device, u
 static inline void
 hv_put_rndis_request(rndis_device *device, rndis_request *request)
 {
-	mtx_lock_spin(&device->req_lock);
+	mtx_lock(&device->req_lock);
 	/* Fixme:  Has O(n) performance */
 	/*
 	 * XXXKYS: Use Doubly linked lists.
 	 */
 	STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_,
 	    mylist_entry);
-	mtx_unlock_spin(&device->req_lock);
+	mtx_unlock(&device->req_lock);
 
 	sema_destroy(&request->wait_sema);
 	free(request, M_NETVSC);
@@ -271,7 +265,7 @@ hv_rf_receive_response(rndis_device *dev
 	rndis_request *next_request;
 	boolean_t found = FALSE;
 
-	mtx_lock_spin(&device->req_lock);
+	mtx_lock(&device->req_lock);
 	request = STAILQ_FIRST(&device->myrequest_list);
 	while (request != NULL) {
 		/*
@@ -286,7 +280,7 @@ hv_rf_receive_response(rndis_device *dev
 		next_request = STAILQ_NEXT(request, mylist_entry);
 		request = next_request;
 	}
-	mtx_unlock_spin(&device->req_lock);
+	mtx_unlock(&device->req_lock);
 
 	if (found) {
 		if (response->msg_len <= sizeof(rndis_msg)) {

Modified: stable/10/sys/dev/hyperv/utilities/hv_kvp.c
==============================================================================
--- stable/10/sys/dev/hyperv/utilities/hv_kvp.c	Mon Jun 13 06:24:41 2016	(r301858)
+++ stable/10/sys/dev/hyperv/utilities/hv_kvp.c	Mon Jun 13 06:38:46 2016	(r301859)
@@ -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);
 }
 

Modified: stable/10/sys/dev/hyperv/utilities/hv_util.c
==============================================================================
--- stable/10/sys/dev/hyperv/utilities/hv_util.c	Mon Jun 13 06:24:41 2016	(r301858)
+++ stable/10/sys/dev/hyperv/utilities/hv_util.c	Mon Jun 13 06:38:46 2016	(r301859)
@@ -52,6 +52,8 @@ static void hv_heartbeat_cb(void *contex
 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_msg = malloc(sizeof(time_sync_data), M_DEVBUF, M_NOWAIT);
+	time_sync_data* time_msg = service_table[HV_TIME_SYNCH].task.ta_context;
 
-	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);

Modified: stable/10/sys/dev/hyperv/vmbus/hv_channel.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_channel.c	Mon Jun 13 06:24:41 2016	(r301858)
+++ stable/10/sys/dev/hyperv/vmbus/hv_channel.c	Mon Jun 13 06:38:46 2016	(r301859)
@@ -69,9 +69,7 @@ vmbus_channel_set_event(hv_vmbus_channel
 				+ ((channel->offer_msg.child_rel_id >> 5))));
 
 		monitor_page = (hv_vmbus_monitor_page *)
-			hv_vmbus_g_connection.monitor_pages;
-
-		monitor_page++; /* Get the child to parent monitor page */
+			hv_vmbus_g_connection.monitor_page_2;
 
 		synch_set_bit(channel->monitor_bit,
 			(uint32_t *)&monitor_page->

Modified: stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c	Mon Jun 13 06:24:41 2016	(r301858)
+++ stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c	Mon Jun 13 06:38:46 2016	(r301859)
@@ -39,8 +39,10 @@ __FBSDID("$FreeBSD$");
  */
 
 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);
@@ -52,41 +54,46 @@ static void vmbus_channel_on_version_res
 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.
@@ -96,120 +103,30 @@ work_item_callback(void *work, int pendi
 {
 	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));
 }
 
 
@@ -224,10 +141,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);
@@ -238,16 +152,6 @@ hv_vmbus_allocate_channel(void)
 }
 
 /**
- * @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
  */
 void
@@ -255,13 +159,8 @@ hv_vmbus_free_vmbus_channel(hv_vmbus_cha
 {
 	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);
 }
 
 /**
@@ -459,7 +358,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;
 
@@ -469,10 +368,25 @@ vmbus_channel_on_offer(hv_vmbus_channel_
 	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
@@ -512,6 +426,8 @@ vmbus_channel_on_offer(hv_vmbus_channel_
 	new_channel->monitor_bit = (uint8_t) offer->monitor_id % 32;
 
 	vmbus_channel_process_offer(new_channel);
+
+	free(offer, M_DEVBUF);
 }
 
 /**
@@ -529,13 +445,20 @@ vmbus_channel_on_offer_rescind(hv_vmbus_
 	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);
 }
 
 /**
@@ -712,35 +635,6 @@ vmbus_channel_on_version_response(hv_vmb
 }
 
 /**
- * @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.
  */
 int
@@ -765,8 +659,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);
 }

Modified: stable/10/sys/dev/hyperv/vmbus/hv_connection.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_connection.c	Mon Jun 13 06:24:41 2016	(r301858)
+++ stable/10/sys/dev/hyperv/vmbus/hv_connection.c	Mon Jun 13 06:38:46 2016	(r301859)
@@ -90,12 +90,10 @@ hv_vmbus_negotiate_version(hv_vmbus_chan
 		hv_vmbus_g_connection.interrupt_page);
 
 	msg->monitor_page_1 = hv_get_phys_addr(
-		hv_vmbus_g_connection.monitor_pages);
+		hv_vmbus_g_connection.monitor_page_1);
 
-	msg->monitor_page_2 =
-		hv_get_phys_addr(
-			((uint8_t *) hv_vmbus_g_connection.monitor_pages
-			+ PAGE_SIZE));
+	msg->monitor_page_2 = hv_get_phys_addr(
+		hv_vmbus_g_connection.monitor_page_2);
 
 	/**
 	 * Add to list before we send the request since we may receive the
@@ -168,8 +166,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",
@@ -183,18 +179,9 @@ hv_vmbus_connect(void) {
 	 * Setup the vmbus event connection for channel interrupt abstraction
 	 * stuff
 	 */
-	hv_vmbus_g_connection.interrupt_page = contigmalloc(
+	hv_vmbus_g_connection.interrupt_page = malloc(
 					PAGE_SIZE, M_DEVBUF,
-					M_NOWAIT | M_ZERO, 0UL,
-					BUS_SPACE_MAXADDR,
-					PAGE_SIZE, 0);
-	KASSERT(hv_vmbus_g_connection.interrupt_page != NULL,
-	    ("Error VMBUS: malloc failed to allocate Channel"
-		" Request Event message!"));
-	if (hv_vmbus_g_connection.interrupt_page == NULL) {
-	    ret = ENOMEM;
-	    goto cleanup;
-	}
+					M_WAITOK | M_ZERO);
 
 	hv_vmbus_g_connection.recv_interrupt_page =
 		hv_vmbus_g_connection.interrupt_page;
@@ -207,31 +194,19 @@ hv_vmbus_connect(void) {
 	 * Set up the monitor notification facility. The 1st page for
 	 * parent->child and the 2nd page for child->parent
 	 */
-	hv_vmbus_g_connection.monitor_pages = contigmalloc(
-		2 * PAGE_SIZE,
+	hv_vmbus_g_connection.monitor_page_1 = malloc(
+		PAGE_SIZE,
 		M_DEVBUF,
-		M_NOWAIT | M_ZERO,
-		0UL,
-		BUS_SPACE_MAXADDR,
+		M_WAITOK | M_ZERO);
+	hv_vmbus_g_connection.monitor_page_2 = malloc(
 		PAGE_SIZE,
-		0);
-	KASSERT(hv_vmbus_g_connection.monitor_pages != NULL,
-	    ("Error VMBUS: malloc failed to allocate Monitor Pages!"));
-	if (hv_vmbus_g_connection.monitor_pages == NULL) {
-	    ret = ENOMEM;
-	    goto cleanup;
-	}
+		M_DEVBUF,
+		M_WAITOK | M_ZERO);
 
 	msg_info = (hv_vmbus_channel_msg_info*)
 		malloc(sizeof(hv_vmbus_channel_msg_info) +
 			sizeof(hv_vmbus_channel_initiate_contact),
-			M_DEVBUF, M_NOWAIT | M_ZERO);
-	KASSERT(msg_info != NULL,
-	    ("Error VMBUS: malloc failed for Initiate Contact message!"));
-	if (msg_info == NULL) {
-	    ret = ENOMEM;
-	    goto cleanup;
-	}
+			M_DEVBUF, M_WAITOK | M_ZERO);
 
 	hv_vmbus_g_connection.channels = malloc(sizeof(hv_vmbus_channel*) *
 		HV_CHANNEL_MAX_COUNT,
@@ -273,8 +248,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);
 
@@ -286,13 +259,8 @@ hv_vmbus_connect(void) {
 		hv_vmbus_g_connection.interrupt_page = NULL;
 	}
 
-	if (hv_vmbus_g_connection.monitor_pages != NULL) {
-		contigfree(
-			hv_vmbus_g_connection.monitor_pages,
-			2 * PAGE_SIZE,
-			M_DEVBUF);
-		hv_vmbus_g_connection.monitor_pages = NULL;
-	}
+	free(hv_vmbus_g_connection.monitor_page_1, M_DEVBUF);
+	free(hv_vmbus_g_connection.monitor_page_2, M_DEVBUF);
 
 	if (msg_info) {
 		sema_destroy(&msg_info->wait_sema);
@@ -309,32 +277,19 @@ hv_vmbus_connect(void) {
 int
 hv_vmbus_disconnect(void) {
 	int			 ret = 0;
-	hv_vmbus_channel_unload* msg;
-
-	msg = malloc(sizeof(hv_vmbus_channel_unload),
-	    M_DEVBUF, M_NOWAIT | M_ZERO);
-	KASSERT(msg != NULL,
-	    ("Error VMBUS: malloc failed to allocate Channel Unload Msg!"));
-	if (msg == NULL)
-	    return (ENOMEM);
+	hv_vmbus_channel_unload  msg;
 
-	msg->message_type = HV_CHANNEL_MESSAGE_UNLOAD;
-
-	ret = hv_vmbus_post_message(msg, sizeof(hv_vmbus_channel_unload));
+	msg.message_type = HV_CHANNEL_MESSAGE_UNLOAD;
 
+	ret = hv_vmbus_post_message(&msg, sizeof(hv_vmbus_channel_unload));
 
 	contigfree(hv_vmbus_g_connection.interrupt_page, PAGE_SIZE, M_DEVBUF);
 
 	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;
 
-	free(msg, M_DEVBUF);
-
 	return (ret);
 }
 

Modified: stable/10/sys/dev/hyperv/vmbus/hv_hv.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_hv.c	Mon Jun 13 06:24:41 2016	(r301858)
+++ stable/10/sys/dev/hyperv/vmbus/hv_hv.c	Mon Jun 13 06:38:46 2016	(r301859)
@@ -189,11 +189,7 @@ hv_vmbus_init(void) 
 	 * See if the hypercall page is already set
 	 */
 	hypercall_msr.as_uint64_t = rdmsr(HV_X64_MSR_HYPERCALL);
-	virt_addr = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO);
-	KASSERT(virt_addr != NULL,
-	    ("Error VMBUS: malloc failed to allocate page during init!"));
-	if (virt_addr == NULL)
-	    goto cleanup;
+	virt_addr = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO);
 
 	hypercall_msr.u.enable = 1;
 	hypercall_msr.u.guest_physical_address =

Modified: stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c	Mon Jun 13 06:24:41 2016	(r301858)
+++ stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c	Mon Jun 13 06:38:46 2016	(r301859)
@@ -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;
 
@@ -309,12 +291,7 @@ hv_vmbus_child_device_create(
 	 * Allocate the new child device
 	 */
 	child_dev = malloc(sizeof(hv_device), M_DEVBUF,
-			M_NOWAIT |  M_ZERO);
-	KASSERT(child_dev != NULL,
-	    ("Error VMBUS: malloc failed to allocate hv_device!"));
-
-	if (child_dev == NULL)
-		return (NULL);
+			M_WAITOK |  M_ZERO);
 
 	child_dev->channel = channel;
 	memcpy(&child_dev->class_id, &type, sizeof(hv_guid));
@@ -585,12 +562,7 @@ vmbus_bus_init(void)
 		 */

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201606130638.u5D6clMh066204>