svn commit: r310768 - in stable/10/sys/dev/hyperv: netvsc vmbus

Sepherosa Ziehau sephe at FreeBSD.org
Thu Dec 29 09:02:51 UTC 2016


Author: sephe
Date: Thu Dec 29 09:02:49 2016
New Revision: 310768
URL: https://svnweb.freebsd.org/changeset/base/310768

Log:
  MFC 309310,309311,309316,309318
  
  309310
      hyperv/hn: Nuke the unused TX taskqueue CPU binding tunable.
  
      It was an experimental tunable, and is now deemed to be road blocker
      for further changes.  Time to retire it.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D8654
  
  309311
      hyperv/hn: Allow multiple TX taskqueues.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D8655
  
  309316
      hyperv/vmbus: Add DEVMETHOD to map cpu to event taskq.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D8658
  
  309318
      hyperv/hn: Allow TX to share event taskqueues.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D8659

Modified:
  stable/10/sys/dev/hyperv/netvsc/if_hn.c
  stable/10/sys/dev/hyperv/netvsc/if_hnvar.h
  stable/10/sys/dev/hyperv/vmbus/vmbus.c
  stable/10/sys/dev/hyperv/vmbus/vmbus_if.m
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/hyperv/netvsc/if_hn.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/if_hn.c	Thu Dec 29 08:41:25 2016	(r310767)
+++ stable/10/sys/dev/hyperv/netvsc/if_hn.c	Thu Dec 29 09:02:49 2016	(r310768)
@@ -172,6 +172,8 @@ do {							\
 #define HN_PKTSIZE(m, align)		\
 	roundup2((m)->m_pkthdr.len + HN_RNDIS_PKT_LEN, (align))
 
+#define HN_RING_IDX2CPU(sc, idx)	(((sc)->hn_cpu + (idx)) % mp_ncpus)
+
 struct hn_txdesc {
 #ifndef HN_USE_TXDESC_BUFRING
 	SLIST_ENTRY(hn_txdesc)		link;
@@ -414,10 +416,18 @@ SYSCTL_INT(_hw_hn, OID_AUTO, lro_entry_c
 #endif
 #endif
 
-/* Use shared TX taskqueue */
-static int			hn_share_tx_taskq = 0;
-SYSCTL_INT(_hw_hn, OID_AUTO, share_tx_taskq, CTLFLAG_RDTUN,
-    &hn_share_tx_taskq, 0, "Enable shared TX taskqueue");
+static int			hn_tx_taskq_cnt = 1;
+SYSCTL_INT(_hw_hn, OID_AUTO, tx_taskq_cnt, CTLFLAG_RDTUN,
+    &hn_tx_taskq_cnt, 0, "# of TX taskqueues");
+
+#define HN_TX_TASKQ_M_INDEP	0
+#define HN_TX_TASKQ_M_GLOBAL	1
+#define HN_TX_TASKQ_M_EVTTQ	2
+
+static int			hn_tx_taskq_mode = HN_TX_TASKQ_M_INDEP;
+SYSCTL_INT(_hw_hn, OID_AUTO, tx_taskq_mode, CTLFLAG_RDTUN,
+    &hn_tx_taskq_mode, 0, "TX taskqueue modes: "
+    "0 - independent, 1 - share global tx taskqs, 2 - share event taskqs");
 
 #ifndef HN_USE_TXDESC_BUFRING
 static int			hn_use_txdesc_bufring = 0;
@@ -427,11 +437,6 @@ static int			hn_use_txdesc_bufring = 1;
 SYSCTL_INT(_hw_hn, OID_AUTO, use_txdesc_bufring, CTLFLAG_RD,
     &hn_use_txdesc_bufring, 0, "Use buf_ring for TX descriptors");
 
-/* Bind TX taskqueue to the target CPU */
-static int			hn_bind_tx_taskq = -1;
-SYSCTL_INT(_hw_hn, OID_AUTO, bind_tx_taskq, CTLFLAG_RDTUN,
-    &hn_bind_tx_taskq, 0, "Bind TX taskqueue to the specified cpu");
-
 #ifdef HN_IFSTART_SUPPORT
 /* Use ifnet.if_start instead of ifnet.if_transmit */
 static int			hn_use_if_start = 0;
@@ -473,7 +478,7 @@ SYSCTL_INT(_hw_hn, OID_AUTO, tx_agg_pkts
     &hn_tx_agg_pkts, 0, "Packet transmission aggregation packet limit");
 
 static u_int			hn_cpu_index;	/* next CPU for channel */
-static struct taskqueue		*hn_tx_taskq;	/* shared TX taskqueue */
+static struct taskqueue		**hn_tx_taskque;/* shared TX taskqueues */
 
 static const uint8_t
 hn_rss_key_default[NDIS_HASH_KEYSIZE_TOEPLITZ] = {
@@ -883,19 +888,6 @@ hn_probe(device_t dev)
 	return ENXIO;
 }
 
-static void
-hn_cpuset_setthread_task(void *xmask, int pending __unused)
-{
-	cpuset_t *mask = xmask;
-	int error;
-
-	error = cpuset_setthread(curthread->td_tid, mask);
-	if (error) {
-		panic("curthread=%ju: can't pin; error=%d",
-		    (uintmax_t)curthread->td_tid, error);
-	}
-}
-
 static int
 hn_attach(device_t dev)
 {
@@ -919,26 +911,21 @@ hn_attach(device_t dev)
 	/*
 	 * Setup taskqueue for transmission.
 	 */
-	if (hn_tx_taskq == NULL) {
-		sc->hn_tx_taskq = taskqueue_create("hn_tx", M_WAITOK,
-		    taskqueue_thread_enqueue, &sc->hn_tx_taskq);
-		taskqueue_start_threads(&sc->hn_tx_taskq, 1, PI_NET, "%s tx",
-		    device_get_nameunit(dev));
-		if (hn_bind_tx_taskq >= 0) {
-			int cpu = hn_bind_tx_taskq;
-			struct task cpuset_task;
-			cpuset_t cpu_set;
-
-			if (cpu > mp_ncpus - 1)
-				cpu = mp_ncpus - 1;
-			CPU_SETOF(cpu, &cpu_set);
-			TASK_INIT(&cpuset_task, 0, hn_cpuset_setthread_task,
-			    &cpu_set);
-			taskqueue_enqueue(sc->hn_tx_taskq, &cpuset_task);
-			taskqueue_drain(sc->hn_tx_taskq, &cpuset_task);
+	if (hn_tx_taskq_mode == HN_TX_TASKQ_M_INDEP) {
+		int i;
+
+		sc->hn_tx_taskqs =
+		    malloc(hn_tx_taskq_cnt * sizeof(struct taskqueue *),
+		    M_DEVBUF, M_WAITOK);
+		for (i = 0; i < hn_tx_taskq_cnt; ++i) {
+			sc->hn_tx_taskqs[i] = taskqueue_create("hn_tx",
+			    M_WAITOK, taskqueue_thread_enqueue,
+			    &sc->hn_tx_taskqs[i]);
+			taskqueue_start_threads(&sc->hn_tx_taskqs[i], 1, PI_NET,
+			    "%s tx%d", device_get_nameunit(dev), i);
 		}
-	} else {
-		sc->hn_tx_taskq = hn_tx_taskq;
+	} else if (hn_tx_taskq_mode == HN_TX_TASKQ_M_GLOBAL) {
+		sc->hn_tx_taskqs = hn_tx_taskque;
 	}
 
 	/*
@@ -1243,8 +1230,13 @@ hn_detach(device_t dev)
 	hn_destroy_rx_data(sc);
 	hn_destroy_tx_data(sc);
 
-	if (sc->hn_tx_taskq != hn_tx_taskq)
-		taskqueue_free(sc->hn_tx_taskq);
+	if (sc->hn_tx_taskqs != NULL && sc->hn_tx_taskqs != hn_tx_taskque) {
+		int i;
+
+		for (i = 0; i < hn_tx_taskq_cnt; ++i)
+			taskqueue_free(sc->hn_tx_taskqs[i]);
+		free(sc->hn_tx_taskqs, M_DEVBUF);
+	}
 	taskqueue_free(sc->hn_mgmt_taskq0);
 
 	if (sc->hn_xact != NULL) {
@@ -3338,7 +3330,12 @@ hn_tx_ring_create(struct hn_softc *sc, i
 	    M_WAITOK, &txr->hn_tx_lock);
 #endif
 
-	txr->hn_tx_taskq = sc->hn_tx_taskq;
+	if (hn_tx_taskq_mode == HN_TX_TASKQ_M_EVTTQ) {
+		txr->hn_tx_taskq = VMBUS_GET_EVENT_TASKQ(
+		    device_get_parent(dev), dev, HN_RING_IDX2CPU(sc, id));
+	} else {
+		txr->hn_tx_taskq = sc->hn_tx_taskqs[id % hn_tx_taskq_cnt];
+	}
 
 #ifdef HN_IFSTART_SUPPORT
 	if (hn_use_if_start) {
@@ -4231,7 +4228,7 @@ hn_chan_attach(struct hn_softc *sc, stru
 	}
 
 	/* Bind this channel to a proper CPU. */
-	vmbus_chan_cpu_set(chan, (sc->hn_cpu + idx) % mp_ncpus);
+	vmbus_chan_cpu_set(chan, HN_RING_IDX2CPU(sc, idx));
 
 	/*
 	 * Open this channel
@@ -5377,27 +5374,42 @@ hn_chan_callback(struct vmbus_channel *c
 static void
 hn_tx_taskq_create(void *arg __unused)
 {
+	int i;
+
+	/*
+	 * Fix the # of TX taskqueues.
+	 */
+	if (hn_tx_taskq_cnt <= 0)
+		hn_tx_taskq_cnt = 1;
+	else if (hn_tx_taskq_cnt > mp_ncpus)
+		hn_tx_taskq_cnt = mp_ncpus;
+
+	/*
+	 * Fix the TX taskqueue mode.
+	 */
+	switch (hn_tx_taskq_mode) {
+	case HN_TX_TASKQ_M_INDEP:
+	case HN_TX_TASKQ_M_GLOBAL:
+	case HN_TX_TASKQ_M_EVTTQ:
+		break;
+	default:
+		hn_tx_taskq_mode = HN_TX_TASKQ_M_INDEP;
+		break;
+	}
 
 	if (vm_guest != VM_GUEST_HV)
 		return;
 
-	if (!hn_share_tx_taskq)
+	if (hn_tx_taskq_mode != HN_TX_TASKQ_M_GLOBAL)
 		return;
 
-	hn_tx_taskq = taskqueue_create("hn_tx", M_WAITOK,
-	    taskqueue_thread_enqueue, &hn_tx_taskq);
-	taskqueue_start_threads(&hn_tx_taskq, 1, PI_NET, "hn tx");
-	if (hn_bind_tx_taskq >= 0) {
-		int cpu = hn_bind_tx_taskq;
-		struct task cpuset_task;
-		cpuset_t cpu_set;
-
-		if (cpu > mp_ncpus - 1)
-			cpu = mp_ncpus - 1;
-		CPU_SETOF(cpu, &cpu_set);
-		TASK_INIT(&cpuset_task, 0, hn_cpuset_setthread_task, &cpu_set);
-		taskqueue_enqueue(hn_tx_taskq, &cpuset_task);
-		taskqueue_drain(hn_tx_taskq, &cpuset_task);
+	hn_tx_taskque = malloc(hn_tx_taskq_cnt * sizeof(struct taskqueue *),
+	    M_DEVBUF, M_WAITOK);
+	for (i = 0; i < hn_tx_taskq_cnt; ++i) {
+		hn_tx_taskque[i] = taskqueue_create("hn_tx", M_WAITOK,
+		    taskqueue_thread_enqueue, &hn_tx_taskque[i]);
+		taskqueue_start_threads(&hn_tx_taskque[i], 1, PI_NET,
+		    "hn tx%d", i);
 	}
 }
 SYSINIT(hn_txtq_create, SI_SUB_DRIVERS, SI_ORDER_SECOND,
@@ -5407,8 +5419,13 @@ static void
 hn_tx_taskq_destroy(void *arg __unused)
 {
 
-	if (hn_tx_taskq != NULL)
-		taskqueue_free(hn_tx_taskq);
+	if (hn_tx_taskque != NULL) {
+		int i;
+
+		for (i = 0; i < hn_tx_taskq_cnt; ++i)
+			taskqueue_free(hn_tx_taskque[i]);
+		free(hn_tx_taskque, M_DEVBUF);
+	}
 }
 SYSUNINIT(hn_txtq_destroy, SI_SUB_DRIVERS, SI_ORDER_SECOND,
     hn_tx_taskq_destroy, NULL);

Modified: stable/10/sys/dev/hyperv/netvsc/if_hnvar.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/if_hnvar.h	Thu Dec 29 08:41:25 2016	(r310767)
+++ stable/10/sys/dev/hyperv/netvsc/if_hnvar.h	Thu Dec 29 09:02:49 2016	(r310768)
@@ -193,7 +193,7 @@ struct hn_softc {
 	int		hn_chim_szmax;
 
 	int		hn_cpu;
-	struct taskqueue *hn_tx_taskq;
+	struct taskqueue **hn_tx_taskqs;
 	struct sysctl_oid *hn_tx_sysctl_tree;
 	struct sysctl_oid *hn_rx_sysctl_tree;
 	struct vmbus_xact_ctx *hn_xact;

Modified: stable/10/sys/dev/hyperv/vmbus/vmbus.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/vmbus.c	Thu Dec 29 08:41:25 2016	(r310767)
+++ stable/10/sys/dev/hyperv/vmbus/vmbus.c	Thu Dec 29 09:02:49 2016	(r310768)
@@ -99,6 +99,8 @@ static int			vmbus_probe_guid_method(dev
 				    const struct hyperv_guid *);
 static uint32_t			vmbus_get_vcpu_id_method(device_t bus,
 				    device_t dev, int cpu);
+static struct taskqueue		*vmbus_get_eventtq_method(device_t, device_t,
+				    int);
 
 static int			vmbus_init(struct vmbus_softc *);
 static int			vmbus_connect(struct vmbus_softc *, uint32_t);
@@ -174,6 +176,7 @@ static device_method_t vmbus_methods[] =
 	DEVMETHOD(vmbus_get_version,		vmbus_get_version_method),
 	DEVMETHOD(vmbus_probe_guid,		vmbus_probe_guid_method),
 	DEVMETHOD(vmbus_get_vcpu_id,		vmbus_get_vcpu_id_method),
+	DEVMETHOD(vmbus_get_event_taskq,	vmbus_get_eventtq_method),
 
 	DEVMETHOD_END
 };
@@ -1208,6 +1211,15 @@ vmbus_get_vcpu_id_method(device_t bus, d
 	return (VMBUS_PCPU_GET(sc, vcpuid, cpu));
 }
 
+static struct taskqueue *
+vmbus_get_eventtq_method(device_t bus, device_t dev __unused, int cpu)
+{
+	const struct vmbus_softc *sc = device_get_softc(bus);
+
+	KASSERT(cpu >= 0 && cpu < mp_ncpus, ("invalid cpu%d", cpu));
+	return (VMBUS_PCPU_GET(sc, event_tq, cpu));
+}
+
 #ifdef NEW_PCIB
 #define VTPM_BASE_ADDR 0xfed40000
 #define FOUR_GB (1ULL << 32)

Modified: stable/10/sys/dev/hyperv/vmbus/vmbus_if.m
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/vmbus_if.m	Thu Dec 29 08:41:25 2016	(r310767)
+++ stable/10/sys/dev/hyperv/vmbus/vmbus_if.m	Thu Dec 29 09:02:49 2016	(r310768)
@@ -33,6 +33,7 @@ INTERFACE vmbus;
 
 HEADER {
 	struct hyperv_guid;
+	struct taskqueue;
 };
 
 METHOD uint32_t get_version {
@@ -51,3 +52,9 @@ METHOD uint32_t get_vcpu_id {
 	device_t dev;
 	int cpu;
 };
+
+METHOD struct taskqueue * get_event_taskq {
+	device_t bus;
+	device_t dev;
+	int cpu;
+};


More information about the svn-src-all mailing list