Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
637cba02 | 2 | /* |
77313190 IM |
3 | * APIC driver for "bigsmp" xAPIC machines with more than 8 virtual CPUs. |
4 | * | |
1da177e4 LT |
5 | * Drives the local APIC in "clustered mode". |
6 | */ | |
1da177e4 | 7 | #include <linux/cpumask.h> |
1da177e4 | 8 | #include <linux/dmi.h> |
4696ca5b | 9 | #include <linux/smp.h> |
9f4187f0 | 10 | |
77313190 | 11 | #include <asm/apic.h> |
13c01139 | 12 | #include <asm/io_apic.h> |
8b542da3 | 13 | |
c94f0718 | 14 | #include "local.h" |
9f4187f0 | 15 | |
59f7928c | 16 | static u32 bigsmp_get_apic_id(u32 x) |
9f4187f0 IM |
17 | { |
18 | return (x >> 24) & 0xFF; | |
19 | } | |
20 | ||
9694cd6c | 21 | static void bigsmp_send_IPI_allbutself(int vector) |
9f4187f0 | 22 | { |
43f39890 | 23 | default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector); |
9f4187f0 IM |
24 | } |
25 | ||
9694cd6c | 26 | static void bigsmp_send_IPI_all(int vector) |
9f4187f0 | 27 | { |
500bd02f | 28 | default_send_IPI_mask_sequence_phys(cpu_online_mask, vector); |
9f4187f0 | 29 | } |
1da177e4 LT |
30 | |
31 | static int dmi_bigsmp; /* can be set by dmi scanners */ | |
32 | ||
1855256c | 33 | static int hp_ht_bigsmp(const struct dmi_system_id *d) |
1da177e4 | 34 | { |
1da177e4 LT |
35 | printk(KERN_NOTICE "%s detected: force use of apic=bigsmp\n", d->ident); |
36 | dmi_bigsmp = 1; | |
77313190 | 37 | |
1da177e4 LT |
38 | return 0; |
39 | } | |
40 | ||
41 | ||
1855256c | 42 | static const struct dmi_system_id bigsmp_dmi_table[] = { |
637cba02 | 43 | { hp_ht_bigsmp, "HP ProLiant DL760 G2", |
77313190 IM |
44 | { DMI_MATCH(DMI_BIOS_VENDOR, "HP"), |
45 | DMI_MATCH(DMI_BIOS_VERSION, "P44-"), | |
46 | } | |
637cba02 PC |
47 | }, |
48 | ||
49 | { hp_ht_bigsmp, "HP ProLiant DL740", | |
77313190 IM |
50 | { DMI_MATCH(DMI_BIOS_VENDOR, "HP"), |
51 | DMI_MATCH(DMI_BIOS_VERSION, "P47-"), | |
52 | } | |
637cba02 | 53 | }, |
77313190 | 54 | { } /* NULL entry stops DMI scanning */ |
1da177e4 LT |
55 | }; |
56 | ||
af669c97 | 57 | static int probe_bigsmp(void) |
637cba02 | 58 | { |
79c9a17c | 59 | return dmi_check_system(bigsmp_dmi_table); |
637cba02 | 60 | } |
1da177e4 | 61 | |
404f6aac | 62 | static struct apic apic_bigsmp __ro_after_init = { |
d26b6d66 IM |
63 | |
64 | .name = "bigsmp", | |
65 | .probe = probe_bigsmp, | |
d26b6d66 | 66 | |
8c44963b | 67 | .dest_mode_logical = false, |
d26b6d66 | 68 | |
08125d3e | 69 | .disable_esr = 1, |
d26b6d66 | 70 | |
4114e168 | 71 | .cpu_present_to_apicid = default_cpu_present_to_apicid, |
d26b6d66 | 72 | |
d92e5e7c | 73 | .max_apic_id = 0xFE, |
ca6c8ed4 | 74 | .get_apic_id = bigsmp_get_apic_id, |
d26b6d66 | 75 | |
9f9e3bb1 | 76 | .calc_dest_apicid = apic_default_calc_apicid, |
d26b6d66 | 77 | |
5789a12e | 78 | .send_IPI = default_send_IPI_single_phys, |
500bd02f | 79 | .send_IPI_mask = default_send_IPI_mask_sequence_phys, |
d26b6d66 | 80 | .send_IPI_mask_allbutself = NULL, |
dac5f412 IM |
81 | .send_IPI_allbutself = bigsmp_send_IPI_allbutself, |
82 | .send_IPI_all = bigsmp_send_IPI_all, | |
6b64ee02 | 83 | .send_IPI_self = default_send_IPI_self, |
d26b6d66 | 84 | |
c1eeb2de YL |
85 | .read = native_apic_mem_read, |
86 | .write = native_apic_mem_write, | |
185c8f33 | 87 | .eoi = native_apic_mem_eoi, |
c1eeb2de YL |
88 | .icr_read = native_apic_icr_read, |
89 | .icr_write = native_apic_icr_write, | |
cfebd007 | 90 | .wait_icr_idle = apic_mem_wait_icr_idle, |
e7b6a023 | 91 | .safe_wait_icr_idle = apic_mem_wait_icr_idle_timeout, |
d26b6d66 | 92 | }; |
107e0e0c | 93 | |
79c9a17c | 94 | bool __init apic_bigsmp_possible(bool cmdline_override) |
69c252ff | 95 | { |
79c9a17c TG |
96 | return apic == &apic_bigsmp || !cmdline_override; |
97 | } | |
838312be | 98 | |
79c9a17c TG |
99 | void __init apic_bigsmp_force(void) |
100 | { | |
3af1e415 TG |
101 | if (apic != &apic_bigsmp) |
102 | apic_install_driver(&apic_bigsmp); | |
69c252ff SS |
103 | } |
104 | ||
107e0e0c | 105 | apic_driver(apic_bigsmp); |