Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 23 Jun 2016 06:18:33 +0000 (UTC)
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r302120 - stable/10/sys/dev/hyperv/vmbus
Message-ID:  <201606230618.u5N6IXwH097903@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Thu Jun 23 06:18:32 2016
New Revision: 302120
URL: https://svnweb.freebsd.org/changeset/base/302120

Log:
  MFC 300574
  
      hyperv/vmbus: Factor out functions for vmbus interrupt set/teardown
  
      This paves way for further cleanup and fix.
  
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D6505

Modified:
  stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c	Thu Jun 23 05:56:04 2016	(r302119)
+++ stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c	Thu Jun 23 06:18:32 2016	(r302120)
@@ -72,6 +72,8 @@ static int vmbus_inited;
 
 static char *vmbus_ids[] = { "VMBUS", NULL };
 
+extern inthand_t IDTVEC(rsvd), IDTVEC(hv_vmbus_callback);
+
 static void
 vmbus_msg_task(void *xsc, int pending __unused)
 {
@@ -360,6 +362,165 @@ vmbus_dma_free(struct vmbus_softc *sc)
 	}
 }
 
+/**
+ * @brief Find a free IDT slot and setup the interrupt handler.
+ */
+static int
+vmbus_vector_alloc(void)
+{
+	int vector;
+	uintptr_t func;
+	struct gate_descriptor *ip;
+
+	/*
+	 * Search backwards form the highest IDT vector available for use
+	 * as vmbus channel callback vector. We install 'hv_vmbus_callback'
+	 * handler at that vector and use it to interrupt vcpus.
+	 */
+	vector = APIC_SPURIOUS_INT;
+	while (--vector >= APIC_IPI_INTS) {
+		ip = &idt[vector];
+		func = ((long)ip->gd_hioffset << 16 | ip->gd_looffset);
+		if (func == (uintptr_t)&IDTVEC(rsvd)) {
+#ifdef __i386__
+			setidt(vector , IDTVEC(hv_vmbus_callback), SDT_SYS386IGT,
+			    SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+#else
+			setidt(vector , IDTVEC(hv_vmbus_callback), SDT_SYSIGT,
+			    SEL_KPL, 0);
+#endif
+
+			return (vector);
+		}
+	}
+	return (0);
+}
+
+/**
+ * @brief Restore the IDT slot to rsvd.
+ */
+static void
+vmbus_vector_free(int vector)
+{
+	uintptr_t func;
+	struct gate_descriptor *ip;
+
+	if (vector == 0)
+		return;
+
+	KASSERT(vector >= APIC_IPI_INTS && vector < APIC_SPURIOUS_INT,
+	    ("invalid vector %d", vector));
+
+	ip = &idt[vector];
+	func = ((long)ip->gd_hioffset << 16 | ip->gd_looffset);
+	KASSERT(func == (uintptr_t)&IDTVEC(hv_vmbus_callback),
+	    ("invalid vector %d", vector));
+
+	setidt(vector, IDTVEC(rsvd), SDT_SYSIGT, SEL_KPL, 0);
+}
+
+static void
+vmbus_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
+vmbus_intr_setup(struct vmbus_softc *sc)
+{
+	int cpu;
+
+	/*
+	 * Find a free IDT vector for vmbus messages/events.
+	 */
+	sc->vmbus_idtvec = vmbus_vector_alloc();
+	if (sc->vmbus_idtvec == 0) {
+		device_printf(sc->vmbus_dev, "cannot find free IDT vector\n");
+		return ENXIO;
+	}
+	if(bootverbose) {
+		device_printf(sc->vmbus_dev, "vmbus IDT vector %d\n",
+		    sc->vmbus_idtvec);
+	}
+
+	CPU_FOREACH(cpu) {
+		char buf[MAXCOMLEN + 1];
+
+		snprintf(buf, sizeof(buf), "cpu%d:hyperv", cpu);
+		intrcnt_add(buf, VMBUS_PCPU_PTR(sc, intr_cnt, cpu));
+	}
+
+	/*
+	 * Per cpu setup.
+	 */
+	CPU_FOREACH(cpu) {
+		struct task cpuset_task;
+		cpuset_t cpu_mask;
+
+		/*
+		 * Setup taskqueue to handle events
+		 */
+		hv_vmbus_g_context.hv_event_queue[cpu] =
+		    taskqueue_create_fast("hyperv event", M_WAITOK,
+		    taskqueue_thread_enqueue,
+		    &hv_vmbus_g_context.hv_event_queue[cpu]);
+		taskqueue_start_threads(&hv_vmbus_g_context.hv_event_queue[cpu],
+		    1, PI_NET, "hvevent%d", cpu);
+
+		CPU_SETOF(cpu, &cpu_mask);
+		TASK_INIT(&cpuset_task, 0, vmbus_cpuset_setthread_task,
+		    &cpu_mask);
+		taskqueue_enqueue(hv_vmbus_g_context.hv_event_queue[cpu],
+		    &cpuset_task);
+		taskqueue_drain(hv_vmbus_g_context.hv_event_queue[cpu],
+		    &cpuset_task);
+
+		/*
+		 * Setup per-cpu tasks and taskqueues to handle msg.
+		 */
+		hv_vmbus_g_context.hv_msg_tq[cpu] = taskqueue_create_fast(
+		    "hyperv msg", M_WAITOK, taskqueue_thread_enqueue,
+		    &hv_vmbus_g_context.hv_msg_tq[cpu]);
+		taskqueue_start_threads(&hv_vmbus_g_context.hv_msg_tq[cpu], 1,
+		    PI_NET, "hvmsg%d", cpu);
+		TASK_INIT(&hv_vmbus_g_context.hv_msg_task[cpu], 0,
+		    vmbus_msg_task, sc);
+
+		CPU_SETOF(cpu, &cpu_mask);
+		TASK_INIT(&cpuset_task, 0, vmbus_cpuset_setthread_task,
+		    &cpu_mask);
+		taskqueue_enqueue(hv_vmbus_g_context.hv_msg_tq[cpu],
+		    &cpuset_task);
+		taskqueue_drain(hv_vmbus_g_context.hv_msg_tq[cpu],
+		    &cpuset_task);
+	}
+	return 0;
+}
+
+static void
+vmbus_intr_teardown(struct vmbus_softc *sc)
+{
+	int cpu;
+
+	/*
+	 * remove swi and vmbus callback vector;
+	 */
+	CPU_FOREACH(cpu) {
+		if (hv_vmbus_g_context.hv_event_queue[cpu] != NULL) {
+			taskqueue_free(hv_vmbus_g_context.hv_event_queue[cpu]);
+			hv_vmbus_g_context.hv_event_queue[cpu] = NULL;
+		}
+	}
+	vmbus_vector_free(sc->vmbus_idtvec);
+}
+
 static int
 vmbus_read_ivar(
 	device_t	dev,
@@ -504,78 +665,6 @@ vmbus_probe(device_t dev)
 	return (BUS_PROBE_DEFAULT);
 }
 
-extern inthand_t IDTVEC(rsvd), IDTVEC(hv_vmbus_callback);
-
-/**
- * @brief Find a free IDT slot and setup the interrupt handler.
- */
-static int
-vmbus_vector_alloc(void)
-{
-	int vector;
-	uintptr_t func;
-	struct gate_descriptor *ip;
-
-	/*
-	 * Search backwards form the highest IDT vector available for use
-	 * as vmbus channel callback vector. We install 'hv_vmbus_callback'
-	 * handler at that vector and use it to interrupt vcpus.
-	 */
-	vector = APIC_SPURIOUS_INT;
-	while (--vector >= APIC_IPI_INTS) {
-		ip = &idt[vector];
-		func = ((long)ip->gd_hioffset << 16 | ip->gd_looffset);
-		if (func == (uintptr_t)&IDTVEC(rsvd)) {
-#ifdef __i386__
-			setidt(vector , IDTVEC(hv_vmbus_callback), SDT_SYS386IGT,
-			    SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
-#else
-			setidt(vector , IDTVEC(hv_vmbus_callback), SDT_SYSIGT,
-			    SEL_KPL, 0);
-#endif
-
-			return (vector);
-		}
-	}
-	return (0);
-}
-
-/**
- * @brief Restore the IDT slot to rsvd.
- */
-static void
-vmbus_vector_free(int vector)
-{
-        uintptr_t func;
-        struct gate_descriptor *ip;
-
-	if (vector == 0)
-		return;
-
-        KASSERT(vector >= APIC_IPI_INTS && vector < APIC_SPURIOUS_INT,
-            ("invalid vector %d", vector));
-
-        ip = &idt[vector];
-        func = ((long)ip->gd_hioffset << 16 | ip->gd_looffset);
-        KASSERT(func == (uintptr_t)&IDTVEC(hv_vmbus_callback),
-            ("invalid vector %d", vector));
-
-        setidt(vector, IDTVEC(rsvd), SDT_SYSIGT, SEL_KPL, 0);
-}
-
-static void
-vmbus_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);
-	}
-}
-
 /**
  * @brief Main vmbus driver initialization routine.
  *
@@ -592,9 +681,7 @@ static int
 vmbus_bus_init(void)
 {
 	struct vmbus_softc *sc;
-	int ret, cpu;
-	char buf[MAXCOMLEN + 1];
-	cpuset_t cpu_mask;
+	int ret;
 
 	if (vmbus_inited)
 		return (0);
@@ -603,70 +690,14 @@ vmbus_bus_init(void)
 	sc = vmbus_get_softc();
 
 	/*
-	 * Find a free IDT vector for vmbus messages/events.
+	 * Setup interrupt.
 	 */
-	sc->vmbus_idtvec = vmbus_vector_alloc();
-	if (sc->vmbus_idtvec == 0) {
-		device_printf(sc->vmbus_dev, "cannot find free IDT vector\n");
-		ret = ENXIO;
+	ret = vmbus_intr_setup(sc);
+	if (ret != 0)
 		goto cleanup;
-	}
-	if(bootverbose) {
-		device_printf(sc->vmbus_dev, "vmbus IDT vector %d\n",
-		    sc->vmbus_idtvec);
-	}
-
-	CPU_FOREACH(cpu) {
-		snprintf(buf, sizeof(buf), "cpu%d:hyperv", cpu);
-		intrcnt_add(buf, VMBUS_PCPU_PTR(sc, intr_cnt, cpu));
-	}
-
-	/*
-	 * Per cpu setup.
-	 */
-	CPU_FOREACH(cpu) {
-		struct task cpuset_task;
-
-		/*
-		 * Setup taskqueue to handle events
-		 */
-		hv_vmbus_g_context.hv_event_queue[cpu] =
-		    taskqueue_create_fast("hyperv event", M_WAITOK,
-		    taskqueue_thread_enqueue,
-		    &hv_vmbus_g_context.hv_event_queue[cpu]);
-		taskqueue_start_threads(&hv_vmbus_g_context.hv_event_queue[cpu],
-		    1, PI_NET, "hvevent%d", cpu);
-
-		CPU_SETOF(cpu, &cpu_mask);
-		TASK_INIT(&cpuset_task, 0, vmbus_cpuset_setthread_task,
-		    &cpu_mask);
-		taskqueue_enqueue(hv_vmbus_g_context.hv_event_queue[cpu],
-		    &cpuset_task);
-		taskqueue_drain(hv_vmbus_g_context.hv_event_queue[cpu],
-		    &cpuset_task);
-
-		/*
-		 * Setup per-cpu tasks and taskqueues to handle msg.
-		 */
-		hv_vmbus_g_context.hv_msg_tq[cpu] = taskqueue_create_fast(
-		    "hyperv msg", M_WAITOK, taskqueue_thread_enqueue,
-		    &hv_vmbus_g_context.hv_msg_tq[cpu]);
-		taskqueue_start_threads(&hv_vmbus_g_context.hv_msg_tq[cpu], 1,
-		    PI_NET, "hvmsg%d", cpu);
-		TASK_INIT(&hv_vmbus_g_context.hv_msg_task[cpu], 0,
-		    vmbus_msg_task, sc);
-
-		CPU_SETOF(cpu, &cpu_mask);
-		TASK_INIT(&cpuset_task, 0, vmbus_cpuset_setthread_task,
-		    &cpu_mask);
-		taskqueue_enqueue(hv_vmbus_g_context.hv_msg_tq[cpu],
-		    &cpuset_task);
-		taskqueue_drain(hv_vmbus_g_context.hv_msg_tq[cpu],
-		    &cpuset_task);
-	}
 
 	/*
-	 * Allocate vmbus DMA stuffs.
+	 * Allocate DMA stuffs.
 	 */
 	vmbus_dma_alloc(sc);
 
@@ -681,7 +712,7 @@ vmbus_bus_init(void)
 	ret = hv_vmbus_connect();
 
 	if (ret != 0)
-		goto cleanup1;
+		goto cleanup;
 
 	if (hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008 ||
 	    hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7)
@@ -697,22 +728,10 @@ vmbus_bus_init(void)
 
 	return (ret);
 
-cleanup1:
+cleanup:
 	vmbus_dma_free(sc);
+	vmbus_intr_teardown(sc);
 
-	/*
-	 * remove swi and vmbus callback vector;
-	 */
-	CPU_FOREACH(cpu) {
-		if (hv_vmbus_g_context.hv_event_queue[cpu] != NULL) {
-			taskqueue_free(hv_vmbus_g_context.hv_event_queue[cpu]);
-			hv_vmbus_g_context.hv_event_queue[cpu] = NULL;
-		}
-	}
-
-	vmbus_vector_free(sc->vmbus_idtvec);
-
-	cleanup:
 	return (ret);
 }
 
@@ -767,7 +786,6 @@ static int
 vmbus_detach(device_t dev)
 {
 	struct vmbus_softc *sc = device_get_softc(dev);
-	int i;
 
 	hv_vmbus_release_unattached_channels();
 	hv_vmbus_disconnect();
@@ -775,16 +793,7 @@ vmbus_detach(device_t dev)
 	smp_rendezvous(NULL, vmbus_synic_teardown, NULL, NULL);
 
 	vmbus_dma_free(sc);
-
-	/* remove swi */
-	CPU_FOREACH(i) {
-		if (hv_vmbus_g_context.hv_event_queue[i] != NULL) {
-			taskqueue_free(hv_vmbus_g_context.hv_event_queue[i]);
-			hv_vmbus_g_context.hv_event_queue[i] = NULL;
-		}
-	}
-
-	vmbus_vector_free(sc->vmbus_idtvec);
+	vmbus_intr_teardown(sc);
 
 	return (0);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201606230618.u5N6IXwH097903>