diff options
author | Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> | 2007-07-17 08:20:54 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2007-07-17 12:50:13 -0400 |
commit | 40598cbe9c196f1e84dcfef70541c4a80fd996bb (patch) | |
tree | 4148c14d898ff900227b6cd000015b7f9c394fef /arch/ia64/kernel/iosapic.c | |
parent | c5e3f9e5a2152578db7a37090303ce66d03a7c87 (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.c | 50 |
1 files changed, 20 insertions, 30 deletions
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 29ec86c24194..b3dcdb7e7fc7 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c | |||
@@ -505,7 +505,7 @@ iosapic_version (char __iomem *addr) | |||
505 | static int iosapic_find_sharable_vector (unsigned long trigger, | 505 | static 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; |
765 | again: | 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 | /* |