0001
0002
0003
0004
0005
0006
0007 #include "msi.h"
0008
0009
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
0026
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
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 }