Lines Matching +full:interrupt +full:- +full:affinity

1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
4 * Copyright (C) 2005-2006, Thomas Gleixner, Russell King
6 * This file contains the interrupt descriptor management code. Detailed
7 * information is available in Documentation/core-api/genericirq.rst
13 #include <linux/interrupt.h>
15 #include <linux/radix-tree.h>
23 * lockdep: we want to handle all irq_desc locks as a single lock-class:
57 if (!zalloc_cpumask_var_node(&desc->irq_common_data.affinity, in alloc_masks()
59 return -ENOMEM; in alloc_masks()
62 if (!zalloc_cpumask_var_node(&desc->irq_common_data.effective_affinity, in alloc_masks()
64 free_cpumask_var(desc->irq_common_data.affinity); in alloc_masks()
65 return -ENOMEM; in alloc_masks()
70 if (!zalloc_cpumask_var_node(&desc->pending_mask, GFP_KERNEL, node)) { in alloc_masks()
72 free_cpumask_var(desc->irq_common_data.effective_affinity); in alloc_masks()
74 free_cpumask_var(desc->irq_common_data.affinity); in alloc_masks()
75 return -ENOMEM; in alloc_masks()
82 const struct cpumask *affinity) in desc_smp_init() argument
84 if (!affinity) in desc_smp_init()
85 affinity = irq_default_affinity; in desc_smp_init()
86 cpumask_copy(desc->irq_common_data.affinity, affinity); in desc_smp_init()
89 cpumask_clear(desc->pending_mask); in desc_smp_init()
92 desc->irq_common_data.node = node; in desc_smp_init()
100 desc_smp_init(struct irq_desc *desc, int node, const struct cpumask *affinity) { } in desc_smp_init() argument
104 const struct cpumask *affinity, struct module *owner) in desc_set_defaults() argument
108 desc->irq_common_data.handler_data = NULL; in desc_set_defaults()
109 desc->irq_common_data.msi_desc = NULL; in desc_set_defaults()
111 desc->irq_data.common = &desc->irq_common_data; in desc_set_defaults()
112 desc->irq_data.irq = irq; in desc_set_defaults()
113 desc->irq_data.chip = &no_irq_chip; in desc_set_defaults()
114 desc->irq_data.chip_data = NULL; in desc_set_defaults()
116 irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED); in desc_set_defaults()
117 irqd_set(&desc->irq_data, IRQD_IRQ_MASKED); in desc_set_defaults()
118 desc->handle_irq = handle_bad_irq; in desc_set_defaults()
119 desc->depth = 1; in desc_set_defaults()
120 desc->irq_count = 0; in desc_set_defaults()
121 desc->irqs_unhandled = 0; in desc_set_defaults()
122 desc->tot_count = 0; in desc_set_defaults()
123 desc->name = NULL; in desc_set_defaults()
124 desc->owner = owner; in desc_set_defaults()
126 *per_cpu_ptr(desc->kstat_irqs, cpu) = 0; in desc_set_defaults()
127 desc_smp_init(desc, node, affinity); in desc_set_defaults()
150 int cpu, irq = desc->irq_data.irq; in per_cpu_count_show()
157 ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s%u", p, c); in per_cpu_count_show()
161 ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); in per_cpu_count_show()
172 raw_spin_lock_irq(&desc->lock); in chip_name_show()
173 if (desc->irq_data.chip && desc->irq_data.chip->name) { in chip_name_show()
175 desc->irq_data.chip->name); in chip_name_show()
177 raw_spin_unlock_irq(&desc->lock); in chip_name_show()
189 raw_spin_lock_irq(&desc->lock); in hwirq_show()
190 if (desc->irq_data.domain) in hwirq_show()
191 ret = sprintf(buf, "%d\n", (int)desc->irq_data.hwirq); in hwirq_show()
192 raw_spin_unlock_irq(&desc->lock); in hwirq_show()
204 raw_spin_lock_irq(&desc->lock); in type_show()
206 irqd_is_level_type(&desc->irq_data) ? "level" : "edge"); in type_show()
207 raw_spin_unlock_irq(&desc->lock); in type_show()
220 raw_spin_lock_irq(&desc->lock); in wakeup_show()
222 irqd_is_wakeup_set(&desc->irq_data) ? "enabled" : "disabled"); in wakeup_show()
223 raw_spin_unlock_irq(&desc->lock); in wakeup_show()
236 raw_spin_lock_irq(&desc->lock); in name_show()
237 if (desc->name) in name_show()
238 ret = scnprintf(buf, PAGE_SIZE, "%s\n", desc->name); in name_show()
239 raw_spin_unlock_irq(&desc->lock); in name_show()
253 raw_spin_lock_irq(&desc->lock); in actions_show()
254 for (action = desc->action; action != NULL; action = action->next) { in actions_show()
255 ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s%s", in actions_show()
256 p, action->name); in actions_show()
259 raw_spin_unlock_irq(&desc->lock); in actions_show()
262 ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); in actions_show()
293 if (kobject_add(&desc->kobj, irq_kobj_base, "%d", irq)) in irq_sysfs_add()
307 kobject_del(&desc->kobj); in irq_sysfs_del()
321 return -ENOMEM; in irq_sysfs_init()
366 free_cpumask_var(desc->pending_mask); in free_masks()
368 free_cpumask_var(desc->irq_common_data.affinity); in free_masks()
370 free_cpumask_var(desc->irq_common_data.effective_affinity); in free_masks()
388 const struct cpumask *affinity, in alloc_desc() argument
397 desc->kstat_irqs = alloc_percpu(unsigned int); in alloc_desc()
398 if (!desc->kstat_irqs) in alloc_desc()
404 raw_spin_lock_init(&desc->lock); in alloc_desc()
405 lockdep_set_class(&desc->lock, &irq_desc_lock_class); in alloc_desc()
406 mutex_init(&desc->request_mutex); in alloc_desc()
407 init_rcu_head(&desc->rcu); in alloc_desc()
409 desc_set_defaults(irq, desc, node, affinity, owner); in alloc_desc()
410 irqd_set(&desc->irq_data, flags); in alloc_desc()
411 kobject_init(&desc->kobj, &irq_kobj_type); in alloc_desc()
416 free_percpu(desc->kstat_irqs); in alloc_desc()
427 free_percpu(desc->kstat_irqs); in irq_kobj_release()
435 kobject_put(&desc->kobj); in delayed_free_desc()
463 call_rcu(&desc->rcu, delayed_free_desc); in free_desc()
467 const struct irq_affinity_desc *affinity, in alloc_descs() argument
473 /* Validate affinity mask(s) */ in alloc_descs()
474 if (affinity) { in alloc_descs()
476 if (cpumask_empty(&affinity[i].mask)) in alloc_descs()
477 return -EINVAL; in alloc_descs()
485 if (affinity) { in alloc_descs()
486 if (affinity->is_managed) { in alloc_descs()
490 mask = &affinity->mask; in alloc_descs()
492 affinity++; in alloc_descs()
506 for (i--; i >= 0; i--) in alloc_descs()
508 return -ENOMEM; in alloc_descs()
514 return -ENOMEM; in irq_expand_nr_irqs()
551 [0 ... NR_IRQS-1] = {
554 .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
592 raw_spin_lock_irqsave(&desc->lock, flags); in free_desc()
594 raw_spin_unlock_irqrestore(&desc->lock, flags); in free_desc()
598 const struct irq_affinity_desc *affinity, in alloc_descs() argument
606 desc->owner = owner; in alloc_descs()
614 return -ENOMEM; in irq_expand_nr_irqs()
634 * generic_handle_irq - Invoke the handler for a particular irq
644 return -EINVAL; in generic_handle_irq()
648 return -EPERM; in generic_handle_irq()
657 * __handle_domain_irq - Invoke the handler for a HW irq belonging to a domain
661 * @regs: Register file coming from the low-level handling code
663 * Returns: 0 on success, or -EINVAL if conversion has failed
685 ret = -EINVAL; in __handle_domain_irq()
697 * handle_domain_nmi - Invoke the handler for a HW irq belonging to a domain
700 * @regs: Register file coming from the low-level handling code
704 * Returns: 0 on success, or -EINVAL if conversion has failed
721 * ack_bad_irq is not NMI-safe, just report in handle_domain_nmi()
722 * an invalid interrupt. in handle_domain_nmi()
727 ret = -EINVAL; in handle_domain_nmi()
735 /* Dynamic interrupt handling */
738 * irq_free_descs - free irq descriptors
759 * __irq_alloc_descs - allocate and initialize a range of irq descriptors
765 * @affinity: Optional pointer to an affinity mask array of size @cnt which
773 struct module *owner, const struct irq_affinity_desc *affinity) in __irq_alloc_descs() argument
778 return -EINVAL; in __irq_alloc_descs()
782 return -EINVAL; in __irq_alloc_descs()
797 ret = -EEXIST; in __irq_alloc_descs()
806 ret = alloc_descs(start, cnt, node, affinity, owner); in __irq_alloc_descs()
815 * irq_alloc_hwirqs - Allocate an irq descriptor and initialize the hardware
819 * Returns an interrupt number > 0 or 0, if the allocation fails.
823 int i, irq = __irq_alloc_descs(-1, 0, cnt, node, NULL, NULL); in irq_alloc_hwirqs()
828 for (i = irq; cnt > 0; i++, cnt--) { in irq_alloc_hwirqs()
836 for (i--; i >= irq; i--) { in irq_alloc_hwirqs()
846 * irq_free_hwirqs - Free irq descriptor and cleanup the hardware
855 for (i = from, j = cnt; j > 0; i++, j--) { in irq_free_hwirqs()
865 * irq_get_next_irq - get next allocated irq number
894 raw_spin_lock_irqsave(&desc->lock, *flags); in __irq_get_desc_lock()
900 __releases(&desc->lock) in __irq_put_desc_unlock()
902 raw_spin_unlock_irqrestore(&desc->lock, flags); in __irq_put_desc_unlock()
908 const struct cpumask *affinity) in irq_set_percpu_devid_partition() argument
913 return -EINVAL; in irq_set_percpu_devid_partition()
915 if (desc->percpu_enabled) in irq_set_percpu_devid_partition()
916 return -EINVAL; in irq_set_percpu_devid_partition()
918 desc->percpu_enabled = kzalloc(sizeof(*desc->percpu_enabled), GFP_KERNEL); in irq_set_percpu_devid_partition()
920 if (!desc->percpu_enabled) in irq_set_percpu_devid_partition()
921 return -ENOMEM; in irq_set_percpu_devid_partition()
923 if (affinity) in irq_set_percpu_devid_partition()
924 desc->percpu_affinity = affinity; in irq_set_percpu_devid_partition()
926 desc->percpu_affinity = cpu_possible_mask; in irq_set_percpu_devid_partition()
937 int irq_get_percpu_devid_partition(unsigned int irq, struct cpumask *affinity) in irq_get_percpu_devid_partition() argument
941 if (!desc || !desc->percpu_enabled) in irq_get_percpu_devid_partition()
942 return -EINVAL; in irq_get_percpu_devid_partition()
944 if (affinity) in irq_get_percpu_devid_partition()
945 cpumask_copy(affinity, desc->percpu_affinity); in irq_get_percpu_devid_partition()
957 * kstat_irqs_cpu - Get the statistics for an interrupt on a cpu
958 * @irq: The interrupt number
961 * Returns the sum of interrupt counts on @cpu since boot for
962 * @irq. The caller must ensure that the interrupt is not removed
969 return desc && desc->kstat_irqs ? in kstat_irqs_cpu()
970 *per_cpu_ptr(desc->kstat_irqs, cpu) : 0; in kstat_irqs_cpu()
975 return desc->istate & IRQS_NMI; in irq_is_nmi()
979 * kstat_irqs - Get the statistics for an interrupt
980 * @irq: The interrupt number
982 * Returns the sum of interrupt counts on all cpus since boot for
983 * @irq. The caller must ensure that the interrupt is not removed
992 if (!desc || !desc->kstat_irqs) in kstat_irqs()
997 return desc->tot_count; in kstat_irqs()
1000 sum += *per_cpu_ptr(desc->kstat_irqs, cpu); in kstat_irqs()
1005 * kstat_irqs_usr - Get the statistics for an interrupt
1006 * @irq: The interrupt number
1008 * Returns the sum of interrupt counts on all cpus since boot for @irq.
1010 * It uses rcu since a concurrent removal of an interrupt descriptor is