diff options
author | Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> | 2007-07-17 21:20:54 +0900 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2007-07-17 09:50:13 -0700 |
commit | 40598cbe9c196f1e84dcfef70541c4a80fd996bb (patch) | |
tree | 4148c14d898ff900227b6cd000015b7f9c394fef /arch/ia64/kernel/iosapic.c | |
parent | c5e3f9e5a2152578db7a37090303ce66d03a7c87 (diff) | |
download | op-kernel-dev-40598cbe9c196f1e84dcfef70541c4a80fd996bb.zip op-kernel-dev-40598cbe9c196f1e84dcfef70541c4a80fd996bb.tar.gz |
[IA64] Cleanup lock order in iosapic_register_intr
Cleanup order of irq_desc.lock and iosapic_lock in
iosapic_register_intr() and iosapic_unregister_intr().
Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/kernel/iosapic.c')
-rw-r--r-- | arch/ia64/kernel/iosapic.c | 50 |
1 files changed, 20 insertions, 30 deletions
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 29ec86c..b3dcdb7 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -505,7 +505,7 @@ iosapic_version (char __iomem *addr) static int iosapic_find_sharable_vector (unsigned long trigger, unsigned long pol) { - int i, vector = -1, min_count = -1; + int i, vector = -ENOSPC, min_count = -1; struct iosapic_intr_info *info; /* @@ -513,7 +513,7 @@ static int iosapic_find_sharable_vector (unsigned long trigger, * supported yet */ if (trigger == IOSAPIC_EDGE) - return -1; + return -EINVAL; for (i = IA64_FIRST_DEVICE_VECTOR; i <= IA64_LAST_DEVICE_VECTOR; i++) { info = &iosapic_intr_info[i]; @@ -762,7 +762,7 @@ iosapic_register_intr (unsigned int gsi, unsigned long flags; struct iosapic_rte_info *rte; u32 low32; -again: + /* * If this GSI has already been registered (i.e., it's a * shared interrupt, or we lost a race to register it), @@ -773,36 +773,24 @@ again: if (vector > 0) { rte = gsi_vector_to_rte(gsi, vector); rte->refcnt++; - spin_unlock_irqrestore(&iosapic_lock, flags); - return vector; + goto unlock_iosapic_lock; } - spin_unlock_irqrestore(&iosapic_lock, flags); /* If vector is running out, we try to find a sharable vector */ vector = assign_irq_vector(AUTO_ASSIGN); if (vector < 0) { vector = iosapic_find_sharable_vector(trigger, polarity); if (vector < 0) - return -ENOSPC; - } - - spin_lock_irqsave(&irq_desc[vector].lock, flags); - spin_lock(&iosapic_lock); - if (gsi_to_vector(gsi) > 0) { - if (list_empty(&iosapic_intr_info[vector].rtes)) - free_irq_vector(vector); - spin_unlock(&iosapic_lock); - spin_unlock_irqrestore(&irq_desc[vector].lock, flags); - goto again; + goto unlock_iosapic_lock; } + spin_lock(&irq_desc[vector].lock); dest = get_target_cpu(gsi, vector); err = register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); if (err < 0) { - spin_unlock(&iosapic_lock); - spin_unlock_irqrestore(&irq_desc[vector].lock, flags); - return err; + vector = err; + goto unlock_all; } /* @@ -813,14 +801,15 @@ again: if (vector_is_shared(vector) && !(low32 & IOSAPIC_MASK)) mask = 0; set_rte(gsi, vector, dest, mask); - spin_unlock(&iosapic_lock); - spin_unlock_irqrestore(&irq_desc[vector].lock, flags); printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n", gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), cpu_logical_id(dest), dest, vector); - + unlock_all: + spin_unlock(&irq_desc[vector].lock); + unlock_iosapic_lock: + spin_unlock_irqrestore(&iosapic_lock, flags); return vector; } @@ -849,9 +838,7 @@ iosapic_unregister_intr (unsigned int gsi) } vector = irq_to_vector(irq); - idesc = irq_desc + irq; - spin_lock_irqsave(&idesc->lock, flags); - spin_lock(&iosapic_lock); + spin_lock_irqsave(&iosapic_lock, flags); if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) { printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi); @@ -862,13 +849,17 @@ iosapic_unregister_intr (unsigned int gsi) if (--rte->refcnt > 0) goto out; + /* Remove the rte entry from the list */ + idesc = irq_desc + irq; + spin_lock(&idesc->lock); + list_del(&rte->rte_list); + spin_unlock(&idesc->lock); + /* Mask the interrupt */ low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK; iosapic_write(rte->iosapic->addr, IOSAPIC_RTE_LOW(rte->rte_index), low32); - /* Remove the rte entry from the list */ - list_del(&rte->rte_list); iosapic_intr_info[vector].count--; iosapic_free_rte(rte); index = find_iosapic(gsi); @@ -913,8 +904,7 @@ iosapic_unregister_intr (unsigned int gsi) free_irq_vector(vector); } out: - spin_unlock(&iosapic_lock); - spin_unlock_irqrestore(&idesc->lock, flags); + spin_unlock_irqrestore(&iosapic_lock, flags); } /* |