1 // SPDX-License-Identifier: GPL-2.0
2 /* Marvell OcteonTx2 RVU Devlink
3  *
4  * Copyright (C) 2020 Marvell.
5  *
6  */
7 
8 #include<linux/bitfield.h>
9 
10 #include "rvu.h"
11 #include "rvu_reg.h"
12 #include "rvu_struct.h"
13 
14 #define DRV_NAME "octeontx2-af"
15 
16 static int rvu_report_pair_start(struct devlink_fmsg *fmsg, const char *name)
17 {
18 	int err;
19 
20 	err = devlink_fmsg_pair_nest_start(fmsg, name);
21 	if (err)
22 		return err;
23 
24 	return  devlink_fmsg_obj_nest_start(fmsg);
25 }
26 
27 static int rvu_report_pair_end(struct devlink_fmsg *fmsg)
28 {
29 	int err;
30 
31 	err = devlink_fmsg_obj_nest_end(fmsg);
32 	if (err)
33 		return err;
34 
35 	return devlink_fmsg_pair_nest_end(fmsg);
36 }
37 
38 static bool rvu_common_request_irq(struct rvu *rvu, int offset,
39 				   const char *name, irq_handler_t fn)
40 {
41 	struct rvu_devlink *rvu_dl = rvu->rvu_dl;
42 	int rc;
43 
44 	sprintf(&rvu->irq_name[offset * NAME_SIZE], name);
45 	rc = request_irq(pci_irq_vector(rvu->pdev, offset), fn, 0,
46 			 &rvu->irq_name[offset * NAME_SIZE], rvu_dl);
47 	if (rc)
48 		dev_warn(rvu->dev, "Failed to register %s irq\n", name);
49 	else
50 		rvu->irq_allocated[offset] = true;
51 
52 	return rvu->irq_allocated[offset];
53 }
54 
55 static void rvu_npa_intr_work(struct work_struct *work)
56 {
57 	struct rvu_npa_health_reporters *rvu_npa_health_reporter;
58 
59 	rvu_npa_health_reporter = container_of(work, struct rvu_npa_health_reporters, intr_work);
60 	devlink_health_report(rvu_npa_health_reporter->rvu_hw_npa_intr_reporter,
61 			      "NPA_AF_RVU Error",
62 			      rvu_npa_health_reporter->npa_event_ctx);
63 }
64 
65 static irqreturn_t rvu_npa_af_rvu_intr_handler(int irq, void *rvu_irq)
66 {
67 	struct rvu_npa_event_ctx *npa_event_context;
68 	struct rvu_devlink *rvu_dl = rvu_irq;
69 	struct rvu *rvu;
70 	int blkaddr;
71 	u64 intr;
72 
73 	rvu = rvu_dl->rvu;
74 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
75 	if (blkaddr < 0)
76 		return IRQ_NONE;
77 
78 	npa_event_context = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;
79 	intr = rvu_read64(rvu, blkaddr, NPA_AF_RVU_INT);
80 	npa_event_context->npa_af_rvu_int = intr;
81 
82 	/* Clear interrupts */
83 	rvu_write64(rvu, blkaddr, NPA_AF_RVU_INT, intr);
84 	rvu_write64(rvu, blkaddr, NPA_AF_RVU_INT_ENA_W1C, ~0ULL);
85 	queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_npa_health_reporter->intr_work);
86 
87 	return IRQ_HANDLED;
88 }
89 
90 static void rvu_npa_gen_work(struct work_struct *work)
91 {
92 	struct rvu_npa_health_reporters *rvu_npa_health_reporter;
93 
94 	rvu_npa_health_reporter = container_of(work, struct rvu_npa_health_reporters, gen_work);
95 	devlink_health_report(rvu_npa_health_reporter->rvu_hw_npa_gen_reporter,
96 			      "NPA_AF_GEN Error",
97 			      rvu_npa_health_reporter->npa_event_ctx);
98 }
99 
100 static irqreturn_t rvu_npa_af_gen_intr_handler(int irq, void *rvu_irq)
101 {
102 	struct rvu_npa_event_ctx *npa_event_context;
103 	struct rvu_devlink *rvu_dl = rvu_irq;
104 	struct rvu *rvu;
105 	int blkaddr;
106 	u64 intr;
107 
108 	rvu = rvu_dl->rvu;
109 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
110 	if (blkaddr < 0)
111 		return IRQ_NONE;
112 
113 	npa_event_context = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;
114 	intr = rvu_read64(rvu, blkaddr, NPA_AF_GEN_INT);
115 	npa_event_context->npa_af_rvu_gen = intr;
116 
117 	/* Clear interrupts */
118 	rvu_write64(rvu, blkaddr, NPA_AF_GEN_INT, intr);
119 	rvu_write64(rvu, blkaddr, NPA_AF_GEN_INT_ENA_W1C, ~0ULL);
120 	queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_npa_health_reporter->gen_work);
121 
122 	return IRQ_HANDLED;
123 }
124 
125 static void rvu_npa_err_work(struct work_struct *work)
126 {
127 	struct rvu_npa_health_reporters *rvu_npa_health_reporter;
128 
129 	rvu_npa_health_reporter = container_of(work, struct rvu_npa_health_reporters, err_work);
130 	devlink_health_report(rvu_npa_health_reporter->rvu_hw_npa_err_reporter,
131 			      "NPA_AF_ERR Error",
132 			      rvu_npa_health_reporter->npa_event_ctx);
133 }
134 
135 static irqreturn_t rvu_npa_af_err_intr_handler(int irq, void *rvu_irq)
136 {
137 	struct rvu_npa_event_ctx *npa_event_context;
138 	struct rvu_devlink *rvu_dl = rvu_irq;
139 	struct rvu *rvu;
140 	int blkaddr;
141 	u64 intr;
142 
143 	rvu = rvu_dl->rvu;
144 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
145 	if (blkaddr < 0)
146 		return IRQ_NONE;
147 	npa_event_context = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;
148 	intr = rvu_read64(rvu, blkaddr, NPA_AF_ERR_INT);
149 	npa_event_context->npa_af_rvu_err = intr;
150 
151 	/* Clear interrupts */
152 	rvu_write64(rvu, blkaddr, NPA_AF_ERR_INT, intr);
153 	rvu_write64(rvu, blkaddr, NPA_AF_ERR_INT_ENA_W1C, ~0ULL);
154 	queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_npa_health_reporter->err_work);
155 
156 	return IRQ_HANDLED;
157 }
158 
159 static void rvu_npa_ras_work(struct work_struct *work)
160 {
161 	struct rvu_npa_health_reporters *rvu_npa_health_reporter;
162 
163 	rvu_npa_health_reporter = container_of(work, struct rvu_npa_health_reporters, ras_work);
164 	devlink_health_report(rvu_npa_health_reporter->rvu_hw_npa_ras_reporter,
165 			      "HW NPA_AF_RAS Error reported",
166 			      rvu_npa_health_reporter->npa_event_ctx);
167 }
168 
169 static irqreturn_t rvu_npa_af_ras_intr_handler(int irq, void *rvu_irq)
170 {
171 	struct rvu_npa_event_ctx *npa_event_context;
172 	struct rvu_devlink *rvu_dl = rvu_irq;
173 	struct rvu *rvu;
174 	int blkaddr;
175 	u64 intr;
176 
177 	rvu = rvu_dl->rvu;
178 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
179 	if (blkaddr < 0)
180 		return IRQ_NONE;
181 
182 	npa_event_context = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;
183 	intr = rvu_read64(rvu, blkaddr, NPA_AF_RAS);
184 	npa_event_context->npa_af_rvu_ras = intr;
185 
186 	/* Clear interrupts */
187 	rvu_write64(rvu, blkaddr, NPA_AF_RAS, intr);
188 	rvu_write64(rvu, blkaddr, NPA_AF_RAS_ENA_W1C, ~0ULL);
189 	queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_npa_health_reporter->ras_work);
190 
191 	return IRQ_HANDLED;
192 }
193 
194 static void rvu_npa_unregister_interrupts(struct rvu *rvu)
195 {
196 	struct rvu_devlink *rvu_dl = rvu->rvu_dl;
197 	int i, offs, blkaddr;
198 	u64 reg;
199 
200 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
201 	if (blkaddr < 0)
202 		return;
203 
204 	reg = rvu_read64(rvu, blkaddr, NPA_PRIV_AF_INT_CFG);
205 	offs = reg & 0x3FF;
206 
207 	rvu_write64(rvu, blkaddr, NPA_AF_RVU_INT_ENA_W1C, ~0ULL);
208 	rvu_write64(rvu, blkaddr, NPA_AF_GEN_INT_ENA_W1C, ~0ULL);
209 	rvu_write64(rvu, blkaddr, NPA_AF_ERR_INT_ENA_W1C, ~0ULL);
210 	rvu_write64(rvu, blkaddr, NPA_AF_RAS_ENA_W1C, ~0ULL);
211 
212 	for (i = 0; i < NPA_AF_INT_VEC_CNT; i++)
213 		if (rvu->irq_allocated[offs + i]) {
214 			free_irq(pci_irq_vector(rvu->pdev, offs + i), rvu_dl);
215 			rvu->irq_allocated[offs + i] = false;
216 		}
217 }
218 
219 static int rvu_npa_register_interrupts(struct rvu *rvu)
220 {
221 	int blkaddr, base;
222 	bool rc;
223 
224 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
225 	if (blkaddr < 0)
226 		return blkaddr;
227 
228 	/* Get NPA AF MSIX vectors offset. */
229 	base = rvu_read64(rvu, blkaddr, NPA_PRIV_AF_INT_CFG) & 0x3ff;
230 	if (!base) {
231 		dev_warn(rvu->dev,
232 			 "Failed to get NPA_AF_INT vector offsets\n");
233 		return 0;
234 	}
235 
236 	/* Register and enable NPA_AF_RVU_INT interrupt */
237 	rc = rvu_common_request_irq(rvu, base +  NPA_AF_INT_VEC_RVU,
238 				    "NPA_AF_RVU_INT",
239 				    rvu_npa_af_rvu_intr_handler);
240 	if (!rc)
241 		goto err;
242 	rvu_write64(rvu, blkaddr, NPA_AF_RVU_INT_ENA_W1S, ~0ULL);
243 
244 	/* Register and enable NPA_AF_GEN_INT interrupt */
245 	rc = rvu_common_request_irq(rvu, base + NPA_AF_INT_VEC_GEN,
246 				    "NPA_AF_RVU_GEN",
247 				    rvu_npa_af_gen_intr_handler);
248 	if (!rc)
249 		goto err;
250 	rvu_write64(rvu, blkaddr, NPA_AF_GEN_INT_ENA_W1S, ~0ULL);
251 
252 	/* Register and enable NPA_AF_ERR_INT interrupt */
253 	rc = rvu_common_request_irq(rvu, base + NPA_AF_INT_VEC_AF_ERR,
254 				    "NPA_AF_ERR_INT",
255 				    rvu_npa_af_err_intr_handler);
256 	if (!rc)
257 		goto err;
258 	rvu_write64(rvu, blkaddr, NPA_AF_ERR_INT_ENA_W1S, ~0ULL);
259 
260 	/* Register and enable NPA_AF_RAS interrupt */
261 	rc = rvu_common_request_irq(rvu, base + NPA_AF_INT_VEC_POISON,
262 				    "NPA_AF_RAS",
263 				    rvu_npa_af_ras_intr_handler);
264 	if (!rc)
265 		goto err;
266 	rvu_write64(rvu, blkaddr, NPA_AF_RAS_ENA_W1S, ~0ULL);
267 
268 	return 0;
269 err:
270 	rvu_npa_unregister_interrupts(rvu);
271 	return rc;
272 }
273 
274 static int rvu_npa_report_show(struct devlink_fmsg *fmsg, void *ctx,
275 			       enum npa_af_rvu_health health_reporter)
276 {
277 	struct rvu_npa_event_ctx *npa_event_context;
278 	unsigned int intr_val, alloc_dis, free_dis;
279 	int err;
280 
281 	npa_event_context = ctx;
282 	switch (health_reporter) {
283 	case NPA_AF_RVU_GEN:
284 		intr_val = npa_event_context->npa_af_rvu_gen;
285 		err = rvu_report_pair_start(fmsg, "NPA_AF_GENERAL");
286 		if (err)
287 			return err;
288 		err = devlink_fmsg_u64_pair_put(fmsg, "\tNPA General Interrupt Reg ",
289 						npa_event_context->npa_af_rvu_gen);
290 		if (err)
291 			return err;
292 		if (intr_val & BIT_ULL(32)) {
293 			err = devlink_fmsg_string_put(fmsg, "\n\tUnmap PF Error");
294 			if (err)
295 				return err;
296 		}
297 
298 		free_dis = FIELD_GET(GENMASK(15, 0), intr_val);
299 		if (free_dis & BIT(NPA_INPQ_NIX0_RX)) {
300 			err = devlink_fmsg_string_put(fmsg, "\n\tNIX0: free disabled RX");
301 			if (err)
302 				return err;
303 		}
304 		if (free_dis & BIT(NPA_INPQ_NIX0_TX)) {
305 			err = devlink_fmsg_string_put(fmsg, "\n\tNIX0:free disabled TX");
306 			if (err)
307 				return err;
308 		}
309 		if (free_dis & BIT(NPA_INPQ_NIX1_RX)) {
310 			err = devlink_fmsg_string_put(fmsg, "\n\tNIX1: free disabled RX");
311 			if (err)
312 				return err;
313 		}
314 		if (free_dis & BIT(NPA_INPQ_NIX1_TX)) {
315 			err = devlink_fmsg_string_put(fmsg, "\n\tNIX1:free disabled TX");
316 			if (err)
317 				return err;
318 		}
319 		if (free_dis & BIT(NPA_INPQ_SSO)) {
320 			err = devlink_fmsg_string_put(fmsg, "\n\tFree Disabled for SSO");
321 			if (err)
322 				return err;
323 		}
324 		if (free_dis & BIT(NPA_INPQ_TIM)) {
325 			err = devlink_fmsg_string_put(fmsg, "\n\tFree Disabled for TIM");
326 			if (err)
327 				return err;
328 		}
329 		if (free_dis & BIT(NPA_INPQ_DPI)) {
330 			err = devlink_fmsg_string_put(fmsg, "\n\tFree Disabled for DPI");
331 			if (err)
332 				return err;
333 		}
334 		if (free_dis & BIT(NPA_INPQ_AURA_OP)) {
335 			err = devlink_fmsg_string_put(fmsg, "\n\tFree Disabled for AURA");
336 			if (err)
337 				return err;
338 		}
339 
340 		alloc_dis = FIELD_GET(GENMASK(31, 16), intr_val);
341 		if (alloc_dis & BIT(NPA_INPQ_NIX0_RX)) {
342 			err = devlink_fmsg_string_put(fmsg, "\n\tNIX0: alloc disabled RX");
343 			if (err)
344 				return err;
345 		}
346 		if (alloc_dis & BIT(NPA_INPQ_NIX0_TX)) {
347 			err = devlink_fmsg_string_put(fmsg, "\n\tNIX0:alloc disabled TX");
348 			if (err)
349 				return err;
350 		}
351 		if (alloc_dis & BIT(NPA_INPQ_NIX1_RX)) {
352 			err = devlink_fmsg_string_put(fmsg, "\n\tNIX1: alloc disabled RX");
353 			if (err)
354 				return err;
355 		}
356 		if (alloc_dis & BIT(NPA_INPQ_NIX1_TX)) {
357 			err = devlink_fmsg_string_put(fmsg, "\n\tNIX1:alloc disabled TX");
358 			if (err)
359 				return err;
360 		}
361 		if (alloc_dis & BIT(NPA_INPQ_SSO)) {
362 			err = devlink_fmsg_string_put(fmsg, "\n\tAlloc Disabled for SSO");
363 			if (err)
364 				return err;
365 		}
366 		if (alloc_dis & BIT(NPA_INPQ_TIM)) {
367 			err = devlink_fmsg_string_put(fmsg, "\n\tAlloc Disabled for TIM");
368 			if (err)
369 				return err;
370 		}
371 		if (alloc_dis & BIT(NPA_INPQ_DPI)) {
372 			err = devlink_fmsg_string_put(fmsg, "\n\tAlloc Disabled for DPI");
373 			if (err)
374 				return err;
375 		}
376 		if (alloc_dis & BIT(NPA_INPQ_AURA_OP)) {
377 			err = devlink_fmsg_string_put(fmsg, "\n\tAlloc Disabled for AURA");
378 			if (err)
379 				return err;
380 		}
381 		err = rvu_report_pair_end(fmsg);
382 		if (err)
383 			return err;
384 		break;
385 	case NPA_AF_RVU_ERR:
386 		err = rvu_report_pair_start(fmsg, "NPA_AF_ERR");
387 		if (err)
388 			return err;
389 		err = devlink_fmsg_u64_pair_put(fmsg, "\tNPA Error Interrupt Reg ",
390 						npa_event_context->npa_af_rvu_err);
391 		if (err)
392 			return err;
393 
394 		if (npa_event_context->npa_af_rvu_err & BIT_ULL(14)) {
395 			err = devlink_fmsg_string_put(fmsg, "\n\tFault on NPA_AQ_INST_S read");
396 			if (err)
397 				return err;
398 		}
399 		if (npa_event_context->npa_af_rvu_err & BIT_ULL(13)) {
400 			err = devlink_fmsg_string_put(fmsg, "\n\tFault on NPA_AQ_RES_S write");
401 			if (err)
402 				return err;
403 		}
404 		if (npa_event_context->npa_af_rvu_err & BIT_ULL(12)) {
405 			err = devlink_fmsg_string_put(fmsg, "\n\tAQ Doorbell Error");
406 			if (err)
407 				return err;
408 		}
409 		err = rvu_report_pair_end(fmsg);
410 		if (err)
411 			return err;
412 		break;
413 	case NPA_AF_RVU_RAS:
414 		err = rvu_report_pair_start(fmsg, "NPA_AF_RVU_RAS");
415 		if (err)
416 			return err;
417 		err = devlink_fmsg_u64_pair_put(fmsg, "\tNPA RAS Interrupt Reg ",
418 						npa_event_context->npa_af_rvu_ras);
419 		if (err)
420 			return err;
421 		if (npa_event_context->npa_af_rvu_ras & BIT_ULL(34)) {
422 			err = devlink_fmsg_string_put(fmsg, "\n\tPoison data on NPA_AQ_INST_S");
423 			if (err)
424 				return err;
425 		}
426 		if (npa_event_context->npa_af_rvu_ras & BIT_ULL(33)) {
427 			err = devlink_fmsg_string_put(fmsg, "\n\tPoison data on NPA_AQ_RES_S");
428 			if (err)
429 				return err;
430 		}
431 		if (npa_event_context->npa_af_rvu_ras & BIT_ULL(32)) {
432 			err = devlink_fmsg_string_put(fmsg, "\n\tPoison data on HW context");
433 			if (err)
434 				return err;
435 		}
436 		err = rvu_report_pair_end(fmsg);
437 		if (err)
438 			return err;
439 		break;
440 	case NPA_AF_RVU_INTR:
441 		err = rvu_report_pair_start(fmsg, "NPA_AF_RVU");
442 		if (err)
443 			return err;
444 		err = devlink_fmsg_u64_pair_put(fmsg, "\tNPA RVU Interrupt Reg ",
445 						npa_event_context->npa_af_rvu_int);
446 		if (err)
447 			return err;
448 		if (npa_event_context->npa_af_rvu_int & BIT_ULL(0)) {
449 			err = devlink_fmsg_string_put(fmsg, "\n\tUnmap Slot Error");
450 			if (err)
451 				return err;
452 		}
453 		return rvu_report_pair_end(fmsg);
454 	default:
455 		return -EINVAL;
456 	}
457 
458 	return 0;
459 }
460 
461 static int rvu_hw_npa_intr_dump(struct devlink_health_reporter *reporter,
462 				struct devlink_fmsg *fmsg, void *ctx,
463 				struct netlink_ext_ack *netlink_extack)
464 {
465 	struct rvu *rvu = devlink_health_reporter_priv(reporter);
466 	struct rvu_devlink *rvu_dl = rvu->rvu_dl;
467 	struct rvu_npa_event_ctx *npa_ctx;
468 
469 	npa_ctx = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;
470 
471 	return ctx ? rvu_npa_report_show(fmsg, ctx, NPA_AF_RVU_INTR) :
472 		     rvu_npa_report_show(fmsg, npa_ctx, NPA_AF_RVU_INTR);
473 }
474 
475 static int rvu_hw_npa_intr_recover(struct devlink_health_reporter *reporter,
476 				   void *ctx, struct netlink_ext_ack *netlink_extack)
477 {
478 	struct rvu *rvu = devlink_health_reporter_priv(reporter);
479 	struct rvu_npa_event_ctx *npa_event_ctx = ctx;
480 	int blkaddr;
481 
482 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
483 	if (blkaddr < 0)
484 		return blkaddr;
485 
486 	if (npa_event_ctx->npa_af_rvu_int)
487 		rvu_write64(rvu, blkaddr, NPA_AF_RVU_INT_ENA_W1S, ~0ULL);
488 
489 	return 0;
490 }
491 
492 static int rvu_hw_npa_gen_dump(struct devlink_health_reporter *reporter,
493 			       struct devlink_fmsg *fmsg, void *ctx,
494 			       struct netlink_ext_ack *netlink_extack)
495 {
496 	struct rvu *rvu = devlink_health_reporter_priv(reporter);
497 	struct rvu_devlink *rvu_dl = rvu->rvu_dl;
498 	struct rvu_npa_event_ctx *npa_ctx;
499 
500 	npa_ctx = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;
501 
502 	return ctx ? rvu_npa_report_show(fmsg, ctx, NPA_AF_RVU_GEN) :
503 		     rvu_npa_report_show(fmsg, npa_ctx, NPA_AF_RVU_GEN);
504 }
505 
506 static int rvu_hw_npa_gen_recover(struct devlink_health_reporter *reporter,
507 				  void *ctx, struct netlink_ext_ack *netlink_extack)
508 {
509 	struct rvu *rvu = devlink_health_reporter_priv(reporter);
510 	struct rvu_npa_event_ctx *npa_event_ctx = ctx;
511 	int blkaddr;
512 
513 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
514 	if (blkaddr < 0)
515 		return blkaddr;
516 
517 	if (npa_event_ctx->npa_af_rvu_gen)
518 		rvu_write64(rvu, blkaddr, NPA_AF_GEN_INT_ENA_W1S, ~0ULL);
519 
520 	return 0;
521 }
522 
523 static int rvu_hw_npa_err_dump(struct devlink_health_reporter *reporter,
524 			       struct devlink_fmsg *fmsg, void *ctx,
525 			       struct netlink_ext_ack *netlink_extack)
526 {
527 	struct rvu *rvu = devlink_health_reporter_priv(reporter);
528 	struct rvu_devlink *rvu_dl = rvu->rvu_dl;
529 	struct rvu_npa_event_ctx *npa_ctx;
530 
531 	npa_ctx = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;
532 
533 	return ctx ? rvu_npa_report_show(fmsg, ctx, NPA_AF_RVU_ERR) :
534 		     rvu_npa_report_show(fmsg, npa_ctx, NPA_AF_RVU_ERR);
535 }
536 
537 static int rvu_hw_npa_err_recover(struct devlink_health_reporter *reporter,
538 				  void *ctx, struct netlink_ext_ack *netlink_extack)
539 {
540 	struct rvu *rvu = devlink_health_reporter_priv(reporter);
541 	struct rvu_npa_event_ctx *npa_event_ctx = ctx;
542 	int blkaddr;
543 
544 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
545 	if (blkaddr < 0)
546 		return blkaddr;
547 
548 	if (npa_event_ctx->npa_af_rvu_err)
549 		rvu_write64(rvu, blkaddr, NPA_AF_ERR_INT_ENA_W1S, ~0ULL);
550 
551 	return 0;
552 }
553 
554 static int rvu_hw_npa_ras_dump(struct devlink_health_reporter *reporter,
555 			       struct devlink_fmsg *fmsg, void *ctx,
556 			       struct netlink_ext_ack *netlink_extack)
557 {
558 	struct rvu *rvu = devlink_health_reporter_priv(reporter);
559 	struct rvu_devlink *rvu_dl = rvu->rvu_dl;
560 	struct rvu_npa_event_ctx *npa_ctx;
561 
562 	npa_ctx = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;
563 
564 	return ctx ? rvu_npa_report_show(fmsg, ctx, NPA_AF_RVU_RAS) :
565 		     rvu_npa_report_show(fmsg, npa_ctx, NPA_AF_RVU_RAS);
566 }
567 
568 static int rvu_hw_npa_ras_recover(struct devlink_health_reporter *reporter,
569 				  void *ctx, struct netlink_ext_ack *netlink_extack)
570 {
571 	struct rvu *rvu = devlink_health_reporter_priv(reporter);
572 	struct rvu_npa_event_ctx *npa_event_ctx = ctx;
573 	int blkaddr;
574 
575 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
576 	if (blkaddr < 0)
577 		return blkaddr;
578 
579 	if (npa_event_ctx->npa_af_rvu_ras)
580 		rvu_write64(rvu, blkaddr, NPA_AF_RAS_ENA_W1S, ~0ULL);
581 
582 	return 0;
583 }
584 
585 RVU_REPORTERS(hw_npa_intr);
586 RVU_REPORTERS(hw_npa_gen);
587 RVU_REPORTERS(hw_npa_err);
588 RVU_REPORTERS(hw_npa_ras);
589 
590 static void rvu_npa_health_reporters_destroy(struct rvu_devlink *rvu_dl);
591 
592 static int rvu_npa_register_reporters(struct rvu_devlink *rvu_dl)
593 {
594 	struct rvu_npa_health_reporters *rvu_reporters;
595 	struct rvu_npa_event_ctx *npa_event_context;
596 	struct rvu *rvu = rvu_dl->rvu;
597 
598 	rvu_reporters = kzalloc(sizeof(*rvu_reporters), GFP_KERNEL);
599 	if (!rvu_reporters)
600 		return -ENOMEM;
601 
602 	rvu_dl->rvu_npa_health_reporter = rvu_reporters;
603 	npa_event_context = kzalloc(sizeof(*npa_event_context), GFP_KERNEL);
604 	if (!npa_event_context)
605 		return -ENOMEM;
606 
607 	rvu_reporters->npa_event_ctx = npa_event_context;
608 	rvu_reporters->rvu_hw_npa_intr_reporter =
609 		devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_npa_intr_reporter_ops, 0, rvu);
610 	if (IS_ERR(rvu_reporters->rvu_hw_npa_intr_reporter)) {
611 		dev_warn(rvu->dev, "Failed to create hw_npa_intr reporter, err=%ld\n",
612 			 PTR_ERR(rvu_reporters->rvu_hw_npa_intr_reporter));
613 		return PTR_ERR(rvu_reporters->rvu_hw_npa_intr_reporter);
614 	}
615 
616 	rvu_reporters->rvu_hw_npa_gen_reporter =
617 		devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_npa_gen_reporter_ops, 0, rvu);
618 	if (IS_ERR(rvu_reporters->rvu_hw_npa_gen_reporter)) {
619 		dev_warn(rvu->dev, "Failed to create hw_npa_gen reporter, err=%ld\n",
620 			 PTR_ERR(rvu_reporters->rvu_hw_npa_gen_reporter));
621 		return PTR_ERR(rvu_reporters->rvu_hw_npa_gen_reporter);
622 	}
623 
624 	rvu_reporters->rvu_hw_npa_err_reporter =
625 		devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_npa_err_reporter_ops, 0, rvu);
626 	if (IS_ERR(rvu_reporters->rvu_hw_npa_err_reporter)) {
627 		dev_warn(rvu->dev, "Failed to create hw_npa_err reporter, err=%ld\n",
628 			 PTR_ERR(rvu_reporters->rvu_hw_npa_err_reporter));
629 		return PTR_ERR(rvu_reporters->rvu_hw_npa_err_reporter);
630 	}
631 
632 	rvu_reporters->rvu_hw_npa_ras_reporter =
633 		devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_npa_ras_reporter_ops, 0, rvu);
634 	if (IS_ERR(rvu_reporters->rvu_hw_npa_ras_reporter)) {
635 		dev_warn(rvu->dev, "Failed to create hw_npa_ras reporter, err=%ld\n",
636 			 PTR_ERR(rvu_reporters->rvu_hw_npa_ras_reporter));
637 		return PTR_ERR(rvu_reporters->rvu_hw_npa_ras_reporter);
638 	}
639 
640 	rvu_dl->devlink_wq = create_workqueue("rvu_devlink_wq");
641 	if (!rvu_dl->devlink_wq)
642 		goto err;
643 
644 	INIT_WORK(&rvu_reporters->intr_work, rvu_npa_intr_work);
645 	INIT_WORK(&rvu_reporters->err_work, rvu_npa_err_work);
646 	INIT_WORK(&rvu_reporters->gen_work, rvu_npa_gen_work);
647 	INIT_WORK(&rvu_reporters->ras_work, rvu_npa_ras_work);
648 
649 	return 0;
650 err:
651 	rvu_npa_health_reporters_destroy(rvu_dl);
652 	return -ENOMEM;
653 }
654 
655 static int rvu_npa_health_reporters_create(struct rvu_devlink *rvu_dl)
656 {
657 	struct rvu *rvu = rvu_dl->rvu;
658 	int err;
659 
660 	err = rvu_npa_register_reporters(rvu_dl);
661 	if (err) {
662 		dev_warn(rvu->dev, "Failed to create npa reporter, err =%d\n",
663 			 err);
664 		return err;
665 	}
666 	rvu_npa_register_interrupts(rvu);
667 
668 	return 0;
669 }
670 
671 static void rvu_npa_health_reporters_destroy(struct rvu_devlink *rvu_dl)
672 {
673 	struct rvu_npa_health_reporters *npa_reporters;
674 	struct rvu *rvu = rvu_dl->rvu;
675 
676 	npa_reporters = rvu_dl->rvu_npa_health_reporter;
677 
678 	if (!npa_reporters->rvu_hw_npa_ras_reporter)
679 		return;
680 	if (!IS_ERR_OR_NULL(npa_reporters->rvu_hw_npa_intr_reporter))
681 		devlink_health_reporter_destroy(npa_reporters->rvu_hw_npa_intr_reporter);
682 
683 	if (!IS_ERR_OR_NULL(npa_reporters->rvu_hw_npa_gen_reporter))
684 		devlink_health_reporter_destroy(npa_reporters->rvu_hw_npa_gen_reporter);
685 
686 	if (!IS_ERR_OR_NULL(npa_reporters->rvu_hw_npa_err_reporter))
687 		devlink_health_reporter_destroy(npa_reporters->rvu_hw_npa_err_reporter);
688 
689 	if (!IS_ERR_OR_NULL(npa_reporters->rvu_hw_npa_ras_reporter))
690 		devlink_health_reporter_destroy(npa_reporters->rvu_hw_npa_ras_reporter);
691 
692 	rvu_npa_unregister_interrupts(rvu);
693 	kfree(rvu_dl->rvu_npa_health_reporter->npa_event_ctx);
694 	kfree(rvu_dl->rvu_npa_health_reporter);
695 }
696 
697 static int rvu_health_reporters_create(struct rvu *rvu)
698 {
699 	struct rvu_devlink *rvu_dl;
700 
701 	rvu_dl = rvu->rvu_dl;
702 	return rvu_npa_health_reporters_create(rvu_dl);
703 }
704 
705 static void rvu_health_reporters_destroy(struct rvu *rvu)
706 {
707 	struct rvu_devlink *rvu_dl;
708 
709 	if (!rvu->rvu_dl)
710 		return;
711 
712 	rvu_dl = rvu->rvu_dl;
713 	rvu_npa_health_reporters_destroy(rvu_dl);
714 }
715 
716 static int rvu_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
717 				struct netlink_ext_ack *extack)
718 {
719 	return devlink_info_driver_name_put(req, DRV_NAME);
720 }
721 
722 static const struct devlink_ops rvu_devlink_ops = {
723 	.info_get = rvu_devlink_info_get,
724 };
725 
726 int rvu_register_dl(struct rvu *rvu)
727 {
728 	struct rvu_devlink *rvu_dl;
729 	struct devlink *dl;
730 	int err;
731 
732 	rvu_dl = kzalloc(sizeof(*rvu_dl), GFP_KERNEL);
733 	if (!rvu_dl)
734 		return -ENOMEM;
735 
736 	dl = devlink_alloc(&rvu_devlink_ops, sizeof(struct rvu_devlink));
737 	if (!dl) {
738 		dev_warn(rvu->dev, "devlink_alloc failed\n");
739 		kfree(rvu_dl);
740 		return -ENOMEM;
741 	}
742 
743 	err = devlink_register(dl, rvu->dev);
744 	if (err) {
745 		dev_err(rvu->dev, "devlink register failed with error %d\n", err);
746 		devlink_free(dl);
747 		kfree(rvu_dl);
748 		return err;
749 	}
750 
751 	rvu_dl->dl = dl;
752 	rvu_dl->rvu = rvu;
753 	rvu->rvu_dl = rvu_dl;
754 
755 	return rvu_health_reporters_create(rvu);
756 }
757 
758 void rvu_unregister_dl(struct rvu *rvu)
759 {
760 	struct rvu_devlink *rvu_dl = rvu->rvu_dl;
761 	struct devlink *dl = rvu_dl->dl;
762 
763 	if (!dl)
764 		return;
765 
766 	rvu_health_reporters_destroy(rvu);
767 	devlink_unregister(dl);
768 	devlink_free(dl);
769 	kfree(rvu_dl);
770 }
771