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);
 }
 
 /**
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to