Esempio n. 1
0
static int vfio_msi_enable(struct vfio_pci_device *vdev, int nvec, bool msix)
{
	struct pci_dev *pdev = vdev->pdev;
	int ret;

	if (!is_irq_none(vdev))
		return -EINVAL;

	vdev->ctx = kzalloc(nvec * sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL);
	if (!vdev->ctx)
		return -ENOMEM;

	if (msix) {
		int i;

		vdev->msix = kzalloc(nvec * sizeof(struct msix_entry),
				     GFP_KERNEL);
		if (!vdev->msix) {
			kfree(vdev->ctx);
			return -ENOMEM;
		}

		for (i = 0; i < nvec; i++)
			vdev->msix[i].entry = i;

		ret = pci_enable_msix_range(pdev, vdev->msix, 1, nvec);
		if (ret < nvec) {
			if (ret > 0)
				pci_disable_msix(pdev);
			kfree(vdev->msix);
			kfree(vdev->ctx);
			return ret;
		}
	} else {
		ret = pci_enable_msi_range(pdev, 1, nvec);
		if (ret < nvec) {
			if (ret > 0)
				pci_disable_msi(pdev);
			kfree(vdev->ctx);
			return ret;
		}
	}

	vdev->num_ctx = nvec;
	vdev->irq_type = msix ? VFIO_PCI_MSIX_IRQ_INDEX :
				VFIO_PCI_MSI_IRQ_INDEX;

	if (!msix) {
		/*
		 * Compute the virtual hardware field for max msi vectors -
		 * it is the log base 2 of the number of vectors.
		 */
		vdev->msi_qmax = fls(nvec * 2 - 1) - 1;
	}

	return 0;
}
/* Bus ops */
static int wil_if_pcie_enable(struct wil6210_priv *wil)
{
    struct pci_dev *pdev = wil->pdev;
    int rc;

    pci_set_master(pdev);

    /*
     * how many MSI interrupts to request?
     */
    switch (use_msi) {
    case 3:
    case 1:
        wil_dbg_misc(wil, "Setup %d MSI interrupts\n", use_msi);
        break;
    case 0:
        wil_dbg_misc(wil, "MSI interrupts disabled, use INTx\n");
        break;
    default:
        wil_err(wil, "Invalid use_msi=%d, default to 1\n", use_msi);
        use_msi = 1;
    }

    if (use_msi == 3 && pci_enable_msi_range(pdev, 3, 3) < 0) {
        wil_err(wil, "3 MSI mode failed, try 1 MSI\n");
        use_msi = 1;
    }

    if (use_msi == 1 && pci_enable_msi(pdev)) {
        wil_err(wil, "pci_enable_msi failed, use INTx\n");
        use_msi = 0;
    }

    wil->n_msi = use_msi;

    rc = wil6210_init_irq(wil, pdev->irq);
    if (rc)
        goto stop_master;

    /* need reset here to obtain MAC */
    mutex_lock(&wil->mutex);
    rc = wil_reset(wil);
    mutex_unlock(&wil->mutex);
    if (rc)
        goto release_irq;

    return 0;

release_irq:
    wil6210_fini_irq(wil, pdev->irq);
    /* safe to call if no MSI */
    pci_disable_msi(pdev);
stop_master:
    pci_clear_master(pdev);
    return rc;
}
Esempio n. 3
0
/* Bus ops */
static int wil_if_pcie_enable(struct wil6210_priv *wil)
{
	struct pci_dev *pdev = wil->pdev;
	int rc;
	/* on platforms with buggy ACPI, pdev->msi_enabled may be set to
	 * allow pci_enable_device to work. This indicates INTx was not routed
	 * and only MSI should be used
	 */
	int msi_only = pdev->msi_enabled;

	wil_dbg_misc(wil, "%s()\n", __func__);

	pdev->msi_enabled = 0;

	pci_set_master(pdev);

	/*
	 * how many MSI interrupts to request?
	 */
	switch (use_msi) {
	case 3:
	case 1:
		wil_dbg_misc(wil, "Setup %d MSI interrupts\n", use_msi);
		break;
	case 0:
		wil_dbg_misc(wil, "MSI interrupts disabled, use INTx\n");
		break;
	default:
		wil_err(wil, "Invalid use_msi=%d, default to 1\n", use_msi);
		use_msi = 1;
	}

	if (use_msi == 3 && pci_enable_msi_range(pdev, 3, 3) < 0) {
		wil_err(wil, "3 MSI mode failed, try 1 MSI\n");
		use_msi = 1;
	}

	if (use_msi == 1 && pci_enable_msi(pdev)) {
		wil_err(wil, "pci_enable_msi failed, use INTx\n");
		use_msi = 0;
	}

	wil->n_msi = use_msi;

	if ((wil->n_msi == 0) && msi_only) {
		wil_err(wil, "Interrupt pin not routed, unable to use INTx\n");
		rc = -ENODEV;
		goto stop_master;
	}

	rc = wil6210_init_irq(wil, pdev->irq);
	if (rc)
		goto stop_master;

	/* need reset here to obtain MAC */
	mutex_lock(&wil->mutex);
	rc = wil_reset(wil);
	mutex_unlock(&wil->mutex);
	if (debug_fw)
		rc = 0;
	if (rc)
		goto release_irq;

	return 0;

 release_irq:
	wil6210_fini_irq(wil, pdev->irq);
	/* safe to call if no MSI */
	pci_disable_msi(pdev);
 stop_master:
	pci_clear_master(pdev);
	return rc;
}