Example #1
0
int
ddi_add_softintr(dev_info_t *dip, int preference, ddi_softintr_t *idp,
    ddi_iblock_cookie_t *iblock_cookiep,
    ddi_idevice_cookie_t *idevice_cookiep,
    uint_t (*int_handler)(caddr_t int_handler_arg),
    caddr_t int_handler_arg)
{
	ddi_softint_handle_t	*hdl_p;
	uint64_t		softpri;
	int			ret;

	DDI_INTR_APIDBG((CE_CONT, "ddi_add_softintr: name=%s%d dip=0x%p "
	    "pref=0x%x\n", ddi_driver_name(dip), ddi_get_instance(dip),
	    (void *)dip, preference));

	if ((idp == NULL) || ((preference == DDI_SOFTINT_FIXED) &&
	    (iblock_cookiep == NULL)))
		return (DDI_FAILURE);

	/* Translate the priority preference */
	if (preference == DDI_SOFTINT_FIXED) {
		softpri = (uint64_t)(uintptr_t)*iblock_cookiep;
		softpri = MIN(softpri, DDI_SOFT_INTR_PRI_H);
	} else {
		softpri = (uint64_t)((preference > DDI_SOFTINT_MED) ?
		    DDI_SOFT_INTR_PRI_H : DDI_SOFT_INTR_PRI_M);
	}

	DDI_INTR_APIDBG((CE_CONT, "ddi_add_softintr: preference 0x%x "
	    "softpri 0x%lx\n", preference, (long)softpri));

	hdl_p = kmem_zalloc(sizeof (ddi_softint_handle_t), KM_SLEEP);
	if ((ret = ddi_intr_add_softint(dip, hdl_p, softpri,
	    (ddi_intr_handler_t *)int_handler, int_handler_arg)) !=
	    DDI_SUCCESS) {
		DDI_INTR_APIDBG((CE_CONT, "ddi_add_softintr: "
		    "ddi_intr_add_softint failed, ret 0x%x\n", ret));

		kmem_free(hdl_p, sizeof (ddi_softint_handle_t));
		return (DDI_FAILURE);
	}

	if (iblock_cookiep)
		*iblock_cookiep =  (ddi_iblock_cookie_t)(uintptr_t)softpri;

	if (idevice_cookiep) {
		idevice_cookiep->idev_vector = 0;
		idevice_cookiep->idev_priority = softpri;
	}

	*idp = (ddi_softintr_t)hdl_p;

	DDI_INTR_APIDBG((CE_CONT, "ddi_add_softintr: dip = 0x%p, "
	    "idp = 0x%p, ret = %x\n", (void *)dip, (void *)*idp, ret));

	return (DDI_SUCCESS);
}
Example #2
0
static int
eib_ctl_setup_cq(eib_t *ss, eib_vnic_t *vnic)
{
	eib_chan_t *chan = vnic->vn_ctl_chan;
	ibt_cq_attr_t cq_attr;
	ibt_status_t ret;
	uint_t sz;
	int rv;

	/*
	 * Allocate a completion queue for sending vhub table request
	 * and vhub-update/vnic-alive messages and responses from the
	 * gateway
	 */
	cq_attr.cq_sched = NULL;
	cq_attr.cq_flags = IBT_CQ_NO_FLAGS;
	if (ss->ei_hca_attrs->hca_max_cq_sz < EIB_CTL_CQ_SIZE)
		cq_attr.cq_size = ss->ei_hca_attrs->hca_max_cq_sz;
	else
		cq_attr.cq_size = EIB_CTL_CQ_SIZE;

	ret = ibt_alloc_cq(ss->ei_hca_hdl, &cq_attr, &chan->ch_cq_hdl, &sz);
	if (ret != IBT_SUCCESS) {
		EIB_DPRINTF_ERR(ss->ei_instance, "eib_ctl_setup_cq: "
		    "ibt_alloc_cq(cq_sz=0x%lx) failed, ret=%d",
		    cq_attr.cq_size, ret);
		goto ctl_setup_cq_fail;
	}

	/*
	 * Set up other parameters for collecting completion information
	 */
	chan->ch_cq_sz = sz;
	chan->ch_wc = kmem_zalloc(sizeof (ibt_wc_t) * sz, KM_SLEEP);

	/*
	 * Allocate soft interrupt for this vnic's control channel cq
	 * handler and set up the IBTL cq handler.
	 */
	if ((rv = ddi_intr_add_softint(ss->ei_dip, &vnic->vn_ctl_si_hdl,
	    EIB_SOFTPRI_CTL, eib_ctl_comp_handler, vnic)) != DDI_SUCCESS) {
		EIB_DPRINTF_ERR(ss->ei_instance, "eib_ctl_setup_cq: "
		    "ddi_intr_add_softint() failed for vnic %d ctl qp, ret=%d",
		    vnic->vn_instance, rv);
		goto ctl_setup_cq_fail;
	}

	/*
	 * Now, set up this vnic's control channel completion queue handler
	 */
	ibt_set_cq_handler(chan->ch_cq_hdl, eib_ctl_comp_intr, vnic);

	ret = ibt_enable_cq_notify(chan->ch_cq_hdl, IBT_NEXT_COMPLETION);
	if (ret != IBT_SUCCESS) {
		EIB_DPRINTF_ERR(ss->ei_instance, "eib_ctl_setup_cq: "
		    "ibt_enable_cq_notify() failed, ret=%d", ret);
		goto ctl_setup_cq_fail;
	}

	return (EIB_E_SUCCESS);

ctl_setup_cq_fail:
	eib_rb_ctl_setup_cq(ss, vnic);
	return (EIB_E_FAILURE);
}
Example #3
0
/**
 * Sets IRQ for VMMDev.
 *
 * @returns Solaris error code.
 * @param   pDip     Pointer to the device info structure.
 */
static int vgdrvSolarisAddIRQ(dev_info_t *pDip)
{
    LogFlow(("vgdrvSolarisAddIRQ: pDip=%p\n", pDip));

    /* Get the types of interrupt supported for this hardware. */
    int fIntrType = 0;
    int rc = ddi_intr_get_supported_types(pDip, &fIntrType);
    if (rc == DDI_SUCCESS)
    {
        /* We only support fixed interrupts at this point, not MSIs. */
        if (fIntrType & DDI_INTR_TYPE_FIXED)
        {
            /* Verify the number of interrupts supported by this device. There can only be one fixed interrupt. */
            int cIntrCount = 0;
            rc = ddi_intr_get_nintrs(pDip, fIntrType, &cIntrCount);
            if (   rc == DDI_SUCCESS
                && cIntrCount == 1)
            {
                /* Allocated kernel memory for the interrupt handle. The allocation size is stored internally. */
                g_pahIntrs = RTMemAllocZ(cIntrCount * sizeof(ddi_intr_handle_t));
                if (g_pahIntrs)
                {
                    /* Allocate the interrupt for this device and verify the allocation. */
                    int cIntrAllocated;
                    rc = ddi_intr_alloc(pDip, g_pahIntrs, fIntrType, 0 /* interrupt number */, cIntrCount, &cIntrAllocated,
                                        DDI_INTR_ALLOC_NORMAL);
                    if (   rc == DDI_SUCCESS
                        && cIntrAllocated == 1)
                    {
                        /* Get the interrupt priority assigned by the system. */
                        uint_t uIntrPriority;
                        rc = ddi_intr_get_pri(g_pahIntrs[0], &uIntrPriority);
                        if (rc == DDI_SUCCESS)
                        {
                            /* Check if the interrupt priority is scheduler level or above, if so we need to use a high-level
                               and low-level interrupt handlers with corresponding mutexes. */
                            cmn_err(CE_CONT, "!vboxguest: uIntrPriority=%d hilevel_pri=%d\n", uIntrPriority, ddi_intr_get_hilevel_pri());
                            if (uIntrPriority >= ddi_intr_get_hilevel_pri())
                            {
                                /* Initialize the high-level mutex. */
                                mutex_init(&g_HighLevelIrqMtx, NULL /* pszDesc */, MUTEX_DRIVER, DDI_INTR_PRI(uIntrPriority));

                                /* Assign interrupt handler function to the interrupt handle. */
                                rc = ddi_intr_add_handler(g_pahIntrs[0], (ddi_intr_handler_t *)&vgdrvSolarisHighLevelISR,
                                                          NULL /* pvArg1 */, NULL /* pvArg2 */);

                                if (rc == DDI_SUCCESS)
                                {
                                    /* Add the low-level interrupt handler. */
                                    rc = ddi_intr_add_softint(pDip, &g_hSoftIntr, DDI_INTR_SOFTPRI_MAX,
                                                              (ddi_intr_handler_t *)&vgdrvSolarisISR, NULL /* pvArg1 */);
                                    if (rc == DDI_SUCCESS)
                                    {
                                        /* Initialize the low-level mutex at the corresponding level. */
                                        mutex_init(&g_IrqMtx, NULL /* pszDesc */,  MUTEX_DRIVER,
                                                   DDI_INTR_PRI(DDI_INTR_SOFTPRI_MAX));

                                        g_fSoftIntRegistered = true;
                                        /* Enable the high-level interrupt. */
                                        rc = ddi_intr_enable(g_pahIntrs[0]);
                                        if (rc == DDI_SUCCESS)
                                            return rc;

                                        LogRel((DEVICE_NAME "::AddIRQ: failed to enable interrupt. rc=%d\n", rc));
                                        mutex_destroy(&g_IrqMtx);
                                    }
                                    else
                                        LogRel((DEVICE_NAME "::AddIRQ: failed to add soft interrupt handler. rc=%d\n", rc));

                                    ddi_intr_remove_handler(g_pahIntrs[0]);
                                }
                                else
                                    LogRel((DEVICE_NAME "::AddIRQ: failed to add high-level interrupt handler. rc=%d\n", rc));

                                mutex_destroy(&g_HighLevelIrqMtx);
                            }
                            else
                            {
                                /* Interrupt handler runs at reschedulable level, initialize the mutex at the given priority. */
                                mutex_init(&g_IrqMtx, NULL /* pszDesc */, MUTEX_DRIVER, DDI_INTR_PRI(uIntrPriority));

                                /* Assign interrupt handler function to the interrupt handle. */
                                rc = ddi_intr_add_handler(g_pahIntrs[0], (ddi_intr_handler_t *)vgdrvSolarisISR,
                                                          NULL /* pvArg1 */, NULL /* pvArg2 */);
                                if (rc == DDI_SUCCESS)
                                {
                                    /* Enable the interrupt. */
                                    rc = ddi_intr_enable(g_pahIntrs[0]);
                                    if (rc == DDI_SUCCESS)
                                        return rc;

                                    LogRel((DEVICE_NAME "::AddIRQ: failed to enable interrupt. rc=%d\n", rc));
                                    mutex_destroy(&g_IrqMtx);
                                }
                            }
                        }
                        else
                            LogRel((DEVICE_NAME "::AddIRQ: failed to get priority of interrupt. rc=%d\n", rc));

                        Assert(cIntrAllocated == 1);
                        ddi_intr_free(g_pahIntrs[0]);
                    }
                    else
                        LogRel((DEVICE_NAME "::AddIRQ: failed to allocated IRQs. count=%d\n", cIntrCount));
                    RTMemFree(g_pahIntrs);
                }
                else
                    LogRel((DEVICE_NAME "::AddIRQ: failed to allocated IRQs. count=%d\n", cIntrCount));
            }
            else
                LogRel((DEVICE_NAME "::AddIRQ: failed to get or insufficient number of IRQs. rc=%d cIntrCount=%d\n", rc, cIntrCount));
        }
        else
            LogRel((DEVICE_NAME "::AddIRQ: fixed-type interrupts not supported. IntrType=%#x\n", fIntrType));
    }
    else
        LogRel((DEVICE_NAME "::AddIRQ: failed to get supported interrupt types. rc=%d\n", rc));
    return rc;
}