Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F133162927
D4920.id12739.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D4920.id12739.diff
View Options
Index: head/sys/dev/hyperv/include/hyperv.h
===================================================================
--- head/sys/dev/hyperv/include/hyperv.h
+++ head/sys/dev/hyperv/include/hyperv.h
@@ -755,6 +755,8 @@
struct mtx inbound_lock;
+ struct taskqueue * rxq;
+ struct task channel_task;
hv_vmbus_pfn_channel_callback on_channel_callback;
void* channel_callback_context;
Index: head/sys/dev/hyperv/vmbus/hv_channel.c
===================================================================
--- head/sys/dev/hyperv/vmbus/hv_channel.c
+++ head/sys/dev/hyperv/vmbus/hv_channel.c
@@ -51,6 +51,7 @@
uint32_t* message_count);
static void vmbus_channel_set_event(hv_vmbus_channel* channel);
+static void VmbusProcessChannelEvent(void* channel, int pending);
/**
* @brief Trigger an event notification on the specified channel
@@ -114,6 +115,9 @@
new_channel->on_channel_callback = pfn_on_channel_callback;
new_channel->channel_callback_context = context;
+ new_channel->rxq = hv_vmbus_g_context.hv_event_queue[new_channel->target_cpu];
+ TASK_INIT(&new_channel->channel_task, 0, VmbusProcessChannelEvent, new_channel);
+
/* Allocate the ring buffer */
out = contigmalloc((send_ring_buffer_size + recv_ring_buffer_size),
M_DEVBUF, M_ZERO, 0UL, BUS_SPACE_MAXADDR, PAGE_SIZE, 0);
@@ -517,6 +521,7 @@
hv_vmbus_channel_close_internal(hv_vmbus_channel *channel)
{
int ret = 0;
+ struct taskqueue *rxq = channel->rxq;
hv_vmbus_channel_close_channel* msg;
hv_vmbus_channel_msg_info* info;
@@ -524,6 +529,11 @@
channel->sc_creation_callback = NULL;
/*
+ * set rxq to NULL to avoid more requests be scheduled
+ */
+ channel->rxq = NULL;
+ taskqueue_drain(rxq, &channel->channel_task);
+ /*
* Grab the lock to prevent race condition when a packet received
* and unloading driver is in the process.
*/
@@ -876,3 +886,67 @@
return (0);
}
+
+
+/**
+ * Process a channel event notification
+ */
+static void
+VmbusProcessChannelEvent(void* context, int pending)
+{
+ void* arg;
+ uint32_t bytes_to_read;
+ hv_vmbus_channel* channel = (hv_vmbus_channel*)context;
+ boolean_t is_batched_reading;
+
+ /**
+ * Find the channel based on this relid and invokes
+ * the channel callback to process the event
+ */
+
+ if (channel == NULL) {
+ return;
+ }
+ /**
+ * To deal with the race condition where we might
+ * receive a packet while the relevant driver is
+ * being unloaded, dispatch the callback while
+ * holding the channel lock. The unloading driver
+ * will acquire the same channel lock to set the
+ * callback to NULL. This closes the window.
+ */
+
+ /*
+ * Disable the lock due to newly added WITNESS check in r277723.
+ * Will seek other way to avoid race condition.
+ * -- whu
+ */
+ // mtx_lock(&channel->inbound_lock);
+ if (channel->on_channel_callback != NULL) {
+ arg = channel->channel_callback_context;
+ is_batched_reading = channel->batched_reading;
+ /*
+ * Optimize host to guest signaling by ensuring:
+ * 1. While reading the channel, we disable interrupts from
+ * host.
+ * 2. Ensure that we process all posted messages from the host
+ * before returning from this callback.
+ * 3. Once we return, enable signaling from the host. Once this
+ * state is set we check to see if additional packets are
+ * available to read. In this case we repeat the process.
+ */
+ do {
+ if (is_batched_reading)
+ hv_ring_buffer_read_begin(&channel->inbound);
+
+ channel->on_channel_callback(arg);
+
+ if (is_batched_reading)
+ bytes_to_read =
+ hv_ring_buffer_read_end(&channel->inbound);
+ else
+ bytes_to_read = 0;
+ } while (is_batched_reading && (bytes_to_read != 0));
+ }
+ // mtx_unlock(&channel->inbound_lock);
+}
Index: head/sys/dev/hyperv/vmbus/hv_connection.c
===================================================================
--- head/sys/dev/hyperv/vmbus/hv_connection.c
+++ head/sys/dev/hyperv/vmbus/hv_connection.c
@@ -335,78 +335,12 @@
}
/**
- * Process a channel event notification
- */
-static void
-VmbusProcessChannelEvent(uint32_t relid)
-{
- void* arg;
- uint32_t bytes_to_read;
- hv_vmbus_channel* channel;
- boolean_t is_batched_reading;
-
- /**
- * Find the channel based on this relid and invokes
- * the channel callback to process the event
- */
-
- channel = hv_vmbus_g_connection.channels[relid];
-
- if (channel == NULL) {
- return;
- }
- /**
- * To deal with the race condition where we might
- * receive a packet while the relevant driver is
- * being unloaded, dispatch the callback while
- * holding the channel lock. The unloading driver
- * will acquire the same channel lock to set the
- * callback to NULL. This closes the window.
- */
-
- /*
- * Disable the lock due to newly added WITNESS check in r277723.
- * Will seek other way to avoid race condition.
- * -- whu
- */
- // mtx_lock(&channel->inbound_lock);
- if (channel->on_channel_callback != NULL) {
- arg = channel->channel_callback_context;
- is_batched_reading = channel->batched_reading;
- /*
- * Optimize host to guest signaling by ensuring:
- * 1. While reading the channel, we disable interrupts from
- * host.
- * 2. Ensure that we process all posted messages from the host
- * before returning from this callback.
- * 3. Once we return, enable signaling from the host. Once this
- * state is set we check to see if additional packets are
- * available to read. In this case we repeat the process.
- */
- do {
- if (is_batched_reading)
- hv_ring_buffer_read_begin(&channel->inbound);
-
- channel->on_channel_callback(arg);
-
- if (is_batched_reading)
- bytes_to_read =
- hv_ring_buffer_read_end(&channel->inbound);
- else
- bytes_to_read = 0;
- } while (is_batched_reading && (bytes_to_read != 0));
- }
- // mtx_unlock(&channel->inbound_lock);
-}
-
-/**
* Handler for events
*/
void
-hv_vmbus_on_events(void *arg)
+hv_vmbus_on_events(int cpu)
{
int bit;
- int cpu;
int dword;
void *page_addr;
uint32_t* recv_interrupt_page = NULL;
@@ -415,7 +349,6 @@
hv_vmbus_synic_event_flags *event;
/* int maxdword = PAGE_SIZE >> 3; */
- cpu = (int)(long)arg;
KASSERT(cpu <= mp_maxid, ("VMBUS: hv_vmbus_on_events: "
"cpu out of range!"));
@@ -457,8 +390,14 @@
*/
continue;
} else {
- VmbusProcessChannelEvent(rel_id);
-
+ hv_vmbus_channel * channel = hv_vmbus_g_connection.channels[rel_id];
+ /* if channel is closed or closing */
+ if (channel == NULL || channel->rxq == NULL)
+ continue;
+
+ if (channel->batched_reading)
+ hv_ring_buffer_read_begin(&channel->inbound);
+ taskqueue_enqueue_fast(channel->rxq, &channel->channel_task);
}
}
}
Index: head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
===================================================================
--- head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
+++ head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
@@ -177,7 +177,7 @@
(hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7)) {
/* Since we are a child, we only need to check bit 0 */
if (synch_test_and_clear_bit(0, &event->flags32[0])) {
- swi_sched(hv_vmbus_g_context.event_swintr[cpu], 0);
+ hv_vmbus_on_events(cpu);
}
} else {
/*
@@ -187,7 +187,7 @@
* Directly schedule the event software interrupt on
* current cpu.
*/
- swi_sched(hv_vmbus_g_context.event_swintr[cpu], 0);
+ hv_vmbus_on_events(cpu);
}
/* Check if there are actual msgs to be process */
@@ -225,7 +225,6 @@
return (FILTER_HANDLED);
}
-uint32_t hv_vmbus_swintr_event_cpu[MAXCPU];
u_long *hv_vmbus_intr_cpu[MAXCPU];
void
@@ -472,6 +471,7 @@
{
int i, j, n, ret;
char buf[MAXCOMLEN + 1];
+ cpuset_t cpu_mask;
if (vmbus_inited)
return (0);
@@ -508,10 +508,7 @@
setup_args.vector = hv_vmbus_g_context.hv_cb_vector;
CPU_FOREACH(j) {
- hv_vmbus_swintr_event_cpu[j] = 0;
- hv_vmbus_g_context.hv_event_intr_event[j] = NULL;
hv_vmbus_g_context.hv_msg_intr_event[j] = NULL;
- hv_vmbus_g_context.event_swintr[j] = NULL;
hv_vmbus_g_context.msg_swintr[j] = NULL;
snprintf(buf, sizeof(buf), "cpu%d:hyperv", j);
@@ -526,6 +523,20 @@
*/
CPU_FOREACH(j) {
/*
+ * Setup taskqueue to handle events
+ */
+ hv_vmbus_g_context.hv_event_queue[j] = taskqueue_create_fast("hyperv event", M_WAITOK,
+ taskqueue_thread_enqueue, &hv_vmbus_g_context.hv_event_queue[j]);
+ if (hv_vmbus_g_context.hv_event_queue[j] == NULL) {
+ if (bootverbose)
+ printf("VMBUS: failed to setup taskqueue\n");
+ goto cleanup1;
+ }
+ CPU_SETOF(j, &cpu_mask);
+ taskqueue_start_threads_cpuset(&hv_vmbus_g_context.hv_event_queue[j], 1, PI_NET, &cpu_mask,
+ "hvevent%d", j);
+
+ /*
* Setup software interrupt thread and handler for msg handling.
*/
ret = swi_add(&hv_vmbus_g_context.hv_msg_intr_event[j],
@@ -543,7 +554,7 @@
*/
ret = intr_event_bind(hv_vmbus_g_context.hv_msg_intr_event[j],
j);
- if (ret) {
+ if (ret) {
if(bootverbose)
printf("VMBUS: failed to bind msg swi thread "
"to cpu %d\n", j);
@@ -551,20 +562,6 @@
}
/*
- * Setup software interrupt thread and handler for
- * event handling.
- */
- ret = swi_add(&hv_vmbus_g_context.hv_event_intr_event[j],
- "hv_event", hv_vmbus_on_events, (void *)(long)j,
- SWI_CLOCK, 0, &hv_vmbus_g_context.event_swintr[j]);
- if (ret) {
- if(bootverbose)
- printf("VMBUS: failed to setup event swi for "
- "cpu %d\n", j);
- goto cleanup1;
- }
-
- /*
* Prepare the per cpu msg and event pages to be called on each cpu.
*/
for(i = 0; i < 2; i++) {
@@ -607,12 +604,11 @@
* remove swi and vmbus callback vector;
*/
CPU_FOREACH(j) {
+ if (hv_vmbus_g_context.hv_event_queue[j] != NULL)
+ taskqueue_free(hv_vmbus_g_context.hv_event_queue[j]);
if (hv_vmbus_g_context.msg_swintr[j] != NULL)
swi_remove(hv_vmbus_g_context.msg_swintr[j]);
- if (hv_vmbus_g_context.event_swintr[j] != NULL)
- swi_remove(hv_vmbus_g_context.event_swintr[j]);
hv_vmbus_g_context.hv_msg_intr_event[j] = NULL;
- hv_vmbus_g_context.hv_event_intr_event[j] = NULL;
}
vmbus_vector_free(hv_vmbus_g_context.hv_cb_vector);
@@ -677,12 +673,11 @@
/* remove swi */
CPU_FOREACH(i) {
+ if (hv_vmbus_g_context.hv_event_queue[i] != NULL)
+ taskqueue_free(hv_vmbus_g_context.hv_event_queue[i]);
if (hv_vmbus_g_context.msg_swintr[i] != NULL)
swi_remove(hv_vmbus_g_context.msg_swintr[i]);
- if (hv_vmbus_g_context.event_swintr[i] != NULL)
- swi_remove(hv_vmbus_g_context.event_swintr[i]);
hv_vmbus_g_context.hv_msg_intr_event[i] = NULL;
- hv_vmbus_g_context.hv_event_intr_event[i] = NULL;
}
vmbus_vector_free(hv_vmbus_g_context.hv_cb_vector);
Index: head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
===================================================================
--- head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
+++ head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
@@ -202,9 +202,8 @@
* Each cpu has its own software interrupt handler for channel
* event and msg handling.
*/
- struct intr_event *hv_event_intr_event[MAXCPU];
+ struct taskqueue *hv_event_queue[MAXCPU];
struct intr_event *hv_msg_intr_event[MAXCPU];
- void *event_swintr[MAXCPU];
void *msg_swintr[MAXCPU];
/*
* Host use this vector to intrrupt guest for vmbus channel
@@ -717,7 +716,7 @@
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);
-void hv_vmbus_on_events(void *);
+void hv_vmbus_on_events(int cpu);
/**
* Event Timer interfaces
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Oct 24, 1:28 PM (14 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24119894
Default Alt Text
D4920.id12739.diff (11 KB)
Attached To
Mode
D4920: Hyperv: Event handling code refactor.
Attached
Detach File
Event Timeline
Log In to Comment