Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * PCI Message Signaled Interrupt (MSI).
0004  *
0005  * Legacy architecture specific setup and teardown mechanism.
0006  */
0007 #include "msi.h"
0008 
0009 /* Arch hooks */
0010 int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
0011 {
0012     return -EINVAL;
0013 }
0014 
0015 void __weak arch_teardown_msi_irq(unsigned int irq)
0016 {
0017 }
0018 
0019 int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
0020 {
0021     struct msi_desc *desc;
0022     int ret;
0023 
0024     /*
0025      * If an architecture wants to support multiple MSI, it needs to
0026      * override arch_setup_msi_irqs()
0027      */
0028     if (type == PCI_CAP_ID_MSI && nvec > 1)
0029         return 1;
0030 
0031     msi_for_each_desc(desc, &dev->dev, MSI_DESC_NOTASSOCIATED) {
0032         ret = arch_setup_msi_irq(dev, desc);
0033         if (ret)
0034             return ret < 0 ? ret : -ENOSPC;
0035     }
0036 
0037     return 0;
0038 }
0039 
0040 void __weak arch_teardown_msi_irqs(struct pci_dev *dev)
0041 {
0042     struct msi_desc *desc;
0043     int i;
0044 
0045     msi_for_each_desc(desc, &dev->dev, MSI_DESC_ASSOCIATED) {
0046         for (i = 0; i < desc->nvec_used; i++)
0047             arch_teardown_msi_irq(desc->irq + i);
0048     }
0049 }
0050 
0051 static int pci_msi_setup_check_result(struct pci_dev *dev, int type, int ret)
0052 {
0053     struct msi_desc *desc;
0054     int avail = 0;
0055 
0056     if (type != PCI_CAP_ID_MSIX || ret >= 0)
0057         return ret;
0058 
0059     /* Scan the MSI descriptors for successfully allocated ones. */
0060     msi_for_each_desc(desc, &dev->dev, MSI_DESC_ASSOCIATED)
0061         avail++;
0062 
0063     return avail ? avail : ret;
0064 }
0065 
0066 int pci_msi_legacy_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
0067 {
0068     int ret = arch_setup_msi_irqs(dev, nvec, type);
0069 
0070     ret = pci_msi_setup_check_result(dev, type, ret);
0071     if (!ret)
0072         ret = msi_device_populate_sysfs(&dev->dev);
0073     return ret;
0074 }
0075 
0076 void pci_msi_legacy_teardown_msi_irqs(struct pci_dev *dev)
0077 {
0078     msi_device_destroy_sysfs(&dev->dev);
0079     arch_teardown_msi_irqs(dev);
0080 }