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 | /* |
