Commit 5c1bec61 authored by Stephen Hemminger's avatar Stephen Hemminger Committed by Greg Kroah-Hartman

vmbus: use kernel bitops for traversing interrupt mask

Use standard kernel operations for find first set bit to traverse
the channel bit array. This has added benefit of speeding up
lookup on 64 bit and because it uses find first set instruction.
Signed-off-by: default avatarStephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: default avatarK. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent bb6a4db9
...@@ -47,12 +47,8 @@ void vmbus_setevent(struct vmbus_channel *channel) ...@@ -47,12 +47,8 @@ void vmbus_setevent(struct vmbus_channel *channel)
* For channels marked as in "low latency" mode * For channels marked as in "low latency" mode
* bypass the monitor page mechanism. * bypass the monitor page mechanism.
*/ */
if ((channel->offermsg.monitor_allocated) && if (channel->offermsg.monitor_allocated && !channel->low_latency) {
(!channel->low_latency)) { vmbus_send_interrupt(channel->offermsg.child_relid);
/* Each u32 represents 32 channels */
sync_set_bit(channel->offermsg.child_relid & 31,
(unsigned long *) vmbus_connection.send_int_page +
(channel->offermsg.child_relid >> 5));
/* Get the child to parent monitor page */ /* Get the child to parent monitor page */
monitorpage = vmbus_connection.monitor_pages[1]; monitorpage = vmbus_connection.monitor_pages[1];
......
...@@ -379,17 +379,11 @@ static void process_chn_event(u32 relid) ...@@ -379,17 +379,11 @@ static void process_chn_event(u32 relid)
*/ */
void vmbus_on_event(unsigned long data) void vmbus_on_event(unsigned long data)
{ {
u32 dword; unsigned long *recv_int_page;
u32 maxdword; u32 maxbits, relid;
int bit;
u32 relid;
u32 *recv_int_page = NULL;
void *page_addr;
int cpu = smp_processor_id();
union hv_synic_event_flags *event;
if (vmbus_proto_version < VERSION_WIN8) { if (vmbus_proto_version < VERSION_WIN8) {
maxdword = MAX_NUM_CHANNELS_SUPPORTED >> 5; maxbits = MAX_NUM_CHANNELS_SUPPORTED;
recv_int_page = vmbus_connection.recv_int_page; recv_int_page = vmbus_connection.recv_int_page;
} else { } else {
/* /*
...@@ -397,35 +391,24 @@ void vmbus_on_event(unsigned long data) ...@@ -397,35 +391,24 @@ void vmbus_on_event(unsigned long data)
* can be directly checked to get the id of the channel * can be directly checked to get the id of the channel
* that has the interrupt pending. * that has the interrupt pending.
*/ */
maxdword = HV_EVENT_FLAGS_DWORD_COUNT; int cpu = smp_processor_id();
page_addr = hv_context.synic_event_page[cpu]; void *page_addr = hv_context.synic_event_page[cpu];
event = (union hv_synic_event_flags *)page_addr + union hv_synic_event_flags *event
= (union hv_synic_event_flags *)page_addr +
VMBUS_MESSAGE_SINT; VMBUS_MESSAGE_SINT;
recv_int_page = event->flags32;
}
maxbits = HV_EVENT_FLAGS_COUNT;
recv_int_page = event->flags;
}
/* Check events */ if (unlikely(!recv_int_page))
if (!recv_int_page)
return; return;
for (dword = 0; dword < maxdword; dword++) {
if (!recv_int_page[dword])
continue;
for (bit = 0; bit < 32; bit++) {
if (sync_test_and_clear_bit(bit,
(unsigned long *)&recv_int_page[dword])) {
relid = (dword << 5) + bit;
if (relid == 0)
/*
* Special case - vmbus
* channel protocol msg
*/
continue;
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); process_chn_event(relid);
}
} }
} }
} }
...@@ -491,12 +474,8 @@ void vmbus_set_event(struct vmbus_channel *channel) ...@@ -491,12 +474,8 @@ void vmbus_set_event(struct vmbus_channel *channel)
{ {
u32 child_relid = channel->offermsg.child_relid; u32 child_relid = channel->offermsg.child_relid;
if (!channel->is_dedicated_interrupt) { if (!channel->is_dedicated_interrupt)
/* Each u32 represents 32 channels */ vmbus_send_interrupt(child_relid);
sync_set_bit(child_relid & 31,
(unsigned long *)vmbus_connection.send_int_page +
(child_relid >> 5));
}
hv_do_hypercall(HVCALL_SIGNAL_EVENT, channel->sig_event, NULL); hv_do_hypercall(HVCALL_SIGNAL_EVENT, channel->sig_event, NULL);
} }
......
...@@ -40,11 +40,9 @@ ...@@ -40,11 +40,9 @@
*/ */
#define HV_UTIL_NEGO_TIMEOUT 55 #define HV_UTIL_NEGO_TIMEOUT 55
/* Define synthetic interrupt controller flag constants. */
#define HV_EVENT_FLAGS_COUNT (256 * 8)
#define HV_EVENT_FLAGS_LONG_COUNT (256 / sizeof(unsigned long))
#define HV_EVENT_FLAGS_BYTE_COUNT (256)
#define HV_EVENT_FLAGS_DWORD_COUNT (256 / sizeof(u32))
/* /*
* Timer configuration register. * Timer configuration register.
...@@ -65,8 +63,7 @@ union hv_timer_config { ...@@ -65,8 +63,7 @@ union hv_timer_config {
/* Define the synthetic interrupt controller event flags format. */ /* Define the synthetic interrupt controller event flags format. */
union hv_synic_event_flags { union hv_synic_event_flags {
u8 flags8[HV_EVENT_FLAGS_BYTE_COUNT]; unsigned long flags[HV_EVENT_FLAGS_LONG_COUNT];
u32 flags32[HV_EVENT_FLAGS_DWORD_COUNT];
}; };
/* Define SynIC control register. */ /* Define SynIC control register. */
...@@ -358,6 +355,11 @@ struct vmbus_msginfo { ...@@ -358,6 +355,11 @@ struct vmbus_msginfo {
extern struct vmbus_connection vmbus_connection; extern struct vmbus_connection vmbus_connection;
static inline void vmbus_send_interrupt(u32 relid)
{
sync_set_bit(relid, vmbus_connection.send_int_page);
}
enum vmbus_message_handler_type { enum vmbus_message_handler_type {
/* The related handler can sleep. */ /* The related handler can sleep. */
VMHT_BLOCKING = 0, VMHT_BLOCKING = 0,
......
...@@ -908,10 +908,8 @@ static void vmbus_isr(void) ...@@ -908,10 +908,8 @@ static void vmbus_isr(void)
(vmbus_proto_version == VERSION_WIN7)) { (vmbus_proto_version == VERSION_WIN7)) {
/* Since we are a child, we only need to check bit 0 */ /* Since we are a child, we only need to check bit 0 */
if (sync_test_and_clear_bit(0, if (sync_test_and_clear_bit(0, event->flags))
(unsigned long *) &event->flags32[0])) {
handled = true; handled = true;
}
} else { } else {
/* /*
* Our host is win8 or above. The signaling mechanism * Our host is win8 or above. The signaling mechanism
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment