diff -Nur linux-3.10.65/arch/x86/kernel/apic/io_apic.c linux-3.10.65-irq-rr/arch/x86/kernel/apic/io_apic.c --- linux-3.10.65/arch/x86/kernel/apic/io_apic.c 2015-01-16 18:00:00.000000000 +0300 +++ linux-3.10.65-irq-rr/arch/x86/kernel/apic/io_apic.c 2015-05-14 10:29:45.618572555 +0300 @@ -1072,6 +1072,7 @@ { raw_spin_unlock(&vector_lock); } +extern int cpumask_any_and_real(const struct cpumask *src1p, const struct cpumask *src2p); static int __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask) @@ -1101,7 +1102,7 @@ /* Only try and allocate irqs on cpus that are present */ err = -ENOSPC; cpumask_clear(cfg->old_domain); - cpu = cpumask_first_and(mask, cpu_online_mask); + cpu = cpumask_any_and_real(mask, cpu_online_mask); while (cpu < nr_cpu_ids) { int new_cpu, vector, offset; @@ -1135,7 +1136,7 @@ if (unlikely(current_vector == vector)) { cpumask_or(cfg->old_domain, cfg->old_domain, tmp_mask); cpumask_andnot(tmp_mask, mask, cfg->old_domain); - cpu = cpumask_first_and(tmp_mask, cpu_online_mask); + cpu = cpumask_any_and_real(tmp_mask, cpu_online_mask); continue; } diff -Nur linux-3.10.65/lib/cpumask.c linux-3.10.65-irq-rr/lib/cpumask.c --- linux-3.10.65/lib/cpumask.c 2015-01-16 18:00:00.000000000 +0300 +++ linux-3.10.65-irq-rr/lib/cpumask.c 2015-05-14 10:28:28.410574546 +0300 @@ -164,3 +164,31 @@ free_bootmem(__pa(mask), cpumask_size()); } #endif + +int cpumask_any_and_real(const struct cpumask *src1p, + const struct cpumask *src2p) +{ + int i; + int n = 0; + static int seed = 0; + + for_each_cpu_and(i, src1p, src2p) { /* total number of cpus */ + n ++; + } + + if (!n) /* no cpus */ + return nr_cpu_ids; + + n = (seed ^ jiffies) % n; + + seed ++; + + for_each_cpu_and(i, src1p, src2p) { /* total number of cpus */ + if (!n) + return i; + n --; + } + return nr_cpu_ids; +} + +EXPORT_SYMBOL(cpumask_any_and_real);