* [PATCH v2 0/2] x86/hyperv: MSI parent domain conversion @ 2025-06-30 10:26 Nam Cao 2025-06-30 10:26 ` [PATCH v2 1/2] irqchip/irq-msi-lib: Select CONFIG_GENERIC_MSI_IRQ Nam Cao 2025-06-30 10:26 ` [PATCH v2 2/2] x86/hyperv: Switch to msi_create_parent_irq_domain() Nam Cao 0 siblings, 2 replies; 6+ messages in thread From: Nam Cao @ 2025-06-30 10:26 UTC (permalink / raw) To: K . Y . Srinivasan, Marc Zyngier, Haiyang Zhang, Wei Liu, Dexuan Cui, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H . Peter Anvin, linux-hyperv, linux-kernel Cc: Nam Cao The initial implementation of PCI/MSI interrupt domains in the hierarchical interrupt domain model used a shortcut by providing a global PCI/MSI domain. This works because the PCI/MSI[X] hardware is standardized and uniform, but it violates the basic design principle of hierarchical interrupt domains: Each hardware block involved in the interrupt delivery chain should have a separate interrupt domain. For PCI/MSI[X], the interrupt controller is per PCI device and not a global made-up entity. Unsurprisingly, the shortcut turned out to have downsides as it does not allow dynamic allocation of interrupt vectors after initialization and it prevents supporting IMS on PCI. For further details, see: https://lore.kernel.org/lkml/20221111120501.026511281@linutronix.de/ The solution is implementing per device MSI domains, this means the entities which provide global PCI/MSI domain so far have to implement MSI parent domain functionality instead. This series: - Fixup a dependency problem with CONFIG_GENERIC_MSI_IRQ - converts the x86 hyperv driver to implement MSI parent domain. Changes in v2: - Add the first fixup patch to resolve a build failure - Add clarification to the TODO note. arch/x86/hyperv/irqdomain.c | 111 ++++++++++++++++++++++++------------ drivers/hv/Kconfig | 1 + drivers/irqchip/Kconfig | 1 + 3 files changed, 78 insertions(+), 35 deletions(-) -- 2.39.5 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 1/2] irqchip/irq-msi-lib: Select CONFIG_GENERIC_MSI_IRQ 2025-06-30 10:26 [PATCH v2 0/2] x86/hyperv: MSI parent domain conversion Nam Cao @ 2025-06-30 10:26 ` Nam Cao 2025-06-30 10:26 ` [PATCH v2 2/2] x86/hyperv: Switch to msi_create_parent_irq_domain() Nam Cao 1 sibling, 0 replies; 6+ messages in thread From: Nam Cao @ 2025-06-30 10:26 UTC (permalink / raw) To: K . Y . Srinivasan, Marc Zyngier, Haiyang Zhang, Wei Liu, Dexuan Cui, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H . Peter Anvin, linux-hyperv, linux-kernel Cc: Nam Cao, kernel test robot irq-msi-lib directly uses struct msi_domain_info and MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS (and likely more) which are only available when CONFIG_GENERIC_MSI_IRQ=y. However, no dependency is specified. If it happens that CONFIG_IRQ_MSI_LIB=y while CONFIG_GENERIC_MSI_IRQ=n, the kernel fails to build. Specify this dependency and fix the build. Fixes: 72e257c6f058 ("irqchip: Provide irq-msi-lib") Reported-by: kernel test robot <lkp@intel.com> Closes: https://lore.kernel.org/oe-kbuild-all/202506282256.cHlEHrdc-lkp@intel.com/ Signed-off-by: Nam Cao <namcao@linutronix.de> --- drivers/irqchip/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 0d196e4471426..c3928ef793449 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -74,6 +74,7 @@ config ARM_VIC_NR config IRQ_MSI_LIB bool + select GENERIC_MSI_IRQ config ARMADA_370_XP_IRQ bool -- 2.39.5 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 2/2] x86/hyperv: Switch to msi_create_parent_irq_domain() 2025-06-30 10:26 [PATCH v2 0/2] x86/hyperv: MSI parent domain conversion Nam Cao 2025-06-30 10:26 ` [PATCH v2 1/2] irqchip/irq-msi-lib: Select CONFIG_GENERIC_MSI_IRQ Nam Cao @ 2025-06-30 10:26 ` Nam Cao 2025-07-09 23:40 ` Wei Liu 1 sibling, 1 reply; 6+ messages in thread From: Nam Cao @ 2025-06-30 10:26 UTC (permalink / raw) To: K . Y . Srinivasan, Marc Zyngier, Haiyang Zhang, Wei Liu, Dexuan Cui, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H . Peter Anvin, linux-hyperv, linux-kernel Cc: Nam Cao Move away from the legacy MSI domain setup, switch to use msi_create_parent_irq_domain(). While doing the conversion, I noticed that hv_irq_compose_msi_msg() is doing more than it is supposed to (composing message content). The interrupt allocation bits should be moved into hv_msi_domain_alloc(). However, I have no hardware to test this change, therefore I leave a TODO note. Signed-off-by: Nam Cao <namcao@linutronix.de> --- arch/x86/hyperv/irqdomain.c | 111 ++++++++++++++++++++++++------------ drivers/hv/Kconfig | 1 + 2 files changed, 77 insertions(+), 35 deletions(-) diff --git a/arch/x86/hyperv/irqdomain.c b/arch/x86/hyperv/irqdomain.c index 31f0d29cbc5e3..9b3b65ffbd2e2 100644 --- a/arch/x86/hyperv/irqdomain.c +++ b/arch/x86/hyperv/irqdomain.c @@ -10,6 +10,7 @@ #include <linux/pci.h> #include <linux/irq.h> +#include <linux/irqchip/irq-msi-lib.h> #include <asm/mshyperv.h> static int hv_map_interrupt(union hv_device_id device_id, bool level, @@ -276,59 +277,99 @@ static void hv_teardown_msi_irq(struct pci_dev *dev, struct irq_data *irqd) hv_status_err(status, "\n"); } -static void hv_msi_free_irq(struct irq_domain *domain, - struct msi_domain_info *info, unsigned int virq) -{ - struct irq_data *irqd = irq_get_irq_data(virq); - struct msi_desc *desc; - - if (!irqd) - return; - - desc = irq_data_get_msi_desc(irqd); - if (!desc || !desc->irq || WARN_ON_ONCE(!dev_is_pci(desc->dev))) - return; - - hv_teardown_msi_irq(to_pci_dev(desc->dev), irqd); -} - /* * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices, * which implement the MSI or MSI-X Capability Structure. */ static struct irq_chip hv_pci_msi_controller = { .name = "HV-PCI-MSI", - .irq_unmask = pci_msi_unmask_irq, - .irq_mask = pci_msi_mask_irq, .irq_ack = irq_chip_ack_parent, - .irq_retrigger = irq_chip_retrigger_hierarchy, .irq_compose_msi_msg = hv_irq_compose_msi_msg, - .irq_set_affinity = msi_domain_set_affinity, - .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MOVE_DEFERRED, + .irq_set_affinity = irq_chip_set_affinity_parent, }; -static struct msi_domain_ops pci_msi_domain_ops = { - .msi_free = hv_msi_free_irq, - .msi_prepare = pci_msi_prepare, +static bool hv_init_dev_msi_info(struct device *dev, struct irq_domain *domain, + struct irq_domain *real_parent, struct msi_domain_info *info) +{ + struct irq_chip *chip = info->chip; + + if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info)) + return false; + + chip->flags |= IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MOVE_DEFERRED; + + info->ops->msi_prepare = pci_msi_prepare; + + return true; +} + +#define HV_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | MSI_FLAG_PCI_MSIX) +#define HV_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS) + +static struct msi_parent_ops hv_msi_parent_ops = { + .supported_flags = HV_MSI_FLAGS_SUPPORTED, + .required_flags = HV_MSI_FLAGS_REQUIRED, + .bus_select_token = DOMAIN_BUS_NEXUS, + .bus_select_mask = MATCH_PCI_MSI, + .chip_flags = MSI_CHIP_FLAG_SET_ACK, + .prefix = "HV-", + .init_dev_msi_info = hv_init_dev_msi_info, }; -static struct msi_domain_info hv_pci_msi_domain_info = { - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | - MSI_FLAG_PCI_MSIX, - .ops = &pci_msi_domain_ops, - .chip = &hv_pci_msi_controller, - .handler = handle_edge_irq, - .handler_name = "edge", +static int hv_msi_domain_alloc(struct irq_domain *d, unsigned int virq, unsigned int nr_irqs, + void *arg) +{ + /* + * TODO: The allocation bits of hv_irq_compose_msi_msg(), i.e. everything except + * entry_to_msi_msg() should be in here. + */ + + int ret; + + ret = irq_domain_alloc_irqs_parent(d, virq, nr_irqs, arg); + if (ret) + return ret; + + for (int i = 0; i < nr_irqs; ++i) { + irq_domain_set_info(d, virq + i, 0, &hv_pci_msi_controller, NULL, + handle_edge_irq, NULL, "edge"); + } + return 0; +} + +static void hv_msi_domain_free(struct irq_domain *d, unsigned int virq, unsigned int nr_irqs) +{ + for (int i = 0; i < nr_irqs; ++i) { + struct irq_data *irqd = irq_domain_get_irq_data(d, virq); + struct msi_desc *desc; + + desc = irq_data_get_msi_desc(irqd); + if (!desc || !desc->irq || WARN_ON_ONCE(!dev_is_pci(desc->dev))) + continue; + + hv_teardown_msi_irq(to_pci_dev(desc->dev), irqd); + } + irq_domain_free_irqs_top(d, virq, nr_irqs); +} + +static const struct irq_domain_ops hv_msi_domain_ops = { + .select = msi_lib_irq_domain_select, + .alloc = hv_msi_domain_alloc, + .free = hv_msi_domain_free, }; struct irq_domain * __init hv_create_pci_msi_domain(void) { struct irq_domain *d = NULL; - struct fwnode_handle *fn; - fn = irq_domain_alloc_named_fwnode("HV-PCI-MSI"); - if (fn) - d = pci_msi_create_irq_domain(fn, &hv_pci_msi_domain_info, x86_vector_domain); + struct irq_domain_info info = { + .fwnode = irq_domain_alloc_named_fwnode("HV-PCI-MSI"), + .ops = &hv_msi_domain_ops, + .parent = x86_vector_domain, + }; + + if (info.fwnode) + d = msi_create_parent_irq_domain(&info, &hv_msi_parent_ops); /* No point in going further if we can't get an irq domain */ BUG_ON(!d); diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig index 1cd188b73b743..e62a0f8b34198 100644 --- a/drivers/hv/Kconfig +++ b/drivers/hv/Kconfig @@ -10,6 +10,7 @@ config HYPERV select X86_HV_CALLBACK_VECTOR if X86 select OF_EARLY_FLATTREE if OF select SYSFB if !HYPERV_VTL_MODE + select IRQ_MSI_LIB if X86 help Select this option to run Linux as a Hyper-V client operating system. -- 2.39.5 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 2/2] x86/hyperv: Switch to msi_create_parent_irq_domain() 2025-06-30 10:26 ` [PATCH v2 2/2] x86/hyperv: Switch to msi_create_parent_irq_domain() Nam Cao @ 2025-07-09 23:40 ` Wei Liu 2025-07-15 19:09 ` Nuno Das Neves 0 siblings, 1 reply; 6+ messages in thread From: Wei Liu @ 2025-07-09 23:40 UTC (permalink / raw) To: Nam Cao Cc: K . Y . Srinivasan, Marc Zyngier, Haiyang Zhang, Wei Liu, Dexuan Cui, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H . Peter Anvin, linux-hyperv, linux-kernel, nunodasneves CC Nuno who is also touching on this file. Nam, thanks for this patch. Nuno's patches fix a few bugs with the current implementation. I expect those patches to have contextual conflicts with this patch. I would like to commit Nuno's patches first since those are bug fixes, and then circle back to this one. Nuno, can you please review this patch? On Mon, Jun 30, 2025 at 12:26:15PM +0200, Nam Cao wrote: > Move away from the legacy MSI domain setup, switch to use > msi_create_parent_irq_domain(). > > While doing the conversion, I noticed that hv_irq_compose_msi_msg() is > doing more than it is supposed to (composing message content). The > interrupt allocation bits should be moved into hv_msi_domain_alloc(). > However, I have no hardware to test this change, therefore I leave a TODO > note. > > Signed-off-by: Nam Cao <namcao@linutronix.de> > --- > arch/x86/hyperv/irqdomain.c | 111 ++++++++++++++++++++++++------------ > drivers/hv/Kconfig | 1 + > 2 files changed, 77 insertions(+), 35 deletions(-) > > diff --git a/arch/x86/hyperv/irqdomain.c b/arch/x86/hyperv/irqdomain.c > index 31f0d29cbc5e3..9b3b65ffbd2e2 100644 > --- a/arch/x86/hyperv/irqdomain.c > +++ b/arch/x86/hyperv/irqdomain.c > @@ -10,6 +10,7 @@ > > #include <linux/pci.h> > #include <linux/irq.h> > +#include <linux/irqchip/irq-msi-lib.h> > #include <asm/mshyperv.h> > > static int hv_map_interrupt(union hv_device_id device_id, bool level, > @@ -276,59 +277,99 @@ static void hv_teardown_msi_irq(struct pci_dev *dev, struct irq_data *irqd) > hv_status_err(status, "\n"); > } > > -static void hv_msi_free_irq(struct irq_domain *domain, > - struct msi_domain_info *info, unsigned int virq) > -{ > - struct irq_data *irqd = irq_get_irq_data(virq); > - struct msi_desc *desc; > - > - if (!irqd) > - return; > - > - desc = irq_data_get_msi_desc(irqd); > - if (!desc || !desc->irq || WARN_ON_ONCE(!dev_is_pci(desc->dev))) > - return; > - > - hv_teardown_msi_irq(to_pci_dev(desc->dev), irqd); > -} > - > /* > * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices, > * which implement the MSI or MSI-X Capability Structure. > */ > static struct irq_chip hv_pci_msi_controller = { > .name = "HV-PCI-MSI", > - .irq_unmask = pci_msi_unmask_irq, > - .irq_mask = pci_msi_mask_irq, > .irq_ack = irq_chip_ack_parent, > - .irq_retrigger = irq_chip_retrigger_hierarchy, > .irq_compose_msi_msg = hv_irq_compose_msi_msg, > - .irq_set_affinity = msi_domain_set_affinity, > - .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MOVE_DEFERRED, > + .irq_set_affinity = irq_chip_set_affinity_parent, > }; > > -static struct msi_domain_ops pci_msi_domain_ops = { > - .msi_free = hv_msi_free_irq, > - .msi_prepare = pci_msi_prepare, > +static bool hv_init_dev_msi_info(struct device *dev, struct irq_domain *domain, > + struct irq_domain *real_parent, struct msi_domain_info *info) > +{ > + struct irq_chip *chip = info->chip; > + > + if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info)) > + return false; > + > + chip->flags |= IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MOVE_DEFERRED; > + > + info->ops->msi_prepare = pci_msi_prepare; > + > + return true; > +} > + > +#define HV_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | MSI_FLAG_PCI_MSIX) > +#define HV_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS) > + > +static struct msi_parent_ops hv_msi_parent_ops = { > + .supported_flags = HV_MSI_FLAGS_SUPPORTED, > + .required_flags = HV_MSI_FLAGS_REQUIRED, > + .bus_select_token = DOMAIN_BUS_NEXUS, > + .bus_select_mask = MATCH_PCI_MSI, > + .chip_flags = MSI_CHIP_FLAG_SET_ACK, > + .prefix = "HV-", > + .init_dev_msi_info = hv_init_dev_msi_info, > }; > > -static struct msi_domain_info hv_pci_msi_domain_info = { > - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | > - MSI_FLAG_PCI_MSIX, > - .ops = &pci_msi_domain_ops, > - .chip = &hv_pci_msi_controller, > - .handler = handle_edge_irq, > - .handler_name = "edge", > +static int hv_msi_domain_alloc(struct irq_domain *d, unsigned int virq, unsigned int nr_irqs, > + void *arg) > +{ > + /* > + * TODO: The allocation bits of hv_irq_compose_msi_msg(), i.e. everything except > + * entry_to_msi_msg() should be in here. > + */ > + > + int ret; > + > + ret = irq_domain_alloc_irqs_parent(d, virq, nr_irqs, arg); > + if (ret) > + return ret; > + > + for (int i = 0; i < nr_irqs; ++i) { > + irq_domain_set_info(d, virq + i, 0, &hv_pci_msi_controller, NULL, > + handle_edge_irq, NULL, "edge"); > + } > + return 0; > +} > + > +static void hv_msi_domain_free(struct irq_domain *d, unsigned int virq, unsigned int nr_irqs) > +{ > + for (int i = 0; i < nr_irqs; ++i) { > + struct irq_data *irqd = irq_domain_get_irq_data(d, virq); > + struct msi_desc *desc; > + > + desc = irq_data_get_msi_desc(irqd); > + if (!desc || !desc->irq || WARN_ON_ONCE(!dev_is_pci(desc->dev))) > + continue; > + > + hv_teardown_msi_irq(to_pci_dev(desc->dev), irqd); > + } > + irq_domain_free_irqs_top(d, virq, nr_irqs); > +} > + > +static const struct irq_domain_ops hv_msi_domain_ops = { > + .select = msi_lib_irq_domain_select, > + .alloc = hv_msi_domain_alloc, > + .free = hv_msi_domain_free, > }; > > struct irq_domain * __init hv_create_pci_msi_domain(void) > { > struct irq_domain *d = NULL; > - struct fwnode_handle *fn; > > - fn = irq_domain_alloc_named_fwnode("HV-PCI-MSI"); > - if (fn) > - d = pci_msi_create_irq_domain(fn, &hv_pci_msi_domain_info, x86_vector_domain); > + struct irq_domain_info info = { > + .fwnode = irq_domain_alloc_named_fwnode("HV-PCI-MSI"), > + .ops = &hv_msi_domain_ops, > + .parent = x86_vector_domain, > + }; > + > + if (info.fwnode) > + d = msi_create_parent_irq_domain(&info, &hv_msi_parent_ops); > > /* No point in going further if we can't get an irq domain */ > BUG_ON(!d); > diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig > index 1cd188b73b743..e62a0f8b34198 100644 > --- a/drivers/hv/Kconfig > +++ b/drivers/hv/Kconfig > @@ -10,6 +10,7 @@ config HYPERV > select X86_HV_CALLBACK_VECTOR if X86 > select OF_EARLY_FLATTREE if OF > select SYSFB if !HYPERV_VTL_MODE > + select IRQ_MSI_LIB if X86 > help > Select this option to run Linux as a Hyper-V client operating > system. > -- > 2.39.5 > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 2/2] x86/hyperv: Switch to msi_create_parent_irq_domain() 2025-07-09 23:40 ` Wei Liu @ 2025-07-15 19:09 ` Nuno Das Neves 2025-07-18 19:08 ` Thomas Gleixner 0 siblings, 1 reply; 6+ messages in thread From: Nuno Das Neves @ 2025-07-15 19:09 UTC (permalink / raw) To: Wei Liu, Nam Cao Cc: K . Y . Srinivasan, Marc Zyngier, Haiyang Zhang, Dexuan Cui, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H . Peter Anvin, linux-hyperv, linux-kernel On 7/9/2025 4:40 PM, Wei Liu wrote: > CC Nuno who is also touching on this file. > > Nam, thanks for this patch. > > Nuno's patches fix a few bugs with the current implementation. I expect > those patches to have contextual conflicts with this patch. I would like > to commit Nuno's patches first since those are bug fixes, and then > circle back to this one. > > Nuno, can you please review this patch? > I don't think I can give a Reviewed-by since I don't have the context for these changes. It doesn't look like this conflicts with the changes in my patches. The TODO looks fine to me, it can be addressed in a followup. Nuno > On Mon, Jun 30, 2025 at 12:26:15PM +0200, Nam Cao wrote: >> Move away from the legacy MSI domain setup, switch to use >> msi_create_parent_irq_domain(). >> >> While doing the conversion, I noticed that hv_irq_compose_msi_msg() is >> doing more than it is supposed to (composing message content). The >> interrupt allocation bits should be moved into hv_msi_domain_alloc(). >> However, I have no hardware to test this change, therefore I leave a TODO >> note. >> >> Signed-off-by: Nam Cao <namcao@linutronix.de> >> --- >> arch/x86/hyperv/irqdomain.c | 111 ++++++++++++++++++++++++------------ >> drivers/hv/Kconfig | 1 + >> 2 files changed, 77 insertions(+), 35 deletions(-) >> >> diff --git a/arch/x86/hyperv/irqdomain.c b/arch/x86/hyperv/irqdomain.c >> index 31f0d29cbc5e3..9b3b65ffbd2e2 100644 >> --- a/arch/x86/hyperv/irqdomain.c >> +++ b/arch/x86/hyperv/irqdomain.c >> @@ -10,6 +10,7 @@ >> >> #include <linux/pci.h> >> #include <linux/irq.h> >> +#include <linux/irqchip/irq-msi-lib.h> >> #include <asm/mshyperv.h> >> >> static int hv_map_interrupt(union hv_device_id device_id, bool level, >> @@ -276,59 +277,99 @@ static void hv_teardown_msi_irq(struct pci_dev *dev, struct irq_data *irqd) >> hv_status_err(status, "\n"); >> } >> >> -static void hv_msi_free_irq(struct irq_domain *domain, >> - struct msi_domain_info *info, unsigned int virq) >> -{ >> - struct irq_data *irqd = irq_get_irq_data(virq); >> - struct msi_desc *desc; >> - >> - if (!irqd) >> - return; >> - >> - desc = irq_data_get_msi_desc(irqd); >> - if (!desc || !desc->irq || WARN_ON_ONCE(!dev_is_pci(desc->dev))) >> - return; >> - >> - hv_teardown_msi_irq(to_pci_dev(desc->dev), irqd); >> -} >> - >> /* >> * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices, >> * which implement the MSI or MSI-X Capability Structure. >> */ >> static struct irq_chip hv_pci_msi_controller = { >> .name = "HV-PCI-MSI", >> - .irq_unmask = pci_msi_unmask_irq, >> - .irq_mask = pci_msi_mask_irq, >> .irq_ack = irq_chip_ack_parent, >> - .irq_retrigger = irq_chip_retrigger_hierarchy, >> .irq_compose_msi_msg = hv_irq_compose_msi_msg, >> - .irq_set_affinity = msi_domain_set_affinity, >> - .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MOVE_DEFERRED, >> + .irq_set_affinity = irq_chip_set_affinity_parent, >> }; >> >> -static struct msi_domain_ops pci_msi_domain_ops = { >> - .msi_free = hv_msi_free_irq, >> - .msi_prepare = pci_msi_prepare, >> +static bool hv_init_dev_msi_info(struct device *dev, struct irq_domain *domain, >> + struct irq_domain *real_parent, struct msi_domain_info *info) >> +{ >> + struct irq_chip *chip = info->chip; >> + >> + if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info)) >> + return false; >> + >> + chip->flags |= IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MOVE_DEFERRED; >> + >> + info->ops->msi_prepare = pci_msi_prepare; >> + >> + return true; >> +} >> + >> +#define HV_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | MSI_FLAG_PCI_MSIX) >> +#define HV_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS) >> + >> +static struct msi_parent_ops hv_msi_parent_ops = { >> + .supported_flags = HV_MSI_FLAGS_SUPPORTED, >> + .required_flags = HV_MSI_FLAGS_REQUIRED, >> + .bus_select_token = DOMAIN_BUS_NEXUS, >> + .bus_select_mask = MATCH_PCI_MSI, >> + .chip_flags = MSI_CHIP_FLAG_SET_ACK, >> + .prefix = "HV-", >> + .init_dev_msi_info = hv_init_dev_msi_info, >> }; >> >> -static struct msi_domain_info hv_pci_msi_domain_info = { >> - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | >> - MSI_FLAG_PCI_MSIX, >> - .ops = &pci_msi_domain_ops, >> - .chip = &hv_pci_msi_controller, >> - .handler = handle_edge_irq, >> - .handler_name = "edge", >> +static int hv_msi_domain_alloc(struct irq_domain *d, unsigned int virq, unsigned int nr_irqs, >> + void *arg) >> +{ >> + /* >> + * TODO: The allocation bits of hv_irq_compose_msi_msg(), i.e. everything except >> + * entry_to_msi_msg() should be in here. >> + */ >> + >> + int ret; >> + >> + ret = irq_domain_alloc_irqs_parent(d, virq, nr_irqs, arg); >> + if (ret) >> + return ret; >> + >> + for (int i = 0; i < nr_irqs; ++i) { >> + irq_domain_set_info(d, virq + i, 0, &hv_pci_msi_controller, NULL, >> + handle_edge_irq, NULL, "edge"); >> + } >> + return 0; >> +} >> + >> +static void hv_msi_domain_free(struct irq_domain *d, unsigned int virq, unsigned int nr_irqs) >> +{ >> + for (int i = 0; i < nr_irqs; ++i) { >> + struct irq_data *irqd = irq_domain_get_irq_data(d, virq); >> + struct msi_desc *desc; >> + >> + desc = irq_data_get_msi_desc(irqd); >> + if (!desc || !desc->irq || WARN_ON_ONCE(!dev_is_pci(desc->dev))) >> + continue; >> + >> + hv_teardown_msi_irq(to_pci_dev(desc->dev), irqd); >> + } >> + irq_domain_free_irqs_top(d, virq, nr_irqs); >> +} >> + >> +static const struct irq_domain_ops hv_msi_domain_ops = { >> + .select = msi_lib_irq_domain_select, >> + .alloc = hv_msi_domain_alloc, >> + .free = hv_msi_domain_free, >> }; >> >> struct irq_domain * __init hv_create_pci_msi_domain(void) >> { >> struct irq_domain *d = NULL; >> - struct fwnode_handle *fn; >> >> - fn = irq_domain_alloc_named_fwnode("HV-PCI-MSI"); >> - if (fn) >> - d = pci_msi_create_irq_domain(fn, &hv_pci_msi_domain_info, x86_vector_domain); >> + struct irq_domain_info info = { >> + .fwnode = irq_domain_alloc_named_fwnode("HV-PCI-MSI"), >> + .ops = &hv_msi_domain_ops, >> + .parent = x86_vector_domain, >> + }; >> + >> + if (info.fwnode) >> + d = msi_create_parent_irq_domain(&info, &hv_msi_parent_ops); >> >> /* No point in going further if we can't get an irq domain */ >> BUG_ON(!d); >> diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig >> index 1cd188b73b743..e62a0f8b34198 100644 >> --- a/drivers/hv/Kconfig >> +++ b/drivers/hv/Kconfig >> @@ -10,6 +10,7 @@ config HYPERV >> select X86_HV_CALLBACK_VECTOR if X86 >> select OF_EARLY_FLATTREE if OF >> select SYSFB if !HYPERV_VTL_MODE >> + select IRQ_MSI_LIB if X86 >> help >> Select this option to run Linux as a Hyper-V client operating >> system. >> -- >> 2.39.5 >> ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 2/2] x86/hyperv: Switch to msi_create_parent_irq_domain() 2025-07-15 19:09 ` Nuno Das Neves @ 2025-07-18 19:08 ` Thomas Gleixner 0 siblings, 0 replies; 6+ messages in thread From: Thomas Gleixner @ 2025-07-18 19:08 UTC (permalink / raw) To: Nuno Das Neves, Wei Liu, Nam Cao Cc: K . Y . Srinivasan, Marc Zyngier, Haiyang Zhang, Dexuan Cui, Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H . Peter Anvin, linux-hyperv, linux-kernel On Tue, Jul 15 2025 at 12:09, Nuno Das Neves wrote: > On 7/9/2025 4:40 PM, Wei Liu wrote: >> CC Nuno who is also touching on this file. >> >> Nam, thanks for this patch. >> >> Nuno's patches fix a few bugs with the current implementation. I expect >> those patches to have contextual conflicts with this patch. I would like >> to commit Nuno's patches first since those are bug fixes, and then >> circle back to this one. >> >> Nuno, can you please review this patch? >> > > I don't think I can give a Reviewed-by since I don't have the context > for these changes. The cover letter provides the information along with a link for deeper information: https://lore.kernel.org/all/cover.1751277765.git.namcao@linutronix.de > It doesn't look like this conflicts with the changes in my patches. It might not look like it, but reality tells a different story: Applying patch _PATCH_v2_2_2_x86_hyperv_Switch_to_msi_create_parent_irq_domain_.patch patching file arch/x86/hyperv/irqdomain.c Hunk #1 FAILED at 10. Hunk #2 FAILED at 276. 2 out of 2 hunks FAILED -- rejects in file arch/x86/hyperv/irqdomain.c patching file drivers/hv/Kconfig Hunk #1 FAILED at 10. 1 out of 1 hunk FAILED -- rejects in file drivers/hv/Kconfig Nam, can you please redo the patch against the hyperv tree? Thanks, tglx ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-07-18 19:08 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-06-30 10:26 [PATCH v2 0/2] x86/hyperv: MSI parent domain conversion Nam Cao 2025-06-30 10:26 ` [PATCH v2 1/2] irqchip/irq-msi-lib: Select CONFIG_GENERIC_MSI_IRQ Nam Cao 2025-06-30 10:26 ` [PATCH v2 2/2] x86/hyperv: Switch to msi_create_parent_irq_domain() Nam Cao 2025-07-09 23:40 ` Wei Liu 2025-07-15 19:09 ` Nuno Das Neves 2025-07-18 19:08 ` Thomas Gleixner
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).