hyperv/vmbus: Use unsigned long for event bits.

And move base channel id calculation out of inner loop.  This prepares
for more event processing optimization.

MFC after:	1 week
Sponsored by:	Microsoft OSTC
Differential Revision:	https://reviews.freebsd.org/D6384
This commit is contained in:
Sepherosa Ziehau 2016-05-18 02:59:46 +00:00
parent 2d3192783d
commit 8080722aee
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=300101
2 changed files with 31 additions and 21 deletions

View File

@ -294,13 +294,10 @@ hv_vmbus_disconnect(void) {
void
hv_vmbus_on_events(int cpu)
{
int bit;
int dword;
void *page_addr;
uint32_t* recv_interrupt_page = NULL;
int rel_id;
int maxdword;
unsigned long *intr_page;
hv_vmbus_synic_event_flags *event;
void *page_addr;
int page_cnt, pg;
KASSERT(cpu <= mp_maxid, ("VMBUS: hv_vmbus_on_events: "
"cpu out of range!"));
@ -310,39 +307,42 @@ hv_vmbus_on_events(int cpu)
page_addr + HV_VMBUS_MESSAGE_SINT;
if ((hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008) ||
(hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7)) {
maxdword = HV_MAX_NUM_CHANNELS_SUPPORTED >> 5;
page_cnt = HV_MAX_NUM_CHANNELS_SUPPORTED >>
HV_CHANNEL_ULONG_SHIFT;
/*
* receive size is 1/2 page and divide that by 4 bytes
*/
if (atomic_testandclear_int(&event->flags32[0], 0)) {
recv_interrupt_page =
hv_vmbus_g_connection.recv_interrupt_page;
} else {
if (atomic_testandclear_int(&event->flags32[0], 0))
intr_page = hv_vmbus_g_connection.recv_interrupt_page;
else
return;
}
} else {
/*
* On Host with Win8 or above, the event page can be
* checked directly to get the id of the channel
* that has the pending interrupt.
*/
maxdword = HV_EVENT_FLAGS_DWORD_COUNT;
recv_interrupt_page = event->flags32;
page_cnt = HV_EVENT_FLAGS_ULONG_COUNT;
intr_page = event->flagsul;
}
/*
* Check events
*/
for (dword = 0; dword < maxdword; dword++) {
if (recv_interrupt_page[dword] == 0)
for (pg = 0; pg < page_cnt; pg++) {
uint32_t rel_id_base;
int bit;
if (intr_page[pg] == 0)
continue;
for (bit = 0; bit < HV_CHANNEL_DWORD_LEN; bit++) {
if (atomic_testandclear_int(
&recv_interrupt_page[dword], bit)) {
rel_id_base = pg << HV_CHANNEL_ULONG_SHIFT;
for (bit = 0; bit < HV_CHANNEL_ULONG_LEN; bit++) {
if (atomic_testandclear_long(&intr_page[pg], bit)) {
struct hv_vmbus_channel *channel;
uint32_t rel_id;
rel_id = (dword << 5) + bit;
rel_id = rel_id_base + bit;
channel =
hv_vmbus_g_connection.channels[rel_id];
@ -357,7 +357,7 @@ hv_vmbus_on_events(int cpu)
taskqueue_enqueue(channel->rxq,
&channel->channel_task);
}
}
}
}
}

View File

@ -57,10 +57,18 @@ typedef uint16_t hv_vmbus_status;
#define HV_EVENT_FLAGS_COUNT (256 * 8)
#define HV_EVENT_FLAGS_BYTE_COUNT (256)
#define HV_EVENT_FLAGS_DWORD_COUNT (256 / sizeof(uint32_t))
#define HV_EVENT_FLAGS_ULONG_COUNT (256 / sizeof(unsigned long))
/**
* max channel count <== event_flags_dword_count * bit_of_dword
*/
#ifdef __LP64__
#define HV_CHANNEL_ULONG_LEN (64)
#define HV_CHANNEL_ULONG_SHIFT (6)
#else
#define HV_CHANNEL_ULONG_LEN (32)
#define HV_CHANNEL_ULONG_SHIFT (5)
#endif
#define HV_CHANNEL_DWORD_LEN (32)
#define HV_CHANNEL_MAX_COUNT \
((HV_EVENT_FLAGS_DWORD_COUNT) * HV_CHANNEL_DWORD_LEN)
@ -575,7 +583,9 @@ typedef struct {
typedef union {
uint8_t flags8[HV_EVENT_FLAGS_BYTE_COUNT];
uint32_t flags32[HV_EVENT_FLAGS_DWORD_COUNT];
unsigned long flagsul[HV_EVENT_FLAGS_ULONG_COUNT];
} hv_vmbus_synic_event_flags;
CTASSERT(sizeof(hv_vmbus_synic_event_flags) == HV_EVENT_FLAGS_BYTE_COUNT);
#define HV_X64_CPUID_MIN (0x40000005)
#define HV_X64_CPUID_MAX (0x4000ffff)