History

Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull irq updates from Thomas Gleixner: "The irq department provides: - a major update to the auto affinity management code, which is used by multi-queue devices - move of the microblaze irq chip driver into the common driver code so it can be shared between microblaze, powerpc and MIPS - a series of updates to the ARM GICV3 interrupt controller - the usual pile of fixes and small improvements all over the place" * 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (25 commits) powerpc/virtex: Use generic xilinx irqchip driver irqchip/xilinx: Try to fall back if xlnx,kind-of-intr not provided irqchip/xilinx: Add support for parent intc irqchip/xilinx: Rename get_irq to xintc_get_irq irqchip/xilinx: Restructure and use jump label api irqchip/xilinx: Clean up print messages microblaze/irqchip: Move intc driver to irqchip ARM: virt: Select ARM_GIC_V3_ITS ARM: gic-v3-its: Add 32bit support to GICv3 ITS irqchip/gic-v3-its: Specialise readq and writeq accesses irqchip/gic-v3-its: Specialise flush_dcache operation irqchip/gic-v3-its: Narrow down Entry Size when used as a divider irqchip/gic-v3-its: Change unsigned types for AArch32 compatibility irqchip/gic-v3: Use nops macro for Cavium ThunderX erratum 23154 irqchip/gic-v3: Convert arm64 GIC accessors to {read,write}_sysreg_s genirq/msi: Drop artificial PCI dependency irqchip/bcm7038-l1: Implement irq_cpu_offline() callback genirq/affinity: Use default affinity mask for reserved vectors genirq/affinity: Take reserved vectors into account when spreading irqs PCI: Remove the irq_affinity mask from struct pci_dev ...

Linus Torvalds committed 9 years ago

Commit f082f022 parents 9465d9c 2cae3a125 files · +518 −572Browse files

Unified · Split

25 files
  1. arch/arm/Kconfig +1 −0
  2. arch/arm/include/asm/arch_gicv3.h +47 −7
  3. arch/arm64/include/asm/arch_gicv3.h +31 −30
  4. arch/microblaze/Kconfig +1 −0
  5. arch/microblaze/include/asm/irq.h +1 −1
  6. arch/microblaze/kernel/Makefile +1 −1
  7. arch/microblaze/kernel/intc.c +0 −196
  8. arch/microblaze/kernel/irq.c +2 −2
  9. arch/powerpc/include/asm/xilinx_intc.h +1 −1
  10. arch/powerpc/platforms/40x/Kconfig +1 −0
  11. arch/powerpc/platforms/40x/virtex.c +1 −1
  12. arch/powerpc/platforms/44x/Kconfig +1 −0
  13. arch/powerpc/platforms/44x/virtex.c +1 −1
  14. arch/powerpc/sysdev/xilinx_intc.c +2 −209
  15. drivers/irqchip/Kconfig +4 −0
  16. drivers/irqchip/Makefile +1 −0
  17. drivers/irqchip/irq-bcm7038-l1.c +26 −0
  18. drivers/irqchip/irq-gic-v3-its.c +37 −38
  19. drivers/irqchip/irq-xilinx-intc.c +241 −0
  20. drivers/pci/msi.c +43 −35
  21. include/linux/interrupt.h +16 −4
  22. include/linux/irqchip/arm-gic-v3.h +2 −2
  23. include/linux/pci.h +19 −6
  24. kernel/irq/affinity.c +37 −35
  25. kernel/irq/msi.c +1 −3
arch/arm/Kconfig+1−0
@@ -703,6 +703,7 @@ config ARCH_VIRT · 702 unmodified lines
703 select ARM_GIC703 select ARM_GIC
704 select ARM_GIC_V2M if PCI704 select ARM_GIC_V2M if PCI
705 select ARM_GIC_V3705 select ARM_GIC_V3
706 select ARM_GIC_V3_ITS if PCI
706 select ARM_PSCI707 select ARM_PSCI
707 select HAVE_ARM_ARCH_TIMER708 select HAVE_ARM_ARCH_TIMER
708 709
arch/arm/include/asm/arch_gicv3.h+47−7
@@ -22,6 +22,7 @@ · 21 unmodified lines
22 22
23#include <linux/io.h>23#include <linux/io.h>
24#include <asm/barrier.h>24#include <asm/barrier.h>
25#include <asm/cacheflush.h>
25#include <asm/cp15.h>26#include <asm/cp15.h>
26 27
27#define ICC_EOIR1 __ACCESS_CP15(c12, 0, c12, 1)28#define ICC_EOIR1 __ACCESS_CP15(c12, 0, c12, 1)
@@ -230,19 +231,14 @@ static inline void gic_write_bpr1(u32 val) · 202 unmodified lines
230 * AArch32, since the syndrome register doesn't provide any information for231 * AArch32, since the syndrome register doesn't provide any information for
231 * them.232 * them.
232 * Consequently, the following IO helpers use 32bit accesses.233 * Consequently, the following IO helpers use 32bit accesses.
233 *
234 * There are only two registers that need 64bit accesses in this driver:
235 * - GICD_IROUTERn, contain the affinity values associated to each interrupt.
236 * The upper-word (aff3) will always be 0, so there is no need for a lock.
237 * - GICR_TYPER is an ID register and doesn't need atomicity.
238 */234 */
239static inline void gic_write_irouter(u64 val, volatile void __iomem *addr)235static inline void __gic_writeq_nonatomic(u64 val, volatile void __iomem *addr)
240{236{
241 writel_relaxed((u32)val, addr);237 writel_relaxed((u32)val, addr);
242 writel_relaxed((u32)(val >> 32), addr + 4);238 writel_relaxed((u32)(val >> 32), addr + 4);
243}239}
244 240
245static inline u64 gic_read_typer(const volatile void __iomem *addr)241static inline u64 __gic_readq_nonatomic(const volatile void __iomem *addr)
246{242{
247 u64 val;243 u64 val;
248 244
@@ -251,5 +247,49 @@ static inline u64 gic_read_typer(const volatile void __iomem *addr) · 2 unmodified lines
251 return val;247 return val;
252}248}
253 249
250#define gic_flush_dcache_to_poc(a,l) __cpuc_flush_dcache_area((a), (l))
251
252/*
253 * GICD_IROUTERn, contain the affinity values associated to each interrupt.
254 * The upper-word (aff3) will always be 0, so there is no need for a lock.
255 */
256#define gic_write_irouter(v, c) __gic_writeq_nonatomic(v, c)
257
258/*
259 * GICR_TYPER is an ID register and doesn't need atomicity.
260 */
261#define gic_read_typer(c) __gic_readq_nonatomic(c)
262
263/*
264 * GITS_BASER - hi and lo bits may be accessed independently.
265 */
266#define gits_read_baser(c) __gic_readq_nonatomic(c)
267#define gits_write_baser(v, c) __gic_writeq_nonatomic(v, c)
268
269/*
270 * GICR_PENDBASER and GICR_PROPBASE are changed with LPIs disabled, so they
271 * won't be being used during any updates and can be changed non-atomically
272 */
273#define gicr_read_propbaser(c) __gic_readq_nonatomic(c)
274#define gicr_write_propbaser(v, c) __gic_writeq_nonatomic(v, c)
275#define gicr_read_pendbaser(c) __gic_readq_nonatomic(c)
276#define gicr_write_pendbaser(v, c) __gic_writeq_nonatomic(v, c)
277
278/*
279 * GITS_TYPER is an ID register and doesn't need atomicity.
280 */
281#define gits_read_typer(c) __gic_readq_nonatomic(c)
282
283/*
284 * GITS_CBASER - hi and lo bits may be accessed independently.
285 */
286#define gits_read_cbaser(c) __gic_readq_nonatomic(c)
287#define gits_write_cbaser(v, c) __gic_writeq_nonatomic(v, c)
288
289/*
290 * GITS_CWRITER - hi and lo bits may be accessed independently.
291 */
292#define gits_write_cwriter(v, c) __gic_writeq_nonatomic(v, c)
293
254#endif /* !__ASSEMBLY__ */294#endif /* !__ASSEMBLY__ */
255#endif /* !__ASM_ARCH_GICV3_H */295#endif /* !__ASM_ARCH_GICV3_H */
arch/arm64/include/asm/arch_gicv3.h+31−30
@@ -79,19 +79,10 @@ · 78 unmodified lines
79 79
80#include <linux/stringify.h>80#include <linux/stringify.h>
81#include <asm/barrier.h>81#include <asm/barrier.h>
82#include <asm/cacheflush.h>
82 83
83#define read_gicreg(r) \84#define read_gicreg read_sysreg_s
84 ({ \85#define write_gicreg write_sysreg_s
85 u64 reg; \
86 asm volatile("mrs_s %0, " __stringify(r) : "=r" (reg)); \
87 reg; \
88 })
89
90#define write_gicreg(v,r) \
91 do { \
92 u64 __val = (v); \
93 asm volatile("msr_s " __stringify(r) ", %0" : : "r" (__val));\
94 } while (0)
95 86
96/*87/*
97 * Low-level accessors88 * Low-level accessors
@@ -102,13 +93,13 @@ · 4 unmodified lines
102 93
103static inline void gic_write_eoir(u32 irq)94static inline void gic_write_eoir(u32 irq)
104{95{
105 asm volatile("msr_s " __stringify(ICC_EOIR1_EL1) ", %0" : : "r" ((u64)irq));96 write_sysreg_s(irq, ICC_EOIR1_EL1);
106 isb();97 isb();
107}98}
108 99
109static inline void gic_write_dir(u32 irq)100static inline void gic_write_dir(u32 irq)
110{101{
111 asm volatile("msr_s " __stringify(ICC_DIR_EL1) ", %0" : : "r" ((u64)irq));102 write_sysreg_s(irq, ICC_DIR_EL1);
112 isb();103 isb();
113}104}
114 105
@@ -116,7 +107,7 @@ static inline u64 gic_read_iar_common(void) · 1 unmodified line
116{107{
117 u64 irqstat;108 u64 irqstat;
118 109
119 asm volatile("mrs_s %0, " __stringify(ICC_IAR1_EL1) : "=r" (irqstat));110 irqstat = read_sysreg_s(ICC_IAR1_EL1);
120 dsb(sy);111 dsb(sy);
121 return irqstat;112 return irqstat;
122}113}
@@ -132,12 +123,9 @@ static inline u64 gic_read_iar_cavium_thunderx(void) · 9 unmodified lines
132{123{
133 u64 irqstat;124 u64 irqstat;
134 125
135 asm volatile(126 nops(8);
136 "nop;nop;nop;nop\n\t"127 irqstat = read_sysreg_s(ICC_IAR1_EL1);
137 "nop;nop;nop;nop\n\t"128 nops(4);
138 "mrs_s %0, " __stringify(ICC_IAR1_EL1) "\n\t"
139 "nop;nop;nop;nop"
140 : "=r" (irqstat));
141 mb();129 mb();
142 130
143 return irqstat;131 return irqstat;
@@ -145,37 +133,34 @@ static inline u64 gic_read_iar_cavium_thunderx(void) · 1 unmodified line
145 133
146static inline void gic_write_pmr(u32 val)134static inline void gic_write_pmr(u32 val)
147{135{
148 asm volatile("msr_s " __stringify(ICC_PMR_EL1) ", %0" : : "r" ((u64)val));136 write_sysreg_s(val, ICC_PMR_EL1);
149}137}
150 138
151static inline void gic_write_ctlr(u32 val)139static inline void gic_write_ctlr(u32 val)
152{140{
153 asm volatile("msr_s " __stringify(ICC_CTLR_EL1) ", %0" : : "r" ((u64)val));141 write_sysreg_s(val, ICC_CTLR_EL1);
154 isb();142 isb();
155}143}
156 144
157static inline void gic_write_grpen1(u32 val)145static inline void gic_write_grpen1(u32 val)
158{146{
159 asm volatile("msr_s " __stringify(ICC_GRPEN1_EL1) ", %0" : : "r" ((u64)val));147 write_sysreg_s(val, ICC_GRPEN1_EL1);
160 isb();148 isb();
161}149}
162 150
163static inline void gic_write_sgi1r(u64 val)151static inline void gic_write_sgi1r(u64 val)
164{152{
165 asm volatile("msr_s " __stringify(ICC_SGI1R_EL1) ", %0" : : "r" (val));153 write_sysreg_s(val, ICC_SGI1R_EL1);
166}154}
167 155
168static inline u32 gic_read_sre(void)156static inline u32 gic_read_sre(void)
169{157{
170 u64 val;158 return read_sysreg_s(ICC_SRE_EL1);
171
172 asm volatile("mrs_s %0, " __stringify(ICC_SRE_EL1) : "=r" (val));
173 return val;
174}159}
175 160
176static inline void gic_write_sre(u32 val)161static inline void gic_write_sre(u32 val)
177{162{
178 asm volatile("msr_s " __stringify(ICC_SRE_EL1) ", %0" : : "r" ((u64)val));163 write_sysreg_s(val, ICC_SRE_EL1);
179 isb();164 isb();
180}165}
181 166
@@ -187,5 +172,21 @@ static inline void gic_write_bpr1(u32 val) · 5 unmodified lines
187#define gic_read_typer(c) readq_relaxed(c)172#define gic_read_typer(c) readq_relaxed(c)
188#define gic_write_irouter(v, c) writeq_relaxed(v, c)173#define gic_write_irouter(v, c) writeq_relaxed(v, c)
189 174
175#define gic_flush_dcache_to_poc(a,l) __flush_dcache_area((a), (l))
176
177#define gits_read_baser(c) readq_relaxed(c)
178#define gits_write_baser(v, c) writeq_relaxed(v, c)
179
180#define gits_read_cbaser(c) readq_relaxed(c)
181#define gits_write_cbaser(v, c) writeq_relaxed(v, c)
182
183#define gits_write_cwriter(v, c) writeq_relaxed(v, c)
184
185#define gicr_read_propbaser(c) readq_relaxed(c)
186#define gicr_write_propbaser(v, c) writeq_relaxed(v, c)
187
188#define gicr_write_pendbaser(v, c) writeq_relaxed(v, c)
189#define gicr_read_pendbaser(c) readq_relaxed(c)
190
190#endif /* __ASSEMBLY__ */191#endif /* __ASSEMBLY__ */
191#endif /* __ASM_ARCH_GICV3_H */192#endif /* __ASM_ARCH_GICV3_H */
arch/microblaze/Kconfig+1−0
@@ -27,6 +27,7 @@ config MICROBLAZE · 26 unmodified lines
27 select HAVE_MEMBLOCK_NODE_MAP27 select HAVE_MEMBLOCK_NODE_MAP
28 select HAVE_OPROFILE28 select HAVE_OPROFILE
29 select IRQ_DOMAIN29 select IRQ_DOMAIN
30 select XILINX_INTC
30 select MODULES_USE_ELF_RELA31 select MODULES_USE_ELF_RELA
31 select OF32 select OF
32 select OF_EARLY_FLATTREE33 select OF_EARLY_FLATTREE
arch/microblaze/include/asm/irq.h+1−1
@@ -16,6 +16,6 @@ struct pt_regs; · 15 unmodified lines
16extern void do_IRQ(struct pt_regs *regs);16extern void do_IRQ(struct pt_regs *regs);
17 17
18/* should be defined in each interrupt controller driver */18/* should be defined in each interrupt controller driver */
19extern unsigned int get_irq(void);19extern unsigned int xintc_get_irq(void);
20 20
21#endif /* _ASM_MICROBLAZE_IRQ_H */21#endif /* _ASM_MICROBLAZE_IRQ_H */
arch/microblaze/kernel/Makefile+1−1
@@ -15,7 +15,7 @@ endif · 14 unmodified lines
15extra-y := head.o vmlinux.lds15extra-y := head.o vmlinux.lds
16 16
17obj-y += dma.o exceptions.o \17obj-y += dma.o exceptions.o \
18 hw_exception_handler.o intc.o irq.o \18 hw_exception_handler.o irq.o \
19 platform.o process.o prom.o ptrace.o \19 platform.o process.o prom.o ptrace.o \
20 reset.o setup.o signal.o sys_microblaze.o timer.o traps.o unwind.o20 reset.o setup.o signal.o sys_microblaze.o timer.o traps.o unwind.o
21 21
arch/microblaze/kernel/intc.c+0−196
@@ -1,196 +0,0 @@
1/*
2 * Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu>
3 * Copyright (C) 2012-2013 Xilinx, Inc.
4 * Copyright (C) 2007-2009 PetaLogix
5 * Copyright (C) 2006 Atmark Techno, Inc.
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 */
11
12#include <linux/irqdomain.h>
13#include <linux/irq.h>
14#include <linux/irqchip.h>
15#include <linux/of_address.h>
16#include <linux/io.h>
17#include <linux/bug.h>
18
19static void __iomem *intc_baseaddr;
20
21/* No one else should require these constants, so define them locally here. */
22#define ISR 0x00 /* Interrupt Status Register */
23#define IPR 0x04 /* Interrupt Pending Register */
24#define IER 0x08 /* Interrupt Enable Register */
25#define IAR 0x0c /* Interrupt Acknowledge Register */
26#define SIE 0x10 /* Set Interrupt Enable bits */
27#define CIE 0x14 /* Clear Interrupt Enable bits */
28#define IVR 0x18 /* Interrupt Vector Register */
29#define MER 0x1c /* Master Enable Register */
30
31#define MER_ME (1<<0)
32#define MER_HIE (1<<1)
33
34static unsigned int (*read_fn)(void __iomem *);
35static void (*write_fn)(u32, void __iomem *);
36
37static void intc_write32(u32 val, void __iomem *addr)
38{
39 iowrite32(val, addr);
40}
41
42static unsigned int intc_read32(void __iomem *addr)
43{
44 return ioread32(addr);
45}
46
47static void intc_write32_be(u32 val, void __iomem *addr)
48{
49 iowrite32be(val, addr);
50}
51
52static unsigned int intc_read32_be(void __iomem *addr)
53{
54 return ioread32be(addr);
55}
56
57static void intc_enable_or_unmask(struct irq_data *d)
58{
59 unsigned long mask = 1 << d->hwirq;
60
61 pr_debug("enable_or_unmask: %ld\n", d->hwirq);
62
63 /* ack level irqs because they can't be acked during
64 * ack function since the handle_level_irq function
65 * acks the irq before calling the interrupt handler
66 */
67 if (irqd_is_level_type(d))
68 write_fn(mask, intc_baseaddr + IAR);
69
70 write_fn(mask, intc_baseaddr + SIE);
71}
72
73static void intc_disable_or_mask(struct irq_data *d)
74{
75 pr_debug("disable: %ld\n", d->hwirq);
76 write_fn(1 << d->hwirq, intc_baseaddr + CIE);
77}
78
79static void intc_ack(struct irq_data *d)
80{
81 pr_debug("ack: %ld\n", d->hwirq);
82 write_fn(1 << d->hwirq, intc_baseaddr + IAR);
83}
84
85static void intc_mask_ack(struct irq_data *d)
86{
87 unsigned long mask = 1 << d->hwirq;
88
89 pr_debug("disable_and_ack: %ld\n", d->hwirq);
90 write_fn(mask, intc_baseaddr + CIE);
91 write_fn(mask, intc_baseaddr + IAR);
92}
93
94static struct irq_chip intc_dev = {
95 .name = "Xilinx INTC",
96 .irq_unmask = intc_enable_or_unmask,
97 .irq_mask = intc_disable_or_mask,
98 .irq_ack = intc_ack,
99 .irq_mask_ack = intc_mask_ack,
100};
101
102static struct irq_domain *root_domain;
103
104unsigned int get_irq(void)
105{
106 unsigned int hwirq, irq = -1;
107
108 hwirq = read_fn(intc_baseaddr + IVR);
109 if (hwirq != -1U)
110 irq = irq_find_mapping(root_domain, hwirq);
111
112 pr_debug("get_irq: hwirq=%d, irq=%d\n", hwirq, irq);
113
114 return irq;
115}
116
117static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
118{
119 u32 intr_mask = (u32)d->host_data;
120
121 if (intr_mask & (1 << hw)) {
122 irq_set_chip_and_handler_name(irq, &intc_dev,
123 handle_edge_irq, "edge");
124 irq_clear_status_flags(irq, IRQ_LEVEL);
125 } else {
126 irq_set_chip_and_handler_name(irq, &intc_dev,
127 handle_level_irq, "level");
128 irq_set_status_flags(irq, IRQ_LEVEL);
129 }
130 return 0;
131}
132
133static const struct irq_domain_ops xintc_irq_domain_ops = {
134 .xlate = irq_domain_xlate_onetwocell,
135 .map = xintc_map,
136};
137
138static int __init xilinx_intc_of_init(struct device_node *intc,
139 struct device_node *parent)
140{
141 u32 nr_irq, intr_mask;
142 int ret;
143
144 intc_baseaddr = of_iomap(intc, 0);
145 BUG_ON(!intc_baseaddr);
146
147 ret = of_property_read_u32(intc, "xlnx,num-intr-inputs", &nr_irq);
148 if (ret < 0) {
149 pr_err("%s: unable to read xlnx,num-intr-inputs\n", __func__);
150 return ret;
151 }
152
153 ret = of_property_read_u32(intc, "xlnx,kind-of-intr", &intr_mask);
154 if (ret < 0) {
155 pr_err("%s: unable to read xlnx,kind-of-intr\n", __func__);
156 return ret;
157 }
158
159 if (intr_mask >> nr_irq)
160 pr_warn("%s: mismatch in kind-of-intr param\n", __func__);
161
162 pr_info("%s: num_irq=%d, edge=0x%x\n",
163 intc->full_name, nr_irq, intr_mask);
164
165 write_fn = intc_write32;
166 read_fn = intc_read32;
167
168 /*
169 * Disable all external interrupts until they are
170 * explicity requested.
171 */
172 write_fn(0, intc_baseaddr + IER);
173
174 /* Acknowledge any pending interrupts just in case. */
175 write_fn(0xffffffff, intc_baseaddr + IAR);
176
177 /* Turn on the Master Enable. */
178 write_fn(MER_HIE | MER_ME, intc_baseaddr + MER);
179 if (!(read_fn(intc_baseaddr + MER) & (MER_HIE | MER_ME))) {
180 write_fn = intc_write32_be;
181 read_fn = intc_read32_be;
182 write_fn(MER_HIE | MER_ME, intc_baseaddr + MER);
183 }
184
185 /* Yeah, okay, casting the intr_mask to a void* is butt-ugly, but I'm
186 * lazy and Michal can clean it up to something nicer when he tests
187 * and commits this patch. ~~gcl */
188 root_domain = irq_domain_add_linear(intc, nr_irq, &xintc_irq_domain_ops,
189 (void *)intr_mask);
190
191 irq_set_default_host(root_domain);
192
193 return 0;
194}
195
196IRQCHIP_DECLARE(xilinx_intc, "xlnx,xps-intc-1.00.a", xilinx_intc_of_init);
arch/microblaze/kernel/irq.c+2−2
@@ -29,12 +29,12 @@ void __irq_entry do_IRQ(struct pt_regs *regs) · 28 unmodified lines
29 trace_hardirqs_off();29 trace_hardirqs_off();
30 30
31 irq_enter();31 irq_enter();
32 irq = get_irq();32 irq = xintc_get_irq();
33next_irq:33next_irq:
34 BUG_ON(!irq);34 BUG_ON(!irq);
35 generic_handle_irq(irq);35 generic_handle_irq(irq);
36 36
37 irq = get_irq();37 irq = xintc_get_irq();
38 if (irq != -1U) {38 if (irq != -1U) {
39 pr_debug("next irq: %d\n", irq);39 pr_debug("next irq: %d\n", irq);
40 ++concurrent_irq;40 ++concurrent_irq;
arch/powerpc/include/asm/xilinx_intc.h+1−1
@@ -14,7 +14,7 @@ · 13 unmodified lines
14#ifdef __KERNEL__14#ifdef __KERNEL__
15 15
16extern void __init xilinx_intc_init_tree(void);16extern void __init xilinx_intc_init_tree(void);
17extern unsigned int xilinx_intc_get_irq(void);17extern unsigned int xintc_get_irq(void);
18 18
19#endif /* __KERNEL__ */19#endif /* __KERNEL__ */
20#endif /* _ASM_POWERPC_XILINX_INTC_H */20#endif /* _ASM_POWERPC_XILINX_INTC_H */
arch/powerpc/platforms/40x/Kconfig+1−0
@@ -64,6 +64,7 @@ config XILINX_VIRTEX_GENERIC_BOARD · 63 unmodified lines
64 default n64 default n
65 select XILINX_VIRTEX_II_PRO65 select XILINX_VIRTEX_II_PRO
66 select XILINX_VIRTEX_4_FX66 select XILINX_VIRTEX_4_FX
67 select XILINX_INTC
67 help68 help
68 This option enables generic support for Xilinx Virtex based boards.69 This option enables generic support for Xilinx Virtex based boards.
69 70
arch/powerpc/platforms/40x/virtex.c+1−1
@@ -48,7 +48,7 @@ define_machine(virtex) { · 47 unmodified lines
48 .probe = virtex_probe,48 .probe = virtex_probe,
49 .setup_arch = xilinx_pci_init,49 .setup_arch = xilinx_pci_init,
50 .init_IRQ = xilinx_intc_init_tree,50 .init_IRQ = xilinx_intc_init_tree,
51 .get_irq = xilinx_intc_get_irq,51 .get_irq = xintc_get_irq,
52 .restart = ppc4xx_reset_system,52 .restart = ppc4xx_reset_system,
53 .calibrate_decr = generic_calibrate_decr,53 .calibrate_decr = generic_calibrate_decr,
54};54};
arch/powerpc/platforms/44x/Kconfig+1−0
@@ -241,6 +241,7 @@ config XILINX_VIRTEX440_GENERIC_BOARD · 240 unmodified lines
241 depends on 44x241 depends on 44x
242 default n242 default n
243 select XILINX_VIRTEX_5_FXT243 select XILINX_VIRTEX_5_FXT
244 select XILINX_INTC
244 help245 help
245 This option enables generic support for Xilinx Virtex based boards246 This option enables generic support for Xilinx Virtex based boards
246 that use a 440 based processor in the Virtex 5 FXT FPGA architecture.247 that use a 440 based processor in the Virtex 5 FXT FPGA architecture.
arch/powerpc/platforms/44x/virtex.c+1−1
@@ -54,7 +54,7 @@ define_machine(virtex) { · 53 unmodified lines
54 .probe = virtex_probe,54 .probe = virtex_probe,
55 .setup_arch = xilinx_pci_init,55 .setup_arch = xilinx_pci_init,
56 .init_IRQ = xilinx_intc_init_tree,56 .init_IRQ = xilinx_intc_init_tree,
57 .get_irq = xilinx_intc_get_irq,57 .get_irq = xintc_get_irq,
58 .calibrate_decr = generic_calibrate_decr,58 .calibrate_decr = generic_calibrate_decr,
59 .restart = ppc4xx_reset_system,59 .restart = ppc4xx_reset_system,
60};60};
arch/powerpc/sysdev/xilinx_intc.c+2−209
@@ -29,194 +29,7 @@ · 28 unmodified lines
29#include <asm/processor.h>29#include <asm/processor.h>
30#include <asm/i8259.h>30#include <asm/i8259.h>
31#include <asm/irq.h>31#include <asm/irq.h>
32 32#include <linux/irqchip.h>
33/*
34 * INTC Registers
35 */
36#define XINTC_ISR 0 /* Interrupt Status */
37#define XINTC_IPR 4 /* Interrupt Pending */
38#define XINTC_IER 8 /* Interrupt Enable */
39#define XINTC_IAR 12 /* Interrupt Acknowledge */
40#define XINTC_SIE 16 /* Set Interrupt Enable bits */
41#define XINTC_CIE 20 /* Clear Interrupt Enable bits */
42#define XINTC_IVR 24 /* Interrupt Vector */
43#define XINTC_MER 28 /* Master Enable */
44
45static struct irq_domain *master_irqhost;
46
47#define XILINX_INTC_MAXIRQS (32)
48
49/* The following table allows the interrupt type, edge or level,
50 * to be cached after being read from the device tree until the interrupt
51 * is mapped
52 */
53static int xilinx_intc_typetable[XILINX_INTC_MAXIRQS];
54
55/* Map the interrupt type from the device tree to the interrupt types
56 * used by the interrupt subsystem
57 */
58static unsigned char xilinx_intc_map_senses[] = {
59 IRQ_TYPE_EDGE_RISING,
60 IRQ_TYPE_EDGE_FALLING,
61 IRQ_TYPE_LEVEL_HIGH,
62 IRQ_TYPE_LEVEL_LOW,
63};
64
65/*
66 * The interrupt controller is setup such that it doesn't work well with
67 * the level interrupt handler in the kernel because the handler acks the
68 * interrupt before calling the application interrupt handler. To deal with
69 * that, we use 2 different irq chips so that different functions can be
70 * used for level and edge type interrupts.
71 *
72 * IRQ Chip common (across level and edge) operations
73 */
74static void xilinx_intc_mask(struct irq_data *d)
75{
76 int irq = irqd_to_hwirq(d);
77 void * regs = irq_data_get_irq_chip_data(d);
78 pr_debug("mask: %d\n", irq);
79 out_be32(regs + XINTC_CIE, 1 << irq);
80}
81
82static int xilinx_intc_set_type(struct irq_data *d, unsigned int flow_type)
83{
84 return 0;
85}
86
87/*
88 * IRQ Chip level operations
89 */
90static void xilinx_intc_level_unmask(struct irq_data *d)
91{
92 int irq = irqd_to_hwirq(d);
93 void * regs = irq_data_get_irq_chip_data(d);
94 pr_debug("unmask: %d\n", irq);
95 out_be32(regs + XINTC_SIE, 1 << irq);
96
97 /* ack level irqs because they can't be acked during
98 * ack function since the handle_level_irq function
99 * acks the irq before calling the inerrupt handler
100 */
101 out_be32(regs + XINTC_IAR, 1 << irq);
102}
103
104static struct irq_chip xilinx_intc_level_irqchip = {
105 .name = "Xilinx Level INTC",
106 .irq_mask = xilinx_intc_mask,
107 .irq_mask_ack = xilinx_intc_mask,
108 .irq_unmask = xilinx_intc_level_unmask,
109 .irq_set_type = xilinx_intc_set_type,
110};
111
112/*
113 * IRQ Chip edge operations
114 */
115static void xilinx_intc_edge_unmask(struct irq_data *d)
116{
117 int irq = irqd_to_hwirq(d);
118 void *regs = irq_data_get_irq_chip_data(d);
119 pr_debug("unmask: %d\n", irq);
120 out_be32(regs + XINTC_SIE, 1 << irq);
121}
122
123static void xilinx_intc_edge_ack(struct irq_data *d)
124{
125 int irq = irqd_to_hwirq(d);
126 void * regs = irq_data_get_irq_chip_data(d);
127 pr_debug("ack: %d\n", irq);
128 out_be32(regs + XINTC_IAR, 1 << irq);
129}
130
131static struct irq_chip xilinx_intc_edge_irqchip = {
132 .name = "Xilinx Edge INTC",
133 .irq_mask = xilinx_intc_mask,
134 .irq_unmask = xilinx_intc_edge_unmask,
135 .irq_ack = xilinx_intc_edge_ack,
136 .irq_set_type = xilinx_intc_set_type,
137};
138
139/*
140 * IRQ Host operations
141 */
142
143/**
144 * xilinx_intc_xlate - translate virq# from device tree interrupts property
145 */
146static int xilinx_intc_xlate(struct irq_domain *h, struct device_node *ct,
147 const u32 *intspec, unsigned int intsize,
148 irq_hw_number_t *out_hwirq,
149 unsigned int *out_flags)
150{
151 if ((intsize < 2) || (intspec[0] >= XILINX_INTC_MAXIRQS))
152 return -EINVAL;
153
154 /* keep a copy of the interrupt type til the interrupt is mapped
155 */
156 xilinx_intc_typetable[intspec[0]] = xilinx_intc_map_senses[intspec[1]];
157
158 /* Xilinx uses 2 interrupt entries, the 1st being the h/w
159 * interrupt number, the 2nd being the interrupt type, edge or level
160 */
161 *out_hwirq = intspec[0];
162 *out_flags = xilinx_intc_map_senses[intspec[1]];
163
164 return 0;
165}
166static int xilinx_intc_map(struct irq_domain *h, unsigned int virq,
167 irq_hw_number_t irq)
168{
169 irq_set_chip_data(virq, h->host_data);
170
171 if (xilinx_intc_typetable[irq] == IRQ_TYPE_LEVEL_HIGH ||
172 xilinx_intc_typetable[irq] == IRQ_TYPE_LEVEL_LOW) {
173 irq_set_chip_and_handler(virq, &xilinx_intc_level_irqchip,
174 handle_level_irq);
175 } else {
176 irq_set_chip_and_handler(virq, &xilinx_intc_edge_irqchip,
177 handle_edge_irq);
178 }
179 return 0;
180}
181
182static const struct irq_domain_ops xilinx_intc_ops = {
183 .map = xilinx_intc_map,
184 .xlate = xilinx_intc_xlate,
185};
186
187struct irq_domain * __init
188xilinx_intc_init(struct device_node *np)
189{
190 struct irq_domain * irq;
191 void * regs;
192
193 /* Find and map the intc registers */
194 regs = of_iomap(np, 0);
195 if (!regs) {
196 pr_err("xilinx_intc: could not map registers\n");
197 return NULL;
198 }
199
200 /* Setup interrupt controller */
201 out_be32(regs + XINTC_IER, 0); /* disable all irqs */
202 out_be32(regs + XINTC_IAR, ~(u32) 0); /* Acknowledge pending irqs */
203 out_be32(regs + XINTC_MER, 0x3UL); /* Turn on the Master Enable. */
204
205 /* Allocate and initialize an irq_domain structure. */
206 irq = irq_domain_add_linear(np, XILINX_INTC_MAXIRQS, &xilinx_intc_ops,
207 regs);
208 if (!irq)
209 panic(__FILE__ ": Cannot allocate IRQ host\n");
210
211 return irq;
212}
213
214int xilinx_intc_get_irq(void)
215{
216 void * regs = master_irqhost->host_data;
217 pr_debug("get_irq:\n");
218 return irq_linear_revmap(master_irqhost, in_be32(regs + XINTC_IVR));
219}
220 33
221#if defined(CONFIG_PPC_I8259)34#if defined(CONFIG_PPC_I8259)
222/*35/*
@@ -265,31 +78,11 @@ static void __init xilinx_i8259_setup_cascade(void) · 42 unmodified lines
265static inline void xilinx_i8259_setup_cascade(void) { return; }78static inline void xilinx_i8259_setup_cascade(void) { return; }
266#endif /* defined(CONFIG_PPC_I8259) */79#endif /* defined(CONFIG_PPC_I8259) */
267 80
268static const struct of_device_id xilinx_intc_match[] __initconst = {
269 { .compatible = "xlnx,opb-intc-1.00.c", },
270 { .compatible = "xlnx,xps-intc-1.00.a", },
271 {}
272};
273
274/*81/*
275 * Initialize master Xilinx interrupt controller82 * Initialize master Xilinx interrupt controller
276 */83 */
277void __init xilinx_intc_init_tree(void)84void __init xilinx_intc_init_tree(void)
278{85{
279 struct device_node *np;86 irqchip_init();
280
281 /* find top level interrupt controller */
282 for_each_matching_node(np, xilinx_intc_match) {
283 if (!of_get_property(np, "interrupts", NULL))
284 break;
285 }
286 BUG_ON(!np);
287
288 master_irqhost = xilinx_intc_init(np);
289 BUG_ON(!master_irqhost);
290
291 irq_set_default_host(master_irqhost);
292 of_node_put(np);
293
294 xilinx_i8259_setup_cascade();87 xilinx_i8259_setup_cascade();
295}88}
drivers/irqchip/Kconfig+4−0
@@ -211,6 +211,10 @@ config XTENSA_MX · 210 unmodified lines
211 bool211 bool
212 select IRQ_DOMAIN212 select IRQ_DOMAIN
213 213
214config XILINX_INTC
215 bool
216 select IRQ_DOMAIN
217
214config IRQ_CROSSBAR218config IRQ_CROSSBAR
215 bool219 bool
216 help220 help
drivers/irqchip/Makefile+1−0
@@ -52,6 +52,7 @@ obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o · 51 unmodified lines
52obj-$(CONFIG_TS4800_IRQ) += irq-ts4800.o52obj-$(CONFIG_TS4800_IRQ) += irq-ts4800.o
53obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o53obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o
54obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o54obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o
55obj-$(CONFIG_XILINX_INTC) += irq-xilinx-intc.o
55obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o56obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o
56obj-$(CONFIG_SOC_VF610) += irq-vf610-mscm-ir.o57obj-$(CONFIG_SOC_VF610) += irq-vf610-mscm-ir.o
57obj-$(CONFIG_BCM6345_L1_IRQ) += irq-bcm6345-l1.o58obj-$(CONFIG_BCM6345_L1_IRQ) += irq-bcm6345-l1.o
drivers/irqchip/irq-bcm7038-l1.c+26−0
@@ -215,6 +215,31 @@ static int bcm7038_l1_set_affinity(struct irq_data *d, · 214 unmodified lines
215 return 0;215 return 0;
216}216}
217 217
218static void bcm7038_l1_cpu_offline(struct irq_data *d)
219{
220 struct cpumask *mask = irq_data_get_affinity_mask(d);
221 int cpu = smp_processor_id();
222 cpumask_t new_affinity;
223
224 /* This CPU was not on the affinity mask */
225 if (!cpumask_test_cpu(cpu, mask))
226 return;
227
228 if (cpumask_weight(mask) > 1) {
229 /*
230 * Multiple CPU affinity, remove this CPU from the affinity
231 * mask
232 */
233 cpumask_copy(&new_affinity, mask);
234 cpumask_clear_cpu(cpu, &new_affinity);
235 } else {
236 /* Only CPU, put on the lowest online CPU */
237 cpumask_clear(&new_affinity);
238 cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity);
239 }
240 irq_set_affinity_locked(d, &new_affinity, false);
241}
242
218static int __init bcm7038_l1_init_one(struct device_node *dn,243static int __init bcm7038_l1_init_one(struct device_node *dn,
219 unsigned int idx,244 unsigned int idx,
220 struct bcm7038_l1_chip *intc)245 struct bcm7038_l1_chip *intc)
@@ -266,6 +291,7 @@ static struct irq_chip bcm7038_l1_irq_chip = { · 45 unmodified lines
266 .irq_mask = bcm7038_l1_mask,291 .irq_mask = bcm7038_l1_mask,
267 .irq_unmask = bcm7038_l1_unmask,292 .irq_unmask = bcm7038_l1_unmask,
268 .irq_set_affinity = bcm7038_l1_set_affinity,293 .irq_set_affinity = bcm7038_l1_set_affinity,
294 .irq_cpu_offline = bcm7038_l1_cpu_offline,
269};295};
270 296
271static int bcm7038_l1_map(struct irq_domain *d, unsigned int virq,297static int bcm7038_l1_map(struct irq_domain *d, unsigned int virq,
drivers/irqchip/irq-gic-v3-its.c+37−38
@@ -37,7 +37,6 @@ · 36 unmodified lines
37#include <linux/irqchip.h>37#include <linux/irqchip.h>
38#include <linux/irqchip/arm-gic-v3.h>38#include <linux/irqchip/arm-gic-v3.h>
39 39
40#include <asm/cacheflush.h>
41#include <asm/cputype.h>40#include <asm/cputype.h>
42#include <asm/exception.h>41#include <asm/exception.h>
43 42
@@ -196,7 +195,7 @@ typedef struct its_collection *(*its_cmd_builder_t)(struct its_cmd_block *, · 152 unmodified lines
196 195
197static void its_encode_cmd(struct its_cmd_block *cmd, u8 cmd_nr)196static void its_encode_cmd(struct its_cmd_block *cmd, u8 cmd_nr)
198{197{
199 cmd->raw_cmd[0] &= ~0xffUL;198 cmd->raw_cmd[0] &= ~0xffULL;
200 cmd->raw_cmd[0] |= cmd_nr;199 cmd->raw_cmd[0] |= cmd_nr;
201}200}
202 201
@@ -208,43 +207,43 @@ static void its_encode_devid(struct its_cmd_block *cmd, u32 devid) · 5 unmodified lines
208 207
209static void its_encode_event_id(struct its_cmd_block *cmd, u32 id)208static void its_encode_event_id(struct its_cmd_block *cmd, u32 id)
210{209{
211 cmd->raw_cmd[1] &= ~0xffffffffUL;210 cmd->raw_cmd[1] &= ~0xffffffffULL;
212 cmd->raw_cmd[1] |= id;211 cmd->raw_cmd[1] |= id;
213}212}
214 213
215static void its_encode_phys_id(struct its_cmd_block *cmd, u32 phys_id)214static void its_encode_phys_id(struct its_cmd_block *cmd, u32 phys_id)
216{215{
217 cmd->raw_cmd[1] &= 0xffffffffUL;216 cmd->raw_cmd[1] &= 0xffffffffULL;
218 cmd->raw_cmd[1] |= ((u64)phys_id) << 32;217 cmd->raw_cmd[1] |= ((u64)phys_id) << 32;
219}218}
220 219
221static void its_encode_size(struct its_cmd_block *cmd, u8 size)220static void its_encode_size(struct its_cmd_block *cmd, u8 size)
222{221{
223 cmd->raw_cmd[1] &= ~0x1fUL;222 cmd->raw_cmd[1] &= ~0x1fULL;
224 cmd->raw_cmd[1] |= size & 0x1f;223 cmd->raw_cmd[1] |= size & 0x1f;
225}224}
226 225
227static void its_encode_itt(struct its_cmd_block *cmd, u64 itt_addr)226static void its_encode_itt(struct its_cmd_block *cmd, u64 itt_addr)
228{227{
229 cmd->raw_cmd[2] &= ~0xffffffffffffUL;228 cmd->raw_cmd[2] &= ~0xffffffffffffULL;
230 cmd->raw_cmd[2] |= itt_addr & 0xffffffffff00UL;229 cmd->raw_cmd[2] |= itt_addr & 0xffffffffff00ULL;
231}230}
232 231
233static void its_encode_valid(struct its_cmd_block *cmd, int valid)232static void its_encode_valid(struct its_cmd_block *cmd, int valid)
234{233{
235 cmd->raw_cmd[2] &= ~(1UL << 63);234 cmd->raw_cmd[2] &= ~(1ULL << 63);
236 cmd->raw_cmd[2] |= ((u64)!!valid) << 63;235 cmd->raw_cmd[2] |= ((u64)!!valid) << 63;
237}236}
238 237
239static void its_encode_target(struct its_cmd_block *cmd, u64 target_addr)238static void its_encode_target(struct its_cmd_block *cmd, u64 target_addr)
240{239{
241 cmd->raw_cmd[2] &= ~(0xffffffffUL << 16);240 cmd->raw_cmd[2] &= ~(0xffffffffULL << 16);
242 cmd->raw_cmd[2] |= (target_addr & (0xffffffffUL << 16));241 cmd->raw_cmd[2] |= (target_addr & (0xffffffffULL << 16));
243}242}
244 243
245static void its_encode_collection(struct its_cmd_block *cmd, u16 col)244static void its_encode_collection(struct its_cmd_block *cmd, u16 col)
246{245{
247 cmd->raw_cmd[2] &= ~0xffffUL;246 cmd->raw_cmd[2] &= ~0xffffULL;
248 cmd->raw_cmd[2] |= col;247 cmd->raw_cmd[2] |= col;
249}248}
250 249
@@ -433,7 +432,7 @@ static void its_flush_cmd(struct its_node *its, struct its_cmd_block *cmd) · 182 unmodified lines
433 * the ITS.432 * the ITS.
434 */433 */
435 if (its->flags & ITS_FLAGS_CMDQ_NEEDS_FLUSHING)434 if (its->flags & ITS_FLAGS_CMDQ_NEEDS_FLUSHING)
436 __flush_dcache_area(cmd, sizeof(*cmd));435 gic_flush_dcache_to_poc(cmd, sizeof(*cmd));
437 else436 else
438 dsb(ishst);437 dsb(ishst);
439}438}
@@ -602,7 +601,7 @@ static void lpi_set_config(struct irq_data *d, bool enable) · 162 unmodified lines
602 * Humpf...601 * Humpf...
603 */602 */
604 if (gic_rdists->flags & RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING)603 if (gic_rdists->flags & RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING)
605 __flush_dcache_area(cfg, sizeof(*cfg));604 gic_flush_dcache_to_poc(cfg, sizeof(*cfg));
606 else605 else
607 dsb(ishst);606 dsb(ishst);
608 its_send_inv(its_dev, id);607 its_send_inv(its_dev, id);
@@ -657,8 +656,8 @@ static void its_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg) · 48 unmodified lines
657 its = its_dev->its;656 its = its_dev->its;
658 addr = its->phys_base + GITS_TRANSLATER;657 addr = its->phys_base + GITS_TRANSLATER;
659 658
660 msg->address_lo = addr & ((1UL << 32) - 1);659 msg->address_lo = lower_32_bits(addr);
661 msg->address_hi = addr >> 32;660 msg->address_hi = upper_32_bits(addr);
662 msg->data = its_get_event_id(d);661 msg->data = its_get_event_id(d);
663 662
664 iommu_dma_map_msi_msg(d->irq, msg);663 iommu_dma_map_msi_msg(d->irq, msg);
@@ -817,7 +816,7 @@ static int __init its_alloc_lpi_tables(void) · 152 unmodified lines
817 LPI_PROPBASE_SZ);816 LPI_PROPBASE_SZ);
818 817
819 /* Make sure the GIC will observe the written configuration */818 /* Make sure the GIC will observe the written configuration */
820 __flush_dcache_area(page_address(gic_rdists->prop_page), LPI_PROPBASE_SZ);819 gic_flush_dcache_to_poc(page_address(gic_rdists->prop_page), LPI_PROPBASE_SZ);
821 820
822 return 0;821 return 0;
823}822}
@@ -836,7 +835,7 @@ static u64 its_read_baser(struct its_node *its, struct its_baser *baser) · 12 unmodified lines
836{835{
837 u32 idx = baser - its->tables;836 u32 idx = baser - its->tables;
838 837
839 return readq_relaxed(its->base + GITS_BASER + (idx << 3));838 return gits_read_baser(its->base + GITS_BASER + (idx << 3));
840}839}
841 840
842static void its_write_baser(struct its_node *its, struct its_baser *baser,841static void its_write_baser(struct its_node *its, struct its_baser *baser,
@@ -844,7 +843,7 @@ static void its_write_baser(struct its_node *its, struct its_baser *baser, · 1 unmodified line
844{843{
845 u32 idx = baser - its->tables;844 u32 idx = baser - its->tables;
846 845
847 writeq_relaxed(val, its->base + GITS_BASER + (idx << 3));846 gits_write_baser(val, its->base + GITS_BASER + (idx << 3));
848 baser->val = its_read_baser(its, baser);847 baser->val = its_read_baser(its, baser);
849}848}
850 849
@@ -910,7 +909,7 @@ retry_baser: · 59 unmodified lines
910 shr = tmp & GITS_BASER_SHAREABILITY_MASK;909 shr = tmp & GITS_BASER_SHAREABILITY_MASK;
911 if (!shr) {910 if (!shr) {
912 cache = GITS_BASER_nC;911 cache = GITS_BASER_nC;
913 __flush_dcache_area(base, PAGE_ORDER_TO_SIZE(order));912 gic_flush_dcache_to_poc(base, PAGE_ORDER_TO_SIZE(order));
914 }913 }
915 goto retry_baser;914 goto retry_baser;
916 }915 }
@@ -935,9 +934,9 @@ retry_baser: · 18 unmodified lines
935 }934 }
936 935
937 if (val != tmp) {936 if (val != tmp) {
938 pr_err("ITS@%pa: %s doesn't stick: %lx %lx\n",937 pr_err("ITS@%pa: %s doesn't stick: %llx %llx\n",
939 &its->phys_base, its_base_type_string[type],938 &its->phys_base, its_base_type_string[type],
940 (unsigned long) val, (unsigned long) tmp);939 val, tmp);
941 free_pages((unsigned long)base, order);940 free_pages((unsigned long)base, order);
942 return -ENXIO;941 return -ENXIO;
943 }942 }
@@ -948,7 +947,7 @@ retry_baser: · 4 unmodified lines
948 tmp = indirect ? GITS_LVL1_ENTRY_SIZE : esz;947 tmp = indirect ? GITS_LVL1_ENTRY_SIZE : esz;
949 948
950 pr_info("ITS@%pa: allocated %d %s @%lx (%s, esz %d, psz %dK, shr %d)\n",949 pr_info("ITS@%pa: allocated %d %s @%lx (%s, esz %d, psz %dK, shr %d)\n",
951 &its->phys_base, (int)(PAGE_ORDER_TO_SIZE(order) / tmp),950 &its->phys_base, (int)(PAGE_ORDER_TO_SIZE(order) / (int)tmp),
952 its_base_type_string[type],951 its_base_type_string[type],
953 (unsigned long)virt_to_phys(base),952 (unsigned long)virt_to_phys(base),
954 indirect ? "indirect" : "flat", (int)esz,953 indirect ? "indirect" : "flat", (int)esz,
@@ -983,7 +982,7 @@ static bool its_parse_baser_device(struct its_node *its, struct its_baser *baser · 28 unmodified lines
983 * which is reported by ITS hardware times lvl1 table982 * which is reported by ITS hardware times lvl1 table
984 * entry size.983 * entry size.
985 */984 */
986 ids -= ilog2(psz / esz);985 ids -= ilog2(psz / (int)esz);
987 esz = GITS_LVL1_ENTRY_SIZE;986 esz = GITS_LVL1_ENTRY_SIZE;
988 }987 }
989 }988 }
@@ -998,7 +997,7 @@ static bool its_parse_baser_device(struct its_node *its, struct its_baser *baser · 8 unmodified lines
998 new_order = max_t(u32, get_order(esz << ids), new_order);997 new_order = max_t(u32, get_order(esz << ids), new_order);
999 if (new_order >= MAX_ORDER) {998 if (new_order >= MAX_ORDER) {
1000 new_order = MAX_ORDER - 1;999 new_order = MAX_ORDER - 1;
1001 ids = ilog2(PAGE_ORDER_TO_SIZE(new_order) / esz);1000 ids = ilog2(PAGE_ORDER_TO_SIZE(new_order) / (int)esz);
1002 pr_warn("ITS@%pa: Device Table too large, reduce ids %u->%u\n",1001 pr_warn("ITS@%pa: Device Table too large, reduce ids %u->%u\n",
1003 &its->phys_base, its->device_ids, ids);1002 &its->phys_base, its->device_ids, ids);
1004 }1003 }
@@ -1102,7 +1101,7 @@ static void its_cpu_init_lpis(void) · 97 unmodified lines
1102 }1101 }
1103 1102
1104 /* Make sure the GIC will observe the zero-ed page */1103 /* Make sure the GIC will observe the zero-ed page */
1105 __flush_dcache_area(page_address(pend_page), LPI_PENDBASE_SZ);1104 gic_flush_dcache_to_poc(page_address(pend_page), LPI_PENDBASE_SZ);
1106 1105
1107 paddr = page_to_phys(pend_page);1106 paddr = page_to_phys(pend_page);
1108 pr_info("CPU%d: using LPI pending table @%pa\n",1107 pr_info("CPU%d: using LPI pending table @%pa\n",
@@ -1126,8 +1125,8 @@ static void its_cpu_init_lpis(void) · 17 unmodified lines
1126 GICR_PROPBASER_WaWb |1125 GICR_PROPBASER_WaWb |
1127 ((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK));1126 ((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK));
1128 1127
1129 writeq_relaxed(val, rbase + GICR_PROPBASER);1128 gicr_write_propbaser(val, rbase + GICR_PROPBASER);
1130 tmp = readq_relaxed(rbase + GICR_PROPBASER);1129 tmp = gicr_read_propbaser(rbase + GICR_PROPBASER);
1131 1130
1132 if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) {1131 if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) {
1133 if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) {1132 if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) {
@@ -1139,7 +1138,7 @@ static void its_cpu_init_lpis(void) · 5 unmodified lines
1139 val &= ~(GICR_PROPBASER_SHAREABILITY_MASK |1138 val &= ~(GICR_PROPBASER_SHAREABILITY_MASK |
1140 GICR_PROPBASER_CACHEABILITY_MASK);1139 GICR_PROPBASER_CACHEABILITY_MASK);
1141 val |= GICR_PROPBASER_nC;1140 val |= GICR_PROPBASER_nC;
1142 writeq_relaxed(val, rbase + GICR_PROPBASER);1141 gicr_write_propbaser(val, rbase + GICR_PROPBASER);
1143 }1142 }
1144 pr_info_once("GIC: using cache flushing for LPI property table\n");1143 pr_info_once("GIC: using cache flushing for LPI property table\n");
1145 gic_rdists->flags |= RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING;1144 gic_rdists->flags |= RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING;
@@ -1150,8 +1149,8 @@ static void its_cpu_init_lpis(void) · 4 unmodified lines
1150 GICR_PENDBASER_InnerShareable |1149 GICR_PENDBASER_InnerShareable |
1151 GICR_PENDBASER_WaWb);1150 GICR_PENDBASER_WaWb);
1152 1151
1153 writeq_relaxed(val, rbase + GICR_PENDBASER);1152 gicr_write_pendbaser(val, rbase + GICR_PENDBASER);
1154 tmp = readq_relaxed(rbase + GICR_PENDBASER);1153 tmp = gicr_read_pendbaser(rbase + GICR_PENDBASER);
1155 1154
1156 if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) {1155 if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) {
1157 /*1156 /*
@@ -1161,7 +1160,7 @@ static void its_cpu_init_lpis(void) · 3 unmodified lines
1161 val &= ~(GICR_PENDBASER_SHAREABILITY_MASK |1160 val &= ~(GICR_PENDBASER_SHAREABILITY_MASK |
1162 GICR_PENDBASER_CACHEABILITY_MASK);1161 GICR_PENDBASER_CACHEABILITY_MASK);
1163 val |= GICR_PENDBASER_nC;1162 val |= GICR_PENDBASER_nC;
1164 writeq_relaxed(val, rbase + GICR_PENDBASER);1163 gicr_write_pendbaser(val, rbase + GICR_PENDBASER);
1165 }1164 }
1166 1165
1167 /* Enable LPIs */1166 /* Enable LPIs */
@@ -1287,13 +1286,13 @@ static bool its_alloc_device_table(struct its_node *its, u32 dev_id) · 119 unmodified lines
1287 1286
1288 /* Flush Lvl2 table to PoC if hw doesn't support coherency */1287 /* Flush Lvl2 table to PoC if hw doesn't support coherency */
1289 if (!(baser->val & GITS_BASER_SHAREABILITY_MASK))1288 if (!(baser->val & GITS_BASER_SHAREABILITY_MASK))
1290 __flush_dcache_area(page_address(page), baser->psz);1289 gic_flush_dcache_to_poc(page_address(page), baser->psz);
1291 1290
1292 table[idx] = cpu_to_le64(page_to_phys(page) | GITS_BASER_VALID);1291 table[idx] = cpu_to_le64(page_to_phys(page) | GITS_BASER_VALID);
1293 1292
1294 /* Flush Lvl1 entry to PoC if hw doesn't support coherency */1293 /* Flush Lvl1 entry to PoC if hw doesn't support coherency */
1295 if (!(baser->val & GITS_BASER_SHAREABILITY_MASK))1294 if (!(baser->val & GITS_BASER_SHAREABILITY_MASK))
1296 __flush_dcache_area(table + idx, GITS_LVL1_ENTRY_SIZE);1295 gic_flush_dcache_to_poc(table + idx, GITS_LVL1_ENTRY_SIZE);
1297 1296
1298 /* Ensure updated table contents are visible to ITS hardware */1297 /* Ensure updated table contents are visible to ITS hardware */
1299 dsb(sy);1298 dsb(sy);
@@ -1340,7 +1339,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, · 40 unmodified lines
1340 return NULL;1339 return NULL;
1341 }1340 }
1342 1341
1343 __flush_dcache_area(itt, sz);1342 gic_flush_dcache_to_poc(itt, sz);
1344 1343
1345 dev->its = its;1344 dev->its = its;
1346 dev->itt = itt;1345 dev->itt = itt;
@@ -1717,8 +1716,8 @@ static int __init its_probe_one(struct resource *res, · 370 unmodified lines
1717 (ITS_CMD_QUEUE_SZ / SZ_4K - 1) |1716 (ITS_CMD_QUEUE_SZ / SZ_4K - 1) |
1718 GITS_CBASER_VALID);1717 GITS_CBASER_VALID);
1719 1718
1720 writeq_relaxed(baser, its->base + GITS_CBASER);1719 gits_write_cbaser(baser, its->base + GITS_CBASER);
1721 tmp = readq_relaxed(its->base + GITS_CBASER);1720 tmp = gits_read_cbaser(its->base + GITS_CBASER);
1722 1721
1723 if ((tmp ^ baser) & GITS_CBASER_SHAREABILITY_MASK) {1722 if ((tmp ^ baser) & GITS_CBASER_SHAREABILITY_MASK) {
1724 if (!(tmp & GITS_CBASER_SHAREABILITY_MASK)) {1723 if (!(tmp & GITS_CBASER_SHAREABILITY_MASK)) {
@@ -1730,13 +1729,13 @@ static int __init its_probe_one(struct resource *res, · 5 unmodified lines
1730 baser &= ~(GITS_CBASER_SHAREABILITY_MASK |1729 baser &= ~(GITS_CBASER_SHAREABILITY_MASK |
1731 GITS_CBASER_CACHEABILITY_MASK);1730 GITS_CBASER_CACHEABILITY_MASK);
1732 baser |= GITS_CBASER_nC;1731 baser |= GITS_CBASER_nC;
1733 writeq_relaxed(baser, its->base + GITS_CBASER);1732 gits_write_cbaser(baser, its->base + GITS_CBASER);
1734 }1733 }
1735 pr_info("ITS: using cache flushing for cmd queue\n");1734 pr_info("ITS: using cache flushing for cmd queue\n");
1736 its->flags |= ITS_FLAGS_CMDQ_NEEDS_FLUSHING;1735 its->flags |= ITS_FLAGS_CMDQ_NEEDS_FLUSHING;
1737 }1736 }
1738 1737
1739 writeq_relaxed(0, its->base + GITS_CWRITER);1738 gits_write_cwriter(0, its->base + GITS_CWRITER);
1740 writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR);1739 writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR);
1741 1740
1742 err = its_init_domain(handle, its);1741 err = its_init_domain(handle, its);
drivers/irqchip/irq-xilinx-intc.c+241−0
@@ -0,0 +1,241 @@
1/*
2 * Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu>
3 * Copyright (C) 2012-2013 Xilinx, Inc.
4 * Copyright (C) 2007-2009 PetaLogix
5 * Copyright (C) 2006 Atmark Techno, Inc.
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 */
11
12#include <linux/irqdomain.h>
13#include <linux/irq.h>
14#include <linux/irqchip.h>
15#include <linux/irqchip/chained_irq.h>
16#include <linux/of_address.h>
17#include <linux/io.h>
18#include <linux/jump_label.h>
19#include <linux/bug.h>
20#include <linux/of_irq.h>
21
22/* No one else should require these constants, so define them locally here. */
23#define ISR 0x00 /* Interrupt Status Register */
24#define IPR 0x04 /* Interrupt Pending Register */
25#define IER 0x08 /* Interrupt Enable Register */
26#define IAR 0x0c /* Interrupt Acknowledge Register */
27#define SIE 0x10 /* Set Interrupt Enable bits */
28#define CIE 0x14 /* Clear Interrupt Enable bits */
29#define IVR 0x18 /* Interrupt Vector Register */
30#define MER 0x1c /* Master Enable Register */
31
32#define MER_ME (1<<0)
33#define MER_HIE (1<<1)
34
35static DEFINE_STATIC_KEY_FALSE(xintc_is_be);
36
37struct xintc_irq_chip {
38 void __iomem *base;
39 struct irq_domain *root_domain;
40 u32 intr_mask;
41};
42
43static struct xintc_irq_chip *xintc_irqc;
44
45static void xintc_write(int reg, u32 data)
46{
47 if (static_branch_unlikely(&xintc_is_be))
48 iowrite32be(data, xintc_irqc->base + reg);
49 else
50 iowrite32(data, xintc_irqc->base + reg);
51}
52
53static unsigned int xintc_read(int reg)
54{
55 if (static_branch_unlikely(&xintc_is_be))
56 return ioread32be(xintc_irqc->base + reg);
57 else
58 return ioread32(xintc_irqc->base + reg);
59}
60
61static void intc_enable_or_unmask(struct irq_data *d)
62{
63 unsigned long mask = 1 << d->hwirq;
64
65 pr_debug("irq-xilinx: enable_or_unmask: %ld\n", d->hwirq);
66
67 /* ack level irqs because they can't be acked during
68 * ack function since the handle_level_irq function
69 * acks the irq before calling the interrupt handler
70 */
71 if (irqd_is_level_type(d))
72 xintc_write(IAR, mask);
73
74 xintc_write(SIE, mask);
75}
76
77static void intc_disable_or_mask(struct irq_data *d)
78{
79 pr_debug("irq-xilinx: disable: %ld\n", d->hwirq);
80 xintc_write(CIE, 1 << d->hwirq);
81}
82
83static void intc_ack(struct irq_data *d)
84{
85 pr_debug("irq-xilinx: ack: %ld\n", d->hwirq);
86 xintc_write(IAR, 1 << d->hwirq);
87}
88
89static void intc_mask_ack(struct irq_data *d)
90{
91 unsigned long mask = 1 << d->hwirq;
92
93 pr_debug("irq-xilinx: disable_and_ack: %ld\n", d->hwirq);
94 xintc_write(CIE, mask);
95 xintc_write(IAR, mask);
96}
97
98static struct irq_chip intc_dev = {
99 .name = "Xilinx INTC",
100 .irq_unmask = intc_enable_or_unmask,
101 .irq_mask = intc_disable_or_mask,
102 .irq_ack = intc_ack,
103 .irq_mask_ack = intc_mask_ack,
104};
105
106unsigned int xintc_get_irq(void)
107{
108 unsigned int hwirq, irq = -1;
109
110 hwirq = xintc_read(IVR);
111 if (hwirq != -1U)
112 irq = irq_find_mapping(xintc_irqc->root_domain, hwirq);
113
114 pr_debug("irq-xilinx: hwirq=%d, irq=%d\n", hwirq, irq);
115
116 return irq;
117}
118
119static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
120{
121 if (xintc_irqc->intr_mask & (1 << hw)) {
122 irq_set_chip_and_handler_name(irq, &intc_dev,
123 handle_edge_irq, "edge");
124 irq_clear_status_flags(irq, IRQ_LEVEL);
125 } else {
126 irq_set_chip_and_handler_name(irq, &intc_dev,
127 handle_level_irq, "level");
128 irq_set_status_flags(irq, IRQ_LEVEL);
129 }
130 return 0;
131}
132
133static const struct irq_domain_ops xintc_irq_domain_ops = {
134 .xlate = irq_domain_xlate_onetwocell,
135 .map = xintc_map,
136};
137
138static void xil_intc_irq_handler(struct irq_desc *desc)
139{
140 struct irq_chip *chip = irq_desc_get_chip(desc);
141 u32 pending;
142
143 chained_irq_enter(chip, desc);
144 do {
145 pending = xintc_get_irq();
146 if (pending == -1U)
147 break;
148 generic_handle_irq(pending);
149 } while (true);
150 chained_irq_exit(chip, desc);
151}
152
153static int __init xilinx_intc_of_init(struct device_node *intc,
154 struct device_node *parent)
155{
156 u32 nr_irq;
157 int ret, irq;
158 struct xintc_irq_chip *irqc;
159
160 if (xintc_irqc) {
161 pr_err("irq-xilinx: Multiple instances aren't supported\n");
162 return -EINVAL;
163 }
164
165 irqc = kzalloc(sizeof(*irqc), GFP_KERNEL);
166 if (!irqc)
167 return -ENOMEM;
168
169 xintc_irqc = irqc;
170
171 irqc->base = of_iomap(intc, 0);
172 BUG_ON(!irqc->base);
173
174 ret = of_property_read_u32(intc, "xlnx,num-intr-inputs", &nr_irq);
175 if (ret < 0) {
176 pr_err("irq-xilinx: unable to read xlnx,num-intr-inputs\n");
177 goto err_alloc;
178 }
179
180 ret = of_property_read_u32(intc, "xlnx,kind-of-intr", &irqc->intr_mask);
181 if (ret < 0) {
182 pr_warn("irq-xilinx: unable to read xlnx,kind-of-intr\n");
183 irqc->intr_mask = 0;
184 }
185
186 if (irqc->intr_mask >> nr_irq)
187 pr_warn("irq-xilinx: mismatch in kind-of-intr param\n");
188
189 pr_info("irq-xilinx: %s: num_irq=%d, edge=0x%x\n",
190 intc->full_name, nr_irq, irqc->intr_mask);
191
192
193 /*
194 * Disable all external interrupts until they are
195 * explicity requested.
196 */
197 xintc_write(IER, 0);
198
199 /* Acknowledge any pending interrupts just in case. */
200 xintc_write(IAR, 0xffffffff);
201
202 /* Turn on the Master Enable. */
203 xintc_write(MER, MER_HIE | MER_ME);
204 if (!(xintc_read(MER) & (MER_HIE | MER_ME))) {
205 static_branch_enable(&xintc_is_be);
206 xintc_write(MER, MER_HIE | MER_ME);
207 }
208
209 irqc->root_domain = irq_domain_add_linear(intc, nr_irq,
210 &xintc_irq_domain_ops, irqc);
211 if (!irqc->root_domain) {
212 pr_err("irq-xilinx: Unable to create IRQ domain\n");
213 goto err_alloc;
214 }
215
216 if (parent) {
217 irq = irq_of_parse_and_map(intc, 0);
218 if (irq) {
219 irq_set_chained_handler_and_data(irq,
220 xil_intc_irq_handler,
221 irqc);
222 } else {
223 pr_err("irq-xilinx: interrupts property not in DT\n");
224 ret = -EINVAL;
225 goto err_alloc;
226 }
227 } else {
228 irq_set_default_host(irqc->root_domain);
229 }
230
231 return 0;
232
233err_alloc:
234 xintc_irqc = NULL;
235 kfree(irqc);
236 return ret;
237
238}
239
240IRQCHIP_DECLARE(xilinx_intc_xps, "xlnx,xps-intc-1.00.a", xilinx_intc_of_init);
241IRQCHIP_DECLARE(xilinx_intc_opb, "xlnx,opb-intc-1.00.c", xilinx_intc_of_init);
drivers/pci/msi.c+43−35
@@ -551,14 +551,14 @@ error_attrs: · 550 unmodified lines
551}551}
552 552
553static struct msi_desc *553static struct msi_desc *
554msi_setup_entry(struct pci_dev *dev, int nvec, bool affinity)554msi_setup_entry(struct pci_dev *dev, int nvec, const struct irq_affinity *affd)
555{555{
556 struct cpumask *masks = NULL;556 struct cpumask *masks = NULL;
557 struct msi_desc *entry;557 struct msi_desc *entry;
558 u16 control;558 u16 control;
559 559
560 if (affinity) {560 if (affd) {
561 masks = irq_create_affinity_masks(dev->irq_affinity, nvec);561 masks = irq_create_affinity_masks(nvec, affd);
562 if (!masks)562 if (!masks)
563 pr_err("Unable to allocate affinity masks, ignoring\n");563 pr_err("Unable to allocate affinity masks, ignoring\n");
564 }564 }
@@ -618,7 +618,8 @@ static int msi_verify_entries(struct pci_dev *dev) · 53 unmodified lines
618 * an error, and a positive return value indicates the number of interrupts618 * an error, and a positive return value indicates the number of interrupts
619 * which could have been allocated.619 * which could have been allocated.
620 */620 */
621static int msi_capability_init(struct pci_dev *dev, int nvec, bool affinity)621static int msi_capability_init(struct pci_dev *dev, int nvec,
622 const struct irq_affinity *affd)
622{623{
623 struct msi_desc *entry;624 struct msi_desc *entry;
624 int ret;625 int ret;
@@ -626,7 +627,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec, bool affinity) · 1 unmodified line
626 627
627 pci_msi_set_enable(dev, 0); /* Disable MSI during set up */628 pci_msi_set_enable(dev, 0); /* Disable MSI during set up */
628 629
629 entry = msi_setup_entry(dev, nvec, affinity);630 entry = msi_setup_entry(dev, nvec, affd);
630 if (!entry)631 if (!entry)
631 return -ENOMEM;632 return -ENOMEM;
632 633
@@ -690,14 +691,14 @@ static void __iomem *msix_map_region(struct pci_dev *dev, unsigned nr_entries) · 57 unmodified lines
690 691
691static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,692static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
692 struct msix_entry *entries, int nvec,693 struct msix_entry *entries, int nvec,
693 bool affinity)694 const struct irq_affinity *affd)
694{695{
695 struct cpumask *curmsk, *masks = NULL;696 struct cpumask *curmsk, *masks = NULL;
696 struct msi_desc *entry;697 struct msi_desc *entry;
697 int ret, i;698 int ret, i;
698 699
699 if (affinity) {700 if (affd) {
700 masks = irq_create_affinity_masks(dev->irq_affinity, nvec);701 masks = irq_create_affinity_masks(nvec, affd);
701 if (!masks)702 if (!masks)
702 pr_err("Unable to allocate affinity masks, ignoring\n");703 pr_err("Unable to allocate affinity masks, ignoring\n");
703 }704 }
@@ -753,14 +754,14 @@ static void msix_program_entries(struct pci_dev *dev, · 49 unmodified lines
753 * @dev: pointer to the pci_dev data structure of MSI-X device function754 * @dev: pointer to the pci_dev data structure of MSI-X device function
754 * @entries: pointer to an array of struct msix_entry entries755 * @entries: pointer to an array of struct msix_entry entries
755 * @nvec: number of @entries756 * @nvec: number of @entries
756 * @affinity: flag to indicate cpu irq affinity mask should be set757 * @affd: Optional pointer to enable automatic affinity assignement
757 *758 *
758 * Setup the MSI-X capability structure of device function with a759 * Setup the MSI-X capability structure of device function with a
759 * single MSI-X irq. A return of zero indicates the successful setup of760 * single MSI-X irq. A return of zero indicates the successful setup of
760 * requested MSI-X entries with allocated irqs or non-zero for otherwise.761 * requested MSI-X entries with allocated irqs or non-zero for otherwise.
761 **/762 **/
762static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,763static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
763 int nvec, bool affinity)764 int nvec, const struct irq_affinity *affd)
764{765{
765 int ret;766 int ret;
766 u16 control;767 u16 control;
@@ -775,7 +776,7 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, · 8 unmodified lines
775 if (!base)776 if (!base)
776 return -ENOMEM;777 return -ENOMEM;
777 778
778 ret = msix_setup_entries(dev, base, entries, nvec, affinity);779 ret = msix_setup_entries(dev, base, entries, nvec, affd);
779 if (ret)780 if (ret)
780 return ret;781 return ret;
781 782
@@ -956,7 +957,7 @@ int pci_msix_vec_count(struct pci_dev *dev) · 174 unmodified lines
956EXPORT_SYMBOL(pci_msix_vec_count);957EXPORT_SYMBOL(pci_msix_vec_count);
957 958
958static int __pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries,959static int __pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries,
959 int nvec, bool affinity)960 int nvec, const struct irq_affinity *affd)
960{961{
961 int nr_entries;962 int nr_entries;
962 int i, j;963 int i, j;
@@ -988,7 +989,7 @@ static int __pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, · 25 unmodified lines
988 dev_info(&dev->dev, "can't enable MSI-X (MSI IRQ already assigned)\n");989 dev_info(&dev->dev, "can't enable MSI-X (MSI IRQ already assigned)\n");
989 return -EINVAL;990 return -EINVAL;
990 }991 }
991 return msix_capability_init(dev, entries, nvec, affinity);992 return msix_capability_init(dev, entries, nvec, affd);
992}993}
993 994
994/**995/**
@@ -1008,7 +1009,7 @@ static int __pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, · 13 unmodified lines
1008 **/1009 **/
1009int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)1010int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)
1010{1011{
1011 return __pci_enable_msix(dev, entries, nvec, false);1012 return __pci_enable_msix(dev, entries, nvec, NULL);
1012}1013}
1013EXPORT_SYMBOL(pci_enable_msix);1014EXPORT_SYMBOL(pci_enable_msix);
1014 1015
@@ -1059,9 +1060,8 @@ int pci_msi_enabled(void) · 44 unmodified lines
1059EXPORT_SYMBOL(pci_msi_enabled);1060EXPORT_SYMBOL(pci_msi_enabled);
1060 1061
1061static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec,1062static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec,
1062 unsigned int flags)1063 const struct irq_affinity *affd)
1063{1064{
1064 bool affinity = flags & PCI_IRQ_AFFINITY;
1065 int nvec;1065 int nvec;
1066 int rc;1066 int rc;
1067 1067
@@ -1090,14 +1090,13 @@ static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, · 22 unmodified lines
1090 nvec = maxvec;1090 nvec = maxvec;
1091 1091
1092 for (;;) {1092 for (;;) {
1093 if (affinity) {1093 if (affd) {
1094 nvec = irq_calc_affinity_vectors(dev->irq_affinity,1094 nvec = irq_calc_affinity_vectors(nvec, affd);
1095 nvec);
1096 if (nvec < minvec)1095 if (nvec < minvec)
1097 return -ENOSPC;1096 return -ENOSPC;
1098 }1097 }
1099 1098
1100 rc = msi_capability_init(dev, nvec, affinity);1099 rc = msi_capability_init(dev, nvec, affd);
1101 if (rc == 0)1100 if (rc == 0)
1102 return nvec;1101 return nvec;
1103 1102
@@ -1124,29 +1123,27 @@ static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, · 20 unmodified lines
1124 **/1123 **/
1125int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec)1124int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec)
1126{1125{
1127 return __pci_enable_msi_range(dev, minvec, maxvec, 0);1126 return __pci_enable_msi_range(dev, minvec, maxvec, NULL);
1128}1127}
1129EXPORT_SYMBOL(pci_enable_msi_range);1128EXPORT_SYMBOL(pci_enable_msi_range);
1130 1129
1131static int __pci_enable_msix_range(struct pci_dev *dev,1130static int __pci_enable_msix_range(struct pci_dev *dev,
1132 struct msix_entry *entries, int minvec, int maxvec,1131 struct msix_entry *entries, int minvec,
1133 unsigned int flags)1132 int maxvec, const struct irq_affinity *affd)
1134{1133{
1135 bool affinity = flags & PCI_IRQ_AFFINITY;
1136 int rc, nvec = maxvec;1134 int rc, nvec = maxvec;
1137 1135
1138 if (maxvec < minvec)1136 if (maxvec < minvec)
1139 return -ERANGE;1137 return -ERANGE;
1140 1138
1141 for (;;) {1139 for (;;) {
1142 if (affinity) {1140 if (affd) {
1143 nvec = irq_calc_affinity_vectors(dev->irq_affinity,1141 nvec = irq_calc_affinity_vectors(nvec, affd);
1144 nvec);
1145 if (nvec < minvec)1142 if (nvec < minvec)
1146 return -ENOSPC;1143 return -ENOSPC;
1147 }1144 }
1148 1145
1149 rc = __pci_enable_msix(dev, entries, nvec, affinity);1146 rc = __pci_enable_msix(dev, entries, nvec, affd);
1150 if (rc == 0)1147 if (rc == 0)
1151 return nvec;1148 return nvec;
1152 1149
@@ -1177,16 +1174,17 @@ static int __pci_enable_msix_range(struct pci_dev *dev, · 24 unmodified lines
1177int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,1174int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,
1178 int minvec, int maxvec)1175 int minvec, int maxvec)
1179{1176{
1180 return __pci_enable_msix_range(dev, entries, minvec, maxvec, 0);1177 return __pci_enable_msix_range(dev, entries, minvec, maxvec, NULL);
1181}1178}
1182EXPORT_SYMBOL(pci_enable_msix_range);1179EXPORT_SYMBOL(pci_enable_msix_range);
1183 1180
1184/**1181/**
1185 * pci_alloc_irq_vectors - allocate multiple IRQs for a device1182 * pci_alloc_irq_vectors_affinity - allocate multiple IRQs for a device
1186 * @dev: PCI device to operate on1183 * @dev: PCI device to operate on
1187 * @min_vecs: minimum number of vectors required (must be >= 1)1184 * @min_vecs: minimum number of vectors required (must be >= 1)
1188 * @max_vecs: maximum (desired) number of vectors1185 * @max_vecs: maximum (desired) number of vectors
1189 * @flags: flags or quirks for the allocation1186 * @flags: flags or quirks for the allocation
1187 * @affd: optional description of the affinity requirements
1190 *1188 *
1191 * Allocate up to @max_vecs interrupt vectors for @dev, using MSI-X or MSI1189 * Allocate up to @max_vecs interrupt vectors for @dev, using MSI-X or MSI
1192 * vectors if available, and fall back to a single legacy vector1190 * vectors if available, and fall back to a single legacy vector
@@ -1198,20 +1196,30 @@ EXPORT_SYMBOL(pci_enable_msix_range); · 5 unmodified lines
1198 * To get the Linux IRQ number used for a vector that can be passed to1196 * To get the Linux IRQ number used for a vector that can be passed to
1199 * request_irq() use the pci_irq_vector() helper.1197 * request_irq() use the pci_irq_vector() helper.
1200 */1198 */
1201int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,1199int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
1202 unsigned int max_vecs, unsigned int flags)1200 unsigned int max_vecs, unsigned int flags,
1201 const struct irq_affinity *affd)
1203{1202{
1203 static const struct irq_affinity msi_default_affd;
1204 int vecs = -ENOSPC;1204 int vecs = -ENOSPC;
1205 1205
1206 if (flags & PCI_IRQ_AFFINITY) {
1207 if (!affd)
1208 affd = &msi_default_affd;
1209 } else {
1210 if (WARN_ON(affd))
1211 affd = NULL;
1212 }
1213
1206 if (flags & PCI_IRQ_MSIX) {1214 if (flags & PCI_IRQ_MSIX) {
1207 vecs = __pci_enable_msix_range(dev, NULL, min_vecs, max_vecs,1215 vecs = __pci_enable_msix_range(dev, NULL, min_vecs, max_vecs,
1208 flags);1216 affd);
1209 if (vecs > 0)1217 if (vecs > 0)
1210 return vecs;1218 return vecs;
1211 }1219 }
1212 1220
1213 if (flags & PCI_IRQ_MSI) {1221 if (flags & PCI_IRQ_MSI) {
1214 vecs = __pci_enable_msi_range(dev, min_vecs, max_vecs, flags);1222 vecs = __pci_enable_msi_range(dev, min_vecs, max_vecs, affd);
1215 if (vecs > 0)1223 if (vecs > 0)
1216 return vecs;1224 return vecs;
1217 }1225 }
@@ -1224,7 +1232,7 @@ int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, · 6 unmodified lines
1224 1232
1225 return vecs;1233 return vecs;
1226}1234}
1227EXPORT_SYMBOL(pci_alloc_irq_vectors);1235EXPORT_SYMBOL(pci_alloc_irq_vectors_affinity);
1228 1236
1229/**1237/**
1230 * pci_free_irq_vectors - free previously allocated IRQs for a device1238 * pci_free_irq_vectors - free previously allocated IRQs for a device
include/linux/interrupt.h+16−4
@@ -232,6 +232,18 @@ struct irq_affinity_notify { · 231 unmodified lines
232 void (*release)(struct kref *ref);232 void (*release)(struct kref *ref);
233};233};
234 234
235/**
236 * struct irq_affinity - Description for automatic irq affinity assignements
237 * @pre_vectors: Don't apply affinity to @pre_vectors at beginning of
238 * the MSI(-X) vector space
239 * @post_vectors: Don't apply affinity to @post_vectors at end of
240 * the MSI(-X) vector space
241 */
242struct irq_affinity {
243 int pre_vectors;
244 int post_vectors;
245};
246
235#if defined(CONFIG_SMP)247#if defined(CONFIG_SMP)
236 248
237extern cpumask_var_t irq_default_affinity;249extern cpumask_var_t irq_default_affinity;
@@ -278,8 +290,8 @@ extern int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m); · 40 unmodified lines
278extern int290extern int
279irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify);291irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify);
280 292
281struct cpumask *irq_create_affinity_masks(const struct cpumask *affinity, int nvec);293struct cpumask *irq_create_affinity_masks(int nvec, const struct irq_affinity *affd);
282int irq_calc_affinity_vectors(const struct cpumask *affinity, int maxvec);294int irq_calc_affinity_vectors(int maxvec, const struct irq_affinity *affd);
283 295
284#else /* CONFIG_SMP */296#else /* CONFIG_SMP */
285 297
@@ -313,13 +325,13 @@ irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify) · 27 unmodified lines
313}325}
314 326
315static inline struct cpumask *327static inline struct cpumask *
316irq_create_affinity_masks(const struct cpumask *affinity, int nvec)328irq_create_affinity_masks(int nvec, const struct irq_affinity *affd)
317{329{
318 return NULL;330 return NULL;
319}331}
320 332
321static inline int333static inline int
322irq_calc_affinity_vectors(const struct cpumask *affinity, int maxvec)334irq_calc_affinity_vectors(int maxvec, const struct irq_affinity *affd)
323{335{
324 return maxvec;336 return maxvec;
325}337}
include/linux/irqchip/arm-gic-v3.h+2−2
@@ -239,7 +239,7 @@ · 238 unmodified lines
239#define GITS_TYPER_PTA (1UL << 19)239#define GITS_TYPER_PTA (1UL << 19)
240#define GITS_TYPER_HWCOLLCNT_SHIFT 24240#define GITS_TYPER_HWCOLLCNT_SHIFT 24
241 241
242#define GITS_CBASER_VALID (1UL << 63)242#define GITS_CBASER_VALID (1ULL << 63)
243#define GITS_CBASER_SHAREABILITY_SHIFT (10)243#define GITS_CBASER_SHAREABILITY_SHIFT (10)
244#define GITS_CBASER_INNER_CACHEABILITY_SHIFT (59)244#define GITS_CBASER_INNER_CACHEABILITY_SHIFT (59)
245#define GITS_CBASER_OUTER_CACHEABILITY_SHIFT (53)245#define GITS_CBASER_OUTER_CACHEABILITY_SHIFT (53)
@@ -265,7 +265,7 @@ · 19 unmodified lines
265 265
266#define GITS_BASER_NR_REGS 8266#define GITS_BASER_NR_REGS 8
267 267
268#define GITS_BASER_VALID (1UL << 63)268#define GITS_BASER_VALID (1ULL << 63)
269#define GITS_BASER_INDIRECT (1ULL << 62)269#define GITS_BASER_INDIRECT (1ULL << 62)
270 270
271#define GITS_BASER_INNER_CACHEABILITY_SHIFT (59)271#define GITS_BASER_INNER_CACHEABILITY_SHIFT (59)
include/linux/pci.h+19−6
@@ -244,6 +244,7 @@ struct pci_cap_saved_state { · 243 unmodified lines
244 struct pci_cap_saved_data cap;244 struct pci_cap_saved_data cap;
245};245};
246 246
247struct irq_affinity;
247struct pcie_link_state;248struct pcie_link_state;
248struct pci_vpd;249struct pci_vpd;
249struct pci_sriov;250struct pci_sriov;
@@ -332,7 +333,6 @@ struct pci_dev { · 82 unmodified lines
332 * directly, use the values stored here. They might be different!333 * directly, use the values stored here. They might be different!
333 */334 */
334 unsigned int irq;335 unsigned int irq;
335 struct cpumask *irq_affinity;
336 struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */336 struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
337 337
338 bool match_driver; /* Skip attaching driver */338 bool match_driver; /* Skip attaching driver */
@@ -1310,8 +1310,10 @@ static inline int pci_enable_msix_exact(struct pci_dev *dev, · 971 unmodified lines
1310 return rc;1310 return rc;
1311 return 0;1311 return 0;
1312}1312}
1313int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,1313int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
1314 unsigned int max_vecs, unsigned int flags);1314 unsigned int max_vecs, unsigned int flags,
1315 const struct irq_affinity *affd);
1316
1315void pci_free_irq_vectors(struct pci_dev *dev);1317void pci_free_irq_vectors(struct pci_dev *dev);
1316int pci_irq_vector(struct pci_dev *dev, unsigned int nr);1318int pci_irq_vector(struct pci_dev *dev, unsigned int nr);
1317const struct cpumask *pci_irq_get_affinity(struct pci_dev *pdev, int vec);1319const struct cpumask *pci_irq_get_affinity(struct pci_dev *pdev, int vec);
@@ -1339,14 +1341,17 @@ static inline int pci_enable_msix_range(struct pci_dev *dev, · 21 unmodified lines
1339static inline int pci_enable_msix_exact(struct pci_dev *dev,1341static inline int pci_enable_msix_exact(struct pci_dev *dev,
1340 struct msix_entry *entries, int nvec)1342 struct msix_entry *entries, int nvec)
1341{ return -ENOSYS; }1343{ return -ENOSYS; }
1342static inline int pci_alloc_irq_vectors(struct pci_dev *dev,1344
1343 unsigned int min_vecs, unsigned int max_vecs,1345static inline int
1344 unsigned int flags)1346pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
1347 unsigned int max_vecs, unsigned int flags,
1348 const struct irq_affinity *aff_desc)
1345{1349{
1346 if (min_vecs > 1)1350 if (min_vecs > 1)
1347 return -EINVAL;1351 return -EINVAL;
1348 return 1;1352 return 1;
1349}1353}
1354
1350static inline void pci_free_irq_vectors(struct pci_dev *dev)1355static inline void pci_free_irq_vectors(struct pci_dev *dev)
1351{1356{
1352}1357}
@@ -1364,6 +1369,14 @@ static inline const struct cpumask *pci_irq_get_affinity(struct pci_dev *pdev, · 11 unmodified lines
1364}1369}
1365#endif1370#endif
1366 1371
1372static inline int
1373pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
1374 unsigned int max_vecs, unsigned int flags)
1375{
1376 return pci_alloc_irq_vectors_affinity(dev, min_vecs, max_vecs, flags,
1377 NULL);
1378}
1379
1367#ifdef CONFIG_PCIEPORTBUS1380#ifdef CONFIG_PCIEPORTBUS
1368extern bool pcie_ports_disabled;1381extern bool pcie_ports_disabled;
1369extern bool pcie_ports_auto;1382extern bool pcie_ports_auto;
kernel/irq/affinity.c+37−35
@@ -51,16 +51,17 @@ static int get_nodes_in_cpumask(const struct cpumask *mask, nodemask_t *nodemsk) · 50 unmodified lines
51 51
52/**52/**
53 * irq_create_affinity_masks - Create affinity masks for multiqueue spreading53 * irq_create_affinity_masks - Create affinity masks for multiqueue spreading
54 * @affinity: The affinity mask to spread. If NULL cpu_online_mask54 * @nvecs: The total number of vectors
55 * is used55 * @affd: Description of the affinity requirements
56 * @nvecs: The number of vectors
57 *56 *
58 * Returns the masks pointer or NULL if allocation failed.57 * Returns the masks pointer or NULL if allocation failed.
59 */58 */
60struct cpumask *irq_create_affinity_masks(const struct cpumask *affinity,59struct cpumask *
61 int nvec)60irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
62{61{
63 int n, nodes, vecs_per_node, cpus_per_vec, extra_vecs, curvec = 0;62 int n, nodes, vecs_per_node, cpus_per_vec, extra_vecs, curvec;
63 int affv = nvecs - affd->pre_vectors - affd->post_vectors;
64 int last_affv = affv + affd->pre_vectors;
64 nodemask_t nodemsk = NODE_MASK_NONE;65 nodemask_t nodemsk = NODE_MASK_NONE;
65 struct cpumask *masks;66 struct cpumask *masks;
66 cpumask_var_t nmsk;67 cpumask_var_t nmsk;
@@ -68,46 +69,47 @@ struct cpumask *irq_create_affinity_masks(const struct cpumask *affinity, · 1 unmodified line
68 if (!zalloc_cpumask_var(&nmsk, GFP_KERNEL))69 if (!zalloc_cpumask_var(&nmsk, GFP_KERNEL))
69 return NULL;70 return NULL;
70 71
71 masks = kzalloc(nvec * sizeof(*masks), GFP_KERNEL);72 masks = kcalloc(nvecs, sizeof(*masks), GFP_KERNEL);
72 if (!masks)73 if (!masks)
73 goto out;74 goto out;
74 75
76 /* Fill out vectors at the beginning that don't need affinity */
77 for (curvec = 0; curvec < affd->pre_vectors; curvec++)
78 cpumask_copy(masks + curvec, irq_default_affinity);
79
75 /* Stabilize the cpumasks */80 /* Stabilize the cpumasks */
76 get_online_cpus();81 get_online_cpus();
77 /* If the supplied affinity mask is NULL, use cpu online mask */82 nodes = get_nodes_in_cpumask(cpu_online_mask, &nodemsk);
78 if (!affinity)
79 affinity = cpu_online_mask;
80
81 nodes = get_nodes_in_cpumask(affinity, &nodemsk);
82 83
83 /*84 /*
84 * If the number of nodes in the mask is less than or equal the85 * If the number of nodes in the mask is less than or equal the
85 * number of vectors we just spread the vectors across the nodes.86 * number of vectors we just spread the vectors across the nodes.
86 */87 */
87 if (nvec <= nodes) {88 if (affv <= nodes) {
88 for_each_node_mask(n, nodemsk) {89 for_each_node_mask(n, nodemsk) {
89 cpumask_copy(masks + curvec, cpumask_of_node(n));90 cpumask_copy(masks + curvec, cpumask_of_node(n));
90 if (++curvec == nvec)91 if (++curvec == last_affv)
91 break;92 break;
92 }93 }
93 goto outonl;94 goto done;
94 }95 }
95 96
96 /* Spread the vectors per node */97 /* Spread the vectors per node */
97 vecs_per_node = nvec / nodes;98 vecs_per_node = affv / nodes;
98 /* Account for rounding errors */99 /* Account for rounding errors */
99 extra_vecs = nvec - (nodes * vecs_per_node);100 extra_vecs = affv - (nodes * vecs_per_node);
100 101
101 for_each_node_mask(n, nodemsk) {102 for_each_node_mask(n, nodemsk) {
102 int ncpus, v, vecs_to_assign = vecs_per_node;103 int ncpus, v, vecs_to_assign = vecs_per_node;
103 104
104 /* Get the cpus on this node which are in the mask */105 /* Get the cpus on this node which are in the mask */
105 cpumask_and(nmsk, affinity, cpumask_of_node(n));106 cpumask_and(nmsk, cpu_online_mask, cpumask_of_node(n));
106 107
107 /* Calculate the number of cpus per vector */108 /* Calculate the number of cpus per vector */
108 ncpus = cpumask_weight(nmsk);109 ncpus = cpumask_weight(nmsk);
109 110
110 for (v = 0; curvec < nvec && v < vecs_to_assign; curvec++, v++) {111 for (v = 0; curvec < last_affv && v < vecs_to_assign;
112 curvec++, v++) {
111 cpus_per_vec = ncpus / vecs_to_assign;113 cpus_per_vec = ncpus / vecs_to_assign;
112 114
113 /* Account for extra vectors to compensate rounding errors */115 /* Account for extra vectors to compensate rounding errors */
@@ -119,36 +121,36 @@ struct cpumask *irq_create_affinity_masks(const struct cpumask *affinity, · 5 unmodified lines
119 irq_spread_init_one(masks + curvec, nmsk, cpus_per_vec);121 irq_spread_init_one(masks + curvec, nmsk, cpus_per_vec);
120 }122 }
121 123
122 if (curvec >= nvec)124 if (curvec >= last_affv)
123 break;125 break;
124 }126 }
125 127
126outonl:128done:
127 put_online_cpus();129 put_online_cpus();
130
131 /* Fill out vectors at the end that don't need affinity */
132 for (; curvec < nvecs; curvec++)
133 cpumask_copy(masks + curvec, irq_default_affinity);
128out:134out:
129 free_cpumask_var(nmsk);135 free_cpumask_var(nmsk);
130 return masks;136 return masks;
131}137}
132 138
133/**139/**
134 * irq_calc_affinity_vectors - Calculate to optimal number of vectors for a given affinity mask140 * irq_calc_affinity_vectors - Calculate the optimal number of vectors
135 * @affinity: The affinity mask to spread. If NULL cpu_online_mask141 * @maxvec: The maximum number of vectors available
136 * is used142 * @affd: Description of the affinity requirements
137 * @maxvec: The maximum number of vectors available
138 */143 */
139int irq_calc_affinity_vectors(const struct cpumask *affinity, int maxvec)144int irq_calc_affinity_vectors(int maxvec, const struct irq_affinity *affd)
140{145{
141 int cpus, ret;146 int resv = affd->pre_vectors + affd->post_vectors;
147 int vecs = maxvec - resv;
148 int cpus;
142 149
143 /* Stabilize the cpumasks */150 /* Stabilize the cpumasks */
144 get_online_cpus();151 get_online_cpus();
145 /* If the supplied affinity mask is NULL, use cpu online mask */152 cpus = cpumask_weight(cpu_online_mask);
146 if (!affinity)
147 affinity = cpu_online_mask;
148
149 cpus = cpumask_weight(affinity);
150 ret = (cpus < maxvec) ? cpus : maxvec;
151
152 put_online_cpus();153 put_online_cpus();
153 return ret;154
155 return min(cpus, vecs) + resv;
154}156}
kernel/irq/msi.c+1−3
@@ -14,9 +14,7 @@ · 13 unmodified lines
14#include <linux/irq.h>14#include <linux/irq.h>
15#include <linux/irqdomain.h>15#include <linux/irqdomain.h>
16#include <linux/msi.h>16#include <linux/msi.h>
17 17#include <linux/slab.h>
18/* Temparory solution for building, will be removed later */
19#include <linux/pci.h>
20 18
21/**19/**
22 * alloc_msi_entry - Allocate an initialize msi_entry20 * alloc_msi_entry - Allocate an initialize msi_entry