Commit df0e5a8f authored by Martin J. Bligh's avatar Martin J. Bligh Committed by Patrick Mochel

[PATCH] abstract out clustered APIC code

Code originally by James Cleverdon.

This abstracts out some sections that were switched by
clustered_apic_mode into the following functions:

 - apic_id_registered()
 - init_apic_ldr()
 - multi_timer_check()

Changes the return check in balance_irq from testing clustered_apic_mode
to testing "no_balance_irq" to be more general.

The removal of:
	entry.dest.logical.logical_dest = TARGET_CPUS;
is because it's a duplicate (we do it twice in the same function for
no reason).
parent 172a3ef7
...@@ -311,11 +311,9 @@ void __init setup_local_APIC (void) ...@@ -311,11 +311,9 @@ void __init setup_local_APIC (void)
__error_in_apic_c(); __error_in_apic_c();
/* /*
* Double-check wether this APIC is really registered. * Double-check whether this APIC is really registered.
* This is meaningless in clustered apic mode, so we skip it.
*/ */
if (!clustered_apic_mode && if (!apic_id_registered())
!test_bit(GET_APIC_ID(apic_read(APIC_ID)), &phys_cpu_present_map))
BUG(); BUG();
/* /*
...@@ -323,21 +321,7 @@ void __init setup_local_APIC (void) ...@@ -323,21 +321,7 @@ void __init setup_local_APIC (void)
* an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
* document number 292116). So here it goes... * document number 292116). So here it goes...
*/ */
init_apic_ldr();
if (!clustered_apic_mode) {
/*
* In clustered apic mode, the firmware does this for us
* Put the APIC into flat delivery mode.
* Must be "all ones" explicitly for 82489DX.
*/
apic_write_around(APIC_DFR, APIC_DFR_VALUE);
/*
* Set up the logical destination ID.
*/
value = apic_read(APIC_LDR);
apic_write_around(APIC_LDR, calculate_ldr(value));
}
/* /*
* Set Task Priority to 'accept all'. We never change this * Set Task Priority to 'accept all'. We never change this
......
...@@ -262,7 +262,7 @@ static inline void balance_irq(int irq) ...@@ -262,7 +262,7 @@ static inline void balance_irq(int irq)
irq_balance_t *entry = irq_balance + irq; irq_balance_t *entry = irq_balance + irq;
unsigned long now = jiffies; unsigned long now = jiffies;
if (clustered_apic_mode) if (no_balance_irq)
return; return;
if (unlikely(time_after(now, entry->timestamp + IRQ_BALANCE_INTERVAL))) { if (unlikely(time_after(now, entry->timestamp + IRQ_BALANCE_INTERVAL))) {
...@@ -740,7 +740,6 @@ void __init setup_IO_APIC_irqs(void) ...@@ -740,7 +740,6 @@ void __init setup_IO_APIC_irqs(void)
if (irq_trigger(idx)) { if (irq_trigger(idx)) {
entry.trigger = 1; entry.trigger = 1;
entry.mask = 1; entry.mask = 1;
entry.dest.logical.logical_dest = TARGET_CPUS;
} }
irq = pin_2_irq(idx, apic, pin); irq = pin_2_irq(idx, apic, pin);
...@@ -748,7 +747,7 @@ void __init setup_IO_APIC_irqs(void) ...@@ -748,7 +747,7 @@ void __init setup_IO_APIC_irqs(void)
* skip adding the timer int on secondary nodes, which causes * skip adding the timer int on secondary nodes, which causes
* a small but painful rift in the time-space continuum * a small but painful rift in the time-space continuum
*/ */
if (clustered_apic_mode && (apic != 0) && (irq == 0)) if (multi_timer_check(apic, irq))
continue; continue;
else else
add_pin_to_irq(irq, apic, pin); add_pin_to_irq(irq, apic, pin);
......
#ifndef __ASM_MACH_APIC_H #ifndef __ASM_MACH_APIC_H
#define __ASM_MACH_APIC_H #define __ASM_MACH_APIC_H
static inline unsigned long calculate_ldr(unsigned long old)
{
unsigned long id;
id = 1UL << smp_processor_id();
return ((old & ~APIC_LDR_MASK) | SET_APIC_LOGICAL_ID(id));
}
#define APIC_DFR_VALUE (APIC_DFR_FLAT) #define APIC_DFR_VALUE (APIC_DFR_FLAT)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
...@@ -17,6 +9,8 @@ static inline unsigned long calculate_ldr(unsigned long old) ...@@ -17,6 +9,8 @@ static inline unsigned long calculate_ldr(unsigned long old)
#define TARGET_CPUS 0x01 #define TARGET_CPUS 0x01
#endif #endif
#define no_balance_irq (0)
#define APIC_BROADCAST_ID 0x0F #define APIC_BROADCAST_ID 0x0F
#define check_apicid_used(bitmap, apicid) (bitmap & (1 << apicid)) #define check_apicid_used(bitmap, apicid) (bitmap & (1 << apicid))
...@@ -24,12 +18,40 @@ static inline void summit_check(char *oem, char *productid) ...@@ -24,12 +18,40 @@ static inline void summit_check(char *oem, char *productid)
{ {
} }
static inline int apic_id_registered(void)
{
return (test_bit(GET_APIC_ID(apic_read(APIC_ID)),
&phys_cpu_present_map));
}
/*
* Set up the logical destination ID.
*
* Intel recommends to set DFR, LDR and TPR before enabling
* an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
* document number 292116). So here it goes...
*/
static inline void init_apic_ldr(void)
{
unsigned long val;
apic_write_around(APIC_DFR, APIC_DFR_VALUE);
val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id());
apic_write_around(APIC_LDR, val);
}
static inline void clustered_apic_check(void) static inline void clustered_apic_check(void)
{ {
printk("Enabling APIC mode: %s. Using %d I/O APICs\n", printk("Enabling APIC mode: %s. Using %d I/O APICs\n",
"Flat", nr_ioapics); "Flat", nr_ioapics);
} }
static inline int multi_timer_check(int apic, int irq)
{
return 0;
}
static inline int cpu_present_to_apicid(int mps_cpu) static inline int cpu_present_to_apicid(int mps_cpu)
{ {
return mps_cpu; return mps_cpu;
......
#ifndef __ASM_MACH_APIC_H #ifndef __ASM_MACH_APIC_H
#define __ASM_MACH_APIC_H #define __ASM_MACH_APIC_H
static inline unsigned long calculate_ldr(unsigned long old)
{
unsigned long id;
id = 1UL << smp_processor_id();
return ((old & ~APIC_LDR_MASK) | SET_APIC_LOGICAL_ID(id));
}
#define APIC_DFR_VALUE (APIC_DFR_FLAT) #define APIC_DFR_VALUE (APIC_DFR_FLAT)
#define TARGET_CPUS (0xf) #define TARGET_CPUS (0xf)
#define no_balance_irq (1)
#define APIC_BROADCAST_ID 0x0F #define APIC_BROADCAST_ID 0x0F
#define check_apicid_used(bitmap, apicid) (bitmap & (1 << apicid)) #define check_apicid_used(bitmap, apicid) (bitmap & (1 << apicid))
...@@ -20,12 +14,27 @@ static inline void summit_check(char *oem, char *productid) ...@@ -20,12 +14,27 @@ static inline void summit_check(char *oem, char *productid)
{ {
} }
static inline int apic_id_registered(void)
{
return (1);
}
static inline void init_apic_ldr(void)
{
/* Already done in NUMA-Q firmware */
}
static inline void clustered_apic_check(void) static inline void clustered_apic_check(void)
{ {
printk("Enabling APIC mode: %s. Using %d I/O APICs\n", printk("Enabling APIC mode: %s. Using %d I/O APICs\n",
"NUMA-Q", nr_ioapics); "NUMA-Q", nr_ioapics);
} }
static inline int multi_timer_check(int apic, int irq)
{
return (apic != 0 && irq == 0);
}
static inline int cpu_present_to_apicid(int mps_cpu) static inline int cpu_present_to_apicid(int mps_cpu)
{ {
return ( ((mps_cpu/4)*16) + (1<<(mps_cpu%4)) ); return ( ((mps_cpu/4)*16) + (1<<(mps_cpu%4)) );
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment