aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/iosapic.c
diff options
context:
space:
mode:
authorYasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>2007-07-17 08:20:54 -0400
committerTony Luck <tony.luck@intel.com>2007-07-17 12:50:13 -0400
commit40598cbe9c196f1e84dcfef70541c4a80fd996bb (patch)
tree4148c14d898ff900227b6cd000015b7f9c394fef /arch/ia64/kernel/iosapic.c
parentc5e3f9e5a2152578db7a37090303ce66d03a7c87 (diff)
[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.c50
1 files changed, 20 insertions, 30 deletions
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 29ec86c2419..b3dcdb7e7fc 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -505,7 +505,7 @@ iosapic_version (char __iomem *addr)
505static int iosapic_find_sharable_vector (unsigned long trigger, 505static int iosapic_find_sharable_vector (unsigned long trigger,
506 unsigned long pol) 506 unsigned long pol)
507{ 507{
508 int i, vector = -1, min_count = -1; 508 int i, vector = -ENOSPC, min_count = -1;
509 struct iosapic_intr_info *info; 509 struct iosapic_intr_info *info;
510 510
511 /* 511 /*
@@ -513,7 +513,7 @@ static int iosapic_find_sharable_vector (unsigned long trigger,
513 * supported yet 513 * supported yet
514 */ 514 */
515 if (trigger == IOSAPIC_EDGE) 515 if (trigger == IOSAPIC_EDGE)
516 return -1; 516 return -EINVAL;
517 517
518 for (i = IA64_FIRST_DEVICE_VECTOR; i <= IA64_LAST_DEVICE_VECTOR; i++) { 518 for (i = IA64_FIRST_DEVICE_VECTOR; i <= IA64_LAST_DEVICE_VECTOR; i++) {
519 info = &iosapic_intr_info[i]; 519 info = &iosapic_intr_info[i];
@@ -762,7 +762,7 @@ iosapic_register_intr (unsigned int gsi,
762 unsigned long flags; 762 unsigned long flags;
763 struct iosapic_rte_info *rte; 763 struct iosapic_rte_info *rte;
764 u32 low32; 764 u32 low32;
765again: 765
766 /* 766 /*
767 * If this GSI has already been registered (i.e., it's a 767 * If this GSI has already been registered (i.e., it's a
768 * shared interrupt, or we lost a race to register it), 768 * shared interrupt, or we lost a race to register it),
@@ -773,36 +773,24 @@ again:
773 if (vector > 0) { 773 if (vector > 0) {
774 rte = gsi_vector_to_rte(gsi, vector); 774 rte = gsi_vector_to_rte(gsi, vector);
775 rte->refcnt++; 775 rte->refcnt++;
776 spin_unlock_irqrestore(&iosapic_lock, flags); 776 goto unlock_iosapic_lock;
777 return vector;
778 } 777 }
779 spin_unlock_irqrestore(&iosapic_lock, flags);
780 778
781 /* If vector is running out, we try to find a sharable vector */ 779 /* If vector is running out, we try to find a sharable vector */
782 vector = assign_irq_vector(AUTO_ASSIGN); 780 vector = assign_irq_vector(AUTO_ASSIGN);
783 if (vector < 0) { 781 if (vector < 0) {
784 vector = iosapic_find_sharable_vector(trigger, polarity); 782 vector = iosapic_find_sharable_vector(trigger, polarity);
785 if (vector < 0) 783 if (vector < 0)
786 return -ENOSPC; 784 goto unlock_iosapic_lock;
787 }
788
789 spin_lock_irqsave(&irq_desc[vector].lock, flags);
790 spin_lock(&iosapic_lock);
791 if (gsi_to_vector(gsi) > 0) {
792 if (list_empty(&iosapic_intr_info[vector].rtes))
793 free_irq_vector(vector);
794 spin_unlock(&iosapic_lock);
795 spin_unlock_irqrestore(&irq_desc[vector].lock, flags);
796 goto again;
797 } 785 }
798 786
787 spin_lock(&irq_desc[vector].lock);
799 dest = get_target_cpu(gsi, vector); 788 dest = get_target_cpu(gsi, vector);
800 err = register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, 789 err = register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
801 polarity, trigger); 790 polarity, trigger);
802 if (err < 0) { 791 if (err < 0) {
803 spin_unlock(&iosapic_lock); 792 vector = err;
804 spin_unlock_irqrestore(&irq_desc[vector].lock, flags); 793 goto unlock_all;
805 return err;
806 } 794 }
807 795
808 /* 796 /*
@@ -813,14 +801,15 @@ again:
813 if (vector_is_shared(vector) && !(low32 & IOSAPIC_MASK)) 801 if (vector_is_shared(vector) && !(low32 & IOSAPIC_MASK))
814 mask = 0; 802 mask = 0;
815 set_rte(gsi, vector, dest, mask); 803 set_rte(gsi, vector, dest, mask);
816 spin_unlock(&iosapic_lock);
817 spin_unlock_irqrestore(&irq_desc[vector].lock, flags);
818 804
819 printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n", 805 printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n",
820 gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), 806 gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
821 (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), 807 (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
822 cpu_logical_id(dest), dest, vector); 808 cpu_logical_id(dest), dest, vector);
823 809 unlock_all:
810 spin_unlock(&irq_desc[vector].lock);
811 unlock_iosapic_lock:
812 spin_unlock_irqrestore(&iosapic_lock, flags);
824 return vector; 813 return vector;
825} 814}
826 815
@@ -849,9 +838,7 @@ iosapic_unregister_intr (unsigned int gsi)
849 } 838 }
850 vector = irq_to_vector(irq); 839 vector = irq_to_vector(irq);
851 840
852 idesc = irq_desc + irq; 841 spin_lock_irqsave(&iosapic_lock, flags);
853 spin_lock_irqsave(&idesc->lock, flags);
854 spin_lock(&iosapic_lock);
855 if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) { 842 if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) {
856 printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", 843 printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n",
857 gsi); 844 gsi);
@@ -862,13 +849,17 @@ iosapic_unregister_intr (unsigned int gsi)
862 if (--rte->refcnt > 0) 849 if (--rte->refcnt > 0)
863 goto out; 850 goto out;
864 851
852 /* Remove the rte entry from the list */
853 idesc = irq_desc + irq;
854 spin_lock(&idesc->lock);
855 list_del(&rte->rte_list);
856 spin_unlock(&idesc->lock);
857
865 /* Mask the interrupt */ 858 /* Mask the interrupt */
866 low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK; 859 low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK;
867 iosapic_write(rte->iosapic->addr, 860 iosapic_write(rte->iosapic->addr,
868 IOSAPIC_RTE_LOW(rte->rte_index), low32); 861 IOSAPIC_RTE_LOW(rte->rte_index), low32);
869 862
870 /* Remove the rte entry from the list */
871 list_del(&rte->rte_list);
872 iosapic_intr_info[vector].count--; 863 iosapic_intr_info[vector].count--;
873 iosapic_free_rte(rte); 864 iosapic_free_rte(rte);
874 index = find_iosapic(gsi); 865 index = find_iosapic(gsi);
@@ -913,8 +904,7 @@ iosapic_unregister_intr (unsigned int gsi)
913 free_irq_vector(vector); 904 free_irq_vector(vector);
914 } 905 }
915 out: 906 out:
916 spin_unlock(&iosapic_lock); 907 spin_unlock_irqrestore(&iosapic_lock, flags);
917 spin_unlock_irqrestore(&idesc->lock, flags);
918} 908}
919 909
920/* 910/*