* [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).