You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
sparse irq_desc[] array: core kernel and x86 changes
Impact: new feature Problem on distro kernels: irq_desc[NR_IRQS] takes megabytes of RAM with NR_CPUS set to large values. The goal is to be able to scale up to much larger NR_IRQS value without impacting the (important) common case. To solve this, we generalize irq_desc[NR_IRQS] to an (optional) array of irq_desc pointers. When CONFIG_SPARSE_IRQ=y is used, we use kzalloc_node to get irq_desc, this also makes the IRQ descriptors NUMA-local (to the site that calls request_irq()). This gets rid of the irq_cfg[] static array on x86 as well: irq_cfg now uses desc->chip_data for x86 to store irq_cfg. Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
@@ -238,6 +238,16 @@ config X86_HAS_BOOT_CPU_ID
|
||||
def_bool y
|
||||
depends on X86_VOYAGER
|
||||
|
||||
config SPARSE_IRQ
|
||||
bool "Support sparse irq numbering"
|
||||
depends on PCI_MSI || HT_IRQ
|
||||
default y
|
||||
help
|
||||
This enables support for sparse irq, esp for msi/msi-x. You may need
|
||||
if you have lots of cards supports msi-x installed.
|
||||
|
||||
If you don't know what to do here, say Y.
|
||||
|
||||
config X86_FIND_SMP_CONFIG
|
||||
def_bool y
|
||||
depends on X86_MPPARSE || X86_VOYAGER
|
||||
|
||||
@@ -102,11 +102,20 @@
|
||||
#define invalid_vm86_irq(irq) ((irq) < 3 || (irq) > 15)
|
||||
|
||||
#if defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_VOYAGER)
|
||||
|
||||
#ifndef CONFIG_SPARSE_IRQ
|
||||
# if NR_CPUS < MAX_IO_APICS
|
||||
# define NR_IRQS (NR_VECTORS + (32 * NR_CPUS))
|
||||
# else
|
||||
# define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS))
|
||||
# endif
|
||||
#else
|
||||
# if (8 * NR_CPUS) > (32 * MAX_IO_APICS)
|
||||
# define NR_IRQS (NR_VECTORS + (8 * NR_CPUS))
|
||||
# else
|
||||
# define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#elif defined(CONFIG_X86_VOYAGER)
|
||||
|
||||
|
||||
+200
-121
File diff suppressed because it is too large
Load Diff
@@ -118,6 +118,9 @@ int show_interrupts(struct seq_file *p, void *v)
|
||||
}
|
||||
|
||||
desc = irq_to_desc(i);
|
||||
if (!desc)
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
#ifndef CONFIG_SMP
|
||||
any_count = kstat_irqs(i);
|
||||
|
||||
@@ -242,6 +242,8 @@ void fixup_irqs(cpumask_t map)
|
||||
for_each_irq_desc(irq, desc) {
|
||||
cpumask_t mask;
|
||||
|
||||
if (!desc)
|
||||
continue;
|
||||
if (irq == 2)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -94,6 +94,8 @@ void fixup_irqs(cpumask_t map)
|
||||
int break_affinity = 0;
|
||||
int set_affinity = 1;
|
||||
|
||||
if (!desc)
|
||||
continue;
|
||||
if (irq == 2)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -69,7 +69,6 @@ void __init init_ISA_irqs (void)
|
||||
* 16 old-style INTA-cycle interrupts:
|
||||
*/
|
||||
for (i = 0; i < 16; i++) {
|
||||
/* first time call this irq_desc */
|
||||
struct irq_desc *desc = irq_to_desc(i);
|
||||
|
||||
desc->status = IRQ_DISABLED;
|
||||
|
||||
@@ -143,7 +143,6 @@ void __init init_ISA_irqs(void)
|
||||
init_8259A(0);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
/* first time call this irq_desc */
|
||||
struct irq_desc *desc = irq_to_desc(i);
|
||||
|
||||
desc->status = IRQ_DISABLED;
|
||||
|
||||
+5
-17
@@ -558,23 +558,9 @@ struct timer_rand_state {
|
||||
unsigned dont_count_entropy:1;
|
||||
};
|
||||
|
||||
static struct timer_rand_state *irq_timer_state[NR_IRQS];
|
||||
|
||||
static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
|
||||
{
|
||||
if (irq >= nr_irqs)
|
||||
return NULL;
|
||||
|
||||
return irq_timer_state[irq];
|
||||
}
|
||||
|
||||
static void set_timer_rand_state(unsigned int irq, struct timer_rand_state *state)
|
||||
{
|
||||
if (irq >= nr_irqs)
|
||||
return;
|
||||
|
||||
irq_timer_state[irq] = state;
|
||||
}
|
||||
#ifndef CONFIG_SPARSE_IRQ
|
||||
struct timer_rand_state *irq_timer_state[NR_IRQS];
|
||||
#endif
|
||||
|
||||
static struct timer_rand_state input_timer_state;
|
||||
|
||||
@@ -933,8 +919,10 @@ void rand_initialize_irq(int irq)
|
||||
{
|
||||
struct timer_rand_state *state;
|
||||
|
||||
#ifndef CONFIG_SPARSE_IRQ
|
||||
if (irq >= nr_irqs)
|
||||
return;
|
||||
#endif
|
||||
|
||||
state = get_timer_rand_state(irq);
|
||||
|
||||
|
||||
@@ -19,17 +19,75 @@ struct irq_2_iommu {
|
||||
u8 irte_mask;
|
||||
};
|
||||
|
||||
static struct irq_2_iommu irq_2_iommuX[NR_IRQS];
|
||||
#ifdef CONFIG_SPARSE_IRQ
|
||||
static struct irq_2_iommu *get_one_free_irq_2_iommu(int cpu)
|
||||
{
|
||||
struct irq_2_iommu *iommu;
|
||||
int node;
|
||||
|
||||
node = cpu_to_node(cpu);
|
||||
|
||||
iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node);
|
||||
printk(KERN_DEBUG "alloc irq_2_iommu on cpu %d node %d\n", cpu, node);
|
||||
|
||||
return iommu;
|
||||
}
|
||||
|
||||
static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
|
||||
{
|
||||
return (irq < nr_irqs) ? irq_2_iommuX + irq : NULL;
|
||||
struct irq_desc *desc;
|
||||
|
||||
desc = irq_to_desc(irq);
|
||||
|
||||
if (WARN_ON_ONCE(!desc))
|
||||
return NULL;
|
||||
|
||||
return desc->irq_2_iommu;
|
||||
}
|
||||
|
||||
static struct irq_2_iommu *irq_2_iommu_alloc_cpu(unsigned int irq, int cpu)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
struct irq_2_iommu *irq_iommu;
|
||||
|
||||
/*
|
||||
* alloc irq desc if not allocated already.
|
||||
*/
|
||||
desc = irq_to_desc_alloc_cpu(irq, cpu);
|
||||
if (!desc) {
|
||||
printk(KERN_INFO "can not get irq_desc for %d\n", irq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
irq_iommu = desc->irq_2_iommu;
|
||||
|
||||
if (!irq_iommu)
|
||||
desc->irq_2_iommu = get_one_free_irq_2_iommu(cpu);
|
||||
|
||||
return desc->irq_2_iommu;
|
||||
}
|
||||
|
||||
static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
|
||||
{
|
||||
return irq_2_iommu_alloc_cpu(irq, boot_cpu_id);
|
||||
}
|
||||
|
||||
#else /* !CONFIG_SPARSE_IRQ */
|
||||
|
||||
static struct irq_2_iommu irq_2_iommuX[NR_IRQS];
|
||||
|
||||
static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
|
||||
{
|
||||
if (irq < nr_irqs)
|
||||
return &irq_2_iommuX[irq];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
|
||||
{
|
||||
return irq_2_iommu(irq);
|
||||
}
|
||||
#endif
|
||||
|
||||
static DEFINE_SPINLOCK(irq_2_ir_lock);
|
||||
|
||||
@@ -86,9 +144,11 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
|
||||
if (!count)
|
||||
return -1;
|
||||
|
||||
#ifndef CONFIG_SPARSE_IRQ
|
||||
/* protect irq_2_iommu_alloc later */
|
||||
if (irq >= nr_irqs)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* start the IRTE search from index 0.
|
||||
@@ -130,6 +190,12 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
|
||||
table->base[i].present = 1;
|
||||
|
||||
irq_iommu = irq_2_iommu_alloc(irq);
|
||||
if (!irq_iommu) {
|
||||
spin_unlock(&irq_2_ir_lock);
|
||||
printk(KERN_ERR "can't allocate irq_2_iommu\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
irq_iommu->iommu = iommu;
|
||||
irq_iommu->irte_index = index;
|
||||
irq_iommu->sub_handle = 0;
|
||||
@@ -177,6 +243,12 @@ int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
|
||||
|
||||
irq_iommu = irq_2_iommu_alloc(irq);
|
||||
|
||||
if (!irq_iommu) {
|
||||
spin_unlock(&irq_2_ir_lock);
|
||||
printk(KERN_ERR "can't allocate irq_2_iommu\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
irq_iommu->iommu = iommu;
|
||||
irq_iommu->irte_index = index;
|
||||
irq_iommu->sub_handle = subhandle;
|
||||
|
||||
@@ -141,8 +141,12 @@ static void init_evtchn_cpu_bindings(void)
|
||||
int i;
|
||||
|
||||
/* By default all event channels notify CPU#0. */
|
||||
for_each_irq_desc(i, desc)
|
||||
for_each_irq_desc(i, desc) {
|
||||
if (!desc)
|
||||
continue;
|
||||
|
||||
desc->affinity = cpumask_of_cpu(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
|
||||
@@ -231,7 +235,7 @@ static int find_unbound_irq(void)
|
||||
int irq;
|
||||
|
||||
/* Only allocate from dynirq range */
|
||||
for_each_irq_nr(irq)
|
||||
for (irq = 0; irq < nr_irqs; irq++)
|
||||
if (irq_bindcount[irq] == 0)
|
||||
break;
|
||||
|
||||
@@ -792,7 +796,7 @@ void xen_irq_resume(void)
|
||||
mask_evtchn(evtchn);
|
||||
|
||||
/* No IRQ <-> event-channel mappings. */
|
||||
for_each_irq_nr(irq)
|
||||
for (irq = 0; irq < nr_irqs; irq++)
|
||||
irq_info[irq].evtchn = 0; /* zap event-channel binding */
|
||||
|
||||
for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
|
||||
@@ -824,7 +828,7 @@ void __init xen_init_IRQ(void)
|
||||
mask_evtchn(i);
|
||||
|
||||
/* Dynamic IRQ space is currently unbound. Zero the refcnts. */
|
||||
for_each_irq_nr(i)
|
||||
for (i = 0; i < nr_irqs; i++)
|
||||
irq_bindcount[i] = 0;
|
||||
|
||||
irq_ctx_init(smp_processor_id());
|
||||
|
||||
+11
-6
@@ -27,6 +27,7 @@ static int show_stat(struct seq_file *p, void *v)
|
||||
u64 sum = 0;
|
||||
struct timespec boottime;
|
||||
unsigned int per_irq_sum;
|
||||
struct irq_desc *desc;
|
||||
|
||||
user = nice = system = idle = iowait =
|
||||
irq = softirq = steal = cputime64_zero;
|
||||
@@ -44,10 +45,11 @@ static int show_stat(struct seq_file *p, void *v)
|
||||
softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq);
|
||||
steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal);
|
||||
guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest);
|
||||
|
||||
for_each_irq_nr(j)
|
||||
for_each_irq_desc(j, desc) {
|
||||
if (!desc)
|
||||
continue;
|
||||
sum += kstat_irqs_cpu(j, i);
|
||||
|
||||
}
|
||||
sum += arch_irq_stat_cpu(i);
|
||||
}
|
||||
sum += arch_irq_stat();
|
||||
@@ -90,11 +92,14 @@ static int show_stat(struct seq_file *p, void *v)
|
||||
seq_printf(p, "intr %llu", (unsigned long long)sum);
|
||||
|
||||
/* sum again ? it could be updated? */
|
||||
for_each_irq_nr(j) {
|
||||
for (j = 0; j < NR_IRQS; j++) {
|
||||
desc = irq_to_desc(j);
|
||||
per_irq_sum = 0;
|
||||
|
||||
for_each_possible_cpu(i)
|
||||
per_irq_sum += kstat_irqs_cpu(j, i);
|
||||
if (desc) {
|
||||
for_each_possible_cpu(i)
|
||||
per_irq_sum += kstat_irqs_cpu(j, i);
|
||||
}
|
||||
|
||||
seq_printf(p, " %u", per_irq_sum);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
extern int nr_irqs;
|
||||
|
||||
/*
|
||||
* These correspond to the IORESOURCE_IRQ_* defines in
|
||||
* linux/ioport.h to select the interrupt line behaviour. When
|
||||
|
||||
+53
-1
@@ -129,6 +129,8 @@ struct irq_chip {
|
||||
const char *typename;
|
||||
};
|
||||
|
||||
struct timer_rand_state;
|
||||
struct irq_2_iommu;
|
||||
/**
|
||||
* struct irq_desc - interrupt descriptor
|
||||
* @irq: interrupt number for this descriptor
|
||||
@@ -154,6 +156,13 @@ struct irq_chip {
|
||||
*/
|
||||
struct irq_desc {
|
||||
unsigned int irq;
|
||||
#ifdef CONFIG_SPARSE_IRQ
|
||||
struct timer_rand_state *timer_rand_state;
|
||||
unsigned int *kstat_irqs;
|
||||
# ifdef CONFIG_INTR_REMAP
|
||||
struct irq_2_iommu *irq_2_iommu;
|
||||
# endif
|
||||
#endif
|
||||
irq_flow_handler_t handle_irq;
|
||||
struct irq_chip *chip;
|
||||
struct msi_desc *msi_desc;
|
||||
@@ -181,13 +190,51 @@ struct irq_desc {
|
||||
const char *name;
|
||||
} ____cacheline_internodealigned_in_smp;
|
||||
|
||||
extern void early_irq_init(void);
|
||||
extern void arch_early_irq_init(void);
|
||||
extern void arch_init_chip_data(struct irq_desc *desc, int cpu);
|
||||
extern void arch_init_copy_chip_data(struct irq_desc *old_desc,
|
||||
struct irq_desc *desc, int cpu);
|
||||
extern void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc);
|
||||
|
||||
#ifndef CONFIG_SPARSE_IRQ
|
||||
|
||||
extern struct irq_desc irq_desc[NR_IRQS];
|
||||
|
||||
static inline struct irq_desc *irq_to_desc(unsigned int irq)
|
||||
{
|
||||
return (irq < nr_irqs) ? irq_desc + irq : NULL;
|
||||
return (irq < NR_IRQS) ? irq_desc + irq : NULL;
|
||||
}
|
||||
static inline struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu)
|
||||
{
|
||||
return irq_to_desc(irq);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GENERIC_HARDIRQS
|
||||
# define for_each_irq_desc(irq, desc) \
|
||||
for (irq = 0, desc = irq_desc; irq < nr_irqs; irq++, desc++)
|
||||
# define for_each_irq_desc_reverse(irq, desc) \
|
||||
for (irq = nr_irqs - 1, desc = irq_desc + (nr_irqs - 1); \
|
||||
irq >= 0; irq--, desc--)
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
extern struct irq_desc *irq_to_desc(unsigned int irq);
|
||||
extern struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu);
|
||||
extern struct irq_desc *move_irq_desc(struct irq_desc *old_desc, int cpu);
|
||||
|
||||
# define for_each_irq_desc(irq, desc) \
|
||||
for (irq = 0, desc = irq_to_desc(irq); irq < nr_irqs; irq++, desc = irq_to_desc(irq))
|
||||
# define for_each_irq_desc_reverse(irq, desc) \
|
||||
for (irq = nr_irqs - 1, desc = irq_to_desc(irq); irq >= 0; irq--, desc = irq_to_desc(irq))
|
||||
|
||||
#define kstat_irqs_this_cpu(DESC) \
|
||||
((DESC)->kstat_irqs[smp_processor_id()])
|
||||
#define kstat_incr_irqs_this_cpu(irqno, DESC) \
|
||||
((DESC)->kstat_irqs[smp_processor_id()]++)
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Migration helpers for obsolete names, they will go away:
|
||||
@@ -380,6 +427,11 @@ extern int set_irq_msi(unsigned int irq, struct msi_desc *entry);
|
||||
#define get_irq_data(irq) (irq_to_desc(irq)->handler_data)
|
||||
#define get_irq_msi(irq) (irq_to_desc(irq)->msi_desc)
|
||||
|
||||
#define get_irq_desc_chip(desc) ((desc)->chip)
|
||||
#define get_irq_desc_chip_data(desc) ((desc)->chip_data)
|
||||
#define get_irq_desc_data(desc) ((desc)->handler_data)
|
||||
#define get_irq_desc_msi(desc) ((desc)->msi_desc)
|
||||
|
||||
#endif /* CONFIG_GENERIC_HARDIRQS */
|
||||
|
||||
#endif /* !CONFIG_S390 */
|
||||
|
||||
+3
-11
@@ -7,18 +7,10 @@
|
||||
|
||||
# define for_each_irq_desc(irq, desc) \
|
||||
for (irq = 0; irq < nr_irqs; irq++)
|
||||
#else
|
||||
extern int nr_irqs;
|
||||
|
||||
# define for_each_irq_desc(irq, desc) \
|
||||
for (irq = 0, desc = irq_desc; irq < nr_irqs; irq++, desc++)
|
||||
|
||||
# define for_each_irq_desc_reverse(irq, desc) \
|
||||
for (irq = nr_irqs - 1, desc = irq_desc + (nr_irqs - 1); \
|
||||
irq >= 0; irq--, desc--)
|
||||
static inline early_sparse_irq_init(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#define for_each_irq_nr(irq) \
|
||||
for (irq = 0; irq < nr_irqs; irq++)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,7 +28,9 @@ struct cpu_usage_stat {
|
||||
|
||||
struct kernel_stat {
|
||||
struct cpu_usage_stat cpustat;
|
||||
unsigned int irqs[NR_IRQS];
|
||||
#ifndef CONFIG_SPARSE_IRQ
|
||||
unsigned int irqs[NR_IRQS];
|
||||
#endif
|
||||
};
|
||||
|
||||
DECLARE_PER_CPU(struct kernel_stat, kstat);
|
||||
@@ -39,6 +41,10 @@ DECLARE_PER_CPU(struct kernel_stat, kstat);
|
||||
|
||||
extern unsigned long long nr_context_switches(void);
|
||||
|
||||
#ifndef CONFIG_SPARSE_IRQ
|
||||
#define kstat_irqs_this_cpu(irq) \
|
||||
(kstat_this_cpu.irqs[irq])
|
||||
|
||||
struct irq_desc;
|
||||
|
||||
static inline void kstat_incr_irqs_this_cpu(unsigned int irq,
|
||||
@@ -46,11 +52,17 @@ static inline void kstat_incr_irqs_this_cpu(unsigned int irq,
|
||||
{
|
||||
kstat_this_cpu.irqs[irq]++;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef CONFIG_SPARSE_IRQ
|
||||
static inline unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
|
||||
{
|
||||
return kstat_cpu(cpu).irqs[irq];
|
||||
}
|
||||
#else
|
||||
extern unsigned int kstat_irqs_cpu(unsigned int irq, int cpu);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Number of interrupts per specific IRQ source, since bootup
|
||||
|
||||
@@ -44,6 +44,57 @@ struct rand_pool_info {
|
||||
|
||||
extern void rand_initialize_irq(int irq);
|
||||
|
||||
struct timer_rand_state;
|
||||
#ifndef CONFIG_SPARSE_IRQ
|
||||
|
||||
extern struct timer_rand_state *irq_timer_state[];
|
||||
|
||||
extern int nr_irqs;
|
||||
static inline struct timer_rand_state *get_timer_rand_state(unsigned int irq)
|
||||
{
|
||||
if (irq >= nr_irqs)
|
||||
return NULL;
|
||||
|
||||
return irq_timer_state[irq];
|
||||
}
|
||||
|
||||
static inline void set_timer_rand_state(unsigned int irq, struct timer_rand_state *state)
|
||||
{
|
||||
if (irq >= nr_irqs)
|
||||
return;
|
||||
|
||||
irq_timer_state[irq] = state;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <linux/irq.h>
|
||||
static inline struct timer_rand_state *get_timer_rand_state(unsigned int irq)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
|
||||
desc = irq_to_desc(irq);
|
||||
|
||||
if (!desc)
|
||||
return NULL;
|
||||
|
||||
return desc->timer_rand_state;
|
||||
}
|
||||
|
||||
static inline void set_timer_rand_state(unsigned int irq, struct timer_rand_state *state)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
|
||||
desc = irq_to_desc(irq);
|
||||
|
||||
if (!desc)
|
||||
return;
|
||||
|
||||
desc->timer_rand_state = state;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
extern void add_input_randomness(unsigned int type, unsigned int code,
|
||||
unsigned int value);
|
||||
extern void add_interrupt_randomness(int irq);
|
||||
|
||||
+11
@@ -539,6 +539,15 @@ void __init __weak thread_info_cache_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void __init __weak arch_early_irq_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void __init __weak early_irq_init(void)
|
||||
{
|
||||
arch_early_irq_init();
|
||||
}
|
||||
|
||||
asmlinkage void __init start_kernel(void)
|
||||
{
|
||||
char * command_line;
|
||||
@@ -603,6 +612,8 @@ asmlinkage void __init start_kernel(void)
|
||||
sort_main_extable();
|
||||
trap_init();
|
||||
rcu_init();
|
||||
/* init some links before init_ISA_irqs() */
|
||||
early_irq_init();
|
||||
init_IRQ();
|
||||
pidhash_init();
|
||||
init_timers();
|
||||
|
||||
@@ -40,6 +40,9 @@ unsigned long probe_irq_on(void)
|
||||
* flush such a longstanding irq before considering it as spurious.
|
||||
*/
|
||||
for_each_irq_desc_reverse(i, desc) {
|
||||
if (!desc)
|
||||
continue;
|
||||
|
||||
spin_lock_irq(&desc->lock);
|
||||
if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
|
||||
/*
|
||||
@@ -68,6 +71,9 @@ unsigned long probe_irq_on(void)
|
||||
* happened in the previous stage, it may have masked itself)
|
||||
*/
|
||||
for_each_irq_desc_reverse(i, desc) {
|
||||
if (!desc)
|
||||
continue;
|
||||
|
||||
spin_lock_irq(&desc->lock);
|
||||
if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
|
||||
desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
|
||||
@@ -86,6 +92,9 @@ unsigned long probe_irq_on(void)
|
||||
* Now filter out any obviously spurious interrupts
|
||||
*/
|
||||
for_each_irq_desc(i, desc) {
|
||||
if (!desc)
|
||||
continue;
|
||||
|
||||
spin_lock_irq(&desc->lock);
|
||||
status = desc->status;
|
||||
|
||||
@@ -124,6 +133,9 @@ unsigned int probe_irq_mask(unsigned long val)
|
||||
int i;
|
||||
|
||||
for_each_irq_desc(i, desc) {
|
||||
if (!desc)
|
||||
continue;
|
||||
|
||||
spin_lock_irq(&desc->lock);
|
||||
status = desc->status;
|
||||
|
||||
@@ -166,6 +178,9 @@ int probe_irq_off(unsigned long val)
|
||||
unsigned int status;
|
||||
|
||||
for_each_irq_desc(i, desc) {
|
||||
if (!desc)
|
||||
continue;
|
||||
|
||||
spin_lock_irq(&desc->lock);
|
||||
status = desc->status;
|
||||
|
||||
|
||||
+2
-1
@@ -24,9 +24,10 @@
|
||||
*/
|
||||
void dynamic_irq_init(unsigned int irq)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
struct irq_desc *desc;
|
||||
unsigned long flags;
|
||||
|
||||
desc = irq_to_desc(irq);
|
||||
if (!desc) {
|
||||
WARN(1, KERN_ERR "Trying to initialize invalid IRQ%d\n", irq);
|
||||
return;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user