summaryrefslogtreecommitdiff
path: root/drivers/hv/connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hv/connection.c')
-rw-r--r--drivers/hv/connection.c27
1 files changed, 12 insertions, 15 deletions
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index 27e72dc07e12..a8366fec1458 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -300,9 +300,7 @@ struct vmbus_channel *relid2channel(u32 relid)
void vmbus_on_event(unsigned long data)
{
struct vmbus_channel *channel = (void *) data;
- void *arg;
- bool read_state;
- u32 bytes_to_read;
+ void (*callback_fn)(void *);
/*
* A channel once created is persistent even when there
@@ -312,9 +310,13 @@ void vmbus_on_event(unsigned long data)
* Thus, checking and invoking the driver specific callback takes
* care of orderly unloading of the driver.
*/
- if (channel->onchannel_callback != NULL) {
- arg = channel->channel_callback_context;
- read_state = channel->batched_reading;
+ callback_fn = READ_ONCE(channel->onchannel_callback);
+ if (unlikely(callback_fn == NULL))
+ return;
+
+ (*callback_fn)(channel->channel_callback_context);
+
+ if (channel->callback_mode == HV_CALL_BATCHED) {
/*
* This callback reads the messages sent by the host.
* We can optimize host to guest signaling by ensuring:
@@ -326,16 +328,11 @@ void vmbus_on_event(unsigned long data)
* state is set we check to see if additional packets are
* available to read. In this case we repeat the process.
*/
+ if (hv_end_read(&channel->inbound) != 0) {
+ hv_begin_read(&channel->inbound);
- do {
- if (read_state)
- hv_begin_read(&channel->inbound);
- channel->onchannel_callback(arg);
- if (read_state)
- bytes_to_read = hv_end_read(&channel->inbound);
- else
- bytes_to_read = 0;
- } while (read_state && (bytes_to_read != 0));
+ tasklet_schedule(&channel->callback_event);
+ }
}
}