10
10
#include <asm/smp.h>
11
11
#include "x2apic.h"
12
12
13
+ struct cluster_mask {
14
+ unsigned int clusterid ;
15
+ int node ;
16
+ struct cpumask mask ;
17
+ };
18
+
13
19
static DEFINE_PER_CPU (u32 , x86_cpu_to_logical_apicid ) ;
14
- static DEFINE_PER_CPU (cpumask_var_t , cpus_in_cluster ) ;
15
20
static DEFINE_PER_CPU (cpumask_var_t , ipi_mask ) ;
21
+ static DEFINE_PER_CPU (struct cluster_mask * , cluster_masks ) ;
22
+ static struct cluster_mask * cluster_hotplug_mask ;
16
23
17
24
static int x2apic_acpi_madt_oem_check (char * oem_id , char * oem_table_id )
18
25
{
19
26
return x2apic_enabled ();
20
27
}
21
28
22
- static inline u32 x2apic_cluster (int cpu )
23
- {
24
- return per_cpu (x86_cpu_to_logical_apicid , cpu ) >> 16 ;
25
- }
26
-
27
29
static void x2apic_send_IPI (int cpu , int vector )
28
30
{
29
31
u32 dest = per_cpu (x86_cpu_to_logical_apicid , cpu );
@@ -35,49 +37,34 @@ static void x2apic_send_IPI(int cpu, int vector)
35
37
static void
36
38
__x2apic_send_IPI_mask (const struct cpumask * mask , int vector , int apic_dest )
37
39
{
38
- struct cpumask * cpus_in_cluster_ptr ;
39
- struct cpumask * ipi_mask_ptr ;
40
- unsigned int cpu , this_cpu ;
40
+ unsigned int cpu , clustercpu ;
41
+ struct cpumask * tmpmsk ;
41
42
unsigned long flags ;
42
43
u32 dest ;
43
44
44
45
x2apic_wrmsr_fence ();
45
-
46
46
local_irq_save (flags );
47
47
48
- this_cpu = smp_processor_id ();
48
+ tmpmsk = this_cpu_cpumask_var_ptr (ipi_mask );
49
+ cpumask_copy (tmpmsk , mask );
50
+ /* If IPI should not be sent to self, clear current CPU */
51
+ if (apic_dest != APIC_DEST_ALLINC )
52
+ cpumask_clear_cpu (smp_processor_id (), tmpmsk );
49
53
50
- /*
51
- * We are to modify mask, so we need an own copy
52
- * and be sure it's manipulated with irq off.
53
- */
54
- ipi_mask_ptr = this_cpu_cpumask_var_ptr (ipi_mask );
55
- cpumask_copy (ipi_mask_ptr , mask );
54
+ /* Collapse cpus in a cluster so a single IPI per cluster is sent */
55
+ for_each_cpu (cpu , tmpmsk ) {
56
+ struct cluster_mask * cmsk = per_cpu (cluster_masks , cpu );
56
57
57
- /*
58
- * The idea is to send one IPI per cluster.
59
- */
60
- for_each_cpu (cpu , ipi_mask_ptr ) {
61
- unsigned long i ;
62
-
63
- cpus_in_cluster_ptr = per_cpu (cpus_in_cluster , cpu );
64
58
dest = 0 ;
65
-
66
- /* Collect cpus in cluster. */
67
- for_each_cpu_and (i , ipi_mask_ptr , cpus_in_cluster_ptr ) {
68
- if (apic_dest == APIC_DEST_ALLINC || i != this_cpu )
69
- dest |= per_cpu (x86_cpu_to_logical_apicid , i );
70
- }
59
+ for_each_cpu_and (clustercpu , tmpmsk , & cmsk -> mask )
60
+ dest |= per_cpu (x86_cpu_to_logical_apicid , clustercpu );
71
61
72
62
if (!dest )
73
63
continue ;
74
64
75
65
__x2apic_send_IPI_dest (dest , vector , apic -> dest_logical );
76
- /*
77
- * Cluster sibling cpus should be discared now so
78
- * we would not send IPI them second time.
79
- */
80
- cpumask_andnot (ipi_mask_ptr , ipi_mask_ptr , cpus_in_cluster_ptr );
66
+ /* Remove cluster CPUs from tmpmask */
67
+ cpumask_andnot (tmpmsk , tmpmsk , & cmsk -> mask );
81
68
}
82
69
83
70
local_irq_restore (flags );
@@ -109,91 +96,100 @@ x2apic_cpu_mask_to_apicid(const struct cpumask *mask, struct irq_data *irqdata,
109
96
unsigned int * apicid )
110
97
{
111
98
struct cpumask * effmsk = irq_data_get_effective_affinity_mask (irqdata );
99
+ struct cluster_mask * cmsk ;
112
100
unsigned int cpu ;
113
101
u32 dest = 0 ;
114
- u16 cluster ;
115
102
116
103
cpu = cpumask_first (mask );
117
104
if (cpu >= nr_cpu_ids )
118
105
return - EINVAL ;
119
106
120
- dest = per_cpu (x86_cpu_to_logical_apicid , cpu );
121
- cluster = x2apic_cluster (cpu );
122
-
107
+ cmsk = per_cpu (cluster_masks , cpu );
123
108
cpumask_clear (effmsk );
124
- for_each_cpu (cpu , mask ) {
125
- if (cluster != x2apic_cluster (cpu ))
126
- continue ;
109
+ for_each_cpu_and (cpu , & cmsk -> mask , mask ) {
127
110
dest |= per_cpu (x86_cpu_to_logical_apicid , cpu );
128
111
cpumask_set_cpu (cpu , effmsk );
129
112
}
130
-
131
113
* apicid = dest ;
132
114
return 0 ;
133
115
}
134
116
135
117
static void init_x2apic_ldr (void )
136
118
{
137
- unsigned int this_cpu = smp_processor_id ();
119
+ struct cluster_mask * cmsk = this_cpu_read (cluster_masks );
120
+ u32 cluster , apicid = apic_read (APIC_LDR );
138
121
unsigned int cpu ;
139
122
140
- per_cpu (x86_cpu_to_logical_apicid , this_cpu ) = apic_read ( APIC_LDR );
123
+ this_cpu_write (x86_cpu_to_logical_apicid , apicid );
141
124
142
- cpumask_set_cpu (this_cpu , per_cpu (cpus_in_cluster , this_cpu ));
125
+ if (cmsk )
126
+ goto update ;
127
+
128
+ cluster = apicid >> 16 ;
143
129
for_each_online_cpu (cpu ) {
144
- if ( x2apic_cluster ( this_cpu ) != x2apic_cluster ( cpu ))
145
- continue ;
146
- cpumask_set_cpu ( this_cpu , per_cpu ( cpus_in_cluster , cpu ));
147
- cpumask_set_cpu ( cpu , per_cpu ( cpus_in_cluster , this_cpu )) ;
130
+ cmsk = per_cpu ( cluster_masks , cpu );
131
+ /* Matching cluster found. Link and update it. */
132
+ if ( cmsk && cmsk -> clusterid == cluster )
133
+ goto update ;
148
134
}
135
+ cmsk = cluster_hotplug_mask ;
136
+ cluster_hotplug_mask = NULL ;
137
+ update :
138
+ this_cpu_write (cluster_masks , cmsk );
139
+ cpumask_set_cpu (smp_processor_id (), & cmsk -> mask );
149
140
}
150
141
151
- /*
152
- * At CPU state changes, update the x2apic cluster sibling info.
153
- */
154
- static int x2apic_prepare_cpu (unsigned int cpu )
142
+ static int alloc_clustermask (unsigned int cpu , int node )
155
143
{
156
- if (!zalloc_cpumask_var (& per_cpu (cpus_in_cluster , cpu ), GFP_KERNEL ))
157
- return - ENOMEM ;
144
+ if (per_cpu (cluster_masks , cpu ))
145
+ return 0 ;
146
+ /*
147
+ * If a hotplug spare mask exists, check whether it's on the right
148
+ * node. If not, free it and allocate a new one.
149
+ */
150
+ if (cluster_hotplug_mask ) {
151
+ if (cluster_hotplug_mask -> node == node )
152
+ return 0 ;
153
+ kfree (cluster_hotplug_mask );
154
+ }
158
155
159
- if (!zalloc_cpumask_var (& per_cpu (ipi_mask , cpu ), GFP_KERNEL )) {
160
- free_cpumask_var (per_cpu (cpus_in_cluster , cpu ));
156
+ cluster_hotplug_mask = kzalloc_node (sizeof (* cluster_hotplug_mask ),
157
+ GFP_KERNEL , node );
158
+ if (!cluster_hotplug_mask )
161
159
return - ENOMEM ;
162
- }
160
+ cluster_hotplug_mask -> node = node ;
161
+ return 0 ;
162
+ }
163
163
164
+ static int x2apic_prepare_cpu (unsigned int cpu )
165
+ {
166
+ if (alloc_clustermask (cpu , cpu_to_node (cpu )) < 0 )
167
+ return - ENOMEM ;
168
+ if (!zalloc_cpumask_var (& per_cpu (ipi_mask , cpu ), GFP_KERNEL ))
169
+ return - ENOMEM ;
164
170
return 0 ;
165
171
}
166
172
167
- static int x2apic_dead_cpu (unsigned int this_cpu )
173
+ static int x2apic_dead_cpu (unsigned int dead_cpu )
168
174
{
169
- int cpu ;
175
+ struct cluster_mask * cmsk = per_cpu ( cluster_masks , dead_cpu ) ;
170
176
171
- for_each_online_cpu (cpu ) {
172
- if (x2apic_cluster (this_cpu ) != x2apic_cluster (cpu ))
173
- continue ;
174
- cpumask_clear_cpu (this_cpu , per_cpu (cpus_in_cluster , cpu ));
175
- cpumask_clear_cpu (cpu , per_cpu (cpus_in_cluster , this_cpu ));
176
- }
177
- free_cpumask_var (per_cpu (cpus_in_cluster , this_cpu ));
178
- free_cpumask_var (per_cpu (ipi_mask , this_cpu ));
177
+ cpumask_clear_cpu (smp_processor_id (), & cmsk -> mask );
178
+ free_cpumask_var (per_cpu (ipi_mask , dead_cpu ));
179
179
return 0 ;
180
180
}
181
181
182
182
static int x2apic_cluster_probe (void )
183
183
{
184
- int cpu = smp_processor_id ();
185
- int ret ;
186
-
187
184
if (!x2apic_mode )
188
185
return 0 ;
189
186
190
- ret = cpuhp_setup_state (CPUHP_X2APIC_PREPARE , "x86/x2apic:prepare" ,
191
- x2apic_prepare_cpu , x2apic_dead_cpu );
192
- if (ret < 0 ) {
187
+ if (cpuhp_setup_state (CPUHP_X2APIC_PREPARE , "x86/x2apic:prepare" ,
188
+ x2apic_prepare_cpu , x2apic_dead_cpu ) < 0 ) {
193
189
pr_err ("Failed to register X2APIC_PREPARE\n" );
194
190
return 0 ;
195
191
}
196
- cpumask_set_cpu ( cpu , per_cpu ( cpus_in_cluster , cpu ) );
192
+ init_x2apic_ldr ( );
197
193
return 1 ;
198
194
}
199
195
@@ -208,6 +204,8 @@ static const struct cpumask *x2apic_cluster_target_cpus(void)
208
204
static void cluster_vector_allocation_domain (int cpu , struct cpumask * retmask ,
209
205
const struct cpumask * mask )
210
206
{
207
+ struct cluster_mask * cmsk = per_cpu (cluster_masks , cpu );
208
+
211
209
/*
212
210
* To minimize vector pressure, default case of boot, device bringup
213
211
* etc will use a single cpu for the interrupt destination.
@@ -220,7 +218,7 @@ static void cluster_vector_allocation_domain(int cpu, struct cpumask *retmask,
220
218
if (mask == x2apic_cluster_target_cpus ())
221
219
cpumask_copy (retmask , cpumask_of (cpu ));
222
220
else
223
- cpumask_and (retmask , mask , per_cpu ( cpus_in_cluster , cpu ) );
221
+ cpumask_and (retmask , mask , & cmsk -> mask );
224
222
}
225
223
226
224
static struct apic apic_x2apic_cluster __ro_after_init = {
0 commit comments