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