예제 #1
0
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);
}