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.

irqdomain: Add firmware info reporting interface

Add an irqdomain callback to report firmware-provided information that is
otherwise not available in a generic way. This is reported using a new data
structure (struct irq_fwspec_info).

This callback is optional and the only information that can be reported
currently is the affinity of an interrupt. However, the containing
structure is designed to be extensible, allowing other potentially relevant
information to be reported in the future.

Signed-off-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Will Deacon <will@kernel.org>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Link: https://patch.msgid.link/20251020122944.3074811-2-maz@kernel.org

authored by

Marc Zyngier and committed by
Thomas Gleixner
87b0031f 3a866087

+54 -5
+27
include/linux/irqdomain.h
··· 44 44 u32 param[IRQ_DOMAIN_IRQ_SPEC_PARAMS]; 45 45 }; 46 46 47 + /** 48 + * struct irq_fwspec_info - firmware provided IRQ information structure 49 + * 50 + * @flags: Information validity flags 51 + * @cpumask: Affinity mask for this interrupt 52 + * 53 + * This structure reports firmware-specific information about an 54 + * interrupt. The only significant information is the affinity of a 55 + * per-CPU interrupt, but this is designed to be extended as required. 56 + */ 57 + struct irq_fwspec_info { 58 + unsigned long flags; 59 + const struct cpumask *affinity; 60 + }; 61 + 62 + #define IRQ_FWSPEC_INFO_AFFINITY_VALID BIT(0) 63 + 47 64 /* Conversion function from of_phandle_args fields to fwspec */ 48 65 void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args, 49 66 unsigned int count, struct irq_fwspec *fwspec); ··· 86 69 * @translate: Given @fwspec, decode the hardware irq number (@out_hwirq) and 87 70 * linux irq type value (@out_type). This is a generalised @xlate 88 71 * (over struct irq_fwspec) and is preferred if provided. 72 + * @get_fwspec_info: 73 + * Given @fwspec, report additional firmware-provided information in 74 + * @info. Optional. 89 75 * @debug_show: For domains to show specific data for an interrupt in debugfs. 90 76 * 91 77 * Functions below are provided by the driver and called whenever a new mapping ··· 116 96 void (*deactivate)(struct irq_domain *d, struct irq_data *irq_data); 117 97 int (*translate)(struct irq_domain *d, struct irq_fwspec *fwspec, 118 98 unsigned long *out_hwirq, unsigned int *out_type); 99 + int (*get_fwspec_info)(struct irq_fwspec *fwspec, struct irq_fwspec_info *info); 119 100 #endif 120 101 #ifdef CONFIG_GENERIC_IRQ_DEBUGFS 121 102 void (*debug_show)(struct seq_file *m, struct irq_domain *d, ··· 623 602 624 603 int irq_domain_disconnect_hierarchy(struct irq_domain *domain, unsigned int virq); 625 604 605 + int irq_populate_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info); 606 + 626 607 static inline bool irq_domain_is_hierarchy(struct irq_domain *domain) 627 608 { 628 609 return domain->flags & IRQ_DOMAIN_FLAG_HIERARCHY; ··· 708 685 return false; 709 686 } 710 687 688 + static inline int irq_populate_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info) 689 + { 690 + return -EINVAL; 691 + } 711 692 #endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */ 712 693 713 694 #ifdef CONFIG_GENERIC_MSI_IRQ
+27 -5
kernel/irq/irqdomain.c
··· 867 867 } 868 868 EXPORT_SYMBOL_GPL(of_phandle_args_to_fwspec); 869 869 870 - unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec) 870 + static struct irq_domain *fwspec_to_domain(struct irq_fwspec *fwspec) 871 871 { 872 872 struct irq_domain *domain; 873 - struct irq_data *irq_data; 874 - irq_hw_number_t hwirq; 875 - unsigned int type = IRQ_TYPE_NONE; 876 - int virq; 877 873 878 874 if (fwspec->fwnode) { 879 875 domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_WIRED); ··· 879 883 domain = irq_default_domain; 880 884 } 881 885 886 + return domain; 887 + } 888 + 889 + #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY 890 + int irq_populate_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info) 891 + { 892 + struct irq_domain *domain = fwspec_to_domain(fwspec); 893 + 894 + memset(info, 0, sizeof(*info)); 895 + 896 + if (!domain || !domain->ops->get_fwspec_info) 897 + return 0; 898 + 899 + return domain->ops->get_fwspec_info(fwspec, info); 900 + } 901 + #endif 902 + 903 + unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec) 904 + { 905 + unsigned int type = IRQ_TYPE_NONE; 906 + struct irq_domain *domain; 907 + struct irq_data *irq_data; 908 + irq_hw_number_t hwirq; 909 + int virq; 910 + 911 + domain = fwspec_to_domain(fwspec); 882 912 if (!domain) { 883 913 pr_warn("no irq domain found for %s !\n", 884 914 of_node_full_name(to_of_node(fwspec->fwnode)));