29f354a699d50258a82a7960bdc4ee9676f0fdab
[sfrench/cifs-2.6.git] / arch / x86 / kernel / apic / bigsmp_32.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * APIC driver for "bigsmp" xAPIC machines with more than 8 virtual CPUs.
4  *
5  * Drives the local APIC in "clustered mode".
6  */
7 #include <linux/cpumask.h>
8 #include <linux/dmi.h>
9 #include <linux/smp.h>
10
11 #include <asm/apic.h>
12 #include <asm/io_apic.h>
13
14 #include "local.h"
15
16 static u32 bigsmp_get_apic_id(u32 x)
17 {
18         return (x >> 24) & 0xFF;
19 }
20
21 static void bigsmp_send_IPI_allbutself(int vector)
22 {
23         default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector);
24 }
25
26 static void bigsmp_send_IPI_all(int vector)
27 {
28         default_send_IPI_mask_sequence_phys(cpu_online_mask, vector);
29 }
30
31 static int dmi_bigsmp; /* can be set by dmi scanners */
32
33 static int hp_ht_bigsmp(const struct dmi_system_id *d)
34 {
35         printk(KERN_NOTICE "%s detected: force use of apic=bigsmp\n", d->ident);
36         dmi_bigsmp = 1;
37
38         return 0;
39 }
40
41
42 static const struct dmi_system_id bigsmp_dmi_table[] = {
43         { hp_ht_bigsmp, "HP ProLiant DL760 G2",
44                 {       DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
45                         DMI_MATCH(DMI_BIOS_VERSION, "P44-"),
46                 }
47         },
48
49         { hp_ht_bigsmp, "HP ProLiant DL740",
50                 {       DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
51                         DMI_MATCH(DMI_BIOS_VERSION, "P47-"),
52                 }
53         },
54         { } /* NULL entry stops DMI scanning */
55 };
56
57 static int probe_bigsmp(void)
58 {
59         return dmi_check_system(bigsmp_dmi_table);
60 }
61
62 static struct apic apic_bigsmp __ro_after_init = {
63
64         .name                           = "bigsmp",
65         .probe                          = probe_bigsmp,
66
67         .dest_mode_logical              = false,
68
69         .disable_esr                    = 1,
70
71         .cpu_present_to_apicid          = default_cpu_present_to_apicid,
72
73         .max_apic_id                    = 0xFE,
74         .get_apic_id                    = bigsmp_get_apic_id,
75         .set_apic_id                    = NULL,
76
77         .calc_dest_apicid               = apic_default_calc_apicid,
78
79         .send_IPI                       = default_send_IPI_single_phys,
80         .send_IPI_mask                  = default_send_IPI_mask_sequence_phys,
81         .send_IPI_mask_allbutself       = NULL,
82         .send_IPI_allbutself            = bigsmp_send_IPI_allbutself,
83         .send_IPI_all                   = bigsmp_send_IPI_all,
84         .send_IPI_self                  = default_send_IPI_self,
85
86         .read                           = native_apic_mem_read,
87         .write                          = native_apic_mem_write,
88         .eoi                            = native_apic_mem_eoi,
89         .icr_read                       = native_apic_icr_read,
90         .icr_write                      = native_apic_icr_write,
91         .wait_icr_idle                  = apic_mem_wait_icr_idle,
92         .safe_wait_icr_idle             = apic_mem_wait_icr_idle_timeout,
93 };
94
95 bool __init apic_bigsmp_possible(bool cmdline_override)
96 {
97         return apic == &apic_bigsmp || !cmdline_override;
98 }
99
100 void __init apic_bigsmp_force(void)
101 {
102         if (apic != &apic_bigsmp)
103                 apic_install_driver(&apic_bigsmp);
104 }
105
106 apic_driver(apic_bigsmp);