aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic/io_apic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/apic/io_apic.c')
-rw-r--r--arch/x86/kernel/apic/io_apic.c31
1 files changed, 15 insertions, 16 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 8a08f09aa505..9684f963befe 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -1113,7 +1113,6 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
1113 */ 1113 */
1114 static int current_vector = FIRST_EXTERNAL_VECTOR + VECTOR_OFFSET_START; 1114 static int current_vector = FIRST_EXTERNAL_VECTOR + VECTOR_OFFSET_START;
1115 static int current_offset = VECTOR_OFFSET_START % 16; 1115 static int current_offset = VECTOR_OFFSET_START % 16;
1116 unsigned int old_vector;
1117 int cpu, err; 1116 int cpu, err;
1118 cpumask_var_t tmp_mask; 1117 cpumask_var_t tmp_mask;
1119 1118
@@ -1123,28 +1122,28 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
1123 if (!alloc_cpumask_var(&tmp_mask, GFP_ATOMIC)) 1122 if (!alloc_cpumask_var(&tmp_mask, GFP_ATOMIC))
1124 return -ENOMEM; 1123 return -ENOMEM;
1125 1124
1126 old_vector = cfg->vector;
1127 if (old_vector) {
1128 cpumask_and(tmp_mask, mask, cpu_online_mask);
1129 if (cpumask_subset(tmp_mask, cfg->domain)) {
1130 free_cpumask_var(tmp_mask);
1131 return 0;
1132 }
1133 }
1134
1135 /* Only try and allocate irqs on cpus that are present */ 1125 /* Only try and allocate irqs on cpus that are present */
1136 err = -ENOSPC; 1126 err = -ENOSPC;
1137 cpumask_clear(cfg->old_domain); 1127 cpumask_clear(cfg->old_domain);
1138 cpu = cpumask_first_and(mask, cpu_online_mask); 1128 cpu = cpumask_first_and(mask, cpu_online_mask);
1139 while (cpu < nr_cpu_ids) { 1129 while (cpu < nr_cpu_ids) {
1140 int new_cpu; 1130 int new_cpu, vector, offset;
1141 int vector, offset;
1142 1131
1143 apic->vector_allocation_domain(cpu, tmp_mask); 1132 apic->vector_allocation_domain(cpu, tmp_mask, mask);
1144 1133
1145 if (cpumask_subset(tmp_mask, cfg->domain)) { 1134 if (cpumask_subset(tmp_mask, cfg->domain)) {
1146 free_cpumask_var(tmp_mask); 1135 err = 0;
1147 return 0; 1136 if (cpumask_equal(tmp_mask, cfg->domain))
1137 break;
1138 /*
1139 * New cpumask using the vector is a proper subset of
1140 * the current in use mask. So cleanup the vector
1141 * allocation for the members that are not used anymore.
1142 */
1143 cpumask_andnot(cfg->old_domain, cfg->domain, tmp_mask);
1144 cfg->move_in_progress = 1;
1145 cpumask_and(cfg->domain, cfg->domain, tmp_mask);
1146 break;
1148 } 1147 }
1149 1148
1150 vector = current_vector; 1149 vector = current_vector;
@@ -1172,7 +1171,7 @@ next:
1172 /* Found one! */ 1171 /* Found one! */
1173 current_vector = vector; 1172 current_vector = vector;
1174 current_offset = offset; 1173 current_offset = offset;
1175 if (old_vector) { 1174 if (cfg->vector) {
1176 cfg->move_in_progress = 1; 1175 cfg->move_in_progress = 1;
1177 cpumask_copy(cfg->old_domain, cfg->domain); 1176 cpumask_copy(cfg->old_domain, cfg->domain);
1178 } 1177 }