diff options
author | Stephen Hemminger | 2017-02-11 23:02:20 -0700 |
---|---|---|
committer | Greg Kroah-Hartman | 2017-02-14 10:20:35 -0800 |
commit | 631e63a9f346cb657761ae22138f294718696501 (patch) | |
tree | 9d207333ca07e73282e8c7e8a4c36cf73f0d7b63 /drivers/hv/connection.c | |
parent | 37cdd991fac810a727cd285629d1640fcf53cd19 (diff) |
vmbus: change to per channel tasklet
Make the event handling tasklet per channel rather than per-cpu.
This allows for better fairness when getting lots of data on the same
cpu.
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/connection.c')
-rw-r--r-- | drivers/hv/connection.c | 78 |
1 files changed, 3 insertions, 75 deletions
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index 158f12823baf..27e72dc07e12 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -260,29 +260,6 @@ void vmbus_disconnect(void) } /* - * Map the given relid to the corresponding channel based on the - * per-cpu list of channels that have been affinitized to this CPU. - * This will be used in the channel callback path as we can do this - * mapping in a lock-free fashion. - */ -static struct vmbus_channel *pcpu_relid2channel(u32 relid) -{ - struct hv_per_cpu_context *hv_cpu - = this_cpu_ptr(hv_context.cpu_context); - struct vmbus_channel *found_channel = NULL; - struct vmbus_channel *channel; - - list_for_each_entry(channel, &hv_cpu->chan_list, percpu_list) { - if (channel->offermsg.child_relid == relid) { - found_channel = channel; - break; - } - } - - return found_channel; -} - -/* * relid2channel - Get the channel object given its * child relative id (ie channel id) */ @@ -318,25 +295,16 @@ struct vmbus_channel *relid2channel(u32 relid) } /* - * process_chn_event - Process a channel event notification + * vmbus_on_event - Process a channel event notification */ -static void process_chn_event(u32 relid) +void vmbus_on_event(unsigned long data) { - struct vmbus_channel *channel; + struct vmbus_channel *channel = (void *) data; void *arg; bool read_state; u32 bytes_to_read; /* - * Find the channel based on this relid and invokes the - * channel callback to process the event - */ - channel = pcpu_relid2channel(relid); - - if (!channel) - return; - - /* * A channel once created is persistent even when there * is no driver handling the device. An unloading driver * sets the onchannel_callback to NULL on the same CPU @@ -344,7 +312,6 @@ static void process_chn_event(u32 relid) * 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; @@ -373,45 +340,6 @@ static void process_chn_event(u32 relid) } /* - * vmbus_on_event - Handler for events - */ -void vmbus_on_event(unsigned long data) -{ - struct hv_per_cpu_context *hv_cpu = (void *)data; - unsigned long *recv_int_page; - u32 maxbits, relid; - - if (vmbus_proto_version < VERSION_WIN8) { - maxbits = MAX_NUM_CHANNELS_SUPPORTED; - recv_int_page = vmbus_connection.recv_int_page; - } else { - /* - * When the host is win8 and beyond, the event page - * can be directly checked to get the id of the channel - * that has the interrupt pending. - */ - void *page_addr = hv_cpu->synic_event_page; - union hv_synic_event_flags *event - = (union hv_synic_event_flags *)page_addr + - VMBUS_MESSAGE_SINT; - - maxbits = HV_EVENT_FLAGS_COUNT; - recv_int_page = event->flags; - } - - if (unlikely(!recv_int_page)) - return; - - for_each_set_bit(relid, recv_int_page, maxbits) { - if (sync_test_and_clear_bit(relid, recv_int_page)) { - /* Special case - vmbus channel protocol msg */ - if (relid != 0) - process_chn_event(relid); - } - } -} - -/* * vmbus_post_msg - Send a msg on the vmbus's message connection */ int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep) |