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
This commit is contained in:
Sepherosa Ziehau 2016-05-24 06:42:14 +00:00
parent bcc9e3e995
commit b28956a456

View File

@ -72,6 +72,8 @@ static int vmbus_inited;
static char *vmbus_ids[] = { "VMBUS", NULL };
extern inthand_t IDTVEC(hv_vmbus_callback);
static void
vmbus_msg_task(void *xsc, int pending __unused)
{
@ -360,6 +362,82 @@ vmbus_dma_free(struct vmbus_softc *sc)
}
}
static int
vmbus_intr_setup(struct vmbus_softc *sc)
{
int cpu;
/*
* Find a free IDT vector for vmbus messages/events.
*/
sc->vmbus_idtvec = lapic_ipi_alloc(IDTVEC(hv_vmbus_callback));
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) {
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]);
CPU_SETOF(cpu, &cpu_mask);
taskqueue_start_threads_cpuset(
&hv_vmbus_g_context.hv_event_queue[cpu], 1, PI_NET,
&cpu_mask, "hvevent%d", cpu);
/*
* 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]);
CPU_SETOF(cpu, &cpu_mask);
taskqueue_start_threads_cpuset(
&hv_vmbus_g_context.hv_msg_tq[cpu], 1, PI_NET,
&cpu_mask, "hvmsg%d", cpu);
TASK_INIT(&hv_vmbus_g_context.hv_msg_task[cpu], 0,
vmbus_msg_task, sc);
}
return 0;
}
static void
vmbus_intr_teardown(struct vmbus_softc *sc)
{
int cpu;
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;
}
}
if (sc->vmbus_idtvec >= 0) {
lapic_ipi_free(sc->vmbus_idtvec);
sc->vmbus_idtvec = -1;
}
}
static int
vmbus_read_ivar(
device_t dev,
@ -504,8 +582,6 @@ vmbus_probe(device_t dev)
return (BUS_PROBE_DEFAULT);
}
extern inthand_t IDTVEC(hv_vmbus_callback);
/**
* @brief Main vmbus driver initialization routine.
*
@ -522,9 +598,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);
@ -533,56 +607,14 @@ vmbus_bus_init(void)
sc = vmbus_get_softc();
/*
* Find a free IDT vector for vmbus messages/events.
* Setup interrupt.
*/
sc->vmbus_idtvec = lapic_ipi_alloc(IDTVEC(hv_vmbus_callback));
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) {
/*
* 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]);
CPU_SETOF(cpu, &cpu_mask);
taskqueue_start_threads_cpuset(
&hv_vmbus_g_context.hv_event_queue[cpu], 1, PI_NET,
&cpu_mask, "hvevent%d", cpu);
/*
* 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]);
CPU_SETOF(cpu, &cpu_mask);
taskqueue_start_threads_cpuset(
&hv_vmbus_g_context.hv_msg_tq[cpu], 1, PI_NET,
&cpu_mask, "hvmsg%d", cpu);
TASK_INIT(&hv_vmbus_g_context.hv_msg_task[cpu], 0,
vmbus_msg_task, sc);
}
/*
* Allocate vmbus DMA stuffs.
* Allocate DMA stuffs.
*/
vmbus_dma_alloc(sc);
@ -597,7 +629,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)
@ -613,22 +645,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;
}
}
lapic_ipi_free(sc->vmbus_idtvec);
cleanup:
return (ret);
}
@ -642,6 +662,7 @@ vmbus_attach(device_t dev)
{
vmbus_sc = device_get_softc(dev);
vmbus_sc->vmbus_dev = dev;
vmbus_sc->vmbus_idtvec = -1;
/*
* Event processing logic will be configured:
@ -687,7 +708,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();
@ -695,16 +715,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;
}
}
lapic_ipi_free(sc->vmbus_idtvec);
vmbus_intr_teardown(sc);
return (0);
}