Ejemplo n.º 1
0
/**
 * pci_enable_msi - configure device's MSI capability structure
 * @dev: pointer to the pci_dev data structure of MSI device function
 *
 * Setup the MSI capability structure of device function with
 * a single MSI vector upon its software driver call to request for
 * MSI mode enabled on its hardware device function. A return of zero
 * indicates the successful setup of an entry zero with the new MSI
 * vector or non-zero for otherwise.
 **/
int pci_enable_msi(struct pci_dev* dev)
{
    int pos, temp, status = -EINVAL;
    u16 control;

    if (!pci_msi_enable || !dev)
        return status;

    if (dev->no_msi)
        return status;

    temp = dev->irq;

    if ((status = msi_init()) < 0)
        return status;

    if (!(pos = pci_find_capability(dev, PCI_CAP_ID_MSI)))
        return -EINVAL;

    pci_read_config_word(dev, msi_control_reg(pos), &control);
    if (control & PCI_MSI_FLAGS_ENABLE)
        return 0;			/* Already in MSI mode */

    if (!msi_lookup_vector(dev, PCI_CAP_ID_MSI)) {
        /* Lookup Sucess */
        unsigned long flags;

        spin_lock_irqsave(&msi_lock, flags);
        if (!vector_irq[dev->irq]) {
            msi_desc[dev->irq]->msi_attrib.state = 0;
            vector_irq[dev->irq] = -1;
            nr_released_vectors--;
            spin_unlock_irqrestore(&msi_lock, flags);
            enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
            return 0;
        }
        spin_unlock_irqrestore(&msi_lock, flags);
        dev->irq = temp;
    }
    /* Check whether driver already requested for MSI-X vectors */
    if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)) > 0 &&
            !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) {
        printk(KERN_INFO "PCI: %s: Can't enable MSI.  "
               "Device already has MSI-X vectors assigned\n",
               pci_name(dev));
        dev->irq = temp;
        return -EINVAL;
    }
    status = msi_capability_init(dev);
    if (!status) {
        if (!pos)
            nr_reserved_vectors--;	/* Only MSI capable */
        else if (nr_msix_devices > 0)
            nr_msix_devices--;	/* Both MSI and MSI-X capable,
						   but choose enabling MSI */
    }

    return status;
}
Ejemplo n.º 2
0
/**
 * pci_enable_msi - configure device's MSI capability structure
 * @dev: pointer to the pci_dev data structure of MSI device function
 *
 * Setup the MSI capability structure of device function with
 * a single MSI vector upon its software driver call to request for
 * MSI mode enabled on its hardware device function. A return of zero
 * indicates the successful setup of an entry zero with the new MSI
 * vector or non-zero for otherwise.
 **/
int pci_enable_msi(struct pci_dev* dev)
{
	int pos, temp, status;

	if (pci_msi_supported(dev) < 0)
		return -EINVAL;

	temp = dev->irq;

	status = msi_init();
	if (status < 0)
		return status;

	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
	if (!pos)
		return -EINVAL;

	WARN_ON(!msi_lookup_vector(dev, PCI_CAP_ID_MSI));

	/* Check whether driver already requested for MSI-X vectors */
	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
	if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) {
			printk(KERN_INFO "PCI: %s: Can't enable MSI.  "
			       "Device already has MSI-X vectors assigned\n",
			       pci_name(dev));
			dev->irq = temp;
			return -EINVAL;
	}
	status = msi_capability_init(dev);
	if (!status) {
   		if (!pos)
			nr_reserved_vectors--;	/* Only MSI capable */
	}

	return status;
}