···3131 This device also represents the FIQ interrupt sources on platforms using AIC,3232 which do not go through a discrete interrupt controller.33333434+ IPIs may be performed via MMIO registers on all variants of AIC. Starting3535+ from A11, system registers may also be used for "fast" IPIs. Starting from3636+ M1, even faster IPIs within the same cluster may be achieved by writing to3737+ a "local" fast IPI register as opposed to using the "global" fast IPI3838+ register.3939+3440allOf:3541 - $ref: /schemas/interrupt-controller.yaml#36423743properties:3844 compatible:3945 items:4040- - const: apple,t8103-aic4646+ - enum:4747+ - apple,s5l8960x-aic4848+ - apple,t7000-aic4949+ - apple,s8000-aic5050+ - apple,t8010-aic5151+ - apple,t8015-aic5252+ - apple,t8103-aic4153 - const: apple,aic42544355 interrupt-controller: true
···685685 depends on PCI686686 default MACH_LOONGSON64687687 select IRQ_DOMAIN_HIERARCHY688688+ select IRQ_MSI_LIB688689 select PCI_MSI689690 help690691 Support for the Loongson PCH MSI Controller.
···128128 * Keep iterating over all registered FPGA IRQ controllers until there are129129 * no pending interrupts.130130 */131131-static asmlinkage void __exception_irq_entry fpga_handle_irq(struct pt_regs *regs)131131+static void __exception_irq_entry fpga_handle_irq(struct pt_regs *regs)132132{133133 int i, handled;134134
···276276#define IRQ_AFFINITY_MAX_SETS 4277277278278/**279279- * struct irq_affinity - Description for automatic irq affinity assignements279279+ * struct irq_affinity - Description for automatic irq affinity assignments280280 * @pre_vectors: Don't apply affinity to @pre_vectors at beginning of281281 * the MSI(-X) vector space282282 * @post_vectors: Don't apply affinity to @post_vectors at end of···594594595595struct softirq_action596596{597597- void (*action)(struct softirq_action *);597597+ void (*action)(void);598598};599599600600asmlinkage void do_softirq(void);···609609}610610#endif611611612612-extern void open_softirq(int nr, void (*action)(struct softirq_action *));612612+extern void open_softirq(int nr, void (*action)(void));613613extern void softirq_init(void);614614extern void __raise_softirq_irqoff(unsigned int nr);615615
-6
include/linux/irq.h
···991991 * @ack: Ack register offset to reg_base992992 * @eoi: Eoi register offset to reg_base993993 * @type: Type configuration register offset to reg_base994994- * @polarity: Polarity configuration register offset to reg_base995994 */996995struct irq_chip_regs {997996 unsigned long enable;···9991000 unsigned long ack;10001001 unsigned long eoi;10011002 unsigned long type;10021002- unsigned long polarity;10031003};1004100410051005/**···10381040 * @irq_base: Interrupt base nr for this chip10391041 * @irq_cnt: Number of interrupts handled by this chip10401042 * @mask_cache: Cached mask register shared between all chip types10411041- * @type_cache: Cached type register10421042- * @polarity_cache: Cached polarity register10431043 * @wake_enabled: Interrupt can wakeup from suspend10441044 * @wake_active: Interrupt is marked as an wakeup from suspend source10451045 * @num_ct: Number of available irq_chip_type instances (usually 1)···10641068 unsigned int irq_base;10651069 unsigned int irq_cnt;10661070 u32 mask_cache;10671067- u32 type_cache;10681068- u32 polarity_cache;10691071 u32 wake_enabled;10701072 u32 wake_active;10711073 unsigned int num_ct;
+8
include/linux/irqdomain.h
···291291 * @hwirq_max: Maximum number of interrupts supported by controller292292 * @direct_max: Maximum value of direct maps;293293 * Use ~0 for no limit; 0 for no direct mapping294294+ * @hwirq_base: The first hardware interrupt number (legacy domains only)295295+ * @virq_base: The first Linux interrupt number for legacy domains to296296+ * immediately associate the interrupts after domain creation294297 * @bus_token: Domain bus token298298+ * @name_suffix: Optional name suffix to avoid collisions when multiple299299+ * domains are added using same fwnode295300 * @ops: Domain operation callbacks296301 * @host_data: Controller private data pointer297302 * @dgc_info: Geneneric chip information structure pointer used to···312307 unsigned int size;313308 irq_hw_number_t hwirq_max;314309 int direct_max;310310+ unsigned int hwirq_base;311311+ unsigned int virq_base;315312 enum irq_domain_bus_token bus_token;313313+ const char *name_suffix;316314 const struct irq_domain_ops *ops;317315 void *host_data;318316#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
+1-1
kernel/irq/chip.c
···198198199199 irqd_clr_managed_shutdown(d);200200201201- if (cpumask_any_and(aff, cpu_online_mask) >= nr_cpu_ids) {201201+ if (!cpumask_intersects(aff, cpu_online_mask)) {202202 /*203203 * Catch code which fiddles with enable_irq() on a managed204204 * and potentially shutdown IRQ. Chained interrupt
+2-2
kernel/irq/cpuhotplug.c
···3737 * has been removed from the online mask already.3838 */3939 if (cpumask_any_but(m, cpu) < nr_cpu_ids &&4040- cpumask_any_and(m, cpu_online_mask) >= nr_cpu_ids) {4040+ !cpumask_intersects(m, cpu_online_mask)) {4141 /*4242 * If this happens then there was a missed IRQ fixup at some4343 * point. Warn about it and enforce fixup.···110110 if (maskchip && chip->irq_mask)111111 chip->irq_mask(d);112112113113- if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {113113+ if (!cpumask_intersects(affinity, cpu_online_mask)) {114114 /*115115 * If the interrupt is managed, then shut it down and leave116116 * the affinity untouched.
-1
kernel/irq/irq_sim.c
···13131414struct irq_sim_work_ctx {1515 struct irq_work work;1616- int irq_base;1716 unsigned int irq_count;1817 unsigned long *pending;1918 struct irq_domain *domain;
+124-86
kernel/irq/irqdomain.c
···128128}129129EXPORT_SYMBOL_GPL(irq_domain_free_fwnode);130130131131-static int irq_domain_set_name(struct irq_domain *domain,132132- const struct fwnode_handle *fwnode,133133- enum irq_domain_bus_token bus_token)131131+static int alloc_name(struct irq_domain *domain, char *base, enum irq_domain_bus_token bus_token)132132+{133133+ if (bus_token == DOMAIN_BUS_ANY)134134+ domain->name = kasprintf(GFP_KERNEL, "%s", base);135135+ else136136+ domain->name = kasprintf(GFP_KERNEL, "%s-%d", base, bus_token);137137+ if (!domain->name)138138+ return -ENOMEM;139139+140140+ domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED;141141+ return 0;142142+}143143+144144+static int alloc_fwnode_name(struct irq_domain *domain, const struct fwnode_handle *fwnode,145145+ enum irq_domain_bus_token bus_token, const char *suffix)146146+{147147+ const char *sep = suffix ? "-" : "";148148+ const char *suf = suffix ? : "";149149+ char *name;150150+151151+ if (bus_token == DOMAIN_BUS_ANY)152152+ name = kasprintf(GFP_KERNEL, "%pfw%s%s", fwnode, sep, suf);153153+ else154154+ name = kasprintf(GFP_KERNEL, "%pfw%s%s-%d", fwnode, sep, suf, bus_token);155155+ if (!name)156156+ return -ENOMEM;157157+158158+ /*159159+ * fwnode paths contain '/', which debugfs is legitimately unhappy160160+ * about. Replace them with ':', which does the trick and is not as161161+ * offensive as '\'...162162+ */163163+ domain->name = strreplace(name, '/', ':');164164+ domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED;165165+ return 0;166166+}167167+168168+static int alloc_unknown_name(struct irq_domain *domain, enum irq_domain_bus_token bus_token)134169{135170 static atomic_t unknown_domains;136136- struct irqchip_fwid *fwid;171171+ int id = atomic_inc_return(&unknown_domains);172172+173173+ if (bus_token == DOMAIN_BUS_ANY)174174+ domain->name = kasprintf(GFP_KERNEL, "unknown-%d", id);175175+ else176176+ domain->name = kasprintf(GFP_KERNEL, "unknown-%d-%d", id, bus_token);177177+ if (!domain->name)178178+ return -ENOMEM;179179+180180+ domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED;181181+ return 0;182182+}183183+184184+static int irq_domain_set_name(struct irq_domain *domain, const struct irq_domain_info *info)185185+{186186+ enum irq_domain_bus_token bus_token = info->bus_token;187187+ const struct fwnode_handle *fwnode = info->fwnode;137188138189 if (is_fwnode_irqchip(fwnode)) {139139- fwid = container_of(fwnode, struct irqchip_fwid, fwnode);190190+ struct irqchip_fwid *fwid = container_of(fwnode, struct irqchip_fwid, fwnode);191191+192192+ /*193193+ * The name_suffix is only intended to be used to avoid a name194194+ * collision when multiple domains are created for a single195195+ * device and the name is picked using a real device node.196196+ * (Typical use-case is regmap-IRQ controllers for devices197197+ * providing more than one physical IRQ.) There should be no198198+ * need to use name_suffix with irqchip-fwnode.199199+ */200200+ if (info->name_suffix)201201+ return -EINVAL;140202141203 switch (fwid->type) {142204 case IRQCHIP_FWNODE_NAMED:143205 case IRQCHIP_FWNODE_NAMED_ID:144144- domain->name = bus_token ?145145- kasprintf(GFP_KERNEL, "%s-%d",146146- fwid->name, bus_token) :147147- kstrdup(fwid->name, GFP_KERNEL);148148- if (!domain->name)149149- return -ENOMEM;150150- domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED;151151- break;206206+ return alloc_name(domain, fwid->name, bus_token);152207 default:153208 domain->name = fwid->name;154154- if (bus_token) {155155- domain->name = kasprintf(GFP_KERNEL, "%s-%d",156156- fwid->name, bus_token);157157- if (!domain->name)158158- return -ENOMEM;159159- domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED;160160- }161161- break;209209+ if (bus_token != DOMAIN_BUS_ANY)210210+ return alloc_name(domain, fwid->name, bus_token);162211 }163163- } else if (is_of_node(fwnode) || is_acpi_device_node(fwnode) ||164164- is_software_node(fwnode)) {165165- char *name;166212167167- /*168168- * fwnode paths contain '/', which debugfs is legitimately169169- * unhappy about. Replace them with ':', which does170170- * the trick and is not as offensive as '\'...171171- */172172- name = bus_token ?173173- kasprintf(GFP_KERNEL, "%pfw-%d", fwnode, bus_token) :174174- kasprintf(GFP_KERNEL, "%pfw", fwnode);175175- if (!name)176176- return -ENOMEM;177177-178178- domain->name = strreplace(name, '/', ':');179179- domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED;213213+ } else if (is_of_node(fwnode) || is_acpi_device_node(fwnode) || is_software_node(fwnode)) {214214+ return alloc_fwnode_name(domain, fwnode, bus_token, info->name_suffix);180215 }181216182182- if (!domain->name) {183183- if (fwnode)184184- pr_err("Invalid fwnode type for irqdomain\n");185185- domain->name = bus_token ?186186- kasprintf(GFP_KERNEL, "unknown-%d-%d",187187- atomic_inc_return(&unknown_domains),188188- bus_token) :189189- kasprintf(GFP_KERNEL, "unknown-%d",190190- atomic_inc_return(&unknown_domains));191191- if (!domain->name)192192- return -ENOMEM;193193- domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED;194194- }217217+ if (domain->name)218218+ return 0;195219196196- return 0;220220+ if (fwnode)221221+ pr_err("Invalid fwnode type for irqdomain\n");222222+ return alloc_unknown_name(domain, bus_token);197223}198224199225static struct irq_domain *__irq_domain_create(const struct irq_domain_info *info)···237211 if (!domain)238212 return ERR_PTR(-ENOMEM);239213240240- err = irq_domain_set_name(domain, info->fwnode, info->bus_token);214214+ err = irq_domain_set_name(domain, info);241215 if (err) {242216 kfree(domain);243217 return ERR_PTR(err);···293267 kfree(domain);294268}295269296296-/**297297- * irq_domain_instantiate() - Instantiate a new irq domain data structure298298- * @info: Domain information pointer pointing to the information for this domain299299- *300300- * Return: A pointer to the instantiated irq domain or an ERR_PTR value.301301- */302302-struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info)270270+static void irq_domain_instantiate_descs(const struct irq_domain_info *info)271271+{272272+ if (!IS_ENABLED(CONFIG_SPARSE_IRQ))273273+ return;274274+275275+ if (irq_alloc_descs(info->virq_base, info->virq_base, info->size,276276+ of_node_to_nid(to_of_node(info->fwnode))) < 0) {277277+ pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",278278+ info->virq_base);279279+ }280280+}281281+282282+static struct irq_domain *__irq_domain_instantiate(const struct irq_domain_info *info,283283+ bool cond_alloc_descs, bool force_associate)303284{304285 struct irq_domain *domain;305286 int err;···339306340307 __irq_domain_publish(domain);341308309309+ if (cond_alloc_descs && info->virq_base > 0)310310+ irq_domain_instantiate_descs(info);311311+312312+ /*313313+ * Legacy interrupt domains have a fixed Linux interrupt number314314+ * associated. Other interrupt domains can request association by315315+ * providing a Linux interrupt number > 0.316316+ */317317+ if (force_associate || info->virq_base > 0) {318318+ irq_domain_associate_many(domain, info->virq_base, info->hwirq_base,319319+ info->size - info->hwirq_base);320320+ }321321+342322 return domain;343323344324err_domain_gc_remove:···360314err_domain_free:361315 irq_domain_free(domain);362316 return ERR_PTR(err);317317+}318318+319319+/**320320+ * irq_domain_instantiate() - Instantiate a new irq domain data structure321321+ * @info: Domain information pointer pointing to the information for this domain322322+ *323323+ * Return: A pointer to the instantiated irq domain or an ERR_PTR value.324324+ */325325+struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info)326326+{327327+ return __irq_domain_instantiate(info, false, false);363328}364329EXPORT_SYMBOL_GPL(irq_domain_instantiate);365330···470413 .fwnode = fwnode,471414 .size = size,472415 .hwirq_max = size,416416+ .virq_base = first_irq,473417 .ops = ops,474418 .host_data = host_data,475419 };476476- struct irq_domain *domain;420420+ struct irq_domain *domain = __irq_domain_instantiate(&info, true, false);477421478478- domain = irq_domain_instantiate(&info);479479- if (IS_ERR(domain))480480- return NULL;481481-482482- if (first_irq > 0) {483483- if (IS_ENABLED(CONFIG_SPARSE_IRQ)) {484484- /* attempt to allocated irq_descs */485485- int rc = irq_alloc_descs(first_irq, first_irq, size,486486- of_node_to_nid(to_of_node(fwnode)));487487- if (rc < 0)488488- pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",489489- first_irq);490490- }491491- irq_domain_associate_many(domain, first_irq, 0, size);492492- }493493-494494- return domain;422422+ return IS_ERR(domain) ? NULL : domain;495423}496424EXPORT_SYMBOL_GPL(irq_domain_create_simple);497425···518476 .fwnode = fwnode,519477 .size = first_hwirq + size,520478 .hwirq_max = first_hwirq + size,479479+ .hwirq_base = first_hwirq,480480+ .virq_base = first_irq,521481 .ops = ops,522482 .host_data = host_data,523483 };524524- struct irq_domain *domain;484484+ struct irq_domain *domain = __irq_domain_instantiate(&info, false, true);525485526526- domain = irq_domain_instantiate(&info);527527- if (IS_ERR(domain))528528- return NULL;529529-530530- irq_domain_associate_many(domain, first_irq, first_hwirq, size);531531-532532- return domain;486486+ return IS_ERR(domain) ? NULL : domain;533487}534488EXPORT_SYMBOL_GPL(irq_domain_create_legacy);535489···14031365 tail = NULL;1404136614051367 /* The first entry must have a valid irqchip */14061406- if (!irq_data->chip || IS_ERR(irq_data->chip))13681368+ if (IS_ERR_OR_NULL(irq_data->chip))14071369 return -EINVAL;1408137014091371 /*
+9-12
kernel/irq/manage.c
···218218static inline void irq_validate_effective_affinity(struct irq_data *data) { }219219#endif220220221221+static DEFINE_PER_CPU(struct cpumask, __tmp_mask);222222+221223int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask,222224 bool force)223225{226226+ struct cpumask *tmp_mask = this_cpu_ptr(&__tmp_mask);224227 struct irq_desc *desc = irq_data_to_desc(data);225228 struct irq_chip *chip = irq_data_get_irq_chip(data);226229 const struct cpumask *prog_mask;227230 int ret;228231229229- static DEFINE_RAW_SPINLOCK(tmp_mask_lock);230230- static struct cpumask tmp_mask;231231-232232 if (!chip || !chip->irq_set_affinity)233233 return -EINVAL;234234235235- raw_spin_lock(&tmp_mask_lock);236235 /*237236 * If this is a managed interrupt and housekeeping is enabled on238237 * it check whether the requested affinity mask intersects with···257258258259 hk_mask = housekeeping_cpumask(HK_TYPE_MANAGED_IRQ);259260260260- cpumask_and(&tmp_mask, mask, hk_mask);261261- if (!cpumask_intersects(&tmp_mask, cpu_online_mask))261261+ cpumask_and(tmp_mask, mask, hk_mask);262262+ if (!cpumask_intersects(tmp_mask, cpu_online_mask))262263 prog_mask = mask;263264 else264264- prog_mask = &tmp_mask;265265+ prog_mask = tmp_mask;265266 } else {266267 prog_mask = mask;267268 }···271272 * unless we are being asked to force the affinity (in which272273 * case we do as we are told).273274 */274274- cpumask_and(&tmp_mask, prog_mask, cpu_online_mask);275275- if (!force && !cpumask_empty(&tmp_mask))276276- ret = chip->irq_set_affinity(data, &tmp_mask, force);275275+ cpumask_and(tmp_mask, prog_mask, cpu_online_mask);276276+ if (!force && !cpumask_empty(tmp_mask))277277+ ret = chip->irq_set_affinity(data, tmp_mask, force);277278 else if (force)278279 ret = chip->irq_set_affinity(data, mask, force);279280 else280281 ret = -EINVAL;281281-282282- raw_spin_unlock(&tmp_mask_lock);283282284283 switch (ret) {285284 case IRQ_SET_MASK_OK:
+2-2
kernel/irq/migration.c
···2626 * The outgoing CPU might be the last online target in a pending2727 * interrupt move. If that's the case clear the pending move bit.2828 */2929- if (cpumask_any_and(desc->pending_mask, cpu_online_mask) >= nr_cpu_ids) {2929+ if (!cpumask_intersects(desc->pending_mask, cpu_online_mask)) {3030 irqd_clr_move_pending(data);3131 return false;3232 }···7474 * For correct operation this depends on the caller7575 * masking the irqs.7676 */7777- if (cpumask_any_and(desc->pending_mask, cpu_online_mask) < nr_cpu_ids) {7777+ if (cpumask_intersects(desc->pending_mask, cpu_online_mask)) {7878 int ret;79798080 ret = irq_do_set_affinity(data, desc->pending_mask, false);
···24402440/*24412441 * This function runs timers and the timer-tq in bottom half context.24422442 */24432443-static __latent_entropy void run_timer_softirq(struct softirq_action *h)24432443+static __latent_entropy void run_timer_softirq(void)24442444{24452445 run_timer_base(BASE_LOCAL);24462446 if (IS_ENABLED(CONFIG_NO_HZ_COMMON)) {