xref: /dpdk/drivers/common/cnxk/roc_nix_inl_dev_irq.c (revision 2490bb897182f57de80fd924dd3ae48dda819b8c)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4 
5 #include "roc_api.h"
6 #include "roc_priv.h"
7 
8 static void
9 nix_inl_sso_work_cb(struct nix_inl_dev *inl_dev)
10 {
11 	uintptr_t getwrk_op = inl_dev->ssow_base + SSOW_LF_GWS_OP_GET_WORK0;
12 	uintptr_t tag_wqe_op = inl_dev->ssow_base + SSOW_LF_GWS_WQE0;
13 	uint32_t wdata = BIT(16) | 1;
14 	union {
15 		__uint128_t get_work;
16 		uint64_t u64[2];
17 	} gw;
18 	uint64_t work;
19 
20 again:
21 	/* Try to do get work */
22 	gw.get_work = wdata;
23 	plt_write64(gw.u64[0], getwrk_op);
24 	do {
25 		roc_load_pair(gw.u64[0], gw.u64[1], tag_wqe_op);
26 	} while (gw.u64[0] & BIT_ULL(63));
27 
28 	work = gw.u64[1];
29 	/* Do we have any work? */
30 	if (work) {
31 		if (inl_dev->work_cb)
32 			inl_dev->work_cb(gw.u64, inl_dev->cb_args);
33 		else
34 			plt_warn("Undelivered inl dev work gw0: %p gw1: %p",
35 				 (void *)gw.u64[0], (void *)gw.u64[1]);
36 		goto again;
37 	}
38 
39 	plt_atomic_thread_fence(__ATOMIC_ACQ_REL);
40 }
41 
42 static int
43 nix_inl_nix_reg_dump(struct nix_inl_dev *inl_dev)
44 {
45 	uintptr_t nix_base = inl_dev->nix_base;
46 
47 	/* General registers */
48 	nix_lf_gen_reg_dump(nix_base, NULL);
49 
50 	/* Rx, Tx stat registers */
51 	nix_lf_stat_reg_dump(nix_base, NULL, inl_dev->lf_tx_stats,
52 			     inl_dev->lf_rx_stats);
53 
54 	/* Intr registers */
55 	nix_lf_int_reg_dump(nix_base, NULL, inl_dev->qints, inl_dev->cints);
56 
57 	return 0;
58 }
59 
60 static void
61 nix_inl_sso_hwgrp_irq(void *param)
62 {
63 	struct nix_inl_dev *inl_dev = (struct nix_inl_dev *)param;
64 	uintptr_t sso_base = inl_dev->sso_base;
65 	uint64_t intr;
66 
67 	intr = plt_read64(sso_base + SSO_LF_GGRP_INT);
68 	if (intr == 0)
69 		return;
70 
71 	/* Check for work executable interrupt */
72 	if (intr & BIT(1))
73 		nix_inl_sso_work_cb(inl_dev);
74 
75 	if (!(intr & BIT(1)))
76 		plt_err("GGRP 0 GGRP_INT=0x%" PRIx64 "", intr);
77 
78 	/* Clear interrupt */
79 	plt_write64(intr, sso_base + SSO_LF_GGRP_INT);
80 }
81 
82 static void
83 nix_inl_sso_hws_irq(void *param)
84 {
85 	struct nix_inl_dev *inl_dev = (struct nix_inl_dev *)param;
86 	uintptr_t ssow_base = inl_dev->ssow_base;
87 	uint64_t intr;
88 
89 	intr = plt_read64(ssow_base + SSOW_LF_GWS_INT);
90 	if (intr == 0)
91 		return;
92 
93 	plt_err("GWS 0 GWS_INT=0x%" PRIx64 "", intr);
94 
95 	/* Clear interrupt */
96 	plt_write64(intr, ssow_base + SSOW_LF_GWS_INT);
97 }
98 
99 int
100 nix_inl_sso_register_irqs(struct nix_inl_dev *inl_dev)
101 {
102 	struct plt_intr_handle *handle = inl_dev->pci_dev->intr_handle;
103 	uintptr_t ssow_base = inl_dev->ssow_base;
104 	uintptr_t sso_base = inl_dev->sso_base;
105 	uint16_t sso_msixoff, ssow_msixoff;
106 	int rc;
107 
108 	ssow_msixoff = inl_dev->ssow_msixoff;
109 	sso_msixoff = inl_dev->sso_msixoff;
110 	if (sso_msixoff == MSIX_VECTOR_INVALID ||
111 	    ssow_msixoff == MSIX_VECTOR_INVALID) {
112 		plt_err("Invalid SSO/SSOW MSIX offsets (0x%x, 0x%x)",
113 			sso_msixoff, ssow_msixoff);
114 		return -EINVAL;
115 	}
116 
117 	/*
118 	 * Setup SSOW interrupt
119 	 */
120 
121 	/* Clear SSOW interrupt enable */
122 	plt_write64(~0ull, ssow_base + SSOW_LF_GWS_INT_ENA_W1C);
123 	/* Register interrupt with vfio */
124 	rc = dev_irq_register(handle, nix_inl_sso_hws_irq, inl_dev,
125 			      ssow_msixoff + SSOW_LF_INT_VEC_IOP);
126 	/* Set SSOW interrupt enable */
127 	plt_write64(~0ull, ssow_base + SSOW_LF_GWS_INT_ENA_W1S);
128 
129 	/*
130 	 * Setup SSO/HWGRP interrupt
131 	 */
132 
133 	/* Clear SSO interrupt enable */
134 	plt_write64(~0ull, sso_base + SSO_LF_GGRP_INT_ENA_W1C);
135 	/* Register IRQ */
136 	rc |= dev_irq_register(handle, nix_inl_sso_hwgrp_irq, (void *)inl_dev,
137 			       sso_msixoff + SSO_LF_INT_VEC_GRP);
138 	/* Enable hw interrupt */
139 	plt_write64(~0ull, sso_base + SSO_LF_GGRP_INT_ENA_W1S);
140 
141 	/* Setup threshold for work exec interrupt to 1 wqe in IAQ */
142 	plt_write64(0x1ull, sso_base + SSO_LF_GGRP_INT_THR);
143 
144 	return rc;
145 }
146 
147 void
148 nix_inl_sso_unregister_irqs(struct nix_inl_dev *inl_dev)
149 {
150 	struct plt_intr_handle *handle = inl_dev->pci_dev->intr_handle;
151 	uintptr_t ssow_base = inl_dev->ssow_base;
152 	uintptr_t sso_base = inl_dev->sso_base;
153 	uint16_t sso_msixoff, ssow_msixoff;
154 
155 	ssow_msixoff = inl_dev->ssow_msixoff;
156 	sso_msixoff = inl_dev->sso_msixoff;
157 
158 	/* Clear SSOW interrupt enable */
159 	plt_write64(~0ull, ssow_base + SSOW_LF_GWS_INT_ENA_W1C);
160 	/* Clear SSO/HWGRP interrupt enable */
161 	plt_write64(~0ull, sso_base + SSO_LF_GGRP_INT_ENA_W1C);
162 	/* Clear SSO threshold */
163 	plt_write64(0, sso_base + SSO_LF_GGRP_INT_THR);
164 
165 	/* Unregister IRQ */
166 	dev_irq_unregister(handle, nix_inl_sso_hws_irq, (void *)inl_dev,
167 			   ssow_msixoff + SSOW_LF_INT_VEC_IOP);
168 	dev_irq_unregister(handle, nix_inl_sso_hwgrp_irq, (void *)inl_dev,
169 			   sso_msixoff + SSO_LF_INT_VEC_GRP);
170 }
171 
172 static void
173 nix_inl_nix_q_irq(void *param)
174 {
175 	struct nix_inl_dev *inl_dev = (struct nix_inl_dev *)param;
176 	uintptr_t nix_base = inl_dev->nix_base;
177 	struct dev *dev = &inl_dev->dev;
178 	volatile void *ctx;
179 	uint64_t reg, intr;
180 	uint8_t irq;
181 	int rc;
182 
183 	intr = plt_read64(nix_base + NIX_LF_QINTX_INT(0));
184 	if (intr == 0)
185 		return;
186 
187 	plt_err("Queue_intr=0x%" PRIx64 " qintx 0 pf=%d, vf=%d", intr, dev->pf,
188 		dev->vf);
189 
190 	/* Get and clear RQ0 interrupt */
191 	reg = roc_atomic64_add_nosync(0,
192 				      (int64_t *)(nix_base + NIX_LF_RQ_OP_INT));
193 	if (reg & BIT_ULL(42) /* OP_ERR */) {
194 		plt_err("Failed to get rq_int");
195 		return;
196 	}
197 	irq = reg & 0xff;
198 	plt_write64(0 | irq, nix_base + NIX_LF_RQ_OP_INT);
199 
200 	if (irq & BIT_ULL(NIX_RQINT_DROP))
201 		plt_err("RQ=0 NIX_RQINT_DROP");
202 
203 	if (irq & BIT_ULL(NIX_RQINT_RED))
204 		plt_err("RQ=0 NIX_RQINT_RED");
205 
206 	/* Clear interrupt */
207 	plt_write64(intr, nix_base + NIX_LF_QINTX_INT(0));
208 
209 	/* Dump registers to std out */
210 	nix_inl_nix_reg_dump(inl_dev);
211 
212 	/* Dump RQ 0 */
213 	rc = nix_q_ctx_get(dev, NIX_AQ_CTYPE_RQ, 0, &ctx);
214 	if (rc) {
215 		plt_err("Failed to get rq context");
216 		return;
217 	}
218 	nix_lf_rq_dump(ctx);
219 }
220 
221 static void
222 nix_inl_nix_ras_irq(void *param)
223 {
224 	struct nix_inl_dev *inl_dev = (struct nix_inl_dev *)param;
225 	uintptr_t nix_base = inl_dev->nix_base;
226 	struct dev *dev = &inl_dev->dev;
227 	volatile void *ctx;
228 	uint64_t intr;
229 	int rc;
230 
231 	intr = plt_read64(nix_base + NIX_LF_RAS);
232 	if (intr == 0)
233 		return;
234 
235 	plt_err("Ras_intr=0x%" PRIx64 " pf=%d, vf=%d", intr, dev->pf, dev->vf);
236 	/* Clear interrupt */
237 	plt_write64(intr, nix_base + NIX_LF_RAS);
238 
239 	/* Dump registers to std out */
240 	nix_inl_nix_reg_dump(inl_dev);
241 
242 	/* Dump RQ 0 */
243 	rc = nix_q_ctx_get(dev, NIX_AQ_CTYPE_RQ, 0, &ctx);
244 	if (rc) {
245 		plt_err("Failed to get rq context");
246 		return;
247 	}
248 	nix_lf_rq_dump(ctx);
249 }
250 
251 static void
252 nix_inl_nix_err_irq(void *param)
253 {
254 	struct nix_inl_dev *inl_dev = (struct nix_inl_dev *)param;
255 	uintptr_t nix_base = inl_dev->nix_base;
256 	struct dev *dev = &inl_dev->dev;
257 	volatile void *ctx;
258 	uint64_t intr;
259 	int rc;
260 
261 	intr = plt_read64(nix_base + NIX_LF_ERR_INT);
262 	if (intr == 0)
263 		return;
264 
265 	plt_err("Err_irq=0x%" PRIx64 " pf=%d, vf=%d", intr, dev->pf, dev->vf);
266 
267 	/* Clear interrupt */
268 	plt_write64(intr, nix_base + NIX_LF_ERR_INT);
269 
270 	/* Dump registers to std out */
271 	nix_inl_nix_reg_dump(inl_dev);
272 
273 	/* Dump RQ 0 */
274 	rc = nix_q_ctx_get(dev, NIX_AQ_CTYPE_RQ, 0, &ctx);
275 	if (rc) {
276 		plt_err("Failed to get rq context");
277 		return;
278 	}
279 	nix_lf_rq_dump(ctx);
280 }
281 
282 int
283 nix_inl_nix_register_irqs(struct nix_inl_dev *inl_dev)
284 {
285 	struct plt_intr_handle *handle = inl_dev->pci_dev->intr_handle;
286 	uintptr_t nix_base = inl_dev->nix_base;
287 	uint16_t msixoff;
288 	int rc;
289 
290 	msixoff = inl_dev->nix_msixoff;
291 	if (msixoff == MSIX_VECTOR_INVALID) {
292 		plt_err("Invalid NIXLF MSIX vector offset: 0x%x", msixoff);
293 		return -EINVAL;
294 	}
295 
296 	/* Disable err interrupts */
297 	plt_write64(~0ull, nix_base + NIX_LF_ERR_INT_ENA_W1C);
298 	/* DIsable RAS interrupts */
299 	plt_write64(~0ull, nix_base + NIX_LF_RAS_ENA_W1C);
300 
301 	/* Register err irq */
302 	rc = dev_irq_register(handle, nix_inl_nix_err_irq, inl_dev,
303 			      msixoff + NIX_LF_INT_VEC_ERR_INT);
304 	rc |= dev_irq_register(handle, nix_inl_nix_ras_irq, inl_dev,
305 			       msixoff + NIX_LF_INT_VEC_POISON);
306 
307 	/* Enable all nix lf error irqs except RQ_DISABLED and CQ_DISABLED */
308 	plt_write64(~(BIT_ULL(11) | BIT_ULL(24)),
309 		    nix_base + NIX_LF_ERR_INT_ENA_W1S);
310 	/* Enable RAS interrupts */
311 	plt_write64(~0ull, nix_base + NIX_LF_RAS_ENA_W1S);
312 
313 	/* Setup queue irq for RQ 0 */
314 
315 	/* Clear QINT CNT, interrupt */
316 	plt_write64(0, nix_base + NIX_LF_QINTX_CNT(0));
317 	plt_write64(~0ull, nix_base + NIX_LF_QINTX_ENA_W1C(0));
318 
319 	/* Register queue irq vector */
320 	rc |= dev_irq_register(handle, nix_inl_nix_q_irq, inl_dev,
321 			       msixoff + NIX_LF_INT_VEC_QINT_START);
322 
323 	plt_write64(0, nix_base + NIX_LF_QINTX_CNT(0));
324 	plt_write64(0, nix_base + NIX_LF_QINTX_INT(0));
325 	/* Enable QINT interrupt */
326 	plt_write64(~0ull, nix_base + NIX_LF_QINTX_ENA_W1S(0));
327 
328 	return rc;
329 }
330 
331 void
332 nix_inl_nix_unregister_irqs(struct nix_inl_dev *inl_dev)
333 {
334 	struct plt_intr_handle *handle = inl_dev->pci_dev->intr_handle;
335 	uintptr_t nix_base = inl_dev->nix_base;
336 	uint16_t msixoff;
337 
338 	msixoff = inl_dev->nix_msixoff;
339 	/* Disable err interrupts */
340 	plt_write64(~0ull, nix_base + NIX_LF_ERR_INT_ENA_W1C);
341 	/* DIsable RAS interrupts */
342 	plt_write64(~0ull, nix_base + NIX_LF_RAS_ENA_W1C);
343 
344 	dev_irq_unregister(handle, nix_inl_nix_err_irq, inl_dev,
345 			   msixoff + NIX_LF_INT_VEC_ERR_INT);
346 	dev_irq_unregister(handle, nix_inl_nix_ras_irq, inl_dev,
347 			   msixoff + NIX_LF_INT_VEC_POISON);
348 
349 	/* Clear QINT CNT */
350 	plt_write64(0, nix_base + NIX_LF_QINTX_CNT(0));
351 	plt_write64(0, nix_base + NIX_LF_QINTX_INT(0));
352 
353 	/* Disable QINT interrupt */
354 	plt_write64(~0ull, nix_base + NIX_LF_QINTX_ENA_W1C(0));
355 
356 	/* Unregister queue irq vector */
357 	dev_irq_unregister(handle, nix_inl_nix_q_irq, inl_dev,
358 			   msixoff + NIX_LF_INT_VEC_QINT_START);
359 }
360