diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h index 68d6dfcf7d92..97dec9eadef3 100644 --- a/arch/x86/include/asm/irq_remapping.h +++ b/arch/x86/include/asm/irq_remapping.h @@ -63,8 +63,6 @@ extern struct irq_domain *irq_remapping_get_irq_domain( struct irq_alloc_info *info); extern int irq_remapping_get_ioapic_entry(struct irq_data *irq_data, struct IR_IO_APIC_route_entry *entry); -extern int irq_remapping_get_msi_entry(struct irq_data *irq_data, - struct msi_msg *entry); extern void irq_remapping_print_chip(struct irq_data *data, struct seq_file *p); /* @@ -142,12 +140,6 @@ static inline int irq_remapping_get_ioapic_entry(struct irq_data *irq_data, return -ENOSYS; } -static inline int irq_remapping_get_msi_entry(struct irq_data *irq_data, - struct msi_msg *entry) -{ - return -ENOSYS; -} - static inline void irq_remapping_domain_set_remapped(struct irq_domain *domain) { } diff --git a/arch/x86/kernel/apic/msi.c b/arch/x86/kernel/apic/msi.c index bd4275038436..0519ab3e43fb 100644 --- a/arch/x86/kernel/apic/msi.c +++ b/arch/x86/kernel/apic/msi.c @@ -35,8 +35,10 @@ static void msi_reset_irq_data_and_handler(struct irq_domain *domain, int virq) irq_set_handler(virq, NULL); } -static void native_compose_msi_msg(struct irq_cfg *cfg, struct msi_msg *msg) +static int msi_compose_msg(struct irq_data *data, struct msi_msg *msg) { + struct irq_cfg *cfg = irqd_cfg(data); + msg->address_hi = MSI_ADDR_BASE_HI; if (x2apic_enabled()) @@ -59,6 +61,8 @@ static void native_compose_msi_msg(struct irq_cfg *cfg, struct msi_msg *msg) MSI_DATA_DELIVERY_FIXED : MSI_DATA_DELIVERY_LOWPRI) | MSI_DATA_VECTOR(cfg->vector); + + return 0; } static void msi_update_msg(struct msi_msg *msg, struct irq_data *irq_data) @@ -74,11 +78,6 @@ static void msi_update_msg(struct msi_msg *msg, struct irq_data *irq_data) MSI_ADDR_EXT_DEST_ID(cfg->dest_apicid); } -static bool msi_irq_remapped(struct irq_data *irq_data) -{ - return irq_remapping_domain_is_remapped(irq_data->domain); -} - static int msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) { @@ -86,8 +85,7 @@ static int msi_set_affinity(struct irq_data *data, const struct cpumask *mask, int ret; ret = parent->chip->irq_set_affinity(parent, mask, force); - /* No need to reprogram MSI registers if interrupt is remapped */ - if (ret >= 0 && !msi_irq_remapped(data)) { + if (ret >= 0 && ret != IRQ_SET_MASK_OK_DONE) { struct msi_msg msg; __get_cached_msi_msg(data->msi_desc, &msg); @@ -110,6 +108,7 @@ static struct irq_chip msi_chip = { .irq_set_affinity = msi_set_affinity, .irq_retrigger = irq_chip_retrigger_hierarchy, .irq_print_chip = irq_remapping_print_chip, + .irq_compose_msi_msg = msi_compose_msg, .flags = IRQCHIP_SKIP_SET_WAKE, }; @@ -164,8 +163,8 @@ static void msi_domain_free(struct irq_domain *domain, unsigned int virq, static int msi_domain_activate(struct irq_domain *domain, struct irq_data *irq_data) { + int ret; struct msi_msg msg; - struct irq_cfg *cfg = irqd_cfg(irq_data); /* * irq_data->chip_data is MSI/MSIx offset. @@ -175,13 +174,11 @@ static int msi_domain_activate(struct irq_domain *domain, if (irq_data->chip_data) return 0; - if (msi_irq_remapped(irq_data)) - irq_remapping_get_msi_entry(irq_data->parent_data, &msg); - else - native_compose_msi_msg(cfg, &msg); - write_msi_msg(irq_data->irq, &msg); + ret = irq_chip_compose_msi_msg(irq_data, &msg); + if (ret == 0) + write_msi_msg(irq_data->irq, &msg); - return 0; + return ret; } static int msi_domain_deactivate(struct irq_domain *domain, @@ -268,17 +265,13 @@ void native_teardown_msi_irq(unsigned int irq) irq_domain_free_irqs(irq, 1); } -static struct irq_domain *msi_create_domain(struct irq_domain *parent, - bool remapped) +static struct irq_domain *msi_create_domain(struct irq_domain *parent) { struct irq_domain *domain; domain = irq_domain_add_tree(NULL, &msi_domain_ops, NULL); - if (domain) { + if (domain) domain->parent = parent; - if (remapped) - irq_remapping_domain_set_remapped(domain); - } return domain; } @@ -288,7 +281,7 @@ void arch_init_msi_domain(struct irq_domain *parent) if (disable_apic) return; - msi_default_domain = msi_create_domain(parent, false); + msi_default_domain = msi_create_domain(parent); if (!msi_default_domain) pr_warn("failed to initialize irqdomain for MSI/MSI-x.\n"); } @@ -296,7 +289,7 @@ void arch_init_msi_domain(struct irq_domain *parent) #ifdef CONFIG_IRQ_REMAP struct irq_domain *arch_create_msi_irq_domain(struct irq_domain *parent) { - return msi_create_domain(parent, true); + return msi_create_domain(parent); } #endif @@ -326,6 +319,7 @@ static struct irq_chip dmar_msi_type = { .irq_ack = irq_chip_ack_parent, .irq_set_affinity = dmar_msi_set_affinity, .irq_retrigger = irq_chip_retrigger_hierarchy, + .irq_compose_msi_msg = msi_compose_msg, .flags = IRQCHIP_SKIP_SET_WAKE, }; @@ -364,12 +358,14 @@ static void dmar_domain_free(struct irq_domain *domain, unsigned int virq, static int dmar_domain_activate(struct irq_domain *domain, struct irq_data *irq_data) { + int ret; struct msi_msg msg; - native_compose_msi_msg(irqd_cfg(irq_data), &msg); - dmar_msi_write(irq_data->irq, &msg); + ret = irq_chip_compose_msi_msg(irq_data, &msg); + if (ret == 0) + dmar_msi_write(irq_data->irq, &msg); - return 0; + return ret; } static int dmar_domain_deactivate(struct irq_domain *domain, @@ -445,8 +441,7 @@ static int hpet_msi_set_affinity(struct irq_data *data, int ret; ret = parent->chip->irq_set_affinity(parent, mask, force); - /* No need to rewrite HPET registers if interrupt is remapped */ - if (ret >= 0 && !msi_irq_remapped(data)) { + if (ret >= 0 && ret != IRQ_SET_MASK_OK_DONE) { hpet_msi_read(data->handler_data, &msg); msi_update_msg(&msg, data); hpet_msi_write(data->handler_data, &msg); @@ -463,6 +458,7 @@ static struct irq_chip hpet_msi_type = { .irq_set_affinity = hpet_msi_set_affinity, .irq_retrigger = irq_chip_retrigger_hierarchy, .irq_print_chip = irq_remapping_print_chip, + .irq_compose_msi_msg = msi_compose_msg, .flags = IRQCHIP_SKIP_SET_WAKE, }; @@ -503,16 +499,14 @@ static void hpet_domain_free(struct irq_domain *domain, unsigned int virq, static int hpet_domain_activate(struct irq_domain *domain, struct irq_data *irq_data) { + int ret; struct msi_msg msg; - struct irq_cfg *cfg = irqd_cfg(irq_data); - if (msi_irq_remapped(irq_data)) - irq_remapping_get_msi_entry(irq_data->parent_data, &msg); - else - native_compose_msi_msg(cfg, &msg); - hpet_msi_write(irq_get_handler_data(irq_data->irq), &msg); + ret = irq_chip_compose_msi_msg(irq_data, &msg); + if (ret == 0) + hpet_msi_write(irq_get_handler_data(irq_data->irq), &msg); - return 0; + return ret; } static int hpet_domain_deactivate(struct irq_domain *domain, @@ -535,27 +529,22 @@ static struct irq_domain_ops hpet_domain_ops = { struct irq_domain *hpet_create_irq_domain(int hpet_id) { - struct irq_domain *parent, *domain; + struct irq_domain *domain; struct irq_alloc_info info; - bool remapped = false; + + if (x86_vector_domain == NULL) + return NULL; init_irq_alloc_info(&info, NULL); info.type = X86_IRQ_ALLOC_TYPE_HPET; info.hpet_id = hpet_id; - parent = irq_remapping_get_ir_irq_domain(&info); - if (parent) - remapped = true; - else - parent = x86_vector_domain; - if (!parent) - return NULL; domain = irq_domain_add_tree(NULL, &hpet_domain_ops, (void *)(long)hpet_id); if (domain) { - domain->parent = parent; - if (remapped) - irq_remapping_domain_set_remapped(domain); + domain->parent = irq_remapping_get_ir_irq_domain(&info); + if (!domain->parent) + domain->parent = x86_vector_domain; } return domain; diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 0b648772c221..8fcd1497b109 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -4260,15 +4260,6 @@ static int get_ioapic_entry(struct irq_data *irq_data, return 0; } -static int get_msi_entry(struct irq_data *irq_data, struct msi_msg *msg) -{ - struct amd_ir_data *ir_data = irq_data->chip_data; - - *msg = ir_data->msi_entry; - - return 0; -} - struct irq_remap_ops amd_iommu_irq_ops = { .supported = amd_iommu_supported, .prepare = amd_iommu_prepare, @@ -4282,7 +4273,6 @@ struct irq_remap_ops amd_iommu_irq_ops = { .get_ir_irq_domain = get_ir_irq_domain, .get_irq_domain = get_irq_domain, .get_ioapic_entry = get_ioapic_entry, - .get_msi_entry = get_msi_entry, }; static void irq_remapping_prepare_irte(struct amd_ir_data *data, @@ -4475,7 +4465,7 @@ static int amd_ir_set_affinity(struct irq_data *data, int ret; ret = parent->chip->irq_set_affinity(parent, mask, force); - if (ret < 0) + if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE) return ret; /* @@ -4494,12 +4484,22 @@ static int amd_ir_set_affinity(struct irq_data *data, if (cfg->move_in_progress) send_cleanup_vector(cfg); - return ret; + return IRQ_SET_MASK_OK_DONE; +} + +static int compose_msi_msg(struct irq_data *irq_data, struct msi_msg *msg) +{ + struct amd_ir_data *ir_data = irq_data->chip_data; + + *msg = ir_data->msi_entry; + + return 0; } static struct irq_chip amd_ir_chip = { .irq_ack = ir_ack_apic_edge, .irq_set_affinity = amd_ir_set_affinity, + .irq_compose_msi_msg = compose_msi_msg, }; int amd_iommu_create_irq_domain(struct amd_iommu *iommu) diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 9742011190fb..e2ea4eccf9c9 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -1029,6 +1029,7 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, send_cleanup_vector(cfg); cpumask_copy(data->affinity, mask); + return 0; } @@ -1089,15 +1090,6 @@ static int intel_get_ioapic_entry(struct irq_data *irq_data, return 0; } -static int intel_get_msi_entry(struct irq_data *irq_data, struct msi_msg *msg) -{ - struct intel_ir_data *ir_data = irq_data->chip_data; - - *msg = ir_data->msi_entry; - - return 0; -} - struct irq_remap_ops intel_irq_remap_ops = { .supported = intel_irq_remapping_supported, .prepare = dmar_table_init, @@ -1111,7 +1103,6 @@ struct irq_remap_ops intel_irq_remap_ops = { .get_ir_irq_domain = intel_get_ir_irq_domain, .get_irq_domain = intel_get_irq_domain, .get_ioapic_entry = intel_get_ioapic_entry, - .get_msi_entry = intel_get_msi_entry, }; /* @@ -1139,7 +1130,7 @@ intel_ir_set_affinity(struct irq_data *data, const struct cpumask *mask, int ret; ret = parent->chip->irq_set_affinity(parent, mask, force); - if (ret < 0) + if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE) return ret; /* @@ -1158,12 +1149,22 @@ intel_ir_set_affinity(struct irq_data *data, const struct cpumask *mask, if (cfg->move_in_progress) send_cleanup_vector(cfg); - return ret; + return IRQ_SET_MASK_OK_DONE; +} + +static int intel_compose_msi_msg(struct irq_data *irq_data, struct msi_msg *msg) +{ + struct intel_ir_data *ir_data = irq_data->chip_data; + + *msg = ir_data->msi_entry; + + return 0; } static struct irq_chip intel_ir_chip = { .irq_ack = ir_ack_apic_edge, .irq_set_affinity = intel_ir_set_affinity, + .irq_compose_msi_msg = intel_compose_msi_msg, }; static void intel_irq_remapping_prepare_irte(struct intel_ir_data *data, diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 8fabc1d05f93..aa0cacc1486a 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -310,18 +310,3 @@ int irq_remapping_get_ioapic_entry(struct irq_data *irq_data, { return remap_ops->get_ioapic_entry(irq_data, entry); } - -/** - * irq_remapping_get_ioapic_entry - Get MSI data rewritten by interrupt - * remapping driver - * @irq_data: irq_data associated with interrupt remapping irqdomain - * @entry: host returned data - * - * Caller must make sure that the interrupt is remapped. - * Return 0 on success, otherwise return error code - */ -int irq_remapping_get_msi_entry(struct irq_data *irq_data, - struct msi_msg *entry) -{ - return remap_ops->get_msi_entry(irq_data, entry); -} diff --git a/drivers/iommu/irq_remapping.h b/drivers/iommu/irq_remapping.h index b01a51ed1780..df73f010c326 100644 --- a/drivers/iommu/irq_remapping.h +++ b/drivers/iommu/irq_remapping.h @@ -79,9 +79,6 @@ struct irq_remap_ops { /* Get IOAPIC entry content rewritten by interrupt remapping driver */ int (*get_ioapic_entry)(struct irq_data *, struct IR_IO_APIC_route_entry *); - - /* Get MSI data rewritten by interrupt remapping driver */ - int (*get_msi_entry)(struct irq_data *, struct msi_msg *); }; extern struct irq_remap_ops intel_irq_remap_ops; diff --git a/include/linux/irq.h b/include/linux/irq.h index 0adcbbbf2e87..226449317b78 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -113,10 +113,14 @@ enum { * * IRQ_SET_MASK_OK - OK, core updates irq_data.affinity * IRQ_SET_MASK_NOCPY - OK, chip did update irq_data.affinity + * IRQ_SET_MASK_OK_DONE - Same as IRQ_SET_MASK_OK for core. Special code to + * support stacked irqchips, which indicates skipping + * all descendent irqchips. */ enum { IRQ_SET_MASK_OK = 0, IRQ_SET_MASK_OK_NOCOPY, + IRQ_SET_MASK_OK_DONE, }; struct msi_desc; @@ -356,6 +360,8 @@ struct irq_chip { int (*irq_request_resources)(struct irq_data *data); void (*irq_release_resources)(struct irq_data *data); + int (*irq_compose_msi_msg)(struct irq_data *data, struct msi_msg *msg); + unsigned long flags; }; @@ -443,6 +449,7 @@ extern void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc); extern void handle_bad_irq(unsigned int irq, struct irq_desc *desc); extern void handle_nested_irq(unsigned int irq); +extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg); #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY extern void irq_chip_ack_parent(struct irq_data *data); extern int irq_chip_retrigger_hierarchy(struct irq_data *data); diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 12f3e72449eb..50cbbff7e27f 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -867,3 +867,15 @@ int irq_chip_retrigger_hierarchy(struct irq_data *data) return -ENOSYS; } #endif + +int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) +{ + int ret = -ENOSYS; + + if (data->parent_data) + ret = irq_chip_compose_msi_msg(data->parent_data, msg); + if (ret == -ENOSYS && data->chip && data->chip->irq_compose_msi_msg) + ret = data->chip->irq_compose_msi_msg(data, msg); + + return ret; +} diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 0a9104b4608b..80692373abd6 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -183,6 +183,7 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, ret = chip->irq_set_affinity(data, mask, force); switch (ret) { case IRQ_SET_MASK_OK: + case IRQ_SET_MASK_OK_DONE: cpumask_copy(data->affinity, mask); case IRQ_SET_MASK_OK_NOCOPY: irq_set_thread_affinity(desc); @@ -600,6 +601,7 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, switch (ret) { case IRQ_SET_MASK_OK: + case IRQ_SET_MASK_OK_DONE: irqd_clear(&desc->irq_data, IRQD_TRIGGER_MASK); irqd_set(&desc->irq_data, flags);