static int sfxge_intr_bus_enable(struct sfxge_softc *sc) { struct sfxge_intr *intr; struct sfxge_intr_hdl *table; driver_filter_t *filter; driver_intr_t *handler; int index; int err; intr = &sc->intr; table = intr->table; switch (intr->type) { case EFX_INTR_MESSAGE: filter = NULL; /* not shared */ handler = sfxge_intr_message; break; case EFX_INTR_LINE: filter = sfxge_intr_line_filter; handler = sfxge_intr_line; break; default: KASSERT(0, ("Invalid interrupt type")); return EINVAL; } /* Try to add the handlers */ for (index = 0; index < intr->n_alloc; index++) { if ((err = bus_setup_intr(sc->dev, table[index].eih_res, INTR_MPSAFE|INTR_TYPE_NET, filter, handler, sc->evq[index], &table[index].eih_tag)) != 0) { goto fail; } #ifdef SFXGE_HAVE_DESCRIBE_INTR if (intr->n_alloc > 1) bus_describe_intr(sc->dev, table[index].eih_res, table[index].eih_tag, "%d", index); #endif bus_bind_intr(sc->dev, table[index].eih_res, index); } return (0); fail: /* Remove remaining handlers */ while (--index >= 0) bus_teardown_intr(sc->dev, table[index].eih_res, table[index].eih_tag); return (err); }
/** * @brief Main vmbus driver initialization routine. * * Here, we * - initialize the vmbus driver context * - setup various driver entry points * - invoke the vmbus hv main init routine * - get the irq resource * - invoke the vmbus to add the vmbus root device * - setup the vmbus root device * - retrieve the channel offers */ static int vmbus_bus_init(void) { struct ioapic_intsrc { struct intsrc io_intsrc; u_int io_irq; u_int io_intpin:8; u_int io_vector:8; u_int io_cpu:8; u_int io_activehi:1; u_int io_edgetrigger:1; u_int io_masked:1; int io_bus:4; uint32_t io_lowreg; }; int ret; unsigned int vector = 0; struct intsrc *isrc; struct ioapic_intsrc *intpin; if (vmbus_inited) return (0); vmbus_inited = 1; ret = hv_vmbus_init(); if (ret) { if(bootverbose) printf("Error VMBUS: Hypervisor Initialization Failed!\n"); return (ret); } ret = swi_add(&hv_msg_intr_event, "hv_msg", vmbus_msg_swintr, NULL, SWI_CLOCK, 0, &msg_swintr); if (ret) goto cleanup; /* * Message SW interrupt handler checks a per-CPU page and * thus the thread needs to be bound to CPU-0 - which is where * all interrupts are processed. */ ret = intr_event_bind(hv_msg_intr_event, 0); if (ret) goto cleanup1; ret = swi_add(&hv_event_intr_event, "hv_event", hv_vmbus_on_events, NULL, SWI_CLOCK, 0, &event_swintr); if (ret) goto cleanup1; intr_res = bus_alloc_resource(vmbus_devp, SYS_RES_IRQ, &vmbus_rid, vmbus_irq, vmbus_irq, 1, RF_ACTIVE); if (intr_res == NULL) { ret = ENOMEM; /* XXXKYS: Need a better errno */ goto cleanup2; } /* * Setup interrupt filter handler */ ret = bus_setup_intr(vmbus_devp, intr_res, INTR_TYPE_NET | INTR_MPSAFE, hv_vmbus_isr, NULL, NULL, &vmbus_cookiep); if (ret != 0) goto cleanup3; ret = bus_bind_intr(vmbus_devp, intr_res, 0); if (ret != 0) goto cleanup4; isrc = intr_lookup_source(vmbus_irq); if ((isrc == NULL) || (isrc->is_event == NULL)) { ret = EINVAL; goto cleanup4; } /* vector = isrc->is_event->ie_vector; */ intpin = (struct ioapic_intsrc *)isrc; vector = intpin->io_vector; if(bootverbose) printf("VMBUS: irq 0x%x vector 0x%x\n", vmbus_irq, vector); /** * Notify the hypervisor of our irq. */ smp_rendezvous(NULL, hv_vmbus_synic_init, NULL, &vector); /** * Connect to VMBus in the root partition */ ret = hv_vmbus_connect(); if (ret) goto cleanup4; hv_vmbus_request_channel_offers(); return (ret); cleanup4: /* * remove swi, bus and intr resource */ bus_teardown_intr(vmbus_devp, intr_res, vmbus_cookiep); cleanup3: bus_release_resource(vmbus_devp, SYS_RES_IRQ, vmbus_rid, intr_res); cleanup2: swi_remove(event_swintr); cleanup1: swi_remove(msg_swintr); cleanup: hv_vmbus_cleanup(); return (ret); }