diff options
-rw-r--r-- | arch/s390/include/asm/hw_irq.h | 22 | ||||
-rw-r--r-- | arch/s390/include/asm/irq.h | 12 | ||||
-rw-r--r-- | arch/s390/include/asm/isc.h | 1 | ||||
-rw-r--r-- | arch/s390/include/asm/pci.h | 27 | ||||
-rw-r--r-- | arch/s390/kernel/irq.c | 2 | ||||
-rw-r--r-- | arch/s390/pci/Makefile | 2 | ||||
-rw-r--r-- | arch/s390/pci/pci.c | 464 | ||||
-rw-r--r-- | arch/s390/pci/pci_clp.c | 3 | ||||
-rw-r--r-- | arch/s390/pci/pci_msi.c | 141 | ||||
-rw-r--r-- | drivers/pci/msi.c | 6 | ||||
-rw-r--r-- | include/linux/irq.h | 10 |
11 files changed, 683 insertions, 7 deletions
diff --git a/arch/s390/include/asm/hw_irq.h b/arch/s390/include/asm/hw_irq.h new file mode 100644 index 000000000000..7e3d2586c1ff --- /dev/null +++ b/arch/s390/include/asm/hw_irq.h | |||
@@ -0,0 +1,22 @@ | |||
1 | #ifndef _HW_IRQ_H | ||
2 | #define _HW_IRQ_H | ||
3 | |||
4 | #include <linux/msi.h> | ||
5 | #include <linux/pci.h> | ||
6 | |||
7 | static inline struct msi_desc *irq_get_msi_desc(unsigned int irq) | ||
8 | { | ||
9 | return __irq_get_msi_desc(irq); | ||
10 | } | ||
11 | |||
12 | /* Must be called with msi map lock held */ | ||
13 | static 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 | |||
22 | #endif | ||
diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h index 6703dd986fd4..e6972f85d2b0 100644 --- a/arch/s390/include/asm/irq.h +++ b/arch/s390/include/asm/irq.h | |||
@@ -33,6 +33,8 @@ enum interruption_class { | |||
33 | IOINT_APB, | 33 | IOINT_APB, |
34 | IOINT_ADM, | 34 | IOINT_ADM, |
35 | IOINT_CSC, | 35 | IOINT_CSC, |
36 | IOINT_PCI, | ||
37 | IOINT_MSI, | ||
36 | NMI_NMI, | 38 | NMI_NMI, |
37 | NR_IRQS, | 39 | NR_IRQS, |
38 | }; | 40 | }; |
@@ -51,4 +53,14 @@ void service_subclass_irq_unregister(void); | |||
51 | void measurement_alert_subclass_register(void); | 53 | void measurement_alert_subclass_register(void); |
52 | void measurement_alert_subclass_unregister(void); | 54 | void measurement_alert_subclass_unregister(void); |
53 | 55 | ||
56 | #ifdef CONFIG_LOCKDEP | ||
57 | # define disable_irq_nosync_lockdep(irq) disable_irq_nosync(irq) | ||
58 | # define disable_irq_nosync_lockdep_irqsave(irq, flags) \ | ||
59 | disable_irq_nosync(irq) | ||
60 | # define disable_irq_lockdep(irq) disable_irq(irq) | ||
61 | # define enable_irq_lockdep(irq) enable_irq(irq) | ||
62 | # define enable_irq_lockdep_irqrestore(irq, flags) \ | ||
63 | enable_irq(irq) | ||
64 | #endif | ||
65 | |||
54 | #endif /* _ASM_IRQ_H */ | 66 | #endif /* _ASM_IRQ_H */ |
diff --git a/arch/s390/include/asm/isc.h b/arch/s390/include/asm/isc.h index 5ae606456b0a..68d7d68300f2 100644 --- a/arch/s390/include/asm/isc.h +++ b/arch/s390/include/asm/isc.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #define CHSC_SCH_ISC 7 /* CHSC subchannels */ | 18 | #define CHSC_SCH_ISC 7 /* CHSC subchannels */ |
19 | /* Adapter interrupts. */ | 19 | /* Adapter interrupts. */ |
20 | #define QDIO_AIRQ_ISC IO_SCH_ISC /* I/O subchannel in qdio mode */ | 20 | #define QDIO_AIRQ_ISC IO_SCH_ISC /* I/O subchannel in qdio mode */ |
21 | #define PCI_ISC 2 /* PCI I/O subchannels */ | ||
21 | #define AP_ISC 6 /* adjunct processor (crypto) devices */ | 22 | #define AP_ISC 6 /* adjunct processor (crypto) devices */ |
22 | 23 | ||
23 | /* Functions for registration of I/O interruption subclasses */ | 24 | /* Functions for registration of I/O interruption subclasses */ |
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h index 6f98a54950ea..2a6084fa4b1a 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h | |||
@@ -20,6 +20,10 @@ void pci_iounmap(struct pci_dev *, void __iomem *); | |||
20 | int pci_domain_nr(struct pci_bus *); | 20 | int pci_domain_nr(struct pci_bus *); |
21 | int pci_proc_domain(struct pci_bus *); | 21 | int pci_proc_domain(struct pci_bus *); |
22 | 22 | ||
23 | /* MSI arch hooks */ | ||
24 | #define arch_setup_msi_irqs arch_setup_msi_irqs | ||
25 | #define arch_teardown_msi_irqs arch_teardown_msi_irqs | ||
26 | |||
23 | #define ZPCI_BUS_NR 0 /* default bus number */ | 27 | #define ZPCI_BUS_NR 0 /* default bus number */ |
24 | #define ZPCI_DEVFN 0 /* default device number */ | 28 | #define ZPCI_DEVFN 0 /* default device number */ |
25 | 29 | ||
@@ -29,6 +33,15 @@ int pci_proc_domain(struct pci_bus *); | |||
29 | #define ZPCI_FC_BLOCKED 0x20 | 33 | #define ZPCI_FC_BLOCKED 0x20 |
30 | #define ZPCI_FC_DMA_ENABLED 0x10 | 34 | #define ZPCI_FC_DMA_ENABLED 0x10 |
31 | 35 | ||
36 | struct msi_map { | ||
37 | unsigned long irq; | ||
38 | struct msi_desc *msi; | ||
39 | struct hlist_node msi_chain; | ||
40 | }; | ||
41 | |||
42 | #define ZPCI_NR_MSI_VECS 64 | ||
43 | #define ZPCI_MSI_MASK (ZPCI_NR_MSI_VECS - 1) | ||
44 | |||
32 | enum zpci_state { | 45 | enum zpci_state { |
33 | ZPCI_FN_STATE_RESERVED, | 46 | ZPCI_FN_STATE_RESERVED, |
34 | ZPCI_FN_STATE_STANDBY, | 47 | ZPCI_FN_STATE_STANDBY, |
@@ -56,6 +69,12 @@ struct zpci_dev { | |||
56 | u8 pfgid; /* function group ID */ | 69 | u8 pfgid; /* function group ID */ |
57 | u16 domain; | 70 | u16 domain; |
58 | 71 | ||
72 | /* IRQ stuff */ | ||
73 | u64 msi_addr; /* MSI address */ | ||
74 | struct zdev_irq_map *irq_map; | ||
75 | struct msi_map *msi_map[ZPCI_NR_MSI_VECS]; | ||
76 | unsigned int aisb; /* number of the summary bit */ | ||
77 | |||
59 | struct zpci_bar_struct bars[PCI_BAR_COUNT]; | 78 | struct zpci_bar_struct bars[PCI_BAR_COUNT]; |
60 | 79 | ||
61 | enum pci_bus_speed max_bus_speed; | 80 | enum pci_bus_speed max_bus_speed; |
@@ -83,6 +102,14 @@ int clp_add_pci_device(u32, u32, int); | |||
83 | int clp_enable_fh(struct zpci_dev *, u8); | 102 | int clp_enable_fh(struct zpci_dev *, u8); |
84 | int clp_disable_fh(struct zpci_dev *); | 103 | int clp_disable_fh(struct zpci_dev *); |
85 | 104 | ||
105 | /* MSI */ | ||
106 | struct msi_desc *__irq_get_msi_desc(unsigned int); | ||
107 | int zpci_msi_set_mask_bits(struct msi_desc *, u32, u32); | ||
108 | int zpci_setup_msi_irq(struct zpci_dev *, struct msi_desc *, unsigned int, int); | ||
109 | void zpci_teardown_msi_irq(struct zpci_dev *, struct msi_desc *); | ||
110 | int zpci_msihash_init(void); | ||
111 | void zpci_msihash_exit(void); | ||
112 | |||
86 | /* Helpers */ | 113 | /* Helpers */ |
87 | struct zpci_dev *get_zdev(struct pci_dev *); | 114 | struct zpci_dev *get_zdev(struct pci_dev *); |
88 | struct zpci_dev *get_zdev_by_fid(u32); | 115 | struct zpci_dev *get_zdev_by_fid(u32); |
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 6cdc55b26d68..bf24293970ce 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c | |||
@@ -58,6 +58,8 @@ static const struct irq_class intrclass_names[] = { | |||
58 | [IOINT_APB] = {.name = "APB", .desc = "[I/O] AP Bus"}, | 58 | [IOINT_APB] = {.name = "APB", .desc = "[I/O] AP Bus"}, |
59 | [IOINT_ADM] = {.name = "ADM", .desc = "[I/O] EADM Subchannel"}, | 59 | [IOINT_ADM] = {.name = "ADM", .desc = "[I/O] EADM Subchannel"}, |
60 | [IOINT_CSC] = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"}, | 60 | [IOINT_CSC] = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"}, |
61 | [IOINT_PCI] = {.name = "PCI", .desc = "[I/O] PCI Interrupt" }, | ||
62 | [IOINT_MSI] = {.name = "MSI", .desc = "[I/O] MSI Interrupt" }, | ||
61 | [NMI_NMI] = {.name = "NMI", .desc = "[NMI] Machine Check"}, | 63 | [NMI_NMI] = {.name = "NMI", .desc = "[NMI] Machine Check"}, |
62 | }; | 64 | }; |
63 | 65 | ||
diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile index 1afd68c4c984..628be7bc006c 100644 --- a/arch/s390/pci/Makefile +++ b/arch/s390/pci/Makefile | |||
@@ -2,4 +2,4 @@ | |||
2 | # Makefile for the s390 PCI subsystem. | 2 | # Makefile for the s390 PCI subsystem. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_PCI) += pci.o pci_clp.o | 5 | obj-$(CONFIG_PCI) += pci.o pci_clp.o pci_msi.o |
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 70f6c56c8d0f..d11dc8a25f34 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c | |||
@@ -23,17 +23,25 @@ | |||
23 | #include <linux/err.h> | 23 | #include <linux/err.h> |
24 | #include <linux/export.h> | 24 | #include <linux/export.h> |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/irq.h> | ||
27 | #include <linux/kernel_stat.h> | ||
26 | #include <linux/seq_file.h> | 28 | #include <linux/seq_file.h> |
27 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
28 | #include <linux/msi.h> | 30 | #include <linux/msi.h> |
29 | 31 | ||
32 | #include <asm/isc.h> | ||
33 | #include <asm/airq.h> | ||
30 | #include <asm/facility.h> | 34 | #include <asm/facility.h> |
31 | #include <asm/pci_insn.h> | 35 | #include <asm/pci_insn.h> |
32 | #include <asm/pci_clp.h> | 36 | #include <asm/pci_clp.h> |
33 | 37 | ||
34 | #define DEBUG /* enable pr_debug */ | 38 | #define DEBUG /* enable pr_debug */ |
35 | 39 | ||
40 | #define SIC_IRQ_MODE_ALL 0 | ||
41 | #define SIC_IRQ_MODE_SINGLE 1 | ||
42 | |||
36 | #define ZPCI_NR_DMA_SPACES 1 | 43 | #define ZPCI_NR_DMA_SPACES 1 |
44 | #define ZPCI_MSI_VEC_BITS 6 | ||
37 | #define ZPCI_NR_DEVICES CONFIG_PCI_NR_FUNCTIONS | 45 | #define ZPCI_NR_DEVICES CONFIG_PCI_NR_FUNCTIONS |
38 | 46 | ||
39 | /* list of all detected zpci devices */ | 47 | /* list of all detected zpci devices */ |
@@ -43,12 +51,63 @@ DEFINE_MUTEX(zpci_list_lock); | |||
43 | static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES); | 51 | static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES); |
44 | static DEFINE_SPINLOCK(zpci_domain_lock); | 52 | static DEFINE_SPINLOCK(zpci_domain_lock); |
45 | 53 | ||
54 | struct callback { | ||
55 | irq_handler_t handler; | ||
56 | void *data; | ||
57 | }; | ||
58 | |||
59 | struct zdev_irq_map { | ||
60 | unsigned long aibv; /* AI bit vector */ | ||
61 | int msi_vecs; /* consecutive MSI-vectors used */ | ||
62 | int __unused; | ||
63 | struct callback cb[ZPCI_NR_MSI_VECS]; /* callback handler array */ | ||
64 | spinlock_t lock; /* protect callbacks against de-reg */ | ||
65 | }; | ||
66 | |||
67 | struct intr_bucket { | ||
68 | /* amap of adapters, one bit per dev, corresponds to one irq nr */ | ||
69 | unsigned long *alloc; | ||
70 | /* AI summary bit, global page for all devices */ | ||
71 | unsigned long *aisb; | ||
72 | /* pointer to aibv and callback data in zdev */ | ||
73 | struct zdev_irq_map *imap[ZPCI_NR_DEVICES]; | ||
74 | /* protects the whole bucket struct */ | ||
75 | spinlock_t lock; | ||
76 | }; | ||
77 | |||
78 | static struct intr_bucket *bucket; | ||
79 | |||
80 | /* Adapter local summary indicator */ | ||
81 | static u8 *zpci_irq_si; | ||
82 | |||
83 | static atomic_t irq_retries = ATOMIC_INIT(0); | ||
84 | |||
46 | /* I/O Map */ | 85 | /* I/O Map */ |
47 | static DEFINE_SPINLOCK(zpci_iomap_lock); | 86 | static DEFINE_SPINLOCK(zpci_iomap_lock); |
48 | static DECLARE_BITMAP(zpci_iomap, ZPCI_IOMAP_MAX_ENTRIES); | 87 | static DECLARE_BITMAP(zpci_iomap, ZPCI_IOMAP_MAX_ENTRIES); |
49 | struct zpci_iomap_entry *zpci_iomap_start; | 88 | struct zpci_iomap_entry *zpci_iomap_start; |
50 | EXPORT_SYMBOL_GPL(zpci_iomap_start); | 89 | EXPORT_SYMBOL_GPL(zpci_iomap_start); |
51 | 90 | ||
91 | /* highest irq summary bit */ | ||
92 | static int __read_mostly aisb_max; | ||
93 | |||
94 | static struct kmem_cache *zdev_irq_cache; | ||
95 | |||
96 | static inline int irq_to_msi_nr(unsigned int irq) | ||
97 | { | ||
98 | return irq & ZPCI_MSI_MASK; | ||
99 | } | ||
100 | |||
101 | static inline int irq_to_dev_nr(unsigned int irq) | ||
102 | { | ||
103 | return irq >> ZPCI_MSI_VEC_BITS; | ||
104 | } | ||
105 | |||
106 | static inline struct zdev_irq_map *get_imap(unsigned int irq) | ||
107 | { | ||
108 | return bucket->imap[irq_to_dev_nr(irq)]; | ||
109 | } | ||
110 | |||
52 | struct zpci_dev *get_zdev(struct pci_dev *pdev) | 111 | struct zpci_dev *get_zdev(struct pci_dev *pdev) |
53 | { | 112 | { |
54 | return (struct zpci_dev *) pdev->sysdata; | 113 | return (struct zpci_dev *) pdev->sysdata; |
@@ -120,6 +179,67 @@ static int zpci_store_fib(struct zpci_dev *zdev, u8 *fc) | |||
120 | return (cc) ? -EIO : 0; | 179 | return (cc) ? -EIO : 0; |
121 | } | 180 | } |
122 | 181 | ||
182 | /* Modify PCI: Register adapter interruptions */ | ||
183 | static int zpci_register_airq(struct zpci_dev *zdev, unsigned int aisb, | ||
184 | u64 aibv) | ||
185 | { | ||
186 | u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_REG_INT); | ||
187 | struct zpci_fib *fib; | ||
188 | int rc; | ||
189 | |||
190 | fib = (void *) get_zeroed_page(GFP_KERNEL); | ||
191 | if (!fib) | ||
192 | return -ENOMEM; | ||
193 | |||
194 | fib->isc = PCI_ISC; | ||
195 | fib->noi = zdev->irq_map->msi_vecs; | ||
196 | fib->sum = 1; /* enable summary notifications */ | ||
197 | fib->aibv = aibv; | ||
198 | fib->aibvo = 0; /* every function has its own page */ | ||
199 | fib->aisb = (u64) bucket->aisb + aisb / 8; | ||
200 | fib->aisbo = aisb & ZPCI_MSI_MASK; | ||
201 | |||
202 | rc = mpcifc_instr(req, fib); | ||
203 | pr_debug("%s mpcifc returned noi: %d\n", __func__, fib->noi); | ||
204 | |||
205 | free_page((unsigned long) fib); | ||
206 | return rc; | ||
207 | } | ||
208 | |||
209 | struct mod_pci_args { | ||
210 | u64 base; | ||
211 | u64 limit; | ||
212 | u64 iota; | ||
213 | }; | ||
214 | |||
215 | static int mod_pci(struct zpci_dev *zdev, int fn, u8 dmaas, struct mod_pci_args *args) | ||
216 | { | ||
217 | u64 req = ZPCI_CREATE_REQ(zdev->fh, dmaas, fn); | ||
218 | struct zpci_fib *fib; | ||
219 | int rc; | ||
220 | |||
221 | /* The FIB must be available even if it's not used */ | ||
222 | fib = (void *) get_zeroed_page(GFP_KERNEL); | ||
223 | if (!fib) | ||
224 | return -ENOMEM; | ||
225 | |||
226 | fib->pba = args->base; | ||
227 | fib->pal = args->limit; | ||
228 | fib->iota = args->iota; | ||
229 | |||
230 | rc = mpcifc_instr(req, fib); | ||
231 | free_page((unsigned long) fib); | ||
232 | return rc; | ||
233 | } | ||
234 | |||
235 | /* Modify PCI: Unregister adapter interruptions */ | ||
236 | static int zpci_unregister_airq(struct zpci_dev *zdev) | ||
237 | { | ||
238 | struct mod_pci_args args = { 0, 0, 0 }; | ||
239 | |||
240 | return mod_pci(zdev, ZPCI_MOD_FC_DEREG_INT, 0, &args); | ||
241 | } | ||
242 | |||
123 | #define ZPCI_PCIAS_CFGSPC 15 | 243 | #define ZPCI_PCIAS_CFGSPC 15 |
124 | 244 | ||
125 | static int zpci_cfg_load(struct zpci_dev *zdev, int offset, u32 *val, u8 len) | 245 | static int zpci_cfg_load(struct zpci_dev *zdev, int offset, u32 *val, u8 len) |
@@ -150,6 +270,55 @@ static int zpci_cfg_store(struct zpci_dev *zdev, int offset, u32 val, u8 len) | |||
150 | return rc; | 270 | return rc; |
151 | } | 271 | } |
152 | 272 | ||
273 | void synchronize_irq(unsigned int irq) | ||
274 | { | ||
275 | /* | ||
276 | * Not needed, the handler is protected by a lock and IRQs that occur | ||
277 | * after the handler is deleted are just NOPs. | ||
278 | */ | ||
279 | } | ||
280 | EXPORT_SYMBOL_GPL(synchronize_irq); | ||
281 | |||
282 | void enable_irq(unsigned int irq) | ||
283 | { | ||
284 | struct msi_desc *msi = irq_get_msi_desc(irq); | ||
285 | |||
286 | zpci_msi_set_mask_bits(msi, 1, 0); | ||
287 | } | ||
288 | EXPORT_SYMBOL_GPL(enable_irq); | ||
289 | |||
290 | void disable_irq(unsigned int irq) | ||
291 | { | ||
292 | struct msi_desc *msi = irq_get_msi_desc(irq); | ||
293 | |||
294 | zpci_msi_set_mask_bits(msi, 1, 1); | ||
295 | } | ||
296 | EXPORT_SYMBOL_GPL(disable_irq); | ||
297 | |||
298 | void disable_irq_nosync(unsigned int irq) | ||
299 | { | ||
300 | disable_irq(irq); | ||
301 | } | ||
302 | EXPORT_SYMBOL_GPL(disable_irq_nosync); | ||
303 | |||
304 | unsigned long probe_irq_on(void) | ||
305 | { | ||
306 | return 0; | ||
307 | } | ||
308 | EXPORT_SYMBOL_GPL(probe_irq_on); | ||
309 | |||
310 | int probe_irq_off(unsigned long val) | ||
311 | { | ||
312 | return 0; | ||
313 | } | ||
314 | EXPORT_SYMBOL_GPL(probe_irq_off); | ||
315 | |||
316 | unsigned int probe_irq_mask(unsigned long val) | ||
317 | { | ||
318 | return val; | ||
319 | } | ||
320 | EXPORT_SYMBOL_GPL(probe_irq_mask); | ||
321 | |||
153 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) | 322 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) |
154 | { | 323 | { |
155 | } | 324 | } |
@@ -219,6 +388,155 @@ static struct pci_ops pci_root_ops = { | |||
219 | .write = pci_write, | 388 | .write = pci_write, |
220 | }; | 389 | }; |
221 | 390 | ||
391 | /* store the last handled bit to implement fair scheduling of devices */ | ||
392 | static DEFINE_PER_CPU(unsigned long, next_sbit); | ||
393 | |||
394 | static void zpci_irq_handler(void *dont, void *need) | ||
395 | { | ||
396 | unsigned long sbit, mbit, last = 0, start = __get_cpu_var(next_sbit); | ||
397 | int rescan = 0, max = aisb_max; | ||
398 | struct zdev_irq_map *imap; | ||
399 | |||
400 | kstat_cpu(smp_processor_id()).irqs[IOINT_PCI]++; | ||
401 | sbit = start; | ||
402 | |||
403 | scan: | ||
404 | /* find summary_bit */ | ||
405 | for_each_set_bit_left_cont(sbit, bucket->aisb, max) { | ||
406 | clear_bit(63 - (sbit & 63), bucket->aisb + (sbit >> 6)); | ||
407 | last = sbit; | ||
408 | |||
409 | /* find vector bit */ | ||
410 | imap = bucket->imap[sbit]; | ||
411 | for_each_set_bit_left(mbit, &imap->aibv, imap->msi_vecs) { | ||
412 | kstat_cpu(smp_processor_id()).irqs[IOINT_MSI]++; | ||
413 | clear_bit(63 - mbit, &imap->aibv); | ||
414 | |||
415 | spin_lock(&imap->lock); | ||
416 | if (imap->cb[mbit].handler) | ||
417 | imap->cb[mbit].handler(mbit, | ||
418 | imap->cb[mbit].data); | ||
419 | spin_unlock(&imap->lock); | ||
420 | } | ||
421 | } | ||
422 | |||
423 | if (rescan) | ||
424 | goto out; | ||
425 | |||
426 | /* scan the skipped bits */ | ||
427 | if (start > 0) { | ||
428 | sbit = 0; | ||
429 | max = start; | ||
430 | start = 0; | ||
431 | goto scan; | ||
432 | } | ||
433 | |||
434 | /* enable interrupts again */ | ||
435 | sic_instr(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC); | ||
436 | |||
437 | /* check again to not lose initiative */ | ||
438 | rmb(); | ||
439 | max = aisb_max; | ||
440 | sbit = find_first_bit_left(bucket->aisb, max); | ||
441 | if (sbit != max) { | ||
442 | atomic_inc(&irq_retries); | ||
443 | rescan++; | ||
444 | goto scan; | ||
445 | } | ||
446 | out: | ||
447 | /* store next device bit to scan */ | ||
448 | __get_cpu_var(next_sbit) = (++last >= aisb_max) ? 0 : last; | ||
449 | } | ||
450 | |||
451 | /* msi_vecs - number of requested interrupts, 0 place function to error state */ | ||
452 | static int zpci_setup_msi(struct pci_dev *pdev, int msi_vecs) | ||
453 | { | ||
454 | struct zpci_dev *zdev = get_zdev(pdev); | ||
455 | unsigned int aisb, msi_nr; | ||
456 | struct msi_desc *msi; | ||
457 | int rc; | ||
458 | |||
459 | /* store the number of used MSI vectors */ | ||
460 | zdev->irq_map->msi_vecs = min(msi_vecs, ZPCI_NR_MSI_VECS); | ||
461 | |||
462 | spin_lock(&bucket->lock); | ||
463 | aisb = find_first_zero_bit(bucket->alloc, PAGE_SIZE); | ||
464 | /* alloc map exhausted? */ | ||
465 | if (aisb == PAGE_SIZE) { | ||
466 | spin_unlock(&bucket->lock); | ||
467 | return -EIO; | ||
468 | } | ||
469 | set_bit(aisb, bucket->alloc); | ||
470 | spin_unlock(&bucket->lock); | ||
471 | |||
472 | zdev->aisb = aisb; | ||
473 | if (aisb + 1 > aisb_max) | ||
474 | aisb_max = aisb + 1; | ||
475 | |||
476 | /* wire up IRQ shortcut pointer */ | ||
477 | bucket->imap[zdev->aisb] = zdev->irq_map; | ||
478 | pr_debug("%s: imap[%u] linked to %p\n", __func__, zdev->aisb, zdev->irq_map); | ||
479 | |||
480 | /* TODO: irq number 0 wont be found if we return less than requested MSIs. | ||
481 | * ignore it for now and fix in common code. | ||
482 | */ | ||
483 | msi_nr = aisb << ZPCI_MSI_VEC_BITS; | ||
484 | |||
485 | list_for_each_entry(msi, &pdev->msi_list, list) { | ||
486 | rc = zpci_setup_msi_irq(zdev, msi, msi_nr, | ||
487 | aisb << ZPCI_MSI_VEC_BITS); | ||
488 | if (rc) | ||
489 | return rc; | ||
490 | msi_nr++; | ||
491 | } | ||
492 | |||
493 | rc = zpci_register_airq(zdev, aisb, (u64) &zdev->irq_map->aibv); | ||
494 | if (rc) { | ||
495 | clear_bit(aisb, bucket->alloc); | ||
496 | dev_err(&pdev->dev, "register MSI failed with: %d\n", rc); | ||
497 | return rc; | ||
498 | } | ||
499 | return (zdev->irq_map->msi_vecs == msi_vecs) ? | ||
500 | 0 : zdev->irq_map->msi_vecs; | ||
501 | } | ||
502 | |||
503 | static void zpci_teardown_msi(struct pci_dev *pdev) | ||
504 | { | ||
505 | struct zpci_dev *zdev = get_zdev(pdev); | ||
506 | struct msi_desc *msi; | ||
507 | int aisb, rc; | ||
508 | |||
509 | rc = zpci_unregister_airq(zdev); | ||
510 | if (rc) { | ||
511 | dev_err(&pdev->dev, "deregister MSI failed with: %d\n", rc); | ||
512 | return; | ||
513 | } | ||
514 | |||
515 | msi = list_first_entry(&pdev->msi_list, struct msi_desc, list); | ||
516 | aisb = irq_to_dev_nr(msi->irq); | ||
517 | |||
518 | list_for_each_entry(msi, &pdev->msi_list, list) | ||
519 | zpci_teardown_msi_irq(zdev, msi); | ||
520 | |||
521 | clear_bit(aisb, bucket->alloc); | ||
522 | if (aisb + 1 == aisb_max) | ||
523 | aisb_max--; | ||
524 | } | ||
525 | |||
526 | int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | ||
527 | { | ||
528 | pr_debug("%s: requesting %d MSI-X interrupts...", __func__, nvec); | ||
529 | if (type != PCI_CAP_ID_MSIX && type != PCI_CAP_ID_MSI) | ||
530 | return -EINVAL; | ||
531 | return zpci_setup_msi(pdev, nvec); | ||
532 | } | ||
533 | |||
534 | void arch_teardown_msi_irqs(struct pci_dev *pdev) | ||
535 | { | ||
536 | pr_info("%s: on pdev: %p\n", __func__, pdev); | ||
537 | zpci_teardown_msi(pdev); | ||
538 | } | ||
539 | |||
222 | static void zpci_map_resources(struct zpci_dev *zdev) | 540 | static void zpci_map_resources(struct zpci_dev *zdev) |
223 | { | 541 | { |
224 | struct pci_dev *pdev = zdev->pdev; | 542 | struct pci_dev *pdev = zdev->pdev; |
@@ -257,11 +575,23 @@ struct zpci_dev *zpci_alloc_device(void) | |||
257 | zdev = kzalloc(sizeof(*zdev), GFP_KERNEL); | 575 | zdev = kzalloc(sizeof(*zdev), GFP_KERNEL); |
258 | if (!zdev) | 576 | if (!zdev) |
259 | return ERR_PTR(-ENOMEM); | 577 | return ERR_PTR(-ENOMEM); |
578 | |||
579 | /* Alloc aibv & callback space */ | ||
580 | zdev->irq_map = kmem_cache_alloc(zdev_irq_cache, GFP_KERNEL); | ||
581 | if (!zdev->irq_map) | ||
582 | goto error; | ||
583 | memset(zdev->irq_map, 0, sizeof(*zdev->irq_map)); | ||
584 | WARN_ON((u64) zdev->irq_map & 0xff); | ||
260 | return zdev; | 585 | return zdev; |
586 | |||
587 | error: | ||
588 | kfree(zdev); | ||
589 | return ERR_PTR(-ENOMEM); | ||
261 | } | 590 | } |
262 | 591 | ||
263 | void zpci_free_device(struct zpci_dev *zdev) | 592 | void zpci_free_device(struct zpci_dev *zdev) |
264 | { | 593 | { |
594 | kmem_cache_free(zdev_irq_cache, zdev->irq_map); | ||
265 | kfree(zdev); | 595 | kfree(zdev); |
266 | } | 596 | } |
267 | 597 | ||
@@ -320,6 +650,118 @@ void pcibios_disable_device(struct pci_dev *pdev) | |||
320 | pdev->sysdata = NULL; | 650 | pdev->sysdata = NULL; |
321 | } | 651 | } |
322 | 652 | ||
653 | int zpci_request_irq(unsigned int irq, irq_handler_t handler, void *data) | ||
654 | { | ||
655 | int msi_nr = irq_to_msi_nr(irq); | ||
656 | struct zdev_irq_map *imap; | ||
657 | struct msi_desc *msi; | ||
658 | |||
659 | msi = irq_get_msi_desc(irq); | ||
660 | if (!msi) | ||
661 | return -EIO; | ||
662 | |||
663 | imap = get_imap(irq); | ||
664 | spin_lock_init(&imap->lock); | ||
665 | |||
666 | pr_debug("%s: register handler for IRQ:MSI %d:%d\n", __func__, irq >> 6, msi_nr); | ||
667 | imap->cb[msi_nr].handler = handler; | ||
668 | imap->cb[msi_nr].data = data; | ||
669 | |||
670 | /* | ||
671 | * The generic MSI code returns with the interrupt disabled on the | ||
672 | * card, using the MSI mask bits. Firmware doesn't appear to unmask | ||
673 | * at that level, so we do it here by hand. | ||
674 | */ | ||
675 | zpci_msi_set_mask_bits(msi, 1, 0); | ||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | void zpci_free_irq(unsigned int irq) | ||
680 | { | ||
681 | struct zdev_irq_map *imap = get_imap(irq); | ||
682 | int msi_nr = irq_to_msi_nr(irq); | ||
683 | unsigned long flags; | ||
684 | |||
685 | pr_debug("%s: for irq: %d\n", __func__, irq); | ||
686 | |||
687 | spin_lock_irqsave(&imap->lock, flags); | ||
688 | imap->cb[msi_nr].handler = NULL; | ||
689 | imap->cb[msi_nr].data = NULL; | ||
690 | spin_unlock_irqrestore(&imap->lock, flags); | ||
691 | } | ||
692 | |||
693 | int request_irq(unsigned int irq, irq_handler_t handler, | ||
694 | unsigned long irqflags, const char *devname, void *dev_id) | ||
695 | { | ||
696 | pr_debug("%s: irq: %d handler: %p flags: %lx dev: %s\n", | ||
697 | __func__, irq, handler, irqflags, devname); | ||
698 | |||
699 | return zpci_request_irq(irq, handler, dev_id); | ||
700 | } | ||
701 | EXPORT_SYMBOL_GPL(request_irq); | ||
702 | |||
703 | void free_irq(unsigned int irq, void *dev_id) | ||
704 | { | ||
705 | zpci_free_irq(irq); | ||
706 | } | ||
707 | EXPORT_SYMBOL_GPL(free_irq); | ||
708 | |||
709 | static int __init zpci_irq_init(void) | ||
710 | { | ||
711 | int cpu, rc; | ||
712 | |||
713 | bucket = kzalloc(sizeof(*bucket), GFP_KERNEL); | ||
714 | if (!bucket) | ||
715 | return -ENOMEM; | ||
716 | |||
717 | bucket->aisb = (unsigned long *) get_zeroed_page(GFP_KERNEL); | ||
718 | if (!bucket->aisb) { | ||
719 | rc = -ENOMEM; | ||
720 | goto out_aisb; | ||
721 | } | ||
722 | |||
723 | bucket->alloc = (unsigned long *) get_zeroed_page(GFP_KERNEL); | ||
724 | if (!bucket->alloc) { | ||
725 | rc = -ENOMEM; | ||
726 | goto out_alloc; | ||
727 | } | ||
728 | |||
729 | isc_register(PCI_ISC); | ||
730 | zpci_irq_si = s390_register_adapter_interrupt(&zpci_irq_handler, NULL, PCI_ISC); | ||
731 | if (IS_ERR(zpci_irq_si)) { | ||
732 | rc = PTR_ERR(zpci_irq_si); | ||
733 | zpci_irq_si = NULL; | ||
734 | goto out_ai; | ||
735 | } | ||
736 | |||
737 | for_each_online_cpu(cpu) | ||
738 | per_cpu(next_sbit, cpu) = 0; | ||
739 | |||
740 | spin_lock_init(&bucket->lock); | ||
741 | /* set summary to 1 to be called every time for the ISC */ | ||
742 | *zpci_irq_si = 1; | ||
743 | sic_instr(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC); | ||
744 | return 0; | ||
745 | |||
746 | out_ai: | ||
747 | isc_unregister(PCI_ISC); | ||
748 | free_page((unsigned long) bucket->alloc); | ||
749 | out_alloc: | ||
750 | free_page((unsigned long) bucket->aisb); | ||
751 | out_aisb: | ||
752 | kfree(bucket); | ||
753 | return rc; | ||
754 | } | ||
755 | |||
756 | static void zpci_irq_exit(void) | ||
757 | { | ||
758 | free_page((unsigned long) bucket->alloc); | ||
759 | free_page((unsigned long) bucket->aisb); | ||
760 | s390_unregister_adapter_interrupt(zpci_irq_si, PCI_ISC); | ||
761 | isc_unregister(PCI_ISC); | ||
762 | kfree(bucket); | ||
763 | } | ||
764 | |||
323 | static struct resource *zpci_alloc_bus_resource(unsigned long start, unsigned long size, | 765 | static struct resource *zpci_alloc_bus_resource(unsigned long start, unsigned long size, |
324 | unsigned long flags, int domain) | 766 | unsigned long flags, int domain) |
325 | { | 767 | { |
@@ -523,13 +965,20 @@ static inline int barsize(u8 size) | |||
523 | 965 | ||
524 | static int zpci_mem_init(void) | 966 | static int zpci_mem_init(void) |
525 | { | 967 | { |
968 | zdev_irq_cache = kmem_cache_create("PCI_IRQ_cache", sizeof(struct zdev_irq_map), | ||
969 | L1_CACHE_BYTES, SLAB_HWCACHE_ALIGN, NULL); | ||
970 | if (!zdev_irq_cache) | ||
971 | goto error_zdev; | ||
972 | |||
526 | /* TODO: use realloc */ | 973 | /* TODO: use realloc */ |
527 | zpci_iomap_start = kzalloc(ZPCI_IOMAP_MAX_ENTRIES * sizeof(*zpci_iomap_start), | 974 | zpci_iomap_start = kzalloc(ZPCI_IOMAP_MAX_ENTRIES * sizeof(*zpci_iomap_start), |
528 | GFP_KERNEL); | 975 | GFP_KERNEL); |
529 | if (!zpci_iomap_start) | 976 | if (!zpci_iomap_start) |
530 | goto error_zdev; | 977 | goto error_iomap; |
531 | return 0; | 978 | return 0; |
532 | 979 | ||
980 | error_iomap: | ||
981 | kmem_cache_destroy(zdev_irq_cache); | ||
533 | error_zdev: | 982 | error_zdev: |
534 | return -ENOMEM; | 983 | return -ENOMEM; |
535 | } | 984 | } |
@@ -537,6 +986,7 @@ error_zdev: | |||
537 | static void zpci_mem_exit(void) | 986 | static void zpci_mem_exit(void) |
538 | { | 987 | { |
539 | kfree(zpci_iomap_start); | 988 | kfree(zpci_iomap_start); |
989 | kmem_cache_destroy(zdev_irq_cache); | ||
540 | } | 990 | } |
541 | 991 | ||
542 | unsigned int pci_probe = 1; | 992 | unsigned int pci_probe = 1; |
@@ -570,6 +1020,14 @@ static int __init pci_base_init(void) | |||
570 | if (rc) | 1020 | if (rc) |
571 | goto out_mem; | 1021 | goto out_mem; |
572 | 1022 | ||
1023 | rc = zpci_msihash_init(); | ||
1024 | if (rc) | ||
1025 | goto out_hash; | ||
1026 | |||
1027 | rc = zpci_irq_init(); | ||
1028 | if (rc) | ||
1029 | goto out_irq; | ||
1030 | |||
573 | rc = clp_find_pci_devices(); | 1031 | rc = clp_find_pci_devices(); |
574 | if (rc) | 1032 | if (rc) |
575 | goto out_find; | 1033 | goto out_find; |
@@ -578,6 +1036,10 @@ static int __init pci_base_init(void) | |||
578 | return 0; | 1036 | return 0; |
579 | 1037 | ||
580 | out_find: | 1038 | out_find: |
1039 | zpci_irq_exit(); | ||
1040 | out_irq: | ||
1041 | zpci_msihash_exit(); | ||
1042 | out_hash: | ||
581 | zpci_mem_exit(); | 1043 | zpci_mem_exit(); |
582 | out_mem: | 1044 | out_mem: |
583 | return rc; | 1045 | return rc; |
diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c index 291da1a96560..72694fb6d525 100644 --- a/arch/s390/pci/pci_clp.c +++ b/arch/s390/pci/pci_clp.c | |||
@@ -48,6 +48,9 @@ static void clp_free_block(void *ptr) | |||
48 | static void clp_store_query_pci_fngrp(struct zpci_dev *zdev, | 48 | static void clp_store_query_pci_fngrp(struct zpci_dev *zdev, |
49 | struct clp_rsp_query_pci_grp *response) | 49 | struct clp_rsp_query_pci_grp *response) |
50 | { | 50 | { |
51 | zdev->msi_addr = response->msia; | ||
52 | |||
53 | pr_debug("Supported number of MSI vectors: %u\n", response->noi); | ||
51 | switch (response->version) { | 54 | switch (response->version) { |
52 | case 1: | 55 | case 1: |
53 | zdev->max_bus_speed = PCIE_SPEED_5_0GT; | 56 | zdev->max_bus_speed = PCIE_SPEED_5_0GT; |
diff --git a/arch/s390/pci/pci_msi.c b/arch/s390/pci/pci_msi.c new file mode 100644 index 000000000000..90fd3482b9e2 --- /dev/null +++ b/arch/s390/pci/pci_msi.c | |||
@@ -0,0 +1,141 @@ | |||
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 */ | ||
20 | static struct hlist_head *msi_hash; | ||
21 | static unsigned int msihash_shift = 6; | ||
22 | #define msi_hashfn(nr) hash_long(nr, msihash_shift) | ||
23 | |||
24 | static DEFINE_SPINLOCK(msi_map_lock); | ||
25 | |||
26 | struct msi_desc *__irq_get_msi_desc(unsigned int irq) | ||
27 | { | ||
28 | struct hlist_node *entry; | ||
29 | struct msi_map *map; | ||
30 | |||
31 | hlist_for_each_entry_rcu(map, entry, | ||
32 | &msi_hash[msi_hashfn(irq)], msi_chain) | ||
33 | if (map->irq == irq) | ||
34 | return map->msi; | ||
35 | return NULL; | ||
36 | } | ||
37 | |||
38 | int 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 | |||
64 | int 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 = kmalloc(sizeof(*map), GFP_KERNEL); | ||
72 | if (map == NULL) | ||
73 | return -ENOMEM; | ||
74 | |||
75 | map->irq = nr; | ||
76 | map->msi = msi; | ||
77 | zdev->msi_map[nr & ZPCI_MSI_MASK] = map; | ||
78 | |||
79 | pr_debug("%s hashing irq: %u to bucket nr: %llu\n", | ||
80 | __func__, nr, msi_hashfn(nr)); | ||
81 | hlist_add_head_rcu(&map->msi_chain, &msi_hash[msi_hashfn(nr)]); | ||
82 | |||
83 | spin_lock(&msi_map_lock); | ||
84 | rc = irq_set_msi_desc(nr, msi); | ||
85 | if (rc) { | ||
86 | spin_unlock(&msi_map_lock); | ||
87 | hlist_del_rcu(&map->msi_chain); | ||
88 | kfree(map); | ||
89 | zdev->msi_map[nr & ZPCI_MSI_MASK] = NULL; | ||
90 | return rc; | ||
91 | } | ||
92 | spin_unlock(&msi_map_lock); | ||
93 | |||
94 | msg.data = nr - offset; | ||
95 | msg.address_lo = zdev->msi_addr & 0xffffffff; | ||
96 | msg.address_hi = zdev->msi_addr >> 32; | ||
97 | write_msi_msg(nr, &msg); | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | void zpci_teardown_msi_irq(struct zpci_dev *zdev, struct msi_desc *msi) | ||
102 | { | ||
103 | int irq = msi->irq & ZPCI_MSI_MASK; | ||
104 | struct msi_map *map; | ||
105 | |||
106 | msi->msg.address_lo = 0; | ||
107 | msi->msg.address_hi = 0; | ||
108 | msi->msg.data = 0; | ||
109 | msi->irq = 0; | ||
110 | zpci_msi_set_mask_bits(msi, 1, 1); | ||
111 | |||
112 | spin_lock(&msi_map_lock); | ||
113 | map = zdev->msi_map[irq]; | ||
114 | hlist_del_rcu(&map->msi_chain); | ||
115 | kfree(map); | ||
116 | zdev->msi_map[irq] = NULL; | ||
117 | spin_unlock(&msi_map_lock); | ||
118 | } | ||
119 | |||
120 | /* | ||
121 | * The msi hash table has 256 entries which is good for 4..20 | ||
122 | * devices (a typical device allocates 10 + CPUs MSI's). Maybe make | ||
123 | * the hash table size adjustable later. | ||
124 | */ | ||
125 | int __init zpci_msihash_init(void) | ||
126 | { | ||
127 | unsigned int i; | ||
128 | |||
129 | msi_hash = kmalloc(256 * sizeof(*msi_hash), GFP_KERNEL); | ||
130 | if (!msi_hash) | ||
131 | return -ENOMEM; | ||
132 | |||
133 | for (i = 0; i < (1U << msihash_shift); i++) | ||
134 | INIT_HLIST_HEAD(&msi_hash[i]); | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | void __init zpci_msihash_exit(void) | ||
139 | { | ||
140 | kfree(msi_hash); | ||
141 | } | ||
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index a825d78fd0aa..5099636a6e5f 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -207,6 +207,8 @@ static void msix_mask_irq(struct msi_desc *desc, u32 flag) | |||
207 | desc->masked = __msix_mask_irq(desc, flag); | 207 | desc->masked = __msix_mask_irq(desc, flag); |
208 | } | 208 | } |
209 | 209 | ||
210 | #ifdef CONFIG_GENERIC_HARDIRQS | ||
211 | |||
210 | static void msi_set_mask_bit(struct irq_data *data, u32 flag) | 212 | static void msi_set_mask_bit(struct irq_data *data, u32 flag) |
211 | { | 213 | { |
212 | struct msi_desc *desc = irq_data_get_msi(data); | 214 | struct msi_desc *desc = irq_data_get_msi(data); |
@@ -230,6 +232,8 @@ void unmask_msi_irq(struct irq_data *data) | |||
230 | msi_set_mask_bit(data, 0); | 232 | msi_set_mask_bit(data, 0); |
231 | } | 233 | } |
232 | 234 | ||
235 | #endif /* CONFIG_GENERIC_HARDIRQS */ | ||
236 | |||
233 | void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg) | 237 | void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg) |
234 | { | 238 | { |
235 | BUG_ON(entry->dev->current_state != PCI_D0); | 239 | BUG_ON(entry->dev->current_state != PCI_D0); |
@@ -337,8 +341,10 @@ static void free_msi_irqs(struct pci_dev *dev) | |||
337 | if (!entry->irq) | 341 | if (!entry->irq) |
338 | continue; | 342 | continue; |
339 | nvec = 1 << entry->msi_attrib.multiple; | 343 | nvec = 1 << entry->msi_attrib.multiple; |
344 | #ifdef CONFIG_GENERIC_HARDIRQS | ||
340 | for (i = 0; i < nvec; i++) | 345 | for (i = 0; i < nvec; i++) |
341 | BUG_ON(irq_has_action(entry->irq + i)); | 346 | BUG_ON(irq_has_action(entry->irq + i)); |
347 | #endif | ||
342 | } | 348 | } |
343 | 349 | ||
344 | arch_teardown_msi_irqs(dev); | 350 | arch_teardown_msi_irqs(dev); |
diff --git a/include/linux/irq.h b/include/linux/irq.h index 216b0ba109d7..e21ed837c673 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -10,9 +10,6 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/smp.h> | 12 | #include <linux/smp.h> |
13 | |||
14 | #ifndef CONFIG_S390 | ||
15 | |||
16 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> |
17 | #include <linux/cache.h> | 14 | #include <linux/cache.h> |
18 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
@@ -737,8 +734,11 @@ static inline void irq_gc_lock(struct irq_chip_generic *gc) { } | |||
737 | static inline void irq_gc_unlock(struct irq_chip_generic *gc) { } | 734 | static inline void irq_gc_unlock(struct irq_chip_generic *gc) { } |
738 | #endif | 735 | #endif |
739 | 736 | ||
740 | #endif /* CONFIG_GENERIC_HARDIRQS */ | 737 | #else /* !CONFIG_GENERIC_HARDIRQS */ |
741 | 738 | ||
742 | #endif /* !CONFIG_S390 */ | 739 | extern struct msi_desc *irq_get_msi_desc(unsigned int irq); |
740 | extern int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry); | ||
741 | |||
742 | #endif /* CONFIG_GENERIC_HARDIRQS */ | ||
743 | 743 | ||
744 | #endif /* _LINUX_IRQ_H */ | 744 | #endif /* _LINUX_IRQ_H */ |