diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2015-12-31 19:30:49 +0300 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2016-01-15 15:44:00 +0300 |
commit | ab25ac02148b600e645f77cfb8b8ea415ed75bb4 (patch) | |
tree | e157cca1190b46a2095bfe35485e0ef87dead58b /arch/x86/kernel/apic | |
parent | 9ac15b7a8af4cf3337a101498c0ed690d23ade75 (diff) | |
download | linux-ab25ac02148b600e645f77cfb8b8ea415ed75bb4.tar.xz |
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/kernel/apic')
-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, */ static int current_vector = FIRST_EXTERNAL_VECTOR + VECTOR_OFFSET_START; static int current_offset = VECTOR_OFFSET_START % 16; - int cpu; + int cpu, vector; if (d->move_in_progress) return -EBUSY; @@ -128,7 +128,7 @@ static int __assign_irq_vector(int irq, struct apic_chip_data *d, cpumask_clear(searched_cpumask); cpu = cpumask_first_and(mask, cpu_online_mask); while (cpu < nr_cpu_ids) { - int new_cpu, vector, offset; + int new_cpu, offset; /* Get the possible target cpus for @mask/@cpu from the apic */ apic->vector_allocation_domain(cpu, vector_cpumask, mask); @@ -148,16 +148,12 @@ static int __assign_irq_vector(int irq, struct apic_chip_data *d, if (cpumask_equal(vector_cpumask, d->domain)) goto success; /* - * New cpumask using the vector is a proper subset of - * the current in use mask. So cleanup the vector - * allocation for the members that are not used anymore. + * Mark the cpus which are not longer in the mask for + * cleanup. */ - cpumask_andnot(d->old_domain, d->domain, - vector_cpumask); - d->move_in_progress = - cpumask_intersects(d->old_domain, cpu_online_mask); - cpumask_copy(d->domain, vector_cpumask); - goto success; + cpumask_andnot(d->old_domain, d->domain, vector_cpumask); + vector = d->cfg.vector; + goto update; } vector = current_vector; @@ -183,16 +179,12 @@ next: /* Found one! */ current_vector = vector; current_offset = offset; - if (d->cfg.vector) { + /* Schedule the old vector for cleanup on all cpus */ + if (d->cfg.vector) cpumask_copy(d->old_domain, d->domain); - d->move_in_progress = - cpumask_intersects(d->old_domain, cpu_online_mask); - } for_each_cpu(new_cpu, vector_searchmask) per_cpu(vector_irq, new_cpu)[vector] = irq_to_desc(irq); - d->cfg.vector = vector; - cpumask_copy(d->domain, vector_cpumask); - goto success; + goto update; next_cpu: /* @@ -209,6 +201,11 @@ next_cpu: } return -ENOSPC; +update: + /* Cleanup required ? */ + d->move_in_progress = cpumask_intersects(d->old_domain, cpu_online_mask); + d->cfg.vector = vector; + cpumask_copy(d->domain, vector_cpumask); success: /* * Cache destination APIC IDs into cfg->dest_apicid. This cannot fail |