legacy.c (1738B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * PCI Message Signaled Interrupt (MSI). 4 * 5 * Legacy architecture specific setup and teardown mechanism. 6 */ 7#include "msi.h" 8 9/* Arch hooks */ 10int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) 11{ 12 return -EINVAL; 13} 14 15void __weak arch_teardown_msi_irq(unsigned int irq) 16{ 17} 18 19int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) 20{ 21 struct msi_desc *desc; 22 int ret; 23 24 /* 25 * If an architecture wants to support multiple MSI, it needs to 26 * override arch_setup_msi_irqs() 27 */ 28 if (type == PCI_CAP_ID_MSI && nvec > 1) 29 return 1; 30 31 msi_for_each_desc(desc, &dev->dev, MSI_DESC_NOTASSOCIATED) { 32 ret = arch_setup_msi_irq(dev, desc); 33 if (ret) 34 return ret < 0 ? ret : -ENOSPC; 35 } 36 37 return 0; 38} 39 40void __weak arch_teardown_msi_irqs(struct pci_dev *dev) 41{ 42 struct msi_desc *desc; 43 int i; 44 45 msi_for_each_desc(desc, &dev->dev, MSI_DESC_ASSOCIATED) { 46 for (i = 0; i < desc->nvec_used; i++) 47 arch_teardown_msi_irq(desc->irq + i); 48 } 49} 50 51static int pci_msi_setup_check_result(struct pci_dev *dev, int type, int ret) 52{ 53 struct msi_desc *desc; 54 int avail = 0; 55 56 if (type != PCI_CAP_ID_MSIX || ret >= 0) 57 return ret; 58 59 /* Scan the MSI descriptors for successfully allocated ones. */ 60 msi_for_each_desc(desc, &dev->dev, MSI_DESC_ASSOCIATED) 61 avail++; 62 63 return avail ? avail : ret; 64} 65 66int pci_msi_legacy_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) 67{ 68 int ret = arch_setup_msi_irqs(dev, nvec, type); 69 70 ret = pci_msi_setup_check_result(dev, type, ret); 71 if (!ret) 72 ret = msi_device_populate_sysfs(&dev->dev); 73 return ret; 74} 75 76void pci_msi_legacy_teardown_msi_irqs(struct pci_dev *dev) 77{ 78 msi_device_destroy_sysfs(&dev->dev); 79 arch_teardown_msi_irqs(dev); 80}