summaryrefslogtreecommitdiffstats
path: root/sys/dev/hyperv/vmbus
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/hyperv/vmbus')
-rw-r--r--sys/dev/hyperv/vmbus/hv_channel_mgmt.c21
-rw-r--r--sys/dev/hyperv/vmbus/hv_connection.c38
-rw-r--r--sys/dev/hyperv/vmbus/hv_vmbus_priv.h11
3 files changed, 32 insertions, 38 deletions
diff --git a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
index c7f3538..4ccb647 100644
--- a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
+++ b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
@@ -274,14 +274,16 @@ vmbus_channel_process_offer(hv_vmbus_channel *new_channel)
boolean_t f_new;
hv_vmbus_channel* channel;
int ret;
+ uint32_t relid;
f_new = TRUE;
channel = NULL;
-
+ relid = new_channel->offer_msg.child_rel_id;
/*
* Make sure this is a new offer
*/
mtx_lock(&hv_vmbus_g_connection.channel_lock);
+ hv_vmbus_g_connection.channels[relid] = new_channel;
TAILQ_FOREACH(channel, &hv_vmbus_g_connection.channel_anchor,
list_entry)
@@ -325,16 +327,18 @@ vmbus_channel_process_offer(hv_vmbus_channel *new_channel)
mtx_unlock(&channel->sc_lock);
/* Insert new channel into channel_anchor. */
- printf("Storvsc get multi-channel offer, rel=%u.\n",
- new_channel->offer_msg.child_rel_id);
+ printf("VMBUS get multi-channel offer, rel=%u,sub=%u\n",
+ new_channel->offer_msg.child_rel_id,
+ new_channel->offer_msg.offer.sub_channel_index);
mtx_lock(&hv_vmbus_g_connection.channel_lock);
TAILQ_INSERT_TAIL(&hv_vmbus_g_connection.channel_anchor,
new_channel, list_entry);
mtx_unlock(&hv_vmbus_g_connection.channel_lock);
if(bootverbose)
- printf("VMBUS: new multi-channel offer <%p>.\n",
- new_channel);
+ printf("VMBUS: new multi-channel offer <%p>, "
+ "its primary channel is <%p>.\n",
+ new_channel, new_channel->primary_channel);
/*XXX add it to percpu_list */
@@ -524,11 +528,14 @@ vmbus_channel_on_offer_rescind(hv_vmbus_channel_msg_header* hdr)
rescind = (hv_vmbus_channel_rescind_offer*) hdr;
- channel = hv_vmbus_get_channel_from_rel_id(rescind->child_rel_id);
+ channel = hv_vmbus_g_connection.channels[rescind->child_rel_id];
if (channel == NULL)
return;
hv_vmbus_child_device_unregister(channel->device);
+ mtx_lock(&hv_vmbus_g_connection.channel_lock);
+ hv_vmbus_g_connection.channels[rescind->child_rel_id] = NULL;
+ mtx_unlock(&hv_vmbus_g_connection.channel_lock);
}
/**
@@ -782,6 +789,8 @@ hv_vmbus_release_unattached_channels(void)
hv_vmbus_child_device_unregister(channel->device);
hv_vmbus_free_vmbus_channel(channel);
}
+ bzero(hv_vmbus_g_connection.channels,
+ sizeof(hv_vmbus_channel*) * HV_CHANNEL_MAX_COUNT);
mtx_unlock(&hv_vmbus_g_connection.channel_lock);
}
diff --git a/sys/dev/hyperv/vmbus/hv_connection.c b/sys/dev/hyperv/vmbus/hv_connection.c
index 7496288..a9e3561 100644
--- a/sys/dev/hyperv/vmbus/hv_connection.c
+++ b/sys/dev/hyperv/vmbus/hv_connection.c
@@ -232,6 +232,9 @@ hv_vmbus_connect(void) {
goto cleanup;
}
+ hv_vmbus_g_connection.channels = malloc(sizeof(hv_vmbus_channel*) *
+ HV_CHANNEL_MAX_COUNT,
+ M_DEVBUF, M_WAITOK | M_ZERO);
/*
* Find the highest vmbus version number we can support.
*/
@@ -295,6 +298,7 @@ hv_vmbus_connect(void) {
free(msg_info, M_DEVBUF);
}
+ free(hv_vmbus_g_connection.channels, M_DEVBUF);
return (ret);
}
@@ -325,6 +329,7 @@ hv_vmbus_disconnect(void) {
hv_work_queue_close(hv_vmbus_g_connection.work_queue);
sema_destroy(&hv_vmbus_g_connection.control_sema);
+ free(hv_vmbus_g_connection.channels, M_DEVBUF);
hv_vmbus_g_connection.connect_state = HV_DISCONNECTED;
free(msg, M_DEVBUF);
@@ -333,35 +338,6 @@ hv_vmbus_disconnect(void) {
}
/**
- * Get the channel object given its child relative id (ie channel id)
- */
-hv_vmbus_channel*
-hv_vmbus_get_channel_from_rel_id(uint32_t rel_id) {
-
- hv_vmbus_channel* channel;
- hv_vmbus_channel* foundChannel = NULL;
-
- /*
- * TODO:
- * Consider optimization where relids are stored in a fixed size array
- * and channels are accessed without the need to take this lock or search
- * the list.
- */
- mtx_lock(&hv_vmbus_g_connection.channel_lock);
- TAILQ_FOREACH(channel,
- &hv_vmbus_g_connection.channel_anchor, list_entry) {
-
- if (channel->offer_msg.child_rel_id == rel_id) {
- foundChannel = channel;
- break;
- }
- }
- mtx_unlock(&hv_vmbus_g_connection.channel_lock);
-
- return (foundChannel);
-}
-
-/**
* Process a channel event notification
*/
static void
@@ -377,7 +353,7 @@ VmbusProcessChannelEvent(uint32_t relid)
* the channel callback to process the event
*/
- channel = hv_vmbus_get_channel_from_rel_id(relid);
+ channel = hv_vmbus_g_connection.channels[relid];
if (channel == NULL) {
return;
@@ -473,7 +449,7 @@ hv_vmbus_on_events(void *arg)
if (recv_interrupt_page != NULL) {
for (dword = 0; dword < maxdword; dword++) {
if (recv_interrupt_page[dword]) {
- for (bit = 0; bit < 32; bit++) {
+ for (bit = 0; bit < HV_CHANNEL_DWORD_LEN; bit++) {
if (synch_test_and_clear_bit(bit,
(uint32_t *) &recv_interrupt_page[dword])) {
rel_id = (dword << 5) + bit;
diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
index 74fe824..13a35c4 100644
--- a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
+++ b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
@@ -58,6 +58,12 @@ typedef uint16_t hv_vmbus_status;
#define HV_EVENT_FLAGS_BYTE_COUNT (256)
#define HV_EVENT_FLAGS_DWORD_COUNT (256 / sizeof(uint32_t))
+/**
+ * max channel count <== event_flags_dword_count * bit_of_dword
+ */
+#define HV_CHANNEL_DWORD_LEN (32)
+#define HV_CHANNEL_MAX_COUNT \
+ ((HV_EVENT_FLAGS_DWORD_COUNT) * HV_CHANNEL_DWORD_LEN)
/*
* MessageId: HV_STATUS_INSUFFICIENT_BUFFERS
* MessageText:
@@ -355,6 +361,10 @@ typedef struct {
TAILQ_HEAD(, hv_vmbus_channel) channel_anchor;
struct mtx channel_lock;
+ /**
+ * channel table for fast lookup through id.
+ */
+ hv_vmbus_channel **channels;
hv_vmbus_handle work_queue;
struct sema control_sema;
} hv_vmbus_connection;
@@ -699,7 +709,6 @@ int hv_vmbus_child_device_register(
struct hv_device *child_dev);
int hv_vmbus_child_device_unregister(
struct hv_device *child_dev);
-hv_vmbus_channel* hv_vmbus_get_channel_from_rel_id(uint32_t rel_id);
/**
* Connection interfaces
OpenPOWER on IntegriCloud