diff options
author | Ganesan Ramalingam <ganesanr@broadcom.com> | 2014-05-09 07:05:49 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-05-30 10:51:02 -0400 |
commit | d66f3f0e10b49df8d0cc0d8eb5bf2ef9863a33cf (patch) | |
tree | 39f0d8fa0dacfd9f7ab7794bbdd330160af173c9 /arch/mips/pci | |
parent | 1c98398662c9b4e2f03f64344f83dd6cb14e0420 (diff) |
MIPS: Add MSI support for XLP9XX
In XLP9XX, the interrupt routing table for MSI-X has been moved to the
PCIe controller's config space from PIC. There are also 32 MSI-X
interrupts available per link on XLP9XX.
Update XLP MSI/MSI-X code to handle this.
Signed-off-by: Ganesan Ramalingam <ganesanr@broadcom.com>
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
Cc: g@linux-mips.org
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/6912/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/pci')
-rw-r--r-- | arch/mips/pci/msi-xlp.c | 184 |
1 files changed, 135 insertions, 49 deletions
diff --git a/arch/mips/pci/msi-xlp.c b/arch/mips/pci/msi-xlp.c index afd8405e0188..1ef3ed607f47 100644 --- a/arch/mips/pci/msi-xlp.c +++ b/arch/mips/pci/msi-xlp.c | |||
@@ -56,8 +56,8 @@ | |||
56 | #include <asm/netlogic/xlp-hal/bridge.h> | 56 | #include <asm/netlogic/xlp-hal/bridge.h> |
57 | 57 | ||
58 | #define XLP_MSIVEC_PER_LINK 32 | 58 | #define XLP_MSIVEC_PER_LINK 32 |
59 | #define XLP_MSIXVEC_TOTAL 32 | 59 | #define XLP_MSIXVEC_TOTAL (cpu_is_xlp9xx() ? 128 : 32) |
60 | #define XLP_MSIXVEC_PER_LINK 8 | 60 | #define XLP_MSIXVEC_PER_LINK (cpu_is_xlp9xx() ? 32 : 8) |
61 | 61 | ||
62 | /* 128 MSI irqs per node, mapped starting at NLM_MSI_VEC_BASE */ | 62 | /* 128 MSI irqs per node, mapped starting at NLM_MSI_VEC_BASE */ |
63 | static inline int nlm_link_msiirq(int link, int msivec) | 63 | static inline int nlm_link_msiirq(int link, int msivec) |
@@ -65,35 +65,44 @@ static inline int nlm_link_msiirq(int link, int msivec) | |||
65 | return NLM_MSI_VEC_BASE + link * XLP_MSIVEC_PER_LINK + msivec; | 65 | return NLM_MSI_VEC_BASE + link * XLP_MSIVEC_PER_LINK + msivec; |
66 | } | 66 | } |
67 | 67 | ||
68 | /* get the link MSI vector from irq number */ | ||
68 | static inline int nlm_irq_msivec(int irq) | 69 | static inline int nlm_irq_msivec(int irq) |
69 | { | 70 | { |
70 | return irq % XLP_MSIVEC_PER_LINK; | 71 | return (irq - NLM_MSI_VEC_BASE) % XLP_MSIVEC_PER_LINK; |
71 | } | 72 | } |
72 | 73 | ||
74 | /* get the link from the irq number */ | ||
73 | static inline int nlm_irq_msilink(int irq) | 75 | static inline int nlm_irq_msilink(int irq) |
74 | { | 76 | { |
75 | return (irq % (XLP_MSIVEC_PER_LINK * PCIE_NLINKS)) / | 77 | int total_msivec = XLP_MSIVEC_PER_LINK * PCIE_NLINKS; |
76 | XLP_MSIVEC_PER_LINK; | 78 | |
79 | return ((irq - NLM_MSI_VEC_BASE) % total_msivec) / | ||
80 | XLP_MSIVEC_PER_LINK; | ||
77 | } | 81 | } |
78 | 82 | ||
79 | /* | 83 | /* |
80 | * Only 32 MSI-X vectors are possible because there are only 32 PIC | 84 | * For XLP 8xx/4xx/3xx/2xx, only 32 MSI-X vectors are possible because |
81 | * interrupts for MSI. We split them statically and use 8 MSI-X vectors | 85 | * there are only 32 PIC interrupts for MSI. We split them statically |
82 | * per link - this keeps the allocation and lookup simple. | 86 | * and use 8 MSI-X vectors per link - this keeps the allocation and |
87 | * lookup simple. | ||
88 | * On XLP 9xx, there are 32 vectors per link, and the interrupts are | ||
89 | * not routed thru PIC, so we can use all 128 MSI-X vectors. | ||
83 | */ | 90 | */ |
84 | static inline int nlm_link_msixirq(int link, int bit) | 91 | static inline int nlm_link_msixirq(int link, int bit) |
85 | { | 92 | { |
86 | return NLM_MSIX_VEC_BASE + link * XLP_MSIXVEC_PER_LINK + bit; | 93 | return NLM_MSIX_VEC_BASE + link * XLP_MSIXVEC_PER_LINK + bit; |
87 | } | 94 | } |
88 | 95 | ||
96 | /* get the link MSI vector from irq number */ | ||
89 | static inline int nlm_irq_msixvec(int irq) | 97 | static inline int nlm_irq_msixvec(int irq) |
90 | { | 98 | { |
91 | return irq % XLP_MSIXVEC_TOTAL; /* works when given xirq */ | 99 | return (irq - NLM_MSIX_VEC_BASE) % XLP_MSIXVEC_TOTAL; |
92 | } | 100 | } |
93 | 101 | ||
94 | static inline int nlm_irq_msixlink(int irq) | 102 | /* get the link from MSIX vec */ |
103 | static inline int nlm_irq_msixlink(int msixvec) | ||
95 | { | 104 | { |
96 | return nlm_irq_msixvec(irq) / XLP_MSIXVEC_PER_LINK; | 105 | return msixvec / XLP_MSIXVEC_PER_LINK; |
97 | } | 106 | } |
98 | 107 | ||
99 | /* | 108 | /* |
@@ -129,7 +138,11 @@ static void xlp_msi_enable(struct irq_data *d) | |||
129 | vec = nlm_irq_msivec(d->irq); | 138 | vec = nlm_irq_msivec(d->irq); |
130 | spin_lock_irqsave(&md->msi_lock, flags); | 139 | spin_lock_irqsave(&md->msi_lock, flags); |
131 | md->msi_enabled_mask |= 1u << vec; | 140 | md->msi_enabled_mask |= 1u << vec; |
132 | nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask); | 141 | if (cpu_is_xlp9xx()) |
142 | nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN, | ||
143 | md->msi_enabled_mask); | ||
144 | else | ||
145 | nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask); | ||
133 | spin_unlock_irqrestore(&md->msi_lock, flags); | 146 | spin_unlock_irqrestore(&md->msi_lock, flags); |
134 | } | 147 | } |
135 | 148 | ||
@@ -142,7 +155,11 @@ static void xlp_msi_disable(struct irq_data *d) | |||
142 | vec = nlm_irq_msivec(d->irq); | 155 | vec = nlm_irq_msivec(d->irq); |
143 | spin_lock_irqsave(&md->msi_lock, flags); | 156 | spin_lock_irqsave(&md->msi_lock, flags); |
144 | md->msi_enabled_mask &= ~(1u << vec); | 157 | md->msi_enabled_mask &= ~(1u << vec); |
145 | nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask); | 158 | if (cpu_is_xlp9xx()) |
159 | nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN, | ||
160 | md->msi_enabled_mask); | ||
161 | else | ||
162 | nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask); | ||
146 | spin_unlock_irqrestore(&md->msi_lock, flags); | 163 | spin_unlock_irqrestore(&md->msi_lock, flags); |
147 | } | 164 | } |
148 | 165 | ||
@@ -156,11 +173,18 @@ static void xlp_msi_mask_ack(struct irq_data *d) | |||
156 | xlp_msi_disable(d); | 173 | xlp_msi_disable(d); |
157 | 174 | ||
158 | /* Ack MSI on bridge */ | 175 | /* Ack MSI on bridge */ |
159 | nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec); | 176 | if (cpu_is_xlp9xx()) |
177 | nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_STATUS, 1u << vec); | ||
178 | else | ||
179 | nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec); | ||
160 | 180 | ||
161 | /* Ack at eirr and PIC */ | 181 | /* Ack at eirr and PIC */ |
162 | ack_c0_eirr(PIC_PCIE_LINK_MSI_IRQ(link)); | 182 | ack_c0_eirr(PIC_PCIE_LINK_MSI_IRQ(link)); |
163 | nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link)); | 183 | if (cpu_is_xlp9xx()) |
184 | nlm_pic_ack(md->node->picbase, | ||
185 | PIC_9XX_IRT_PCIE_LINK_INDEX(link)); | ||
186 | else | ||
187 | nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link)); | ||
164 | } | 188 | } |
165 | 189 | ||
166 | static struct irq_chip xlp_msi_chip = { | 190 | static struct irq_chip xlp_msi_chip = { |
@@ -172,30 +196,45 @@ static struct irq_chip xlp_msi_chip = { | |||
172 | }; | 196 | }; |
173 | 197 | ||
174 | /* | 198 | /* |
175 | * The MSI-X interrupt handling is different from MSI, there are 32 | 199 | * XLP8XX/4XX/3XX/2XX: |
176 | * MSI-X interrupts generated by the PIC and each of these correspond | 200 | * The MSI-X interrupt handling is different from MSI, there are 32 MSI-X |
177 | * to a MSI-X vector (0-31) that can be assigned. | 201 | * interrupts generated by the PIC and each of these correspond to a MSI-X |
202 | * vector (0-31) that can be assigned. | ||
178 | * | 203 | * |
179 | * We divide the MSI-X vectors to 8 per link and do a per-link | 204 | * We divide the MSI-X vectors to 8 per link and do a per-link allocation |
180 | * allocation | 205 | * |
206 | * XLP9XX: | ||
207 | * 32 MSI-X vectors are available per link, and the interrupts are not routed | ||
208 | * thru the PIC. PIC ack not needed. | ||
181 | * | 209 | * |
182 | * Enable and disable done using standard MSI functions. | 210 | * Enable and disable done using standard MSI functions. |
183 | */ | 211 | */ |
184 | static void xlp_msix_mask_ack(struct irq_data *d) | 212 | static void xlp_msix_mask_ack(struct irq_data *d) |
185 | { | 213 | { |
186 | struct xlp_msi_data *md = irq_data_get_irq_handler_data(d); | 214 | struct xlp_msi_data *md; |
187 | int link, msixvec; | 215 | int link, msixvec; |
216 | uint32_t status_reg, bit; | ||
188 | 217 | ||
189 | msixvec = nlm_irq_msixvec(d->irq); | 218 | msixvec = nlm_irq_msixvec(d->irq); |
190 | link = nlm_irq_msixlink(d->irq); | 219 | link = nlm_irq_msixlink(msixvec); |
191 | mask_msi_irq(d); | 220 | mask_msi_irq(d); |
221 | md = irq_data_get_irq_handler_data(d); | ||
192 | 222 | ||
193 | /* Ack MSI on bridge */ | 223 | /* Ack MSI on bridge */ |
194 | nlm_write_reg(md->lnkbase, PCIE_MSIX_STATUS, 1u << msixvec); | 224 | if (cpu_is_xlp9xx()) { |
225 | status_reg = PCIE_9XX_MSIX_STATUSX(link); | ||
226 | bit = msixvec % XLP_MSIXVEC_PER_LINK; | ||
227 | } else { | ||
228 | status_reg = PCIE_MSIX_STATUS; | ||
229 | bit = msixvec; | ||
230 | } | ||
231 | nlm_write_reg(md->lnkbase, status_reg, 1u << bit); | ||
195 | 232 | ||
196 | /* Ack at eirr and PIC */ | 233 | /* Ack at eirr and PIC */ |
197 | ack_c0_eirr(PIC_PCIE_MSIX_IRQ(link)); | 234 | ack_c0_eirr(PIC_PCIE_MSIX_IRQ(link)); |
198 | nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_MSIX_INDEX(msixvec)); | 235 | if (!cpu_is_xlp9xx()) |
236 | nlm_pic_ack(md->node->picbase, | ||
237 | PIC_IRT_PCIE_MSIX_INDEX(msixvec)); | ||
199 | } | 238 | } |
200 | 239 | ||
201 | static struct irq_chip xlp_msix_chip = { | 240 | static struct irq_chip xlp_msix_chip = { |
@@ -225,10 +264,18 @@ static void xlp_config_link_msi(uint64_t lnkbase, int lirq, uint64_t msiaddr) | |||
225 | { | 264 | { |
226 | u32 val; | 265 | u32 val; |
227 | 266 | ||
228 | val = nlm_read_reg(lnkbase, PCIE_INT_EN0); | 267 | if (cpu_is_xlp9xx()) { |
229 | if ((val & 0x200) == 0) { | 268 | val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0); |
230 | val |= 0x200; /* MSI Interrupt enable */ | 269 | if ((val & 0x200) == 0) { |
231 | nlm_write_reg(lnkbase, PCIE_INT_EN0, val); | 270 | val |= 0x200; /* MSI Interrupt enable */ |
271 | nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val); | ||
272 | } | ||
273 | } else { | ||
274 | val = nlm_read_reg(lnkbase, PCIE_INT_EN0); | ||
275 | if ((val & 0x200) == 0) { | ||
276 | val |= 0x200; | ||
277 | nlm_write_reg(lnkbase, PCIE_INT_EN0, val); | ||
278 | } | ||
232 | } | 279 | } |
233 | 280 | ||
234 | val = nlm_read_reg(lnkbase, 0x1); /* CMD */ | 281 | val = nlm_read_reg(lnkbase, 0x1); /* CMD */ |
@@ -275,9 +322,12 @@ static int xlp_setup_msi(uint64_t lnkbase, int node, int link, | |||
275 | 322 | ||
276 | spin_lock_irqsave(&md->msi_lock, flags); | 323 | spin_lock_irqsave(&md->msi_lock, flags); |
277 | if (md->msi_alloc_mask == 0) { | 324 | if (md->msi_alloc_mask == 0) { |
278 | /* switch the link IRQ to MSI range */ | ||
279 | xlp_config_link_msi(lnkbase, lirq, msiaddr); | 325 | xlp_config_link_msi(lnkbase, lirq, msiaddr); |
280 | irt = PIC_IRT_PCIE_LINK_INDEX(link); | 326 | /* switch the link IRQ to MSI range */ |
327 | if (cpu_is_xlp9xx()) | ||
328 | irt = PIC_9XX_IRT_PCIE_LINK_INDEX(link); | ||
329 | else | ||
330 | irt = PIC_IRT_PCIE_LINK_INDEX(link); | ||
281 | nlm_setup_pic_irq(node, lirq, lirq, irt); | 331 | nlm_setup_pic_irq(node, lirq, lirq, irt); |
282 | nlm_pic_init_irt(nlm_get_node(node)->picbase, irt, lirq, | 332 | nlm_pic_init_irt(nlm_get_node(node)->picbase, irt, lirq, |
283 | node * nlm_threads_per_node(), 1 /*en */); | 333 | node * nlm_threads_per_node(), 1 /*en */); |
@@ -319,10 +369,19 @@ static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr) | |||
319 | val |= 0x80000000U; | 369 | val |= 0x80000000U; |
320 | nlm_write_reg(lnkbase, 0x2C, val); | 370 | nlm_write_reg(lnkbase, 0x2C, val); |
321 | } | 371 | } |
322 | val = nlm_read_reg(lnkbase, PCIE_INT_EN0); | 372 | |
323 | if ((val & 0x200) == 0) { | 373 | if (cpu_is_xlp9xx()) { |
324 | val |= 0x200; /* MSI Interrupt enable */ | 374 | val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0); |
325 | nlm_write_reg(lnkbase, PCIE_INT_EN0, val); | 375 | if ((val & 0x200) == 0) { |
376 | val |= 0x200; /* MSI Interrupt enable */ | ||
377 | nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val); | ||
378 | } | ||
379 | } else { | ||
380 | val = nlm_read_reg(lnkbase, PCIE_INT_EN0); | ||
381 | if ((val & 0x200) == 0) { | ||
382 | val |= 0x200; /* MSI Interrupt enable */ | ||
383 | nlm_write_reg(lnkbase, PCIE_INT_EN0, val); | ||
384 | } | ||
326 | } | 385 | } |
327 | 386 | ||
328 | val = nlm_read_reg(lnkbase, 0x1); /* CMD */ | 387 | val = nlm_read_reg(lnkbase, 0x1); /* CMD */ |
@@ -337,10 +396,19 @@ static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr) | |||
337 | val |= (1 << 8) | lirq; | 396 | val |= (1 << 8) | lirq; |
338 | nlm_write_pci_reg(lnkbase, 0xf, val); | 397 | nlm_write_pci_reg(lnkbase, 0xf, val); |
339 | 398 | ||
340 | /* MSI-X addresses */ | 399 | if (cpu_is_xlp9xx()) { |
341 | nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE, msixaddr >> 8); | 400 | /* MSI-X addresses */ |
342 | nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT, | 401 | nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_BASE, |
343 | (msixaddr + MSI_ADDR_SZ) >> 8); | 402 | msixaddr >> 8); |
403 | nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT, | ||
404 | (msixaddr + MSI_ADDR_SZ) >> 8); | ||
405 | } else { | ||
406 | /* MSI-X addresses */ | ||
407 | nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE, | ||
408 | msixaddr >> 8); | ||
409 | nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT, | ||
410 | (msixaddr + MSI_ADDR_SZ) >> 8); | ||
411 | } | ||
344 | } | 412 | } |
345 | 413 | ||
346 | /* | 414 | /* |
@@ -377,6 +445,7 @@ static int xlp_setup_msix(uint64_t lnkbase, int node, int link, | |||
377 | 445 | ||
378 | xirq += t; | 446 | xirq += t; |
379 | msixvec = nlm_irq_msixvec(xirq); | 447 | msixvec = nlm_irq_msixvec(xirq); |
448 | |||
380 | msg.address_hi = msixaddr >> 32; | 449 | msg.address_hi = msixaddr >> 32; |
381 | msg.address_lo = msixaddr & 0xffffffff; | 450 | msg.address_lo = msixaddr & 0xffffffff; |
382 | msg.data = 0xc00 | msixvec; | 451 | msg.data = 0xc00 | msixvec; |
@@ -417,7 +486,7 @@ void __init xlp_init_node_msi_irqs(int node, int link) | |||
417 | { | 486 | { |
418 | struct nlm_soc_info *nodep; | 487 | struct nlm_soc_info *nodep; |
419 | struct xlp_msi_data *md; | 488 | struct xlp_msi_data *md; |
420 | int irq, i, irt, msixvec; | 489 | int irq, i, irt, msixvec, val; |
421 | 490 | ||
422 | pr_info("[%d %d] Init node PCI IRT\n", node, link); | 491 | pr_info("[%d %d] Init node PCI IRT\n", node, link); |
423 | nodep = nlm_get_node(node); | 492 | nodep = nlm_get_node(node); |
@@ -438,19 +507,28 @@ void __init xlp_init_node_msi_irqs(int node, int link) | |||
438 | irq_set_handler_data(i, md); | 507 | irq_set_handler_data(i, md); |
439 | } | 508 | } |
440 | 509 | ||
441 | for (i = 0; i < XLP_MSIXVEC_PER_LINK; i++) { | 510 | for (i = 0; i < XLP_MSIXVEC_PER_LINK ; i++) { |
442 | /* Initialize MSI-X irts to generate one interrupt per link */ | 511 | if (cpu_is_xlp9xx()) { |
443 | msixvec = link * XLP_MSIXVEC_PER_LINK + i; | 512 | val = ((node * nlm_threads_per_node()) << 7 | |
444 | irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec); | 513 | PIC_PCIE_MSIX_IRQ(link) << 1 | 0 << 0); |
445 | nlm_pic_init_irt(nodep->picbase, irt, PIC_PCIE_MSIX_IRQ(link), | 514 | nlm_write_pcie_reg(md->lnkbase, PCIE_9XX_MSIX_VECX(i + |
446 | node * nlm_threads_per_node(), 1 /* enable */); | 515 | (link * XLP_MSIXVEC_PER_LINK)), val); |
516 | } else { | ||
517 | /* Initialize MSI-X irts to generate one interrupt | ||
518 | * per link | ||
519 | */ | ||
520 | msixvec = link * XLP_MSIXVEC_PER_LINK + i; | ||
521 | irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec); | ||
522 | nlm_pic_init_irt(nodep->picbase, irt, | ||
523 | PIC_PCIE_MSIX_IRQ(link), | ||
524 | node * nlm_threads_per_node(), 1); | ||
525 | } | ||
447 | 526 | ||
448 | /* Initialize MSI-X extended irq space for the link */ | 527 | /* Initialize MSI-X extended irq space for the link */ |
449 | irq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, i)); | 528 | irq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, i)); |
450 | irq_set_chip_and_handler(irq, &xlp_msix_chip, handle_level_irq); | 529 | irq_set_chip_and_handler(irq, &xlp_msix_chip, handle_level_irq); |
451 | irq_set_handler_data(irq, md); | 530 | irq_set_handler_data(irq, md); |
452 | } | 531 | } |
453 | |||
454 | } | 532 | } |
455 | 533 | ||
456 | void nlm_dispatch_msi(int node, int lirq) | 534 | void nlm_dispatch_msi(int node, int lirq) |
@@ -462,7 +540,11 @@ void nlm_dispatch_msi(int node, int lirq) | |||
462 | link = lirq - PIC_PCIE_LINK_MSI_IRQ_BASE; | 540 | link = lirq - PIC_PCIE_LINK_MSI_IRQ_BASE; |
463 | irqbase = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0)); | 541 | irqbase = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0)); |
464 | md = irq_get_handler_data(irqbase); | 542 | md = irq_get_handler_data(irqbase); |
465 | status = nlm_read_reg(md->lnkbase, PCIE_MSI_STATUS) & | 543 | if (cpu_is_xlp9xx()) |
544 | status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSI_STATUS) & | ||
545 | md->msi_enabled_mask; | ||
546 | else | ||
547 | status = nlm_read_reg(md->lnkbase, PCIE_MSI_STATUS) & | ||
466 | md->msi_enabled_mask; | 548 | md->msi_enabled_mask; |
467 | while (status) { | 549 | while (status) { |
468 | i = __ffs(status); | 550 | i = __ffs(status); |
@@ -480,10 +562,14 @@ void nlm_dispatch_msix(int node, int lirq) | |||
480 | link = lirq - PIC_PCIE_MSIX_IRQ_BASE; | 562 | link = lirq - PIC_PCIE_MSIX_IRQ_BASE; |
481 | irqbase = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0)); | 563 | irqbase = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0)); |
482 | md = irq_get_handler_data(irqbase); | 564 | md = irq_get_handler_data(irqbase); |
483 | status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS); | 565 | if (cpu_is_xlp9xx()) |
566 | status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSIX_STATUSX(link)); | ||
567 | else | ||
568 | status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS); | ||
484 | 569 | ||
485 | /* narrow it down to the MSI-x vectors for our link */ | 570 | /* narrow it down to the MSI-x vectors for our link */ |
486 | status = (status >> (link * XLP_MSIXVEC_PER_LINK)) & | 571 | if (!cpu_is_xlp9xx()) |
572 | status = (status >> (link * XLP_MSIXVEC_PER_LINK)) & | ||
487 | ((1 << XLP_MSIXVEC_PER_LINK) - 1); | 573 | ((1 << XLP_MSIXVEC_PER_LINK) - 1); |
488 | 574 | ||
489 | while (status) { | 575 | while (status) { |