--- linux-2.6/arch/x86_64/kernel/io_apic.c 2006-10-23 18:44:05.000000000 -0700 +++ linux-2.6.xx/arch/x86_64/kernel/io_apic.c 2006-10-23 18:10:08.000000000 -0700 @@ -613,8 +613,9 @@ * 0x80, because int 0x80 is hm, kind of importantish. ;) */ static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0; - int old_vector = -1; - int cpu; + int vector = -1, old_vector = -1; + cpumask_t domain, new_mask; + int cpu, new_cpu; BUG_ON((unsigned)irq >= NR_IRQ_VECTORS); @@ -624,15 +625,30 @@ if (irq_vector[irq] > 0) old_vector = irq_vector[irq]; if (old_vector > 0) { - cpus_and(*result, irq_domain[irq], mask); - if (!cpus_empty(*result)) - return old_vector; + /* try to reuse vector */ + for_each_cpu_mask(cpu, mask) { + int can_reuse = 1; + domain = vector_allocation_domain(cpu); + cpus_and(new_mask, domain, cpu_online_map); + for_each_cpu_mask(new_cpu, new_mask) { + int old_irq; + old_irq = per_cpu(vector_irq, new_cpu)[old_vector]; + if ( (old_irq != irq) && (old_irq != -1)) { + can_reuse = 0; + break; + } + } + + if(!can_reuse) continue; + + vector = old_vector; + goto found_one; + } + } for_each_cpu_mask(cpu, mask) { - cpumask_t domain, new_mask; - int new_cpu; - int vector, offset; + int offset; domain = vector_allocation_domain(cpu); cpus_and(new_mask, domain, cpu_online_map); @@ -656,21 +672,27 @@ /* Found one! */ current_vector = vector; current_offset = offset; - if (old_vector >= 0) { - cpumask_t old_mask; - int old_cpu; - cpus_and(old_mask, irq_domain[irq], cpu_online_map); - for_each_cpu_mask(old_cpu, old_mask) - per_cpu(vector_irq, old_cpu)[old_vector] = -1; - } - for_each_cpu_mask(new_cpu, new_mask) - per_cpu(vector_irq, new_cpu)[vector] = irq; - irq_vector[irq] = vector; - irq_domain[irq] = domain; - cpus_and(*result, domain, mask); - return vector; + + goto found_one; } + return -ENOSPC; + +found_one: + if (old_vector >= 0) { + cpumask_t old_mask; + int old_cpu; + cpus_and(old_mask, irq_domain[irq], cpu_online_map); + for_each_cpu_mask(old_cpu, old_mask) + per_cpu(vector_irq, old_cpu)[old_vector] = -1; + } + for_each_cpu_mask(new_cpu, new_mask) + per_cpu(vector_irq, new_cpu)[vector] = irq; + irq_vector[irq] = vector; + irq_domain[irq] = domain; + cpus_and(*result, domain, mask); + return vector; + } static int assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)