diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2015-12-31 11:30:49 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2016-01-15 07:44:00 -0500 |
commit | ab25ac02148b600e645f77cfb8b8ea415ed75bb4 (patch) | |
tree | e157cca1190b46a2095bfe35485e0ef87dead58b /arch/x86 | |
parent | 9ac15b7a8af4cf3337a101498c0ed690d23ade75 (diff) |
x86/irq: Get rid of code duplication
Reusing an existing vector and assigning a new vector has duplicated
code. Consolidate it.
This is also a preparatory patch for finally plugging the cleanup race.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Borislav Petkov <bp@alien8.de>
Tested-by: Joe Lawrence <joe.lawrence@stratus.com>
Cc: Jiang Liu <jiang.liu@linux.intel.com>
Cc: Jeremiah Mahler <jmmahler@gmail.com>
Cc: andy.shevchenko@gmail.com
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: stable@vger.kernel.org #4.3+
Link: http://lkml.kernel.org/r/20151231160106.721599216@linutronix.de
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kernel/apic/vector.c | 33 |
1 files changed, 15 insertions, 18 deletions
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 1bd29c624531..fccfa3f5545c 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c | |||
@@ -118,7 +118,7 @@ static int __assign_irq_vector(int irq, struct apic_chip_data *d, | |||
118 | */ | 118 | */ |
119 | static int current_vector = FIRST_EXTERNAL_VECTOR + VECTOR_OFFSET_START; | 119 | static int current_vector = FIRST_EXTERNAL_VECTOR + VECTOR_OFFSET_START; |
120 | static int current_offset = VECTOR_OFFSET_START % 16; | 120 | static int current_offset = VECTOR_OFFSET_START % 16; |
121 | int cpu; | 121 | int cpu, vector; |
122 | 122 | ||
123 | if (d->move_in_progress) | 123 | if (d->move_in_progress) |
124 | return -EBUSY; | 124 | return -EBUSY; |
@@ -128,7 +128,7 @@ static int __assign_irq_vector(int irq, struct apic_chip_data *d, | |||
128 | cpumask_clear(searched_cpumask); | 128 | cpumask_clear(searched_cpumask); |
129 | cpu = cpumask_first_and(mask, cpu_online_mask); | 129 | cpu = cpumask_first_and(mask, cpu_online_mask); |
130 | while (cpu < nr_cpu_ids) { | 130 | while (cpu < nr_cpu_ids) { |
131 | int new_cpu, vector, offset; | 131 | int new_cpu, offset; |
132 | 132 | ||
133 | /* Get the possible target cpus for @mask/@cpu from the apic */ | 133 | /* Get the possible target cpus for @mask/@cpu from the apic */ |
134 | apic->vector_allocation_domain(cpu, vector_cpumask, mask); | 134 | apic->vector_allocation_domain(cpu, vector_cpumask, mask); |
@@ -148,16 +148,12 @@ static int __assign_irq_vector(int irq, struct apic_chip_data *d, | |||
148 | if (cpumask_equal(vector_cpumask, d->domain)) | 148 | if (cpumask_equal(vector_cpumask, d->domain)) |
149 | goto success; | 149 | goto success; |
150 | /* | 150 | /* |
151 | * New cpumask using the vector is a proper subset of | 151 | * Mark the cpus which are not longer in the mask for |
152 | * the current in use mask. So cleanup the vector | 152 | * cleanup. |
153 | * allocation for the members that are not used anymore. | ||
154 | */ | 153 | */ |
155 | cpumask_andnot(d->old_domain, d->domain, | 154 | cpumask_andnot(d->old_domain, d->domain, vector_cpumask); |
156 | vector_cpumask); | 155 | vector = d->cfg.vector; |
157 | d->move_in_progress = | 156 | goto update; |
158 | cpumask_intersects(d->old_domain, cpu_online_mask); | ||
159 | cpumask_copy(d->domain, vector_cpumask); | ||
160 | goto success; | ||
161 | } | 157 | } |
162 | 158 | ||
163 | vector = current_vector; | 159 | vector = current_vector; |
@@ -183,16 +179,12 @@ next: | |||
183 | /* Found one! */ | 179 | /* Found one! */ |
184 | current_vector = vector; | 180 | current_vector = vector; |
185 | current_offset = offset; | 181 | current_offset = offset; |
186 | if (d->cfg.vector) { | 182 | /* Schedule the old vector for cleanup on all cpus */ |
183 | if (d->cfg.vector) | ||
187 | cpumask_copy(d->old_domain, d->domain); | 184 | cpumask_copy(d->old_domain, d->domain); |
188 | d->move_in_progress = | ||
189 | cpumask_intersects(d->old_domain, cpu_online_mask); | ||
190 | } | ||
191 | for_each_cpu(new_cpu, vector_searchmask) | 185 | for_each_cpu(new_cpu, vector_searchmask) |
192 | per_cpu(vector_irq, new_cpu)[vector] = irq_to_desc(irq); | 186 | per_cpu(vector_irq, new_cpu)[vector] = irq_to_desc(irq); |
193 | d->cfg.vector = vector; | 187 | goto update; |
194 | cpumask_copy(d->domain, vector_cpumask); | ||
195 | goto success; | ||
196 | 188 | ||
197 | next_cpu: | 189 | next_cpu: |
198 | /* | 190 | /* |
@@ -209,6 +201,11 @@ next_cpu: | |||
209 | } | 201 | } |
210 | return -ENOSPC; | 202 | return -ENOSPC; |
211 | 203 | ||
204 | update: | ||
205 | /* Cleanup required ? */ | ||
206 | d->move_in_progress = cpumask_intersects(d->old_domain, cpu_online_mask); | ||
207 | d->cfg.vector = vector; | ||
208 | cpumask_copy(d->domain, vector_cpumask); | ||
212 | success: | 209 | success: |
213 | /* | 210 | /* |
214 | * Cache destination APIC IDs into cfg->dest_apicid. This cannot fail | 211 | * Cache destination APIC IDs into cfg->dest_apicid. This cannot fail |