summaryrefslogtreecommitdiffstats
path: root/sys/dev/hyperv/vmbus
diff options
context:
space:
mode:
authorsephe <sephe@FreeBSD.org>2016-02-24 01:30:50 +0000
committersephe <sephe@FreeBSD.org>2016-02-24 01:30:50 +0000
commit63b2f3db69ed14038164268fb5c942d5f7a3d8b4 (patch)
treedb6c17ce357be96a5512942c378ee8d278bc7990 /sys/dev/hyperv/vmbus
parent257e82612c2ce6368f8fbbfa099f699c85f3a718 (diff)
downloadFreeBSD-src-63b2f3db69ed14038164268fb5c942d5f7a3d8b4.zip
FreeBSD-src-63b2f3db69ed14038164268fb5c942d5f7a3d8b4.tar.gz
MFC [Hyper-V]: r294553, r294700
r294553 hyperv/vmbus: Lookup channel through id table Vmbus event handler will need to find the channel by its relative id, when software interrupt for event happens. The original lookup searches the channel list, which is not very efficient. We now create a table indexed by the channel relative id to speed up the channel lookup. Submitted by: Hongjiang Zhang <honzhan microsoft com> Reviewed by: delphij, adrain, sephe, Dexuan Cui <decui microsoft com> Approved by: adrian (mentor) Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D4802 ------------- r294700 hyperv/hn: Partly rework transmission path - Avoid unnecessary malloc/free on transmission path. - busdma(9)-fy transmission path. - Properly handle IFF_DRV_OACTIVE. This should fix the network stalls reported by many. - Properly setup TSO parameters. - Properly handle bpf(4) tapping. This 5 times the performance during TCP sending test, when there is one bpf(4) attached. - Allow size of chimney sending be tuned on a running system. Default value still needs more test to determine. Reviewed by: adrian, delphij Approved by: adrian (mentor) Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D4972 Approved by: re (marius) Sponsored by: Microsoft OSTC
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