Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

PCI/MSI: Add startup/shutdown for per device domains

As the RISC-V PLIC cannot apply affinity settings without invoking
irq_enable(), it will make the interrupt unavailble when used as an
underlying interrupt chip for the MSI controller.

Implement the irq_startup() and irq_shutdown() callbacks for the PCI MSI
and MSI-X templates.

For chips that specify MSI_FLAG_PCI_MSI_STARTUP_PARENT, the parent startup
and shutdown functions are invoked. That allows the interrupt on the parent
chip to be enabled if the interrupt has not been enabled during
allocation. This is necessary for MSI controllers which use PLIC as
underlying parent interrupt chip.

Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Chen Wang <unicorn_wang@outlook.com> # Pioneerbox
Reviewed-by: Chen Wang <unicorn_wang@outlook.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://lore.kernel.org/all/20250813232835.43458-3-inochiama@gmail.com

authored by

Inochi Amaoto and committed by
Thomas Gleixner
54f45a30 7a721a2f

+54
+52
drivers/pci/msi/irqdomain.c
··· 148 148 arg->hwirq = desc->msi_index; 149 149 } 150 150 151 + static void cond_shutdown_parent(struct irq_data *data) 152 + { 153 + struct msi_domain_info *info = data->domain->host_data; 154 + 155 + if (unlikely(info->flags & MSI_FLAG_PCI_MSI_STARTUP_PARENT)) 156 + irq_chip_shutdown_parent(data); 157 + } 158 + 159 + static unsigned int cond_startup_parent(struct irq_data *data) 160 + { 161 + struct msi_domain_info *info = data->domain->host_data; 162 + 163 + if (unlikely(info->flags & MSI_FLAG_PCI_MSI_STARTUP_PARENT)) 164 + return irq_chip_startup_parent(data); 165 + return 0; 166 + } 167 + 151 168 static __always_inline void cond_mask_parent(struct irq_data *data) 152 169 { 153 170 struct msi_domain_info *info = data->domain->host_data; ··· 179 162 180 163 if (unlikely(info->flags & MSI_FLAG_PCI_MSI_MASK_PARENT)) 181 164 irq_chip_unmask_parent(data); 165 + } 166 + 167 + static void pci_irq_shutdown_msi(struct irq_data *data) 168 + { 169 + struct msi_desc *desc = irq_data_get_msi_desc(data); 170 + 171 + pci_msi_mask(desc, BIT(data->irq - desc->irq)); 172 + cond_shutdown_parent(data); 173 + } 174 + 175 + static unsigned int pci_irq_startup_msi(struct irq_data *data) 176 + { 177 + struct msi_desc *desc = irq_data_get_msi_desc(data); 178 + unsigned int ret = cond_startup_parent(data); 179 + 180 + pci_msi_unmask(desc, BIT(data->irq - desc->irq)); 181 + return ret; 182 182 } 183 183 184 184 static void pci_irq_mask_msi(struct irq_data *data) ··· 228 194 static const struct msi_domain_template pci_msi_template = { 229 195 .chip = { 230 196 .name = "PCI-MSI", 197 + .irq_startup = pci_irq_startup_msi, 198 + .irq_shutdown = pci_irq_shutdown_msi, 231 199 .irq_mask = pci_irq_mask_msi, 232 200 .irq_unmask = pci_irq_unmask_msi, 233 201 .irq_write_msi_msg = pci_msi_domain_write_msg, ··· 245 209 .bus_token = DOMAIN_BUS_PCI_DEVICE_MSI, 246 210 }, 247 211 }; 212 + 213 + static void pci_irq_shutdown_msix(struct irq_data *data) 214 + { 215 + pci_msix_mask(irq_data_get_msi_desc(data)); 216 + cond_shutdown_parent(data); 217 + } 218 + 219 + static unsigned int pci_irq_startup_msix(struct irq_data *data) 220 + { 221 + unsigned int ret = cond_startup_parent(data); 222 + 223 + pci_msix_unmask(irq_data_get_msi_desc(data)); 224 + return ret; 225 + } 248 226 249 227 static void pci_irq_mask_msix(struct irq_data *data) 250 228 { ··· 284 234 static const struct msi_domain_template pci_msix_template = { 285 235 .chip = { 286 236 .name = "PCI-MSIX", 237 + .irq_startup = pci_irq_startup_msix, 238 + .irq_shutdown = pci_irq_shutdown_msix, 287 239 .irq_mask = pci_irq_mask_msix, 288 240 .irq_unmask = pci_irq_unmask_msix, 289 241 .irq_write_msi_msg = pci_msi_domain_write_msg,
+2
include/linux/msi.h
··· 568 568 MSI_FLAG_PARENT_PM_DEV = (1 << 8), 569 569 /* Support for parent mask/unmask */ 570 570 MSI_FLAG_PCI_MSI_MASK_PARENT = (1 << 9), 571 + /* Support for parent startup/shutdown */ 572 + MSI_FLAG_PCI_MSI_STARTUP_PARENT = (1 << 10), 571 573 572 574 /* Mask for the generic functionality */ 573 575 MSI_GENERIC_FLAGS_MASK = GENMASK(15, 0),