summaryrefslogtreecommitdiffstats
path: root/drivers/hv/vmbus_drv.c
diff options
context:
space:
mode:
authorStephen Hemminger <stephen@networkplumber.org>2017-02-12 07:02:21 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-02-14 19:20:35 +0100
commitb71e328297a3a578c482fb4814e737a0ec185839 (patch)
treef18a93257c4d74332dafe953ef28da9809bf2bc8 /drivers/hv/vmbus_drv.c
parentvmbus: change to per channel tasklet (diff)
downloadlinux-b71e328297a3a578c482fb4814e737a0ec185839.tar.xz
linux-b71e328297a3a578c482fb4814e737a0ec185839.zip
vmbus: add direct isr callback mode
Change the simple boolean batched_reading into a tri-value. For future NAPI support in netvsc driver, the callback needs to occur directly in interrupt handler. Batched mode is also changed to disable host interrupts immediately in interrupt routine (to avoid unnecessary host signals), and the tasklet is rescheduled if more data is detected. Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hv/vmbus_drv.c')
-rw-r--r--drivers/hv/vmbus_drv.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index eaf1a10b0245..f7f6b9144b07 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -887,6 +887,18 @@ msg_handled:
/*
+ * Direct callback for channels using other deferred processing
+ */
+static void vmbus_channel_isr(struct vmbus_channel *channel)
+{
+ void (*callback_fn)(void *);
+
+ callback_fn = READ_ONCE(channel->onchannel_callback);
+ if (likely(callback_fn != NULL))
+ (*callback_fn)(channel->channel_callback_context);
+}
+
+/*
* Schedule all channels with events pending
*/
static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu)
@@ -927,9 +939,19 @@ static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu)
/* Find channel based on relid */
list_for_each_entry(channel, &hv_cpu->chan_list, percpu_list) {
- if (channel->offermsg.child_relid == relid) {
- tasklet_schedule(&channel->callback_event);
+ if (channel->offermsg.child_relid != relid)
+ continue;
+
+ switch (channel->callback_mode) {
+ case HV_CALL_ISR:
+ vmbus_channel_isr(channel);
break;
+
+ case HV_CALL_BATCHED:
+ hv_begin_read(&channel->inbound);
+ /* fallthrough */
+ case HV_CALL_DIRECT:
+ tasklet_schedule(&channel->callback_event);
}
}
}