1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/printk.h>
4 #include <linux/slab.h>
6 #include "nitrox_dev.h"
7 #include "nitrox_csr.h"
8 #include "nitrox_common.h"
10 #define NR_RING_VECTORS 3
11 #define NPS_CORE_INT_ACTIVE_ENTRY 192
14 * nps_pkt_slc_isr - IRQ handler for NPS solicit port
18 static irqreturn_t
nps_pkt_slc_isr(int irq
, void *data
)
20 struct bh_data
*slc
= data
;
21 union nps_pkt_slc_cnts pkt_slc_cnts
;
23 pkt_slc_cnts
.value
= readq(slc
->completion_cnt_csr_addr
);
24 /* New packet on SLC output port */
25 if (pkt_slc_cnts
.s
.slc_int
)
26 tasklet_hi_schedule(&slc
->resp_handler
);
31 static void clear_nps_core_err_intr(struct nitrox_device
*ndev
)
35 /* Write 1 to clear */
36 value
= nitrox_read_csr(ndev
, NPS_CORE_INT
);
37 nitrox_write_csr(ndev
, NPS_CORE_INT
, value
);
39 dev_err_ratelimited(DEV(ndev
), "NSP_CORE_INT 0x%016llx\n", value
);
42 static void clear_nps_pkt_err_intr(struct nitrox_device
*ndev
)
44 union nps_pkt_int pkt_int
;
45 unsigned long value
, offset
;
48 pkt_int
.value
= nitrox_read_csr(ndev
, NPS_PKT_INT
);
49 dev_err_ratelimited(DEV(ndev
), "NPS_PKT_INT 0x%016llx\n",
52 if (pkt_int
.s
.slc_err
) {
53 offset
= NPS_PKT_SLC_ERR_TYPE
;
54 value
= nitrox_read_csr(ndev
, offset
);
55 nitrox_write_csr(ndev
, offset
, value
);
56 dev_err_ratelimited(DEV(ndev
),
57 "NPS_PKT_SLC_ERR_TYPE 0x%016lx\n", value
);
59 offset
= NPS_PKT_SLC_RERR_LO
;
60 value
= nitrox_read_csr(ndev
, offset
);
61 nitrox_write_csr(ndev
, offset
, value
);
62 /* enable the solicit ports */
63 for_each_set_bit(i
, &value
, BITS_PER_LONG
)
64 enable_pkt_solicit_port(ndev
, i
);
66 dev_err_ratelimited(DEV(ndev
),
67 "NPS_PKT_SLC_RERR_LO 0x%016lx\n", value
);
69 offset
= NPS_PKT_SLC_RERR_HI
;
70 value
= nitrox_read_csr(ndev
, offset
);
71 nitrox_write_csr(ndev
, offset
, value
);
72 dev_err_ratelimited(DEV(ndev
),
73 "NPS_PKT_SLC_RERR_HI 0x%016lx\n", value
);
76 if (pkt_int
.s
.in_err
) {
77 offset
= NPS_PKT_IN_ERR_TYPE
;
78 value
= nitrox_read_csr(ndev
, offset
);
79 nitrox_write_csr(ndev
, offset
, value
);
80 dev_err_ratelimited(DEV(ndev
),
81 "NPS_PKT_IN_ERR_TYPE 0x%016lx\n", value
);
82 offset
= NPS_PKT_IN_RERR_LO
;
83 value
= nitrox_read_csr(ndev
, offset
);
84 nitrox_write_csr(ndev
, offset
, value
);
85 /* enable the input ring */
86 for_each_set_bit(i
, &value
, BITS_PER_LONG
)
87 enable_pkt_input_ring(ndev
, i
);
89 dev_err_ratelimited(DEV(ndev
),
90 "NPS_PKT_IN_RERR_LO 0x%016lx\n", value
);
92 offset
= NPS_PKT_IN_RERR_HI
;
93 value
= nitrox_read_csr(ndev
, offset
);
94 nitrox_write_csr(ndev
, offset
, value
);
95 dev_err_ratelimited(DEV(ndev
),
96 "NPS_PKT_IN_RERR_HI 0x%016lx\n", value
);
100 static void clear_pom_err_intr(struct nitrox_device
*ndev
)
104 value
= nitrox_read_csr(ndev
, POM_INT
);
105 nitrox_write_csr(ndev
, POM_INT
, value
);
106 dev_err_ratelimited(DEV(ndev
), "POM_INT 0x%016llx\n", value
);
109 static void clear_pem_err_intr(struct nitrox_device
*ndev
)
113 value
= nitrox_read_csr(ndev
, PEM0_INT
);
114 nitrox_write_csr(ndev
, PEM0_INT
, value
);
115 dev_err_ratelimited(DEV(ndev
), "PEM(0)_INT 0x%016llx\n", value
);
118 static void clear_lbc_err_intr(struct nitrox_device
*ndev
)
120 union lbc_int lbc_int
;
124 lbc_int
.value
= nitrox_read_csr(ndev
, LBC_INT
);
125 dev_err_ratelimited(DEV(ndev
), "LBC_INT 0x%016llx\n", lbc_int
.value
);
127 if (lbc_int
.s
.dma_rd_err
) {
128 for (i
= 0; i
< NR_CLUSTERS
; i
++) {
129 offset
= EFL_CORE_VF_ERR_INT0X(i
);
130 value
= nitrox_read_csr(ndev
, offset
);
131 nitrox_write_csr(ndev
, offset
, value
);
132 offset
= EFL_CORE_VF_ERR_INT1X(i
);
133 value
= nitrox_read_csr(ndev
, offset
);
134 nitrox_write_csr(ndev
, offset
, value
);
138 if (lbc_int
.s
.cam_soft_err
) {
139 dev_err_ratelimited(DEV(ndev
), "CAM_SOFT_ERR, invalidating LBC\n");
140 invalidate_lbc(ndev
);
143 if (lbc_int
.s
.pref_dat_len_mismatch_err
) {
144 offset
= LBC_PLM_VF1_64_INT
;
145 value
= nitrox_read_csr(ndev
, offset
);
146 nitrox_write_csr(ndev
, offset
, value
);
147 offset
= LBC_PLM_VF65_128_INT
;
148 value
= nitrox_read_csr(ndev
, offset
);
149 nitrox_write_csr(ndev
, offset
, value
);
152 if (lbc_int
.s
.rd_dat_len_mismatch_err
) {
153 offset
= LBC_ELM_VF1_64_INT
;
154 value
= nitrox_read_csr(ndev
, offset
);
155 nitrox_write_csr(ndev
, offset
, value
);
156 offset
= LBC_ELM_VF65_128_INT
;
157 value
= nitrox_read_csr(ndev
, offset
);
158 nitrox_write_csr(ndev
, offset
, value
);
160 nitrox_write_csr(ndev
, LBC_INT
, lbc_int
.value
);
163 static void clear_efl_err_intr(struct nitrox_device
*ndev
)
167 for (i
= 0; i
< NR_CLUSTERS
; i
++) {
168 union efl_core_int core_int
;
171 offset
= EFL_CORE_INTX(i
);
172 core_int
.value
= nitrox_read_csr(ndev
, offset
);
173 nitrox_write_csr(ndev
, offset
, core_int
.value
);
174 dev_err_ratelimited(DEV(ndev
), "ELF_CORE(%d)_INT 0x%016llx\n",
176 if (core_int
.s
.se_err
) {
177 offset
= EFL_CORE_SE_ERR_INTX(i
);
178 value
= nitrox_read_csr(ndev
, offset
);
179 nitrox_write_csr(ndev
, offset
, value
);
184 static void clear_bmi_err_intr(struct nitrox_device
*ndev
)
188 value
= nitrox_read_csr(ndev
, BMI_INT
);
189 nitrox_write_csr(ndev
, BMI_INT
, value
);
190 dev_err_ratelimited(DEV(ndev
), "BMI_INT 0x%016llx\n", value
);
194 * clear_nps_core_int_active - clear NPS_CORE_INT_ACTIVE interrupts
195 * @ndev: NITROX device
197 static void clear_nps_core_int_active(struct nitrox_device
*ndev
)
199 union nps_core_int_active core_int_active
;
201 core_int_active
.value
= nitrox_read_csr(ndev
, NPS_CORE_INT_ACTIVE
);
203 if (core_int_active
.s
.nps_core
)
204 clear_nps_core_err_intr(ndev
);
206 if (core_int_active
.s
.nps_pkt
)
207 clear_nps_pkt_err_intr(ndev
);
209 if (core_int_active
.s
.pom
)
210 clear_pom_err_intr(ndev
);
212 if (core_int_active
.s
.pem
)
213 clear_pem_err_intr(ndev
);
215 if (core_int_active
.s
.lbc
)
216 clear_lbc_err_intr(ndev
);
218 if (core_int_active
.s
.efl
)
219 clear_efl_err_intr(ndev
);
221 if (core_int_active
.s
.bmi
)
222 clear_bmi_err_intr(ndev
);
224 /* If more work callback the ISR, set resend */
225 core_int_active
.s
.resend
= 1;
226 nitrox_write_csr(ndev
, NPS_CORE_INT_ACTIVE
, core_int_active
.value
);
229 static irqreturn_t
nps_core_int_isr(int irq
, void *data
)
231 struct nitrox_device
*ndev
= data
;
233 clear_nps_core_int_active(ndev
);
238 static int nitrox_enable_msix(struct nitrox_device
*ndev
)
240 struct msix_entry
*entries
;
242 int i
, nr_entries
, ret
;
247 * Entry 0: NPS PKT ring 0
248 * Entry 1: AQMQ ring 0
249 * Entry 2: ZQM ring 0
250 * Entry 3: NPS PKT ring 1
251 * Entry 4: AQMQ ring 1
252 * Entry 5: ZQM ring 1
254 * Entry 192: NPS_CORE_INT_ACTIVE
256 nr_entries
= (ndev
->nr_queues
* NR_RING_VECTORS
) + 1;
257 entries
= kcalloc_node(nr_entries
, sizeof(struct msix_entry
),
258 GFP_KERNEL
, ndev
->node
);
262 names
= kcalloc(nr_entries
, sizeof(char *), GFP_KERNEL
);
269 for (i
= 0; i
< (nr_entries
- 1); i
++)
270 entries
[i
].entry
= i
;
272 entries
[i
].entry
= NPS_CORE_INT_ACTIVE_ENTRY
;
274 for (i
= 0; i
< nr_entries
; i
++) {
275 *(names
+ i
) = kzalloc(MAX_MSIX_VECTOR_NAME
, GFP_KERNEL
);
276 if (!(*(names
+ i
))) {
281 ndev
->msix
.entries
= entries
;
282 ndev
->msix
.names
= names
;
283 ndev
->msix
.nr_entries
= nr_entries
;
285 ret
= pci_enable_msix_exact(ndev
->pdev
, ndev
->msix
.entries
,
286 ndev
->msix
.nr_entries
);
288 dev_err(&ndev
->pdev
->dev
, "Failed to enable MSI-X IRQ(s) %d\n",
295 for (i
= 0; i
< nr_entries
; i
++)
303 static void nitrox_cleanup_pkt_slc_bh(struct nitrox_device
*ndev
)
310 for (i
= 0; i
< ndev
->nr_queues
; i
++) {
311 struct bh_data
*bh
= &ndev
->bh
.slc
[i
];
313 tasklet_disable(&bh
->resp_handler
);
314 tasklet_kill(&bh
->resp_handler
);
320 static int nitrox_setup_pkt_slc_bh(struct nitrox_device
*ndev
)
325 size
= ndev
->nr_queues
* sizeof(struct bh_data
);
326 ndev
->bh
.slc
= kzalloc(size
, GFP_KERNEL
);
330 for (i
= 0; i
< ndev
->nr_queues
; i
++) {
331 struct bh_data
*bh
= &ndev
->bh
.slc
[i
];
334 offset
= NPS_PKT_SLC_CNTSX(i
);
335 /* pre calculate completion count address */
336 bh
->completion_cnt_csr_addr
= NITROX_CSR_ADDR(ndev
, offset
);
337 bh
->cmdq
= &ndev
->pkt_cmdqs
[i
];
339 tasklet_init(&bh
->resp_handler
, pkt_slc_resp_handler
,
346 static int nitrox_request_irqs(struct nitrox_device
*ndev
)
348 struct pci_dev
*pdev
= ndev
->pdev
;
349 struct msix_entry
*msix_ent
= ndev
->msix
.entries
;
350 int nr_ring_vectors
, i
= 0, ring
, cpu
, ret
;
356 * Entry 0: NPS PKT ring 0
357 * Entry 1: AQMQ ring 0
358 * Entry 2: ZQM ring 0
359 * Entry 3: NPS PKT ring 1
361 * Entry 192: NPS_CORE_INT_ACTIVE
363 nr_ring_vectors
= ndev
->nr_queues
* NR_RING_VECTORS
;
365 /* request irq for pkt ring/ports only */
366 while (i
< nr_ring_vectors
) {
367 name
= *(ndev
->msix
.names
+ i
);
368 ring
= (i
/ NR_RING_VECTORS
);
369 snprintf(name
, MAX_MSIX_VECTOR_NAME
, "n5(%d)-slc-ring%d",
372 ret
= request_irq(msix_ent
[i
].vector
, nps_pkt_slc_isr
, 0,
373 name
, &ndev
->bh
.slc
[ring
]);
375 dev_err(&pdev
->dev
, "failed to get irq %d for %s\n",
376 msix_ent
[i
].vector
, name
);
379 cpu
= ring
% num_online_cpus();
380 irq_set_affinity_hint(msix_ent
[i
].vector
, get_cpu_mask(cpu
));
382 set_bit(i
, ndev
->msix
.irqs
);
383 i
+= NR_RING_VECTORS
;
386 /* Request IRQ for NPS_CORE_INT_ACTIVE */
387 name
= *(ndev
->msix
.names
+ i
);
388 snprintf(name
, MAX_MSIX_VECTOR_NAME
, "n5(%d)-nps-core-int", ndev
->idx
);
389 ret
= request_irq(msix_ent
[i
].vector
, nps_core_int_isr
, 0, name
, ndev
);
391 dev_err(&pdev
->dev
, "failed to get irq %d for %s\n",
392 msix_ent
[i
].vector
, name
);
395 set_bit(i
, ndev
->msix
.irqs
);
400 static void nitrox_disable_msix(struct nitrox_device
*ndev
)
402 struct msix_entry
*msix_ent
= ndev
->msix
.entries
;
403 char **names
= ndev
->msix
.names
;
404 int i
= 0, ring
, nr_ring_vectors
;
406 nr_ring_vectors
= ndev
->msix
.nr_entries
- 1;
408 /* clear pkt ring irqs */
409 while (i
< nr_ring_vectors
) {
410 if (test_and_clear_bit(i
, ndev
->msix
.irqs
)) {
411 ring
= (i
/ NR_RING_VECTORS
);
412 irq_set_affinity_hint(msix_ent
[i
].vector
, NULL
);
413 free_irq(msix_ent
[i
].vector
, &ndev
->bh
.slc
[ring
]);
415 i
+= NR_RING_VECTORS
;
417 irq_set_affinity_hint(msix_ent
[i
].vector
, NULL
);
418 free_irq(msix_ent
[i
].vector
, ndev
);
419 clear_bit(i
, ndev
->msix
.irqs
);
421 kfree(ndev
->msix
.entries
);
422 for (i
= 0; i
< ndev
->msix
.nr_entries
; i
++)
426 pci_disable_msix(ndev
->pdev
);
430 * nitrox_pf_cleanup_isr: Cleanup PF MSI-X and IRQ
431 * @ndev: NITROX device
433 void nitrox_pf_cleanup_isr(struct nitrox_device
*ndev
)
435 nitrox_disable_msix(ndev
);
436 nitrox_cleanup_pkt_slc_bh(ndev
);
440 * nitrox_init_isr - Initialize PF MSI-X vectors and IRQ
441 * @ndev: NITROX device
443 * Return: 0 on success, a negative value on failure.
445 int nitrox_pf_init_isr(struct nitrox_device
*ndev
)
449 err
= nitrox_setup_pkt_slc_bh(ndev
);
453 err
= nitrox_enable_msix(ndev
);
457 err
= nitrox_request_irqs(ndev
);
464 nitrox_disable_msix(ndev
);
466 nitrox_cleanup_pkt_slc_bh(ndev
);