Line data Source code
1 : /* SPDX-License-Identifier: GPL-2.0 */ 2 : 3 : #include <linux/pci.h> 4 : #include <linux/msi.h> 5 : 6 : #define msix_table_size(flags) ((flags & PCI_MSIX_FLAGS_QSIZE) + 1) 7 : 8 : int pci_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); 9 : void pci_msi_teardown_msi_irqs(struct pci_dev *dev); 10 : 11 : /* Mask/unmask helpers */ 12 : void pci_msi_update_mask(struct msi_desc *desc, u32 clear, u32 set); 13 : 14 : static inline void pci_msi_mask(struct msi_desc *desc, u32 mask) 15 : { 16 0 : pci_msi_update_mask(desc, 0, mask); 17 : } 18 : 19 : static inline void pci_msi_unmask(struct msi_desc *desc, u32 mask) 20 : { 21 0 : pci_msi_update_mask(desc, mask, 0); 22 : } 23 : 24 : static inline void __iomem *pci_msix_desc_addr(struct msi_desc *desc) 25 : { 26 0 : return desc->pci.mask_base + desc->msi_index * PCI_MSIX_ENTRY_SIZE; 27 : } 28 : 29 : /* 30 : * This internal function does not flush PCI writes to the device. All 31 : * users must ensure that they read from the device before either assuming 32 : * that the device state is up to date, or returning out of this file. 33 : * It does not affect the msi_desc::msix_ctrl cache either. Use with care! 34 : */ 35 0 : static inline void pci_msix_write_vector_ctrl(struct msi_desc *desc, u32 ctrl) 36 : { 37 0 : void __iomem *desc_addr = pci_msix_desc_addr(desc); 38 : 39 0 : if (desc->pci.msi_attrib.can_mask) 40 0 : writel(ctrl, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL); 41 0 : } 42 : 43 0 : static inline void pci_msix_mask(struct msi_desc *desc) 44 : { 45 0 : desc->pci.msix_ctrl |= PCI_MSIX_ENTRY_CTRL_MASKBIT; 46 0 : pci_msix_write_vector_ctrl(desc, desc->pci.msix_ctrl); 47 : /* Flush write to device */ 48 0 : readl(desc->pci.mask_base); 49 0 : } 50 : 51 : static inline void pci_msix_unmask(struct msi_desc *desc) 52 : { 53 0 : desc->pci.msix_ctrl &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT; 54 0 : pci_msix_write_vector_ctrl(desc, desc->pci.msix_ctrl); 55 : } 56 : 57 0 : static inline void __pci_msi_mask_desc(struct msi_desc *desc, u32 mask) 58 : { 59 0 : if (desc->pci.msi_attrib.is_msix) 60 0 : pci_msix_mask(desc); 61 : else 62 : pci_msi_mask(desc, mask); 63 0 : } 64 : 65 0 : static inline void __pci_msi_unmask_desc(struct msi_desc *desc, u32 mask) 66 : { 67 0 : if (desc->pci.msi_attrib.is_msix) 68 : pci_msix_unmask(desc); 69 : else 70 : pci_msi_unmask(desc, mask); 71 0 : } 72 : 73 : /* 74 : * PCI 2.3 does not specify mask bits for each MSI interrupt. Attempting to 75 : * mask all MSI interrupts by clearing the MSI enable bit does not work 76 : * reliably as devices without an INTx disable bit will then generate a 77 : * level IRQ which will never be cleared. 78 : */ 79 : static inline __attribute_const__ u32 msi_multi_mask(struct msi_desc *desc) 80 : { 81 : /* Don't shift by >= width of type */ 82 0 : if (desc->pci.msi_attrib.multi_cap >= 5) 83 : return 0xffffffff; 84 0 : return (1 << (1 << desc->pci.msi_attrib.multi_cap)) - 1; 85 : } 86 : 87 : void msix_prepare_msi_desc(struct pci_dev *dev, struct msi_desc *desc); 88 : 89 : /* Subsystem variables */ 90 : extern int pci_msi_enable; 91 : 92 : /* MSI internal functions invoked from the public APIs */ 93 : void pci_msi_shutdown(struct pci_dev *dev); 94 : void pci_msix_shutdown(struct pci_dev *dev); 95 : void pci_free_msi_irqs(struct pci_dev *dev); 96 : int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, struct irq_affinity *affd); 97 : int __pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int minvec, 98 : int maxvec, struct irq_affinity *affd, int flags); 99 : void __pci_restore_msi_state(struct pci_dev *dev); 100 : void __pci_restore_msix_state(struct pci_dev *dev); 101 : 102 : /* irq_domain related functionality */ 103 : 104 : enum support_mode { 105 : ALLOW_LEGACY, 106 : DENY_LEGACY, 107 : }; 108 : 109 : bool pci_msi_domain_supports(struct pci_dev *dev, unsigned int feature_mask, enum support_mode mode); 110 : bool pci_setup_msi_device_domain(struct pci_dev *pdev); 111 : bool pci_setup_msix_device_domain(struct pci_dev *pdev, unsigned int hwsize); 112 : 113 : /* Legacy (!IRQDOMAIN) fallbacks */ 114 : 115 : #ifdef CONFIG_PCI_MSI_ARCH_FALLBACKS 116 : int pci_msi_legacy_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); 117 : void pci_msi_legacy_teardown_msi_irqs(struct pci_dev *dev); 118 : #else 119 0 : static inline int pci_msi_legacy_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) 120 : { 121 0 : WARN_ON_ONCE(1); 122 0 : return -ENODEV; 123 : } 124 : 125 0 : static inline void pci_msi_legacy_teardown_msi_irqs(struct pci_dev *dev) 126 : { 127 0 : WARN_ON_ONCE(1); 128 0 : } 129 : #endif