From 8d1277c729aea7e682ec44307ef5d682ff781154 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 4 Nov 2011 15:55:50 +0100 Subject: [PATCH] x86/IRQ: fix create_irq() after c/s 24068:6928172f7ded init_one_irq_desc() must be called with interrupts enabled (as it may call functions from the xmalloc() group). Rather than mis-using vector_lock to also protect the finding of an unused IRQ, make this lockless through using cmpxchg(), and obtain the lock only around the actual assignment of the vector. Also fold find_unassigned_irq() into its only caller. It is, btw, questionable whether create_irq() calling __assign_irq_vector() (rather than assign_irq_vector()) is actually correct - desc->affinity appears to not get initialized properly in this case. Signed-off-by: Jan Beulich Acked-by: Keir Fraser --- xen/arch/x86/irq.c | 33 ++++++++++++++++----------------- xen/include/asm-x86/irq.h | 3 ++- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index 6875eb36bd..ca80e9c0de 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -151,16 +151,6 @@ int __init bind_irq_vector(int irq, int vector, const cpumask_t *cpu_mask) return ret; } -static inline int find_unassigned_irq(void) -{ - int irq; - - for (irq = nr_irqs_gsi; irq < nr_irqs; irq++) - if (irq_to_desc(irq)->arch.used == IRQ_UNUSED) - return irq; - return -ENOSPC; -} - /* * Dynamic irq allocate and deallocation for MSI */ @@ -170,19 +160,28 @@ int create_irq(void) int irq, ret; struct irq_desc *desc; - spin_lock_irqsave(&vector_lock, flags); + for (irq = nr_irqs_gsi; irq < nr_irqs; irq++) + { + desc = irq_to_desc(irq); + if (cmpxchg(&desc->arch.used, IRQ_UNUSED, IRQ_RESERVED) == IRQ_UNUSED) + break; + } + + if (irq >= nr_irqs) + return -ENOSPC; - irq = find_unassigned_irq(); - if (irq < 0) - goto out; - desc = irq_to_desc(irq); ret = init_one_irq_desc(desc); if (!ret) + { + spin_lock_irqsave(&vector_lock, flags); ret = __assign_irq_vector(irq, desc, TARGET_CPUS); + spin_unlock_irqrestore(&vector_lock, flags); + } if (ret < 0) + { + desc->arch.used = IRQ_UNUSED; irq = ret; -out: - spin_unlock_irqrestore(&vector_lock, flags); + } return irq; } diff --git a/xen/include/asm-x86/irq.h b/xen/include/asm-x86/irq.h index 975adafa7a..3b654dc684 100644 --- a/xen/include/asm-x86/irq.h +++ b/xen/include/asm-x86/irq.h @@ -39,12 +39,13 @@ struct irq_cfg { unsigned move_cleanup_count; vmask_t *used_vectors; u8 move_in_progress : 1; - u8 used: 1; + s8 used; }; /* For use with irq_cfg.used */ #define IRQ_UNUSED (0) #define IRQ_USED (1) +#define IRQ_RESERVED (-1) #define IRQ_VECTOR_UNASSIGNED (-1) -- 2.30.2