svn commit: r302621 - in head/sys/dev/hyperv: include storvsc vmbus
Sepherosa Ziehau
sephe at FreeBSD.org
Tue Jul 12 05:31:34 UTC 2016
Author: sephe
Date: Tue Jul 12 05:31:33 2016
New Revision: 302621
URL: https://svnweb.freebsd.org/changeset/base/302621
Log:
hyperv/vmbus: Don't be oversmart in default cpu selection.
Pin the channel to cpu0 by default. Drivers having special channel-cpu
mapping requirement should call vmbus_channel_cpu_{set,rr}() themselves.
MFC after: 1 week
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6918
Modified:
head/sys/dev/hyperv/include/hyperv.h
head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
head/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
Modified: head/sys/dev/hyperv/include/hyperv.h
==============================================================================
--- head/sys/dev/hyperv/include/hyperv.h Tue Jul 12 05:23:14 2016 (r302620)
+++ head/sys/dev/hyperv/include/hyperv.h Tue Jul 12 05:31:33 2016 (r302621)
@@ -707,6 +707,7 @@ int hv_vmbus_channel_teardown_gpdal(
struct hv_vmbus_channel* vmbus_select_outgoing_channel(struct hv_vmbus_channel *promary);
void vmbus_channel_cpu_set(struct hv_vmbus_channel *chan, int cpu);
+void vmbus_channel_cpu_rr(struct hv_vmbus_channel *chan);
struct hv_vmbus_channel **
vmbus_get_subchan(struct hv_vmbus_channel *pri_chan, int subchan_cnt);
void vmbus_rel_subchan(struct hv_vmbus_channel **subchan, int subchan_cnt);
Modified: head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
==============================================================================
--- head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c Tue Jul 12 05:23:14 2016 (r302620)
+++ head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c Tue Jul 12 05:31:33 2016 (r302621)
@@ -361,6 +361,7 @@ storvsc_subchan_attach(struct hv_vmbus_c
memset(&props, 0, sizeof(props));
+ vmbus_channel_cpu_rr(new_channel);
ret = hv_vmbus_channel_open(new_channel,
sc->hs_drv_props->drv_ringbuffer_size,
sc->hs_drv_props->drv_ringbuffer_size,
@@ -655,7 +656,7 @@ hv_storvsc_connect_vsp(struct hv_device
/*
* Open the channel
*/
-
+ vmbus_channel_cpu_rr(dev->channel);
ret = hv_vmbus_channel_open(
dev->channel,
sc->hs_drv_props->drv_ringbuffer_size,
Modified: head/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_channel_mgmt.c Tue Jul 12 05:23:14 2016 (r302620)
+++ head/sys/dev/hyperv/vmbus/hv_channel_mgmt.c Tue Jul 12 05:31:33 2016 (r302621)
@@ -238,61 +238,25 @@ vmbus_channel_cpu_set(struct hv_vmbus_ch
}
}
-/**
- * Array of device guids that are performance critical. We try to distribute
- * the interrupt load for these devices across all online cpus.
- */
-static const hv_guid high_perf_devices[] = {
- {HV_NIC_GUID, },
- {HV_IDE_GUID, },
- {HV_SCSI_GUID, },
-};
-
-enum {
- PERF_CHN_NIC = 0,
- PERF_CHN_IDE,
- PERF_CHN_SCSI,
- MAX_PERF_CHN,
-};
+void
+vmbus_channel_cpu_rr(struct hv_vmbus_channel *chan)
+{
+ static uint32_t vmbus_chan_nextcpu;
+ int cpu;
-/*
- * We use this static number to distribute the channel interrupt load.
- */
-static uint32_t next_vcpu;
+ cpu = atomic_fetchadd_int(&vmbus_chan_nextcpu, 1) % mp_ncpus;
+ vmbus_channel_cpu_set(chan, cpu);
+}
-/**
- * Starting with Win8, we can statically distribute the incoming
- * channel interrupt load by binding a channel to VCPU. We
- * implement here a simple round robin scheme for distributing
- * the interrupt load.
- * We will bind channels that are not performance critical to cpu 0 and
- * performance critical channels (IDE, SCSI and Network) will be uniformly
- * distributed across all available CPUs.
- */
static void
-vmbus_channel_select_defcpu(struct hv_vmbus_channel *channel)
+vmbus_channel_select_defcpu(struct hv_vmbus_channel *chan)
{
- uint32_t current_cpu;
- int i;
- boolean_t is_perf_channel = FALSE;
- const hv_guid *guid = &channel->offer_msg.offer.interface_type;
-
- for (i = PERF_CHN_NIC; i < MAX_PERF_CHN; i++) {
- if (memcmp(guid->data, high_perf_devices[i].data,
- sizeof(hv_guid)) == 0) {
- is_perf_channel = TRUE;
- break;
- }
- }
-
- if (!is_perf_channel) {
- /* Stick to cpu0 */
- vmbus_channel_cpu_set(channel, 0);
- return;
- }
- /* mp_ncpus should have the number cpus currently online */
- current_cpu = (++next_vcpu % mp_ncpus);
- vmbus_channel_cpu_set(channel, current_cpu);
+ /*
+ * By default, pin the channel to cpu0. Devices having
+ * special channel-cpu mapping requirement should call
+ * vmbus_channel_cpu_{set,rr}().
+ */
+ vmbus_channel_cpu_set(chan, 0);
}
/**
More information about the svn-src-all
mailing list