aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/Kconfig11
-rw-r--r--arch/s390/include/asm/hardirq.h5
-rw-r--r--arch/s390/include/asm/hw_irq.h17
-rw-r--r--arch/s390/include/asm/irq.h35
-rw-r--r--arch/s390/include/asm/pci.h16
-rw-r--r--arch/s390/include/asm/serial.h6
-rw-r--r--arch/s390/kernel/entry.S12
-rw-r--r--arch/s390/kernel/entry64.S9
-rw-r--r--arch/s390/kernel/irq.c160
-rw-r--r--arch/s390/pci/Makefile2
-rw-r--r--arch/s390/pci/pci.c255
-rw-r--r--arch/s390/pci/pci_msi.c134
-rw-r--r--drivers/s390/cio/airq.c21
-rw-r--r--drivers/s390/cio/cio.c46
-rw-r--r--drivers/s390/cio/cio.h3
15 files changed, 249 insertions, 483 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 8a4cae78f03c..8b7892bf6d8b 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -116,6 +116,7 @@ config S390
116 select HAVE_FUNCTION_GRAPH_TRACER 116 select HAVE_FUNCTION_GRAPH_TRACER
117 select HAVE_FUNCTION_TRACER 117 select HAVE_FUNCTION_TRACER
118 select HAVE_FUNCTION_TRACE_MCOUNT_TEST 118 select HAVE_FUNCTION_TRACE_MCOUNT_TEST
119 select HAVE_GENERIC_HARDIRQS
119 select HAVE_KERNEL_BZIP2 120 select HAVE_KERNEL_BZIP2
120 select HAVE_KERNEL_GZIP 121 select HAVE_KERNEL_GZIP
121 select HAVE_KERNEL_LZ4 122 select HAVE_KERNEL_LZ4
@@ -445,6 +446,16 @@ config PCI_NR_FUNCTIONS
445 This allows you to specify the maximum number of PCI functions which 446 This allows you to specify the maximum number of PCI functions which
446 this kernel will support. 447 this kernel will support.
447 448
449config PCI_NR_MSI
450 int "Maximum number of MSI interrupts (64-32768)"
451 range 64 32768
452 default "256"
453 help
454 This defines the number of virtual interrupts the kernel will
455 provide for MSI interrupts. If you configure your system to have
456 too few drivers will fail to allocate MSI interrupts for all
457 PCI devices.
458
448source "drivers/pci/Kconfig" 459source "drivers/pci/Kconfig"
449source "drivers/pci/pcie/Kconfig" 460source "drivers/pci/pcie/Kconfig"
450source "drivers/pci/hotplug/Kconfig" 461source "drivers/pci/hotplug/Kconfig"
diff --git a/arch/s390/include/asm/hardirq.h b/arch/s390/include/asm/hardirq.h
index 0c82ba86e997..a908d2941c5d 100644
--- a/arch/s390/include/asm/hardirq.h
+++ b/arch/s390/include/asm/hardirq.h
@@ -20,4 +20,9 @@
20 20
21#define HARDIRQ_BITS 8 21#define HARDIRQ_BITS 8
22 22
23static inline void ack_bad_irq(unsigned int irq)
24{
25 printk(KERN_CRIT "unexpected IRQ trap at vector %02x\n", irq);
26}
27
23#endif /* __ASM_HARDIRQ_H */ 28#endif /* __ASM_HARDIRQ_H */
diff --git a/arch/s390/include/asm/hw_irq.h b/arch/s390/include/asm/hw_irq.h
index 7e3d2586c1ff..ee96a8b697f9 100644
--- a/arch/s390/include/asm/hw_irq.h
+++ b/arch/s390/include/asm/hw_irq.h
@@ -4,19 +4,8 @@
4#include <linux/msi.h> 4#include <linux/msi.h>
5#include <linux/pci.h> 5#include <linux/pci.h>
6 6
7static inline struct msi_desc *irq_get_msi_desc(unsigned int irq) 7void __init init_airq_interrupts(void);
8{ 8void __init init_cio_interrupts(void);
9 return __irq_get_msi_desc(irq); 9void __init init_ext_interrupts(void);
10}
11
12/* Must be called with msi map lock held */
13static inline int irq_set_msi_desc(unsigned int irq, struct msi_desc *msi)
14{
15 if (!msi)
16 return -EINVAL;
17
18 msi->irq = irq;
19 return 0;
20}
21 10
22#endif 11#endif
diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h
index 87c17bfb2968..1eaa3625803c 100644
--- a/arch/s390/include/asm/irq.h
+++ b/arch/s390/include/asm/irq.h
@@ -1,17 +1,28 @@
1#ifndef _ASM_IRQ_H 1#ifndef _ASM_IRQ_H
2#define _ASM_IRQ_H 2#define _ASM_IRQ_H
3 3
4#define EXT_INTERRUPT 1
5#define IO_INTERRUPT 2
6#define THIN_INTERRUPT 3
7
8#define NR_IRQS_BASE 4
9
10#ifdef CONFIG_PCI_NR_MSI
11# define NR_IRQS (NR_IRQS_BASE + CONFIG_PCI_NR_MSI)
12#else
13# define NR_IRQS NR_IRQS_BASE
14#endif
15
16/* This number is used when no interrupt has been assigned */
17#define NO_IRQ 0
18
19#ifndef __ASSEMBLY__
20
4#include <linux/hardirq.h> 21#include <linux/hardirq.h>
5#include <linux/percpu.h> 22#include <linux/percpu.h>
6#include <linux/cache.h> 23#include <linux/cache.h>
7#include <linux/types.h> 24#include <linux/types.h>
8 25
9enum interruption_main_class {
10 EXTERNAL_INTERRUPT,
11 IO_INTERRUPT,
12 NR_IRQS
13};
14
15enum interruption_class { 26enum interruption_class {
16 IRQEXT_CLK, 27 IRQEXT_CLK,
17 IRQEXT_EXC, 28 IRQEXT_EXC,
@@ -72,14 +83,8 @@ void service_subclass_irq_unregister(void);
72void measurement_alert_subclass_register(void); 83void measurement_alert_subclass_register(void);
73void measurement_alert_subclass_unregister(void); 84void measurement_alert_subclass_unregister(void);
74 85
75#ifdef CONFIG_LOCKDEP 86#define irq_canonicalize(irq) (irq)
76# define disable_irq_nosync_lockdep(irq) disable_irq_nosync(irq) 87
77# define disable_irq_nosync_lockdep_irqsave(irq, flags) \ 88#endif /* __ASSEMBLY__ */
78 disable_irq_nosync(irq)
79# define disable_irq_lockdep(irq) disable_irq(irq)
80# define enable_irq_lockdep(irq) enable_irq(irq)
81# define enable_irq_lockdep_irqrestore(irq, flags) \
82 enable_irq(irq)
83#endif
84 89
85#endif /* _ASM_IRQ_H */ 90#endif /* _ASM_IRQ_H */
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index 7d3295087aa4..d0872769d44e 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -53,12 +53,6 @@ struct zpci_fmb {
53 atomic64_t unmapped_pages; 53 atomic64_t unmapped_pages;
54} __packed __aligned(16); 54} __packed __aligned(16);
55 55
56struct msi_map {
57 unsigned long irq;
58 struct msi_desc *msi;
59 struct hlist_node msi_chain;
60};
61
62#define ZPCI_MSI_VEC_BITS 11 56#define ZPCI_MSI_VEC_BITS 11
63#define ZPCI_MSI_VEC_MAX (1 << ZPCI_MSI_VEC_BITS) 57#define ZPCI_MSI_VEC_MAX (1 << ZPCI_MSI_VEC_BITS)
64#define ZPCI_MSI_VEC_MASK (ZPCI_MSI_VEC_MAX - 1) 58#define ZPCI_MSI_VEC_MASK (ZPCI_MSI_VEC_MAX - 1)
@@ -92,8 +86,6 @@ struct zpci_dev {
92 86
93 /* IRQ stuff */ 87 /* IRQ stuff */
94 u64 msi_addr; /* MSI address */ 88 u64 msi_addr; /* MSI address */
95 struct zdev_irq_map *irq_map;
96 struct msi_map *msi_map;
97 struct airq_iv *aibv; /* adapter interrupt bit vector */ 89 struct airq_iv *aibv; /* adapter interrupt bit vector */
98 unsigned int aisb; /* number of the summary bit */ 90 unsigned int aisb; /* number of the summary bit */
99 91
@@ -153,14 +145,6 @@ int clp_add_pci_device(u32, u32, int);
153int clp_enable_fh(struct zpci_dev *, u8); 145int clp_enable_fh(struct zpci_dev *, u8);
154int clp_disable_fh(struct zpci_dev *); 146int clp_disable_fh(struct zpci_dev *);
155 147
156/* MSI */
157struct msi_desc *__irq_get_msi_desc(unsigned int);
158int zpci_msi_set_mask_bits(struct msi_desc *, u32, u32);
159int zpci_setup_msi_irq(struct zpci_dev *, struct msi_desc *, unsigned int, int);
160void zpci_teardown_msi_irq(struct zpci_dev *, struct msi_desc *);
161int zpci_msihash_init(void);
162void zpci_msihash_exit(void);
163
164#ifdef CONFIG_PCI 148#ifdef CONFIG_PCI
165/* Error handling and recovery */ 149/* Error handling and recovery */
166void zpci_event_error(void *); 150void zpci_event_error(void *);
diff --git a/arch/s390/include/asm/serial.h b/arch/s390/include/asm/serial.h
new file mode 100644
index 000000000000..5b3e48ef534b
--- /dev/null
+++ b/arch/s390/include/asm/serial.h
@@ -0,0 +1,6 @@
1#ifndef _ASM_S390_SERIAL_H
2#define _ASM_S390_SERIAL_H
3
4#define BASE_BAUD 0
5
6#endif /* _ASM_S390_SERIAL_H */
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index be7a408be7a1..5ca70b4b72cb 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -18,6 +18,7 @@
18#include <asm/unistd.h> 18#include <asm/unistd.h>
19#include <asm/page.h> 19#include <asm/page.h>
20#include <asm/sigp.h> 20#include <asm/sigp.h>
21#include <asm/irq.h>
21 22
22__PT_R0 = __PT_GPRS 23__PT_R0 = __PT_GPRS
23__PT_R1 = __PT_GPRS + 4 24__PT_R1 = __PT_GPRS + 4
@@ -435,6 +436,11 @@ io_skip:
435io_loop: 436io_loop:
436 l %r1,BASED(.Ldo_IRQ) 437 l %r1,BASED(.Ldo_IRQ)
437 lr %r2,%r11 # pass pointer to pt_regs 438 lr %r2,%r11 # pass pointer to pt_regs
439 lhi %r3,IO_INTERRUPT
440 tm __PT_INT_CODE+8(%r11),0x80 # adapter interrupt ?
441 jz io_call
442 lhi %r3,THIN_INTERRUPT
443io_call:
438 basr %r14,%r1 # call do_IRQ 444 basr %r14,%r1 # call do_IRQ
439 tm __LC_MACHINE_FLAGS+2,0x10 # MACHINE_FLAG_LPAR 445 tm __LC_MACHINE_FLAGS+2,0x10 # MACHINE_FLAG_LPAR
440 jz io_return 446 jz io_return
@@ -584,9 +590,10 @@ ext_skip:
584 mvc __PT_INT_CODE(4,%r11),__LC_EXT_CPU_ADDR 590 mvc __PT_INT_CODE(4,%r11),__LC_EXT_CPU_ADDR
585 mvc __PT_INT_PARM(4,%r11),__LC_EXT_PARAMS 591 mvc __PT_INT_PARM(4,%r11),__LC_EXT_PARAMS
586 TRACE_IRQS_OFF 592 TRACE_IRQS_OFF
593 l %r1,BASED(.Ldo_IRQ)
587 lr %r2,%r11 # pass pointer to pt_regs 594 lr %r2,%r11 # pass pointer to pt_regs
588 l %r1,BASED(.Ldo_extint) 595 lhi %r3,EXT_INTERRUPT
589 basr %r14,%r1 # call do_extint 596 basr %r14,%r1 # call do_IRQ
590 j io_return 597 j io_return
591 598
592/* 599/*
@@ -902,7 +909,6 @@ cleanup_idle_wait:
902.Ldo_machine_check: .long s390_do_machine_check 909.Ldo_machine_check: .long s390_do_machine_check
903.Lhandle_mcck: .long s390_handle_mcck 910.Lhandle_mcck: .long s390_handle_mcck
904.Ldo_IRQ: .long do_IRQ 911.Ldo_IRQ: .long do_IRQ
905.Ldo_extint: .long do_extint
906.Ldo_signal: .long do_signal 912.Ldo_signal: .long do_signal
907.Ldo_notify_resume: .long do_notify_resume 913.Ldo_notify_resume: .long do_notify_resume
908.Ldo_per_trap: .long do_per_trap 914.Ldo_per_trap: .long do_per_trap
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 1c039d0c24c7..980c7aa1cc5c 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -19,6 +19,7 @@
19#include <asm/unistd.h> 19#include <asm/unistd.h>
20#include <asm/page.h> 20#include <asm/page.h>
21#include <asm/sigp.h> 21#include <asm/sigp.h>
22#include <asm/irq.h>
22 23
23__PT_R0 = __PT_GPRS 24__PT_R0 = __PT_GPRS
24__PT_R1 = __PT_GPRS + 8 25__PT_R1 = __PT_GPRS + 8
@@ -468,6 +469,11 @@ io_skip:
468 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) 469 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
469io_loop: 470io_loop:
470 lgr %r2,%r11 # pass pointer to pt_regs 471 lgr %r2,%r11 # pass pointer to pt_regs
472 lghi %r3,IO_INTERRUPT
473 tm __PT_INT_CODE+8(%r11),0x80 # adapter interrupt ?
474 jz io_call
475 lghi %r3,THIN_INTERRUPT
476io_call:
471 brasl %r14,do_IRQ 477 brasl %r14,do_IRQ
472 tm __LC_MACHINE_FLAGS+6,0x10 # MACHINE_FLAG_LPAR 478 tm __LC_MACHINE_FLAGS+6,0x10 # MACHINE_FLAG_LPAR
473 jz io_return 479 jz io_return
@@ -623,7 +629,8 @@ ext_skip:
623 TRACE_IRQS_OFF 629 TRACE_IRQS_OFF
624 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) 630 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
625 lgr %r2,%r11 # pass pointer to pt_regs 631 lgr %r2,%r11 # pass pointer to pt_regs
626 brasl %r14,do_extint 632 lghi %r3,EXT_INTERRUPT
633 brasl %r14,do_IRQ
627 j io_return 634 j io_return
628 635
629/* 636/*
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index 54b0995514e8..b34ba0ea96a9 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -22,6 +22,7 @@
22#include <asm/cputime.h> 22#include <asm/cputime.h>
23#include <asm/lowcore.h> 23#include <asm/lowcore.h>
24#include <asm/irq.h> 24#include <asm/irq.h>
25#include <asm/hw_irq.h>
25#include "entry.h" 26#include "entry.h"
26 27
27DEFINE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat); 28DEFINE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat);
@@ -42,9 +43,10 @@ struct irq_class {
42 * Since the external and I/O interrupt fields are already sums we would end 43 * Since the external and I/O interrupt fields are already sums we would end
43 * up with having a sum which accounts each interrupt twice. 44 * up with having a sum which accounts each interrupt twice.
44 */ 45 */
45static const struct irq_class irqclass_main_desc[NR_IRQS] = { 46static const struct irq_class irqclass_main_desc[NR_IRQS_BASE] = {
46 [EXTERNAL_INTERRUPT] = {.name = "EXT"}, 47 [EXT_INTERRUPT] = {.name = "EXT"},
47 [IO_INTERRUPT] = {.name = "I/O"} 48 [IO_INTERRUPT] = {.name = "I/O"},
49 [THIN_INTERRUPT] = {.name = "AIO"},
48}; 50};
49 51
50/* 52/*
@@ -86,6 +88,28 @@ static const struct irq_class irqclass_sub_desc[NR_ARCH_IRQS] = {
86 [CPU_RST] = {.name = "RST", .desc = "[CPU] CPU Restart"}, 88 [CPU_RST] = {.name = "RST", .desc = "[CPU] CPU Restart"},
87}; 89};
88 90
91void __init init_IRQ(void)
92{
93 irq_reserve_irqs(0, THIN_INTERRUPT);
94 init_cio_interrupts();
95 init_airq_interrupts();
96 init_ext_interrupts();
97}
98
99void do_IRQ(struct pt_regs *regs, int irq)
100{
101 struct pt_regs *old_regs;
102
103 old_regs = set_irq_regs(regs);
104 irq_enter();
105 if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
106 /* Serve timer interrupts first. */
107 clock_comparator_work();
108 generic_handle_irq(irq);
109 irq_exit();
110 set_irq_regs(old_regs);
111}
112
89/* 113/*
90 * show_interrupts is needed by /proc/interrupts. 114 * show_interrupts is needed by /proc/interrupts.
91 */ 115 */
@@ -100,27 +124,36 @@ int show_interrupts(struct seq_file *p, void *v)
100 for_each_online_cpu(cpu) 124 for_each_online_cpu(cpu)
101 seq_printf(p, "CPU%d ", cpu); 125 seq_printf(p, "CPU%d ", cpu);
102 seq_putc(p, '\n'); 126 seq_putc(p, '\n');
127 goto out;
103 } 128 }
104 if (irq < NR_IRQS) { 129 if (irq < NR_IRQS) {
130 if (irq >= NR_IRQS_BASE)
131 goto out;
105 seq_printf(p, "%s: ", irqclass_main_desc[irq].name); 132 seq_printf(p, "%s: ", irqclass_main_desc[irq].name);
106 for_each_online_cpu(cpu) 133 for_each_online_cpu(cpu)
107 seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[irq]); 134 seq_printf(p, "%10u ", kstat_irqs_cpu(irq, cpu));
108 seq_putc(p, '\n'); 135 seq_putc(p, '\n');
109 goto skip_arch_irqs; 136 goto out;
110 } 137 }
111 for (irq = 0; irq < NR_ARCH_IRQS; irq++) { 138 for (irq = 0; irq < NR_ARCH_IRQS; irq++) {
112 seq_printf(p, "%s: ", irqclass_sub_desc[irq].name); 139 seq_printf(p, "%s: ", irqclass_sub_desc[irq].name);
113 for_each_online_cpu(cpu) 140 for_each_online_cpu(cpu)
114 seq_printf(p, "%10u ", per_cpu(irq_stat, cpu).irqs[irq]); 141 seq_printf(p, "%10u ",
142 per_cpu(irq_stat, cpu).irqs[irq]);
115 if (irqclass_sub_desc[irq].desc) 143 if (irqclass_sub_desc[irq].desc)
116 seq_printf(p, " %s", irqclass_sub_desc[irq].desc); 144 seq_printf(p, " %s", irqclass_sub_desc[irq].desc);
117 seq_putc(p, '\n'); 145 seq_putc(p, '\n');
118 } 146 }
119skip_arch_irqs: 147out:
120 put_online_cpus(); 148 put_online_cpus();
121 return 0; 149 return 0;
122} 150}
123 151
152int arch_show_interrupts(struct seq_file *p, int prec)
153{
154 return 0;
155}
156
124/* 157/*
125 * Switch to the asynchronous interrupt stack for softirq execution. 158 * Switch to the asynchronous interrupt stack for softirq execution.
126 */ 159 */
@@ -159,14 +192,6 @@ asmlinkage void do_softirq(void)
159 local_irq_restore(flags); 192 local_irq_restore(flags);
160} 193}
161 194
162#ifdef CONFIG_PROC_FS
163void init_irq_proc(void)
164{
165 if (proc_mkdir("irq", NULL))
166 create_prof_cpu_mask();
167}
168#endif
169
170/* 195/*
171 * ext_int_hash[index] is the list head for all external interrupts that hash 196 * ext_int_hash[index] is the list head for all external interrupts that hash
172 * to this index. 197 * to this index.
@@ -183,14 +208,6 @@ struct ext_int_info {
183/* ext_int_hash_lock protects the handler lists for external interrupts */ 208/* ext_int_hash_lock protects the handler lists for external interrupts */
184DEFINE_SPINLOCK(ext_int_hash_lock); 209DEFINE_SPINLOCK(ext_int_hash_lock);
185 210
186static void __init init_external_interrupts(void)
187{
188 int idx;
189
190 for (idx = 0; idx < ARRAY_SIZE(ext_int_hash); idx++)
191 INIT_LIST_HEAD(&ext_int_hash[idx]);
192}
193
194static inline int ext_hash(u16 code) 211static inline int ext_hash(u16 code)
195{ 212{
196 return (code + (code >> 9)) & 0xff; 213 return (code + (code >> 9)) & 0xff;
@@ -234,20 +251,13 @@ int unregister_external_interrupt(u16 code, ext_int_handler_t handler)
234} 251}
235EXPORT_SYMBOL(unregister_external_interrupt); 252EXPORT_SYMBOL(unregister_external_interrupt);
236 253
237void __irq_entry do_extint(struct pt_regs *regs) 254static irqreturn_t do_ext_interrupt(int irq, void *dummy)
238{ 255{
256 struct pt_regs *regs = get_irq_regs();
239 struct ext_code ext_code; 257 struct ext_code ext_code;
240 struct pt_regs *old_regs;
241 struct ext_int_info *p; 258 struct ext_int_info *p;
242 int index; 259 int index;
243 260
244 old_regs = set_irq_regs(regs);
245 irq_enter();
246 if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) {
247 /* Serve timer interrupts first. */
248 clock_comparator_work();
249 }
250 kstat_incr_irqs_this_cpu(EXTERNAL_INTERRUPT, NULL);
251 ext_code = *(struct ext_code *) &regs->int_code; 261 ext_code = *(struct ext_code *) &regs->int_code;
252 if (ext_code.code != 0x1004) 262 if (ext_code.code != 0x1004)
253 __get_cpu_var(s390_idle).nohz_delay = 1; 263 __get_cpu_var(s390_idle).nohz_delay = 1;
@@ -259,13 +269,25 @@ void __irq_entry do_extint(struct pt_regs *regs)
259 p->handler(ext_code, regs->int_parm, 269 p->handler(ext_code, regs->int_parm,
260 regs->int_parm_long); 270 regs->int_parm_long);
261 rcu_read_unlock(); 271 rcu_read_unlock();
262 irq_exit(); 272
263 set_irq_regs(old_regs); 273 return IRQ_HANDLED;
264} 274}
265 275
266void __init init_IRQ(void) 276static struct irqaction external_interrupt = {
277 .name = "EXT",
278 .handler = do_ext_interrupt,
279};
280
281void __init init_ext_interrupts(void)
267{ 282{
268 init_external_interrupts(); 283 int idx;
284
285 for (idx = 0; idx < ARRAY_SIZE(ext_int_hash); idx++)
286 INIT_LIST_HEAD(&ext_int_hash[idx]);
287
288 irq_set_chip_and_handler(EXT_INTERRUPT,
289 &dummy_irq_chip, handle_percpu_irq);
290 setup_irq(EXT_INTERRUPT, &external_interrupt);
269} 291}
270 292
271static DEFINE_SPINLOCK(sc_irq_lock); 293static DEFINE_SPINLOCK(sc_irq_lock);
@@ -313,69 +335,3 @@ void measurement_alert_subclass_unregister(void)
313 spin_unlock(&ma_subclass_lock); 335 spin_unlock(&ma_subclass_lock);
314} 336}
315EXPORT_SYMBOL(measurement_alert_subclass_unregister); 337EXPORT_SYMBOL(measurement_alert_subclass_unregister);
316
317#ifdef CONFIG_SMP
318void synchronize_irq(unsigned int irq)
319{
320 /*
321 * Not needed, the handler is protected by a lock and IRQs that occur
322 * after the handler is deleted are just NOPs.
323 */
324}
325EXPORT_SYMBOL_GPL(synchronize_irq);
326#endif
327
328#ifndef CONFIG_PCI
329
330/* Only PCI devices have dynamically-defined IRQ handlers */
331
332int request_irq(unsigned int irq, irq_handler_t handler,
333 unsigned long irqflags, const char *devname, void *dev_id)
334{
335 return -EINVAL;
336}
337EXPORT_SYMBOL_GPL(request_irq);
338
339void free_irq(unsigned int irq, void *dev_id)
340{
341 WARN_ON(1);
342}
343EXPORT_SYMBOL_GPL(free_irq);
344
345void enable_irq(unsigned int irq)
346{
347 WARN_ON(1);
348}
349EXPORT_SYMBOL_GPL(enable_irq);
350
351void disable_irq(unsigned int irq)
352{
353 WARN_ON(1);
354}
355EXPORT_SYMBOL_GPL(disable_irq);
356
357#endif /* !CONFIG_PCI */
358
359void disable_irq_nosync(unsigned int irq)
360{
361 disable_irq(irq);
362}
363EXPORT_SYMBOL_GPL(disable_irq_nosync);
364
365unsigned long probe_irq_on(void)
366{
367 return 0;
368}
369EXPORT_SYMBOL_GPL(probe_irq_on);
370
371int probe_irq_off(unsigned long val)
372{
373 return 0;
374}
375EXPORT_SYMBOL_GPL(probe_irq_off);
376
377unsigned int probe_irq_mask(unsigned long val)
378{
379 return val;
380}
381EXPORT_SYMBOL_GPL(probe_irq_mask);
diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile
index 086a2e37935d..a9e1dc4ae442 100644
--- a/arch/s390/pci/Makefile
+++ b/arch/s390/pci/Makefile
@@ -2,5 +2,5 @@
2# Makefile for the s390 PCI subsystem. 2# Makefile for the s390 PCI subsystem.
3# 3#
4 4
5obj-$(CONFIG_PCI) += pci.o pci_dma.o pci_clp.o pci_msi.o pci_sysfs.o \ 5obj-$(CONFIG_PCI) += pci.o pci_dma.o pci_clp.o pci_sysfs.o \
6 pci_event.o pci_debug.o pci_insn.o 6 pci_event.o pci_debug.o pci_insn.o
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 27e7fed3707d..d65dc4f50e2a 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -50,24 +50,23 @@ EXPORT_SYMBOL_GPL(zpci_list);
50DEFINE_MUTEX(zpci_list_lock); 50DEFINE_MUTEX(zpci_list_lock);
51EXPORT_SYMBOL_GPL(zpci_list_lock); 51EXPORT_SYMBOL_GPL(zpci_list_lock);
52 52
53static struct pci_hp_callback_ops *hotplug_ops;
54 53
55static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES); 54static void zpci_enable_irq(struct irq_data *data);
56static DEFINE_SPINLOCK(zpci_domain_lock); 55static void zpci_disable_irq(struct irq_data *data);
57 56
58struct callback { 57static struct irq_chip zpci_irq_chip = {
59 irq_handler_t handler; 58 .name = "zPCI",
60 void *data; 59 .irq_unmask = zpci_enable_irq,
60 .irq_mask = zpci_disable_irq,
61}; 61};
62 62
63struct zdev_irq_map { 63static struct pci_hp_callback_ops *hotplug_ops;
64 struct airq_iv *aibv; /* Adapter interrupt bit vector */ 64
65 struct callback *cb; /* callback handler array */ 65static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES);
66 int msi_vecs; /* consecutive MSI-vectors used */ 66static DEFINE_SPINLOCK(zpci_domain_lock);
67};
68 67
69static struct airq_iv *zpci_aisb_iv; 68static struct airq_iv *zpci_aisb_iv;
70static struct zdev_irq_map *zpci_imap[ZPCI_NR_DEVICES]; 69static struct airq_iv *zpci_aibv[ZPCI_NR_DEVICES];
71 70
72/* Adapter interrupt definitions */ 71/* Adapter interrupt definitions */
73static void zpci_irq_handler(struct airq_struct *airq); 72static void zpci_irq_handler(struct airq_struct *airq);
@@ -83,19 +82,8 @@ static DECLARE_BITMAP(zpci_iomap, ZPCI_IOMAP_MAX_ENTRIES);
83struct zpci_iomap_entry *zpci_iomap_start; 82struct zpci_iomap_entry *zpci_iomap_start;
84EXPORT_SYMBOL_GPL(zpci_iomap_start); 83EXPORT_SYMBOL_GPL(zpci_iomap_start);
85 84
86static struct kmem_cache *zdev_irq_cache;
87static struct kmem_cache *zdev_fmb_cache; 85static struct kmem_cache *zdev_fmb_cache;
88 86
89static inline int irq_to_msi_nr(unsigned int irq)
90{
91 return irq & ZPCI_MSI_VEC_MASK;
92}
93
94static inline int irq_to_dev_nr(unsigned int irq)
95{
96 return irq >> ZPCI_MSI_VEC_BITS;
97}
98
99struct zpci_dev *get_zdev(struct pci_dev *pdev) 87struct zpci_dev *get_zdev(struct pci_dev *pdev)
100{ 88{
101 return (struct zpci_dev *) pdev->sysdata; 89 return (struct zpci_dev *) pdev->sysdata;
@@ -283,21 +271,42 @@ static int zpci_cfg_store(struct zpci_dev *zdev, int offset, u32 val, u8 len)
283 return rc; 271 return rc;
284} 272}
285 273
286void enable_irq(unsigned int irq) 274static int zpci_msi_set_mask_bits(struct msi_desc *msi, u32 mask, u32 flag)
275{
276 int offset, pos;
277 u32 mask_bits;
278
279 if (msi->msi_attrib.is_msix) {
280 offset = msi->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
281 PCI_MSIX_ENTRY_VECTOR_CTRL;
282 msi->masked = readl(msi->mask_base + offset);
283 writel(flag, msi->mask_base + offset);
284 } else if (msi->msi_attrib.maskbit) {
285 pos = (long) msi->mask_base;
286 pci_read_config_dword(msi->dev, pos, &mask_bits);
287 mask_bits &= ~(mask);
288 mask_bits |= flag & mask;
289 pci_write_config_dword(msi->dev, pos, mask_bits);
290 } else
291 return 0;
292
293 msi->msi_attrib.maskbit = !!flag;
294 return 1;
295}
296
297static void zpci_enable_irq(struct irq_data *data)
287{ 298{
288 struct msi_desc *msi = irq_get_msi_desc(irq); 299 struct msi_desc *msi = irq_get_msi_desc(data->irq);
289 300
290 zpci_msi_set_mask_bits(msi, 1, 0); 301 zpci_msi_set_mask_bits(msi, 1, 0);
291} 302}
292EXPORT_SYMBOL_GPL(enable_irq);
293 303
294void disable_irq(unsigned int irq) 304static void zpci_disable_irq(struct irq_data *data)
295{ 305{
296 struct msi_desc *msi = irq_get_msi_desc(irq); 306 struct msi_desc *msi = irq_get_msi_desc(data->irq);
297 307
298 zpci_msi_set_mask_bits(msi, 1, 1); 308 zpci_msi_set_mask_bits(msi, 1, 1);
299} 309}
300EXPORT_SYMBOL_GPL(disable_irq);
301 310
302void pcibios_fixup_bus(struct pci_bus *bus) 311void pcibios_fixup_bus(struct pci_bus *bus)
303{ 312{
@@ -385,7 +394,7 @@ static struct pci_ops pci_root_ops = {
385static void zpci_irq_handler(struct airq_struct *airq) 394static void zpci_irq_handler(struct airq_struct *airq)
386{ 395{
387 unsigned long si, ai; 396 unsigned long si, ai;
388 struct zdev_irq_map *imap; 397 struct airq_iv *aibv;
389 int irqs_on = 0; 398 int irqs_on = 0;
390 399
391 inc_irq_stat(IRQIO_PCI); 400 inc_irq_stat(IRQIO_PCI);
@@ -403,69 +412,33 @@ static void zpci_irq_handler(struct airq_struct *airq)
403 } 412 }
404 413
405 /* Scan the adapter interrupt vector for this device. */ 414 /* Scan the adapter interrupt vector for this device. */
406 imap = zpci_imap[si]; 415 aibv = zpci_aibv[si];
407 for (ai = 0;;) { 416 for (ai = 0;;) {
408 ai = airq_iv_scan(imap->aibv, ai, imap->msi_vecs); 417 ai = airq_iv_scan(aibv, ai, airq_iv_end(aibv));
409 if (ai == -1UL) 418 if (ai == -1UL)
410 break; 419 break;
411 inc_irq_stat(IRQIO_MSI); 420 inc_irq_stat(IRQIO_MSI);
412 airq_iv_lock(imap->aibv, ai); 421 airq_iv_lock(aibv, ai);
413 if (imap->cb[ai].handler) 422 generic_handle_irq(airq_iv_get_data(aibv, ai));
414 imap->cb[ai].handler(ai, imap->cb[ai].data); 423 airq_iv_unlock(aibv, ai);
415 airq_iv_unlock(imap->aibv, ai);
416 } 424 }
417 } 425 }
418} 426}
419 427
420static int zpci_alloc_msi(struct zpci_dev *zdev, int msi_vecs)
421{
422 unsigned long size;
423
424 /* Alloc aibv & callback space */
425 zdev->irq_map = kmem_cache_zalloc(zdev_irq_cache, GFP_KERNEL);
426 if (!zdev->irq_map)
427 goto out;
428 /* Store the number of used MSI vectors */
429 zdev->irq_map->msi_vecs = msi_vecs;
430 /* Allocate callback array */
431 size = sizeof(struct callback) * msi_vecs;
432 zdev->irq_map->cb = kzalloc(size, GFP_KERNEL);
433 if (!zdev->irq_map->cb)
434 goto out_map;
435 /* Allocate msi_map array */
436 size = sizeof(struct msi_map) * msi_vecs;
437 zdev->msi_map = kzalloc(size, GFP_KERNEL);
438 if (!zdev->msi_map)
439 goto out_cb;
440 return 0;
441
442out_cb:
443 kfree(zdev->irq_map->cb);
444out_map:
445 kmem_cache_free(zdev_irq_cache, zdev->irq_map);
446out:
447 return -ENOMEM;
448}
449
450static void zpci_free_msi(struct zpci_dev *zdev)
451{
452 kfree(zdev->msi_map);
453 kfree(zdev->irq_map->cb);
454 kmem_cache_free(zdev_irq_cache, zdev->irq_map);
455}
456
457int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) 428int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
458{ 429{
459 struct zpci_dev *zdev = get_zdev(pdev); 430 struct zpci_dev *zdev = get_zdev(pdev);
460 unsigned int msi_nr, msi_vecs; 431 unsigned int hwirq, irq, msi_vecs;
461 unsigned long aisb; 432 unsigned long aisb;
462 struct msi_desc *msi; 433 struct msi_desc *msi;
434 struct msi_msg msg;
463 int rc; 435 int rc;
464 436
465 pr_debug("%s: requesting %d MSI-X interrupts...", __func__, nvec); 437 pr_debug("%s: requesting %d MSI-X interrupts...", __func__, nvec);
466 if (type != PCI_CAP_ID_MSIX && type != PCI_CAP_ID_MSI) 438 if (type != PCI_CAP_ID_MSIX && type != PCI_CAP_ID_MSI)
467 return -EINVAL; 439 return -EINVAL;
468 msi_vecs = min(nvec, ZPCI_MSI_VEC_MAX); 440 msi_vecs = min(nvec, ZPCI_MSI_VEC_MAX);
441 msi_vecs = min_t(unsigned int, msi_vecs, CONFIG_PCI_NR_MSI);
469 442
470 /* Allocate adapter summary indicator bit */ 443 /* Allocate adapter summary indicator bit */
471 rc = -EIO; 444 rc = -EIO;
@@ -476,30 +449,31 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
476 449
477 /* Create adapter interrupt vector */ 450 /* Create adapter interrupt vector */
478 rc = -ENOMEM; 451 rc = -ENOMEM;
479 zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_BITLOCK); 452 zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | AIRQ_IV_BITLOCK);
480 if (!zdev->aibv) 453 if (!zdev->aibv)
481 goto out_si; 454 goto out_si;
482 455
483 /* Allocate data structures for msi interrupts */
484 rc = zpci_alloc_msi(zdev, msi_vecs);
485 if (rc)
486 goto out_iv;
487
488 /* Wire up shortcut pointer */ 456 /* Wire up shortcut pointer */
489 zpci_imap[aisb] = zdev->irq_map; 457 zpci_aibv[aisb] = zdev->aibv;
490 zdev->irq_map->aibv = zdev->aibv;
491 458
492 /* 459 /* Request MSI interrupts */
493 * TODO: irq number 0 wont be found if we return less than the 460 hwirq = 0;
494 * requested MSIs. Ignore it for now and fix in common code.
495 */
496 msi_nr = aisb << ZPCI_MSI_VEC_BITS;
497 list_for_each_entry(msi, &pdev->msi_list, list) { 461 list_for_each_entry(msi, &pdev->msi_list, list) {
498 rc = zpci_setup_msi_irq(zdev, msi, msi_nr, 462 rc = -EIO;
499 aisb << ZPCI_MSI_VEC_BITS); 463 irq = irq_alloc_desc(0); /* Alloc irq on node 0 */
464 if (irq == NO_IRQ)
465 goto out_msi;
466 rc = irq_set_msi_desc(irq, msi);
500 if (rc) 467 if (rc)
501 goto out_msi; 468 goto out_msi;
502 msi_nr++; 469 irq_set_chip_and_handler(irq, &zpci_irq_chip,
470 handle_simple_irq);
471 msg.data = hwirq;
472 msg.address_lo = zdev->msi_addr & 0xffffffff;
473 msg.address_hi = zdev->msi_addr >> 32;
474 write_msi_msg(irq, &msg);
475 airq_iv_set_data(zdev->aibv, hwirq, irq);
476 hwirq++;
503 } 477 }
504 478
505 /* Enable adapter interrupts */ 479 /* Enable adapter interrupts */
@@ -510,14 +484,17 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
510 return (msi_vecs == nvec) ? 0 : msi_vecs; 484 return (msi_vecs == nvec) ? 0 : msi_vecs;
511 485
512out_msi: 486out_msi:
513 msi_nr -= aisb << ZPCI_MSI_VEC_BITS;
514 list_for_each_entry(msi, &pdev->msi_list, list) { 487 list_for_each_entry(msi, &pdev->msi_list, list) {
515 if (msi_nr-- == 0) 488 if (hwirq-- == 0)
516 break; 489 break;
517 zpci_teardown_msi_irq(zdev, msi); 490 irq_set_msi_desc(msi->irq, NULL);
491 irq_free_desc(msi->irq);
492 msi->msg.address_lo = 0;
493 msi->msg.address_hi = 0;
494 msi->msg.data = 0;
495 msi->irq = 0;
518 } 496 }
519 zpci_free_msi(zdev); 497 zpci_aibv[aisb] = NULL;
520out_iv:
521 airq_iv_release(zdev->aibv); 498 airq_iv_release(zdev->aibv);
522out_si: 499out_si:
523 airq_iv_free_bit(zpci_aisb_iv, aisb); 500 airq_iv_free_bit(zpci_aisb_iv, aisb);
@@ -541,10 +518,18 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev)
541 return; 518 return;
542 } 519 }
543 520
544 list_for_each_entry(msi, &pdev->msi_list, list) 521 /* Release MSI interrupts */
545 zpci_teardown_msi_irq(zdev, msi); 522 list_for_each_entry(msi, &pdev->msi_list, list) {
523 zpci_msi_set_mask_bits(msi, 1, 1);
524 irq_set_msi_desc(msi->irq, NULL);
525 irq_free_desc(msi->irq);
526 msi->msg.address_lo = 0;
527 msi->msg.address_hi = 0;
528 msi->msg.data = 0;
529 msi->irq = 0;
530 }
546 531
547 zpci_free_msi(zdev); 532 zpci_aibv[zdev->aisb] = NULL;
548 airq_iv_release(zdev->aibv); 533 airq_iv_release(zdev->aibv);
549 airq_iv_free_bit(zpci_aisb_iv, zdev->aisb); 534 airq_iv_free_bit(zpci_aisb_iv, zdev->aisb);
550} 535}
@@ -625,61 +610,6 @@ int pcibios_add_platform_entries(struct pci_dev *pdev)
625 return zpci_sysfs_add_device(&pdev->dev); 610 return zpci_sysfs_add_device(&pdev->dev);
626} 611}
627 612
628int zpci_request_irq(unsigned int irq, irq_handler_t handler, void *data)
629{
630 unsigned int msi_nr = irq_to_msi_nr(irq);
631 unsigned int dev_nr = irq_to_dev_nr(irq);
632 struct zdev_irq_map *imap;
633 struct msi_desc *msi;
634
635 msi = irq_get_msi_desc(irq);
636 if (!msi)
637 return -EIO;
638
639 imap = zpci_imap[dev_nr];
640 imap->cb[msi_nr].handler = handler;
641 imap->cb[msi_nr].data = data;
642
643 /*
644 * The generic MSI code returns with the interrupt disabled on the
645 * card, using the MSI mask bits. Firmware doesn't appear to unmask
646 * at that level, so we do it here by hand.
647 */
648 zpci_msi_set_mask_bits(msi, 1, 0);
649 return 0;
650}
651
652void zpci_free_irq(unsigned int irq)
653{
654 unsigned int msi_nr = irq_to_msi_nr(irq);
655 unsigned int dev_nr = irq_to_dev_nr(irq);
656 struct zdev_irq_map *imap;
657 struct msi_desc *msi;
658
659 /* Disable interrupt */
660 msi = irq_get_msi_desc(irq);
661 if (!msi)
662 return;
663 zpci_msi_set_mask_bits(msi, 1, 1);
664 imap = zpci_imap[dev_nr];
665 imap->cb[msi_nr].handler = NULL;
666 imap->cb[msi_nr].data = NULL;
667 synchronize_rcu();
668}
669
670int request_irq(unsigned int irq, irq_handler_t handler,
671 unsigned long irqflags, const char *devname, void *dev_id)
672{
673 return zpci_request_irq(irq, handler, dev_id);
674}
675EXPORT_SYMBOL_GPL(request_irq);
676
677void free_irq(unsigned int irq, void *dev_id)
678{
679 zpci_free_irq(irq);
680}
681EXPORT_SYMBOL_GPL(free_irq);
682
683static int __init zpci_irq_init(void) 613static int __init zpci_irq_init(void)
684{ 614{
685 int rc; 615 int rc;
@@ -930,15 +860,10 @@ static inline int barsize(u8 size)
930 860
931static int zpci_mem_init(void) 861static int zpci_mem_init(void)
932{ 862{
933 zdev_irq_cache = kmem_cache_create("PCI_IRQ_cache", sizeof(struct zdev_irq_map),
934 L1_CACHE_BYTES, SLAB_HWCACHE_ALIGN, NULL);
935 if (!zdev_irq_cache)
936 goto error_zdev;
937
938 zdev_fmb_cache = kmem_cache_create("PCI_FMB_cache", sizeof(struct zpci_fmb), 863 zdev_fmb_cache = kmem_cache_create("PCI_FMB_cache", sizeof(struct zpci_fmb),
939 16, 0, NULL); 864 16, 0, NULL);
940 if (!zdev_fmb_cache) 865 if (!zdev_fmb_cache)
941 goto error_fmb; 866 goto error_zdev;
942 867
943 /* TODO: use realloc */ 868 /* TODO: use realloc */
944 zpci_iomap_start = kzalloc(ZPCI_IOMAP_MAX_ENTRIES * sizeof(*zpci_iomap_start), 869 zpci_iomap_start = kzalloc(ZPCI_IOMAP_MAX_ENTRIES * sizeof(*zpci_iomap_start),
@@ -949,8 +874,6 @@ static int zpci_mem_init(void)
949 874
950error_iomap: 875error_iomap:
951 kmem_cache_destroy(zdev_fmb_cache); 876 kmem_cache_destroy(zdev_fmb_cache);
952error_fmb:
953 kmem_cache_destroy(zdev_irq_cache);
954error_zdev: 877error_zdev:
955 return -ENOMEM; 878 return -ENOMEM;
956} 879}
@@ -958,7 +881,6 @@ error_zdev:
958static void zpci_mem_exit(void) 881static void zpci_mem_exit(void)
959{ 882{
960 kfree(zpci_iomap_start); 883 kfree(zpci_iomap_start);
961 kmem_cache_destroy(zdev_irq_cache);
962 kmem_cache_destroy(zdev_fmb_cache); 884 kmem_cache_destroy(zdev_fmb_cache);
963} 885}
964 886
@@ -1007,16 +929,12 @@ static int __init pci_base_init(void)
1007 929
1008 rc = zpci_debug_init(); 930 rc = zpci_debug_init();
1009 if (rc) 931 if (rc)
1010 return rc; 932 goto out;
1011 933
1012 rc = zpci_mem_init(); 934 rc = zpci_mem_init();
1013 if (rc) 935 if (rc)
1014 goto out_mem; 936 goto out_mem;
1015 937
1016 rc = zpci_msihash_init();
1017 if (rc)
1018 goto out_hash;
1019
1020 rc = zpci_irq_init(); 938 rc = zpci_irq_init();
1021 if (rc) 939 if (rc)
1022 goto out_irq; 940 goto out_irq;
@@ -1036,11 +954,10 @@ out_find:
1036out_dma: 954out_dma:
1037 zpci_irq_exit(); 955 zpci_irq_exit();
1038out_irq: 956out_irq:
1039 zpci_msihash_exit();
1040out_hash:
1041 zpci_mem_exit(); 957 zpci_mem_exit();
1042out_mem: 958out_mem:
1043 zpci_debug_exit(); 959 zpci_debug_exit();
960out:
1044 return rc; 961 return rc;
1045} 962}
1046subsys_initcall(pci_base_init); 963subsys_initcall(pci_base_init);
diff --git a/arch/s390/pci/pci_msi.c b/arch/s390/pci/pci_msi.c
deleted file mode 100644
index d4b480a18b0f..000000000000
--- a/arch/s390/pci/pci_msi.c
+++ /dev/null
@@ -1,134 +0,0 @@
1/*
2 * Copyright IBM Corp. 2012
3 *
4 * Author(s):
5 * Jan Glauber <jang@linux.vnet.ibm.com>
6 */
7
8#define COMPONENT "zPCI"
9#define pr_fmt(fmt) COMPONENT ": " fmt
10
11#include <linux/kernel.h>
12#include <linux/err.h>
13#include <linux/rculist.h>
14#include <linux/hash.h>
15#include <linux/pci.h>
16#include <linux/msi.h>
17#include <asm/hw_irq.h>
18
19/* mapping of irq numbers to msi_desc */
20static struct hlist_head *msi_hash;
21static const unsigned int msi_hash_bits = 8;
22#define MSI_HASH_BUCKETS (1U << msi_hash_bits)
23#define msi_hashfn(nr) hash_long(nr, msi_hash_bits)
24
25static DEFINE_SPINLOCK(msi_map_lock);
26
27struct msi_desc *__irq_get_msi_desc(unsigned int irq)
28{
29 struct msi_map *map;
30
31 hlist_for_each_entry_rcu(map,
32 &msi_hash[msi_hashfn(irq)], msi_chain)
33 if (map->irq == irq)
34 return map->msi;
35 return NULL;
36}
37
38int zpci_msi_set_mask_bits(struct msi_desc *msi, u32 mask, u32 flag)
39{
40 if (msi->msi_attrib.is_msix) {
41 int offset = msi->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
42 PCI_MSIX_ENTRY_VECTOR_CTRL;
43 msi->masked = readl(msi->mask_base + offset);
44 writel(flag, msi->mask_base + offset);
45 } else {
46 if (msi->msi_attrib.maskbit) {
47 int pos;
48 u32 mask_bits;
49
50 pos = (long) msi->mask_base;
51 pci_read_config_dword(msi->dev, pos, &mask_bits);
52 mask_bits &= ~(mask);
53 mask_bits |= flag & mask;
54 pci_write_config_dword(msi->dev, pos, mask_bits);
55 } else {
56 return 0;
57 }
58 }
59
60 msi->msi_attrib.maskbit = !!flag;
61 return 1;
62}
63
64int zpci_setup_msi_irq(struct zpci_dev *zdev, struct msi_desc *msi,
65 unsigned int nr, int offset)
66{
67 struct msi_map *map;
68 struct msi_msg msg;
69 int rc;
70
71 map = zdev->msi_map + (nr & ZPCI_MSI_VEC_MASK);
72 map->irq = nr;
73 map->msi = msi;
74 INIT_HLIST_NODE(&map->msi_chain);
75
76 pr_debug("%s hashing irq: %u to bucket nr: %llu\n",
77 __func__, nr, msi_hashfn(nr));
78 hlist_add_head_rcu(&map->msi_chain, &msi_hash[msi_hashfn(nr)]);
79
80 spin_lock(&msi_map_lock);
81 rc = irq_set_msi_desc(nr, msi);
82 if (rc) {
83 spin_unlock(&msi_map_lock);
84 hlist_del_rcu(&map->msi_chain);
85 return rc;
86 }
87 spin_unlock(&msi_map_lock);
88
89 msg.data = nr - offset;
90 msg.address_lo = zdev->msi_addr & 0xffffffff;
91 msg.address_hi = zdev->msi_addr >> 32;
92 write_msi_msg(nr, &msg);
93 return 0;
94}
95
96void zpci_teardown_msi_irq(struct zpci_dev *zdev, struct msi_desc *msi)
97{
98 int nr = msi->irq & ZPCI_MSI_VEC_MASK;
99 struct msi_map *map;
100
101 zpci_msi_set_mask_bits(msi, 1, 1);
102 msi->msg.address_lo = 0;
103 msi->msg.address_hi = 0;
104 msi->msg.data = 0;
105 msi->irq = 0;
106
107 spin_lock(&msi_map_lock);
108 map = zdev->msi_map + nr;
109 hlist_del_rcu(&map->msi_chain);
110 spin_unlock(&msi_map_lock);
111}
112
113/*
114 * The msi hash table has 256 entries which is good for 4..20
115 * devices (a typical device allocates 10 + CPUs MSI's). Maybe make
116 * the hash table size adjustable later.
117 */
118int __init zpci_msihash_init(void)
119{
120 unsigned int i;
121
122 msi_hash = kmalloc(MSI_HASH_BUCKETS * sizeof(*msi_hash), GFP_KERNEL);
123 if (!msi_hash)
124 return -ENOMEM;
125
126 for (i = 0; i < MSI_HASH_BUCKETS; i++)
127 INIT_HLIST_HEAD(&msi_hash[i]);
128 return 0;
129}
130
131void __init zpci_msihash_exit(void)
132{
133 kfree(msi_hash);
134}
diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c
index 6ead6d076445..d028fd800c9c 100644
--- a/drivers/s390/cio/airq.c
+++ b/drivers/s390/cio/airq.c
@@ -81,17 +81,34 @@ void unregister_adapter_interrupt(struct airq_struct *airq)
81} 81}
82EXPORT_SYMBOL(unregister_adapter_interrupt); 82EXPORT_SYMBOL(unregister_adapter_interrupt);
83 83
84void do_adapter_IO(u8 isc) 84static irqreturn_t do_airq_interrupt(int irq, void *dummy)
85{ 85{
86 struct tpi_info *tpi_info;
86 struct airq_struct *airq; 87 struct airq_struct *airq;
87 struct hlist_head *head; 88 struct hlist_head *head;
88 89
89 head = &airq_lists[isc]; 90 __this_cpu_write(s390_idle.nohz_delay, 1);
91 tpi_info = (struct tpi_info *) &get_irq_regs()->int_code;
92 head = &airq_lists[tpi_info->isc];
90 rcu_read_lock(); 93 rcu_read_lock();
91 hlist_for_each_entry_rcu(airq, head, list) 94 hlist_for_each_entry_rcu(airq, head, list)
92 if ((*airq->lsi_ptr & airq->lsi_mask) != 0) 95 if ((*airq->lsi_ptr & airq->lsi_mask) != 0)
93 airq->handler(airq); 96 airq->handler(airq);
94 rcu_read_unlock(); 97 rcu_read_unlock();
98
99 return IRQ_HANDLED;
100}
101
102static struct irqaction airq_interrupt = {
103 .name = "AIO",
104 .handler = do_airq_interrupt,
105};
106
107void __init init_airq_interrupts(void)
108{
109 irq_set_chip_and_handler(THIN_INTERRUPT,
110 &dummy_irq_chip, handle_percpu_irq);
111 setup_irq(THIN_INTERRUPT, &airq_interrupt);
95} 112}
96 113
97/** 114/**
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 4eeb4a6bf207..d7da67a31c77 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -561,37 +561,23 @@ out:
561} 561}
562 562
563/* 563/*
564 * do_IRQ() handles all normal I/O device IRQ's (the special 564 * do_cio_interrupt() handles all normal I/O device IRQ's
565 * SMP cross-CPU interrupts have their own specific
566 * handlers).
567 *
568 */ 565 */
569void __irq_entry do_IRQ(struct pt_regs *regs) 566static irqreturn_t do_cio_interrupt(int irq, void *dummy)
570{ 567{
571 struct tpi_info *tpi_info = (struct tpi_info *) &regs->int_code; 568 struct tpi_info *tpi_info;
572 struct subchannel *sch; 569 struct subchannel *sch;
573 struct irb *irb; 570 struct irb *irb;
574 struct pt_regs *old_regs;
575 571
576 old_regs = set_irq_regs(regs);
577 irq_enter();
578 __this_cpu_write(s390_idle.nohz_delay, 1); 572 __this_cpu_write(s390_idle.nohz_delay, 1);
579 if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) 573 tpi_info = (struct tpi_info *) &get_irq_regs()->int_code;
580 /* Serve timer interrupts first. */
581 clock_comparator_work();
582
583 kstat_incr_irqs_this_cpu(IO_INTERRUPT, NULL);
584 irb = (struct irb *) &S390_lowcore.irb; 574 irb = (struct irb *) &S390_lowcore.irb;
585 if (tpi_info->adapter_IO) {
586 do_adapter_IO(tpi_info->isc);
587 goto out;
588 }
589 sch = (struct subchannel *)(unsigned long) tpi_info->intparm; 575 sch = (struct subchannel *)(unsigned long) tpi_info->intparm;
590 if (!sch) { 576 if (!sch) {
591 /* Clear pending interrupt condition. */ 577 /* Clear pending interrupt condition. */
592 inc_irq_stat(IRQIO_CIO); 578 inc_irq_stat(IRQIO_CIO);
593 tsch(tpi_info->schid, irb); 579 tsch(tpi_info->schid, irb);
594 goto out; 580 return IRQ_HANDLED;
595 } 581 }
596 spin_lock(sch->lock); 582 spin_lock(sch->lock);
597 /* Store interrupt response block to lowcore. */ 583 /* Store interrupt response block to lowcore. */
@@ -606,9 +592,23 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
606 } else 592 } else
607 inc_irq_stat(IRQIO_CIO); 593 inc_irq_stat(IRQIO_CIO);
608 spin_unlock(sch->lock); 594 spin_unlock(sch->lock);
609out: 595
610 irq_exit(); 596 return IRQ_HANDLED;
611 set_irq_regs(old_regs); 597}
598
599static struct irq_desc *irq_desc_io;
600
601static struct irqaction io_interrupt = {
602 .name = "IO",
603 .handler = do_cio_interrupt,
604};
605
606void __init init_cio_interrupts(void)
607{
608 irq_set_chip_and_handler(IO_INTERRUPT,
609 &dummy_irq_chip, handle_percpu_irq);
610 setup_irq(IO_INTERRUPT, &io_interrupt);
611 irq_desc_io = irq_to_desc(IO_INTERRUPT);
612} 612}
613 613
614#ifdef CONFIG_CCW_CONSOLE 614#ifdef CONFIG_CCW_CONSOLE
@@ -635,7 +635,7 @@ void cio_tsch(struct subchannel *sch)
635 local_bh_disable(); 635 local_bh_disable();
636 irq_enter(); 636 irq_enter();
637 } 637 }
638 kstat_incr_irqs_this_cpu(IO_INTERRUPT, NULL); 638 kstat_incr_irqs_this_cpu(IO_INTERRUPT, irq_desc_io);
639 if (sch->driver && sch->driver->irq) 639 if (sch->driver && sch->driver->irq)
640 sch->driver->irq(sch); 640 sch->driver->irq(sch);
641 else 641 else
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index d62f5e7f3cf1..d42f67412bd8 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -121,9 +121,6 @@ extern int cio_commit_config(struct subchannel *sch);
121int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key); 121int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key);
122int cio_tm_intrg(struct subchannel *sch); 122int cio_tm_intrg(struct subchannel *sch);
123 123
124void do_adapter_IO(u8 isc);
125void do_IRQ(struct pt_regs *);
126
127/* Use with care. */ 124/* Use with care. */
128#ifdef CONFIG_CCW_CONSOLE 125#ifdef CONFIG_CCW_CONSOLE
129extern struct subchannel *cio_probe_console(void); 126extern struct subchannel *cio_probe_console(void);