Most ARM(64) PCI/MSI domains mask and unmask in the parent domain after or before the PCI mask/unmask operation takes place. So there are more than a dozen of the same wrapper implementation all over the place. Don't make the same mistake with the new per device PCI/MSI domains and provide a static key which lets the domain implementation enable this sequence in the PCI/MSI code. Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Cc: Bjorn Helgaas <bhelgaas@xxxxxxxxxx> --- drivers/pci/msi/irqdomain.c | 30 ++++++++++++++++++++++++++++++ include/linux/msi.h | 2 ++ 2 files changed, 32 insertions(+) --- a/drivers/pci/msi/irqdomain.c +++ b/drivers/pci/msi/irqdomain.c @@ -148,17 +148,45 @@ static void pci_device_domain_set_desc(m arg->hwirq = desc->msi_index; } +static DEFINE_STATIC_KEY_FALSE(pci_msi_mask_unmask_parent); + +/** + * pci_device_msi_mask_unmask_parent_enable - Enable propagation of mask/unmask + * to the parent interrupt chip + * + * For MSI parent interrupt domains which want to mask at the parent interrupt + * chip too. + */ +void pci_device_msi_mask_unmask_parent_enable(void) +{ + static_branch_enable(&pci_msi_mask_unmask_parent); +} + +static __always_inline void cond_mask_parent(struct irq_data *data) +{ + if (static_branch_unlikely(&pci_msi_mask_unmask_parent)) + irq_chip_mask_parent(data); +} + +static __always_inline void cond_unmask_parent(struct irq_data *data) +{ + if (static_branch_unlikely(&pci_msi_mask_unmask_parent)) + irq_chip_unmask_parent(data); +} + static void pci_mask_msi(struct irq_data *data) { struct msi_desc *desc = irq_data_get_msi_desc(data); pci_msi_mask(desc, BIT(data->irq - desc->irq)); + cond_mask_parent(data); } static void pci_unmask_msi(struct irq_data *data) { struct msi_desc *desc = irq_data_get_msi_desc(data); + cond_unmask_parent(data); pci_msi_unmask(desc, BIT(data->irq - desc->irq)); } @@ -195,10 +223,12 @@ static struct msi_domain_template pci_ms static void pci_mask_msix(struct irq_data *data) { pci_msix_mask(irq_data_get_msi_desc(data)); + cond_mask_parent(data); } static void pci_unmask_msix(struct irq_data *data) { + cond_unmask_parent(data); pci_msix_unmask(irq_data_get_msi_desc(data)); } --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -653,12 +653,14 @@ struct irq_domain *pci_msi_create_irq_do struct irq_domain *parent); u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev); struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev); +void pci_device_msi_mask_unmask_parent_enable(void); #else /* CONFIG_PCI_MSI */ static inline struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev) { return NULL; } static inline void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg) { } +static inline void pci_device_msi_mask_unmask_parent_enable(void) { } #endif /* !CONFIG_PCI_MSI */ #endif /* LINUX_MSI_H */