diff options
| -rw-r--r-- | arch/x86/include/asm/x86_init.h | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/probe_32.c | 3 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/probe_64.c | 11 | ||||
| -rw-r--r-- | arch/x86/kernel/vsmp_64.c | 43 |
4 files changed, 46 insertions, 13 deletions
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index 42d2ae18dab2..38155f667144 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h | |||
| @@ -163,6 +163,7 @@ struct x86_cpuinit_ops { | |||
| 163 | * @i8042_detect pre-detect if i8042 controller exists | 163 | * @i8042_detect pre-detect if i8042 controller exists |
| 164 | * @save_sched_clock_state: save state for sched_clock() on suspend | 164 | * @save_sched_clock_state: save state for sched_clock() on suspend |
| 165 | * @restore_sched_clock_state: restore state for sched_clock() on resume | 165 | * @restore_sched_clock_state: restore state for sched_clock() on resume |
| 166 | * @apic_post_init: adjust apic if neeeded | ||
| 166 | */ | 167 | */ |
| 167 | struct x86_platform_ops { | 168 | struct x86_platform_ops { |
| 168 | unsigned long (*calibrate_tsc)(void); | 169 | unsigned long (*calibrate_tsc)(void); |
| @@ -175,6 +176,7 @@ struct x86_platform_ops { | |||
| 175 | int (*i8042_detect)(void); | 176 | int (*i8042_detect)(void); |
| 176 | void (*save_sched_clock_state)(void); | 177 | void (*save_sched_clock_state)(void); |
| 177 | void (*restore_sched_clock_state)(void); | 178 | void (*restore_sched_clock_state)(void); |
| 179 | void (*apic_post_init)(void); | ||
| 178 | }; | 180 | }; |
| 179 | 181 | ||
| 180 | struct pci_dev; | 182 | struct pci_dev; |
diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index eef6bcd1bf1e..eb35ef9ee63f 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c | |||
| @@ -192,6 +192,9 @@ void __init default_setup_apic_routing(void) | |||
| 192 | 192 | ||
| 193 | if (apic->setup_apic_routing) | 193 | if (apic->setup_apic_routing) |
| 194 | apic->setup_apic_routing(); | 194 | apic->setup_apic_routing(); |
| 195 | |||
| 196 | if (x86_platform.apic_post_init) | ||
| 197 | x86_platform.apic_post_init(); | ||
| 195 | } | 198 | } |
| 196 | 199 | ||
| 197 | void __init generic_apic_probe(void) | 200 | void __init generic_apic_probe(void) |
diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c index 3fe986698929..1793dba7a741 100644 --- a/arch/x86/kernel/apic/probe_64.c +++ b/arch/x86/kernel/apic/probe_64.c | |||
| @@ -23,11 +23,6 @@ | |||
| 23 | #include <asm/ipi.h> | 23 | #include <asm/ipi.h> |
| 24 | #include <asm/setup.h> | 24 | #include <asm/setup.h> |
| 25 | 25 | ||
| 26 | static int apicid_phys_pkg_id(int initial_apic_id, int index_msb) | ||
| 27 | { | ||
| 28 | return hard_smp_processor_id() >> index_msb; | ||
| 29 | } | ||
| 30 | |||
| 31 | /* | 26 | /* |
| 32 | * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode. | 27 | * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode. |
| 33 | */ | 28 | */ |
| @@ -48,10 +43,8 @@ void __init default_setup_apic_routing(void) | |||
| 48 | } | 43 | } |
| 49 | } | 44 | } |
| 50 | 45 | ||
| 51 | if (is_vsmp_box()) { | 46 | if (x86_platform.apic_post_init) |
| 52 | /* need to update phys_pkg_id */ | 47 | x86_platform.apic_post_init(); |
| 53 | apic->phys_pkg_id = apicid_phys_pkg_id; | ||
| 54 | } | ||
| 55 | } | 48 | } |
| 56 | 49 | ||
| 57 | /* Same for both flat and physical. */ | 50 | /* Same for both flat and physical. */ |
diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c index 8eeb55a551b4..3f0285ac00fa 100644 --- a/arch/x86/kernel/vsmp_64.c +++ b/arch/x86/kernel/vsmp_64.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/pci_ids.h> | 16 | #include <linux/pci_ids.h> |
| 17 | #include <linux/pci_regs.h> | 17 | #include <linux/pci_regs.h> |
| 18 | #include <linux/smp.h> | 18 | #include <linux/smp.h> |
| 19 | #include <linux/irq.h> | ||
| 19 | 20 | ||
| 20 | #include <asm/apic.h> | 21 | #include <asm/apic.h> |
| 21 | #include <asm/pci-direct.h> | 22 | #include <asm/pci-direct.h> |
| @@ -95,6 +96,18 @@ static void __init set_vsmp_pv_ops(void) | |||
| 95 | ctl = readl(address + 4); | 96 | ctl = readl(address + 4); |
| 96 | printk(KERN_INFO "vSMP CTL: capabilities:0x%08x control:0x%08x\n", | 97 | printk(KERN_INFO "vSMP CTL: capabilities:0x%08x control:0x%08x\n", |
| 97 | cap, ctl); | 98 | cap, ctl); |
| 99 | |||
| 100 | /* If possible, let the vSMP foundation route the interrupt optimally */ | ||
| 101 | #ifdef CONFIG_SMP | ||
| 102 | if (cap & ctl & BIT(8)) { | ||
| 103 | ctl &= ~BIT(8); | ||
| 104 | #ifdef CONFIG_PROC_FS | ||
| 105 | /* Don't let users change irq affinity via procfs */ | ||
| 106 | no_irq_affinity = 1; | ||
| 107 | #endif | ||
| 108 | } | ||
| 109 | #endif | ||
| 110 | |||
| 98 | if (cap & ctl & (1 << 4)) { | 111 | if (cap & ctl & (1 << 4)) { |
| 99 | /* Setup irq ops and turn on vSMP IRQ fastpath handling */ | 112 | /* Setup irq ops and turn on vSMP IRQ fastpath handling */ |
| 100 | pv_irq_ops.irq_disable = PV_CALLEE_SAVE(vsmp_irq_disable); | 113 | pv_irq_ops.irq_disable = PV_CALLEE_SAVE(vsmp_irq_disable); |
| @@ -102,12 +115,11 @@ static void __init set_vsmp_pv_ops(void) | |||
| 102 | pv_irq_ops.save_fl = PV_CALLEE_SAVE(vsmp_save_fl); | 115 | pv_irq_ops.save_fl = PV_CALLEE_SAVE(vsmp_save_fl); |
| 103 | pv_irq_ops.restore_fl = PV_CALLEE_SAVE(vsmp_restore_fl); | 116 | pv_irq_ops.restore_fl = PV_CALLEE_SAVE(vsmp_restore_fl); |
| 104 | pv_init_ops.patch = vsmp_patch; | 117 | pv_init_ops.patch = vsmp_patch; |
| 105 | |||
| 106 | ctl &= ~(1 << 4); | 118 | ctl &= ~(1 << 4); |
| 107 | writel(ctl, address + 4); | ||
| 108 | ctl = readl(address + 4); | ||
| 109 | printk(KERN_INFO "vSMP CTL: control set to:0x%08x\n", ctl); | ||
| 110 | } | 119 | } |
| 120 | writel(ctl, address + 4); | ||
| 121 | ctl = readl(address + 4); | ||
| 122 | pr_info("vSMP CTL: control set to:0x%08x\n", ctl); | ||
| 111 | 123 | ||
| 112 | early_iounmap(address, 8); | 124 | early_iounmap(address, 8); |
| 113 | } | 125 | } |
| @@ -187,12 +199,35 @@ static void __init vsmp_cap_cpus(void) | |||
| 187 | #endif | 199 | #endif |
| 188 | } | 200 | } |
| 189 | 201 | ||
| 202 | static int apicid_phys_pkg_id(int initial_apic_id, int index_msb) | ||
| 203 | { | ||
| 204 | return hard_smp_processor_id() >> index_msb; | ||
| 205 | } | ||
| 206 | |||
| 207 | /* | ||
| 208 | * In vSMP, all cpus should be capable of handling interrupts, regardless of | ||
| 209 | * the APIC used. | ||
| 210 | */ | ||
| 211 | static void fill_vector_allocation_domain(int cpu, struct cpumask *retmask) | ||
| 212 | { | ||
| 213 | cpumask_setall(retmask); | ||
| 214 | } | ||
| 215 | |||
| 216 | static void vsmp_apic_post_init(void) | ||
| 217 | { | ||
| 218 | /* need to update phys_pkg_id */ | ||
| 219 | apic->phys_pkg_id = apicid_phys_pkg_id; | ||
| 220 | apic->vector_allocation_domain = fill_vector_allocation_domain; | ||
| 221 | } | ||
| 222 | |||
| 190 | void __init vsmp_init(void) | 223 | void __init vsmp_init(void) |
| 191 | { | 224 | { |
| 192 | detect_vsmp_box(); | 225 | detect_vsmp_box(); |
| 193 | if (!is_vsmp_box()) | 226 | if (!is_vsmp_box()) |
| 194 | return; | 227 | return; |
| 195 | 228 | ||
| 229 | x86_platform.apic_post_init = vsmp_apic_post_init; | ||
| 230 | |||
| 196 | vsmp_cap_cpus(); | 231 | vsmp_cap_cpus(); |
| 197 | 232 | ||
| 198 | set_vsmp_pv_ops(); | 233 | set_vsmp_pv_ops(); |
