#include <linux/init.h>
#include <linux/delay.h>
#include <linux/sched.h>
+#include <linux/config.h>
#include <linux/smp_lock.h>
#include <linux/mc146818rtc.h>
#include <linux/compiler.h>
#include <asm/desc.h>
#include <asm/timer.h>
#include <asm/i8259.h>
-#include <asm/nmi.h>
#include <mach_apic.h>
static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
static DEFINE_SPINLOCK(ioapic_lock);
-static DEFINE_SPINLOCK(vector_lock);
int timer_over_8254 __initdata = 1;
# include <linux/slab.h> /* kmalloc() */
# include <linux/timer.h> /* time_after() */
-#ifdef CONFIG_BALANCED_IRQ_DEBUG
+# ifdef CONFIG_BALANCED_IRQ_DEBUG
# define TDprintk(x...) do { printk("<%ld:%s:%d>: ", jiffies, __FILE__, __LINE__); printk(x); } while (0)
# define Dprintk(x...) do { TDprintk(x); } while (0)
# else
# define Dprintk(x...)
# endif
-#define IRQBALANCE_CHECK_ARCH -999
-#define MAX_BALANCED_IRQ_INTERVAL (5*HZ)
-#define MIN_BALANCED_IRQ_INTERVAL (HZ/2)
-#define BALANCED_IRQ_MORE_DELTA (HZ/10)
-#define BALANCED_IRQ_LESS_DELTA (HZ)
-static int irqbalance_disabled __read_mostly = IRQBALANCE_CHECK_ARCH;
-static int physical_balance __read_mostly;
-static long balanced_irq_interval __read_mostly = MAX_BALANCED_IRQ_INTERVAL;
+#define IRQBALANCE_CHECK_ARCH -999
+static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH;
+static int physical_balance = 0;
static struct irq_cpu_info {
unsigned long * last_irq;
#define CPU_TO_PACKAGEINDEX(i) (first_cpu(cpu_sibling_map[i]))
-static cpumask_t balance_irq_affinity[NR_IRQS] = {
- [0 ... NR_IRQS-1] = CPU_MASK_ALL
-};
+#define MAX_BALANCED_IRQ_INTERVAL (5*HZ)
+#define MIN_BALANCED_IRQ_INTERVAL (HZ/2)
+#define BALANCED_IRQ_MORE_DELTA (HZ/10)
+#define BALANCED_IRQ_LESS_DELTA (HZ)
-void set_balance_irq_affinity(unsigned int irq, cpumask_t mask)
-{
- balance_irq_affinity[irq] = mask;
-}
+static long balanced_irq_interval = MAX_BALANCED_IRQ_INTERVAL;
static unsigned long move(int curr_cpu, cpumask_t allowed_mask,
unsigned long now, int direction)
if (irqbalance_disabled)
return;
- cpus_and(allowed_mask, cpu_online_map, balance_irq_affinity[irq]);
+ cpus_and(allowed_mask, cpu_online_map, irq_affinity[irq]);
new_cpu = move(cpu, allowed_mask, now, 1);
if (cpu != new_cpu) {
set_pending_irq(irq, cpumask_of_cpu(new_cpu));
{
int i, j;
Dprintk("Rotating IRQs among CPUs.\n");
- for_each_online_cpu(i) {
- for (j = 0; j < NR_IRQS; j++) {
+ for (i = 0; i < NR_CPUS; i++) {
+ for (j = 0; cpu_online(i) && (j < NR_IRQS); j++) {
if (!irq_desc[j].action)
continue;
/* Is it a significant load ? */
unsigned long imbalance = 0;
cpumask_t allowed_mask, target_cpu_mask, tmp;
- for_each_possible_cpu(i) {
+ for (i = 0; i < NR_CPUS; i++) {
int package_index;
CPU_IRQ(i) = 0;
if (!cpu_online(i))
}
}
/* Find the least loaded processor package */
- for_each_online_cpu(i) {
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_online(i))
+ continue;
if (i != CPU_TO_PACKAGEINDEX(i))
continue;
if (min_cpu_irq > CPU_IRQ(i)) {
*/
tmp_cpu_irq = 0;
tmp_loaded = -1;
- for_each_online_cpu(i) {
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_online(i))
+ continue;
if (i != CPU_TO_PACKAGEINDEX(i))
continue;
if (max_cpu_irq <= CPU_IRQ(i))
}
}
- cpus_and(allowed_mask,
- cpu_online_map,
- balance_irq_affinity[selected_irq]);
+ cpus_and(allowed_mask, cpu_online_map, irq_affinity[selected_irq]);
target_cpu_mask = cpumask_of_cpu(min_loaded);
cpus_and(tmp, target_cpu_mask, allowed_mask);
/* push everything to CPU 0 to give us a starting point. */
for (i = 0 ; i < NR_IRQS ; i++) {
- irq_desc[i].pending_mask = cpumask_of_cpu(0);
+ pending_irq_cpumask[i] = cpumask_of_cpu(0);
set_pending_irq(i, cpumask_of_cpu(0));
}
if (smp_num_siblings > 1 && !cpus_empty(tmp))
physical_balance = 1;
- for_each_online_cpu(i) {
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_online(i))
+ continue;
irq_cpu_data[i].irq_delta = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
irq_cpu_data[i].last_irq = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
if (irq_cpu_data[i].irq_delta == NULL || irq_cpu_data[i].last_irq == NULL) {
else
printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq");
failed:
- for_each_possible_cpu(i) {
+ for (i = 0; i < NR_CPUS; i++) {
kfree(irq_cpu_data[i].irq_delta);
- irq_cpu_data[i].irq_delta = NULL;
kfree(irq_cpu_data[i].last_irq);
- irq_cpu_data[i].last_irq = NULL;
}
return 0;
}
int __init irqbalance_disable(char *str)
{
irqbalance_disabled = 1;
- return 1;
+ return 0;
}
__setup("noirqbalance", irqbalance_disable);
int assign_irq_vector(int irq)
{
static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
- unsigned long flags;
- int vector;
- BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
-
- spin_lock_irqsave(&vector_lock, flags);
-
- if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {
- spin_unlock_irqrestore(&vector_lock, flags);
+ BUG_ON(irq >= NR_IRQ_VECTORS);
+ if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
return IO_APIC_VECTOR(irq);
- }
next:
current_vector += 8;
if (current_vector == SYSCALL_VECTOR)
if (current_vector >= FIRST_SYSTEM_VECTOR) {
offset++;
- if (!(offset%8)) {
- spin_unlock_irqrestore(&vector_lock, flags);
+ if (!(offset%8))
return -ENOSPC;
- }
current_vector = FIRST_DEVICE_VECTOR + offset;
}
- vector = current_vector;
- vector_irq[vector] = irq;
+ vector_irq[current_vector] = irq;
if (irq != AUTO_ASSIGN)
- IO_APIC_VECTOR(irq) = vector;
-
- spin_unlock_irqrestore(&vector_lock, flags);
+ IO_APIC_VECTOR(irq) = current_vector;
- return vector;
+ return current_vector;
}
static struct hw_interrupt_type ioapic_level_type;
#define IOAPIC_EDGE 0
#define IOAPIC_LEVEL 1
-static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
+static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger)
{
- unsigned idx;
-
- idx = use_pci_vector() && !platform_legacy_irq(irq) ? vector : irq;
-
- if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
- trigger == IOAPIC_LEVEL)
- irq_desc[idx].chip = &ioapic_level_type;
- else
- irq_desc[idx].chip = &ioapic_edge_type;
- set_intr_gate(vector, interrupt[idx]);
+ if (use_pci_vector() && !platform_legacy_irq(irq)) {
+ if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+ trigger == IOAPIC_LEVEL)
+ irq_desc[vector].handler = &ioapic_level_type;
+ else
+ irq_desc[vector].handler = &ioapic_edge_type;
+ set_intr_gate(vector, interrupt[vector]);
+ } else {
+ if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+ trigger == IOAPIC_LEVEL)
+ irq_desc[irq].handler = &ioapic_level_type;
+ else
+ irq_desc[irq].handler = &ioapic_edge_type;
+ set_intr_gate(vector, interrupt[irq]);
+ }
}
static void __init setup_IO_APIC_irqs(void)
* The timer IRQ doesn't have to know that behind the
* scene we have a 8259A-master in AEOI mode ...
*/
- irq_desc[0].chip = &ioapic_edge_type;
+ irq_desc[0].handler = &ioapic_edge_type;
/*
* Add it to the IO-APIC irq-routing table:
* Don't check I/O APIC IDs for xAPIC systems. They have
* no meaning without the serial APIC bus.
*/
- if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
- || APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
+ if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && boot_cpu_data.x86 < 15))
return;
/*
* This is broken; anything with a real cpu count has to
#endif
#endif
-static int ioapic_retrigger(unsigned int irq)
-{
- send_IPI_self(IO_APIC_VECTOR(irq));
-
- return 1;
-}
-
/*
* Level and edge triggered IO-APIC interrupts need different handling,
* so we use two separate IRQ descriptors. Edge triggered IRQs can be
#ifdef CONFIG_SMP
.set_affinity = set_ioapic_affinity,
#endif
- .retrigger = ioapic_retrigger,
};
static struct hw_interrupt_type ioapic_level_type __read_mostly = {
#ifdef CONFIG_SMP
.set_affinity = set_ioapic_affinity,
#endif
- .retrigger = ioapic_retrigger,
};
static inline void init_IO_APIC_traps(void)
make_8259A_irq(irq);
else
/* Strange. Oh, well.. */
- irq_desc[irq].chip = &no_irq_type;
+ irq_desc[irq].handler = &no_irq_type;
}
}
}
spin_unlock_irqrestore(&ioapic_lock, flags);
}
-int timer_uses_ioapic_pin_0;
-
/*
* This code may look a bit paranoid, but it's supposed to cooperate with
* a wide range of boards and BIOS bugs. Fortunately only the timer IRQ
pin2 = ioapic_i8259.pin;
apic2 = ioapic_i8259.apic;
- if (pin1 == 0)
- timer_uses_ioapic_pin_0 = 1;
-
printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
vector, apic1, pin1, apic2, pin2);
printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
disable_8259A_irq(0);
- irq_desc[0].chip = &lapic_irq_type;
+ irq_desc[0].handler = &lapic_irq_type;
apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector); /* Fixed mode */
enable_8259A_irq(0);