diff options
-rw-r--r-- | arch/x86/kernel/io_apic_64.c | 64 | ||||
-rw-r--r-- | arch/x86/kernel/irq_64.c | 2 | ||||
-rw-r--r-- | drivers/pci/htirq.c | 22 | ||||
-rw-r--r-- | fs/proc/proc_misc.c | 2 | ||||
-rw-r--r-- | include/linux/irq.h | 1 |
5 files changed, 73 insertions, 18 deletions
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index 8ab7ae01773f..b0d4abc55a11 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c | |||
@@ -2520,17 +2520,21 @@ device_initcall(ioapic_init_sysfs); | |||
2520 | /* | 2520 | /* |
2521 | * Dynamic irq allocate and deallocation | 2521 | * Dynamic irq allocate and deallocation |
2522 | */ | 2522 | */ |
2523 | int create_irq(void) | 2523 | unsigned int create_irq_nr(unsigned int irq_want) |
2524 | { | 2524 | { |
2525 | /* Allocate an unused irq */ | 2525 | /* Allocate an unused irq */ |
2526 | int irq; | 2526 | unsigned int irq; |
2527 | int new; | 2527 | unsigned int new; |
2528 | unsigned long flags; | 2528 | unsigned long flags; |
2529 | struct irq_cfg *cfg_new; | 2529 | struct irq_cfg *cfg_new; |
2530 | 2530 | ||
2531 | irq = -ENOSPC; | 2531 | #ifndef CONFIG_HAVE_SPARSE_IRQ |
2532 | irq_want = nr_irqs - 1; | ||
2533 | #endif | ||
2534 | |||
2535 | irq = 0; | ||
2532 | spin_lock_irqsave(&vector_lock, flags); | 2536 | spin_lock_irqsave(&vector_lock, flags); |
2533 | for (new = (nr_irqs - 1); new >= 0; new--) { | 2537 | for (new = irq_want; new > 0; new--) { |
2534 | if (platform_legacy_irq(new)) | 2538 | if (platform_legacy_irq(new)) |
2535 | continue; | 2539 | continue; |
2536 | cfg_new = irq_cfg(new); | 2540 | cfg_new = irq_cfg(new); |
@@ -2545,12 +2549,24 @@ int create_irq(void) | |||
2545 | } | 2549 | } |
2546 | spin_unlock_irqrestore(&vector_lock, flags); | 2550 | spin_unlock_irqrestore(&vector_lock, flags); |
2547 | 2551 | ||
2548 | if (irq >= 0) { | 2552 | if (irq > 0) { |
2549 | dynamic_irq_init(irq); | 2553 | dynamic_irq_init(irq); |
2550 | } | 2554 | } |
2551 | return irq; | 2555 | return irq; |
2552 | } | 2556 | } |
2553 | 2557 | ||
2558 | int create_irq(void) | ||
2559 | { | ||
2560 | int irq; | ||
2561 | |||
2562 | irq = create_irq_nr(nr_irqs - 1); | ||
2563 | |||
2564 | if (irq == 0) | ||
2565 | irq = -1; | ||
2566 | |||
2567 | return irq; | ||
2568 | } | ||
2569 | |||
2554 | void destroy_irq(unsigned int irq) | 2570 | void destroy_irq(unsigned int irq) |
2555 | { | 2571 | { |
2556 | unsigned long flags; | 2572 | unsigned long flags; |
@@ -2803,13 +2819,29 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq) | |||
2803 | return 0; | 2819 | return 0; |
2804 | } | 2820 | } |
2805 | 2821 | ||
2822 | static unsigned int build_irq_for_pci_dev(struct pci_dev *dev) | ||
2823 | { | ||
2824 | unsigned int irq; | ||
2825 | |||
2826 | irq = dev->bus->number; | ||
2827 | irq <<= 8; | ||
2828 | irq |= dev->devfn; | ||
2829 | irq <<= 12; | ||
2830 | |||
2831 | return irq; | ||
2832 | } | ||
2833 | |||
2806 | int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) | 2834 | int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) |
2807 | { | 2835 | { |
2808 | int irq, ret; | 2836 | unsigned int irq; |
2837 | int ret; | ||
2838 | unsigned int irq_want; | ||
2809 | 2839 | ||
2810 | irq = create_irq(); | 2840 | irq_want = build_irq_for_pci_dev(dev) + 0x100; |
2811 | if (irq < 0) | 2841 | |
2812 | return irq; | 2842 | irq = create_irq_nr(irq_want); |
2843 | if (irq == 0) | ||
2844 | return -1; | ||
2813 | 2845 | ||
2814 | #ifdef CONFIG_INTR_REMAP | 2846 | #ifdef CONFIG_INTR_REMAP |
2815 | if (!intr_remapping_enabled) | 2847 | if (!intr_remapping_enabled) |
@@ -2836,18 +2868,22 @@ error: | |||
2836 | 2868 | ||
2837 | int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | 2869 | int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) |
2838 | { | 2870 | { |
2839 | int irq, ret, sub_handle; | 2871 | unsigned int irq; |
2872 | int ret, sub_handle; | ||
2840 | struct msi_desc *desc; | 2873 | struct msi_desc *desc; |
2874 | unsigned int irq_want; | ||
2875 | |||
2841 | #ifdef CONFIG_INTR_REMAP | 2876 | #ifdef CONFIG_INTR_REMAP |
2842 | struct intel_iommu *iommu = 0; | 2877 | struct intel_iommu *iommu = 0; |
2843 | int index = 0; | 2878 | int index = 0; |
2844 | #endif | 2879 | #endif |
2845 | 2880 | ||
2881 | irq_want = build_irq_for_pci_dev(dev) + 0x100; | ||
2846 | sub_handle = 0; | 2882 | sub_handle = 0; |
2847 | list_for_each_entry(desc, &dev->msi_list, list) { | 2883 | list_for_each_entry(desc, &dev->msi_list, list) { |
2848 | irq = create_irq(); | 2884 | irq = create_irq_nr(irq_want--); |
2849 | if (irq < 0) | 2885 | if (irq == 0) |
2850 | return irq; | 2886 | return -1; |
2851 | #ifdef CONFIG_INTR_REMAP | 2887 | #ifdef CONFIG_INTR_REMAP |
2852 | if (!intr_remapping_enabled) | 2888 | if (!intr_remapping_enabled) |
2853 | goto no_ir; | 2889 | goto no_ir; |
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index 7bd841a9c640..348a11168c2b 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c | |||
@@ -112,7 +112,7 @@ int show_interrupts(struct seq_file *p, void *v) | |||
112 | action = desc->action; | 112 | action = desc->action; |
113 | if (!action && !any_count) | 113 | if (!action && !any_count) |
114 | goto skip; | 114 | goto skip; |
115 | seq_printf(p, "%3d: ",i); | 115 | seq_printf(p, "%#x: ",i); |
116 | #ifndef CONFIG_SMP | 116 | #ifndef CONFIG_SMP |
117 | seq_printf(p, "%10u ", kstat_irqs(i)); | 117 | seq_printf(p, "%10u ", kstat_irqs(i)); |
118 | #else | 118 | #else |
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c index 279c940a0039..7c5aef13fcdb 100644 --- a/drivers/pci/htirq.c +++ b/drivers/pci/htirq.c | |||
@@ -82,6 +82,18 @@ void unmask_ht_irq(unsigned int irq) | |||
82 | write_ht_irq_msg(irq, &msg); | 82 | write_ht_irq_msg(irq, &msg); |
83 | } | 83 | } |
84 | 84 | ||
85 | static unsigned int build_irq_for_pci_dev(struct pci_dev *dev) | ||
86 | { | ||
87 | unsigned int irq; | ||
88 | |||
89 | irq = dev->bus->number; | ||
90 | irq <<= 8; | ||
91 | irq |= dev->devfn; | ||
92 | irq <<= 12; | ||
93 | |||
94 | return irq; | ||
95 | } | ||
96 | |||
85 | /** | 97 | /** |
86 | * __ht_create_irq - create an irq and attach it to a device. | 98 | * __ht_create_irq - create an irq and attach it to a device. |
87 | * @dev: The hypertransport device to find the irq capability on. | 99 | * @dev: The hypertransport device to find the irq capability on. |
@@ -97,7 +109,8 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update) | |||
97 | u32 data; | 109 | u32 data; |
98 | int max_irq; | 110 | int max_irq; |
99 | int pos; | 111 | int pos; |
100 | int irq; | 112 | unsigned int irq; |
113 | unsigned int irq_want; | ||
101 | 114 | ||
102 | pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ); | 115 | pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ); |
103 | if (!pos) | 116 | if (!pos) |
@@ -125,8 +138,13 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update) | |||
125 | cfg->msg.address_lo = 0xffffffff; | 138 | cfg->msg.address_lo = 0xffffffff; |
126 | cfg->msg.address_hi = 0xffffffff; | 139 | cfg->msg.address_hi = 0xffffffff; |
127 | 140 | ||
141 | irq_want= build_irq_for_pci_dev(dev); | ||
142 | #ifdef CONFIG_HAVE_SPARSE_IRQ | ||
143 | irq = create_irq_nr(irq_want + idx); | ||
144 | #else | ||
128 | irq = create_irq(); | 145 | irq = create_irq(); |
129 | if (irq < 0) { | 146 | #endif |
147 | if (irq == 0) { | ||
130 | kfree(cfg); | 148 | kfree(cfg); |
131 | return -EBUSY; | 149 | return -EBUSY; |
132 | } | 150 | } |
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 72dd739a7f8a..d68c3592fe4a 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c | |||
@@ -589,7 +589,7 @@ static int show_stat(struct seq_file *p, void *v) | |||
589 | } | 589 | } |
590 | 590 | ||
591 | #ifdef CONFIG_HAVE_SPARSE_IRQ | 591 | #ifdef CONFIG_HAVE_SPARSE_IRQ |
592 | seq_printf(p, " %u:%u", j, per_irq_sum); | 592 | seq_printf(p, " %#x:%u", j, per_irq_sum); |
593 | #else | 593 | #else |
594 | seq_printf(p, " %u", per_irq_sum); | 594 | seq_printf(p, " %u", per_irq_sum); |
595 | #endif | 595 | #endif |
diff --git a/include/linux/irq.h b/include/linux/irq.h index 788d5a35a580..704136138dc7 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -399,6 +399,7 @@ extern void set_irq_noprobe(unsigned int irq); | |||
399 | extern void set_irq_probe(unsigned int irq); | 399 | extern void set_irq_probe(unsigned int irq); |
400 | 400 | ||
401 | /* Handle dynamic irq creation and destruction */ | 401 | /* Handle dynamic irq creation and destruction */ |
402 | extern unsigned int create_irq_nr(unsigned int irq_want); | ||
402 | extern int create_irq(void); | 403 | extern int create_irq(void); |
403 | extern void destroy_irq(unsigned int irq); | 404 | extern void destroy_irq(unsigned int irq); |
404 | 405 | ||