1582 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Marvell RVU Admin Function Devlink3 *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#include "rvu_npc_hash.h"14 15#define DRV_NAME "octeontx2-af"16 17static void rvu_report_pair_start(struct devlink_fmsg *fmsg, const char *name)18{19 devlink_fmsg_pair_nest_start(fmsg, name);20 devlink_fmsg_obj_nest_start(fmsg);21}22 23static void rvu_report_pair_end(struct devlink_fmsg *fmsg)24{25 devlink_fmsg_obj_nest_end(fmsg);26 devlink_fmsg_pair_nest_end(fmsg);27}28 29static bool rvu_common_request_irq(struct rvu *rvu, int offset,30 const char *name, irq_handler_t fn)31{32 struct rvu_devlink *rvu_dl = rvu->rvu_dl;33 int rc;34 35 sprintf(&rvu->irq_name[offset * NAME_SIZE], "%s", name);36 rc = request_irq(pci_irq_vector(rvu->pdev, offset), fn, 0,37 &rvu->irq_name[offset * NAME_SIZE], rvu_dl);38 if (rc)39 dev_warn(rvu->dev, "Failed to register %s irq\n", name);40 else41 rvu->irq_allocated[offset] = true;42 43 return rvu->irq_allocated[offset];44}45 46static void rvu_nix_intr_work(struct work_struct *work)47{48 struct rvu_nix_health_reporters *rvu_nix_health_reporter;49 50 rvu_nix_health_reporter = container_of(work, struct rvu_nix_health_reporters, intr_work);51 devlink_health_report(rvu_nix_health_reporter->rvu_hw_nix_intr_reporter,52 "NIX_AF_RVU Error",53 rvu_nix_health_reporter->nix_event_ctx);54}55 56static irqreturn_t rvu_nix_af_rvu_intr_handler(int irq, void *rvu_irq)57{58 struct rvu_nix_event_ctx *nix_event_context;59 struct rvu_devlink *rvu_dl = rvu_irq;60 struct rvu *rvu;61 int blkaddr;62 u64 intr;63 64 rvu = rvu_dl->rvu;65 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);66 if (blkaddr < 0)67 return IRQ_NONE;68 69 nix_event_context = rvu_dl->rvu_nix_health_reporter->nix_event_ctx;70 intr = rvu_read64(rvu, blkaddr, NIX_AF_RVU_INT);71 nix_event_context->nix_af_rvu_int = intr;72 73 /* Clear interrupts */74 rvu_write64(rvu, blkaddr, NIX_AF_RVU_INT, intr);75 rvu_write64(rvu, blkaddr, NIX_AF_RVU_INT_ENA_W1C, ~0ULL);76 queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_nix_health_reporter->intr_work);77 78 return IRQ_HANDLED;79}80 81static void rvu_nix_gen_work(struct work_struct *work)82{83 struct rvu_nix_health_reporters *rvu_nix_health_reporter;84 85 rvu_nix_health_reporter = container_of(work, struct rvu_nix_health_reporters, gen_work);86 devlink_health_report(rvu_nix_health_reporter->rvu_hw_nix_gen_reporter,87 "NIX_AF_GEN Error",88 rvu_nix_health_reporter->nix_event_ctx);89}90 91static irqreturn_t rvu_nix_af_rvu_gen_handler(int irq, void *rvu_irq)92{93 struct rvu_nix_event_ctx *nix_event_context;94 struct rvu_devlink *rvu_dl = rvu_irq;95 struct rvu *rvu;96 int blkaddr;97 u64 intr;98 99 rvu = rvu_dl->rvu;100 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);101 if (blkaddr < 0)102 return IRQ_NONE;103 104 nix_event_context = rvu_dl->rvu_nix_health_reporter->nix_event_ctx;105 intr = rvu_read64(rvu, blkaddr, NIX_AF_GEN_INT);106 nix_event_context->nix_af_rvu_gen = intr;107 108 /* Clear interrupts */109 rvu_write64(rvu, blkaddr, NIX_AF_GEN_INT, intr);110 rvu_write64(rvu, blkaddr, NIX_AF_GEN_INT_ENA_W1C, ~0ULL);111 queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_nix_health_reporter->gen_work);112 113 return IRQ_HANDLED;114}115 116static void rvu_nix_err_work(struct work_struct *work)117{118 struct rvu_nix_health_reporters *rvu_nix_health_reporter;119 120 rvu_nix_health_reporter = container_of(work, struct rvu_nix_health_reporters, err_work);121 devlink_health_report(rvu_nix_health_reporter->rvu_hw_nix_err_reporter,122 "NIX_AF_ERR Error",123 rvu_nix_health_reporter->nix_event_ctx);124}125 126static irqreturn_t rvu_nix_af_rvu_err_handler(int irq, void *rvu_irq)127{128 struct rvu_nix_event_ctx *nix_event_context;129 struct rvu_devlink *rvu_dl = rvu_irq;130 struct rvu *rvu;131 int blkaddr;132 u64 intr;133 134 rvu = rvu_dl->rvu;135 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);136 if (blkaddr < 0)137 return IRQ_NONE;138 139 nix_event_context = rvu_dl->rvu_nix_health_reporter->nix_event_ctx;140 intr = rvu_read64(rvu, blkaddr, NIX_AF_ERR_INT);141 nix_event_context->nix_af_rvu_err = intr;142 143 /* Clear interrupts */144 rvu_write64(rvu, blkaddr, NIX_AF_ERR_INT, intr);145 rvu_write64(rvu, blkaddr, NIX_AF_ERR_INT_ENA_W1C, ~0ULL);146 queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_nix_health_reporter->err_work);147 148 return IRQ_HANDLED;149}150 151static void rvu_nix_ras_work(struct work_struct *work)152{153 struct rvu_nix_health_reporters *rvu_nix_health_reporter;154 155 rvu_nix_health_reporter = container_of(work, struct rvu_nix_health_reporters, ras_work);156 devlink_health_report(rvu_nix_health_reporter->rvu_hw_nix_ras_reporter,157 "NIX_AF_RAS Error",158 rvu_nix_health_reporter->nix_event_ctx);159}160 161static irqreturn_t rvu_nix_af_rvu_ras_handler(int irq, void *rvu_irq)162{163 struct rvu_nix_event_ctx *nix_event_context;164 struct rvu_devlink *rvu_dl = rvu_irq;165 struct rvu *rvu;166 int blkaddr;167 u64 intr;168 169 rvu = rvu_dl->rvu;170 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);171 if (blkaddr < 0)172 return IRQ_NONE;173 174 nix_event_context = rvu_dl->rvu_nix_health_reporter->nix_event_ctx;175 intr = rvu_read64(rvu, blkaddr, NIX_AF_ERR_INT);176 nix_event_context->nix_af_rvu_ras = intr;177 178 /* Clear interrupts */179 rvu_write64(rvu, blkaddr, NIX_AF_RAS, intr);180 rvu_write64(rvu, blkaddr, NIX_AF_RAS_ENA_W1C, ~0ULL);181 queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_nix_health_reporter->ras_work);182 183 return IRQ_HANDLED;184}185 186static void rvu_nix_unregister_interrupts(struct rvu *rvu)187{188 struct rvu_devlink *rvu_dl = rvu->rvu_dl;189 int offs, i, blkaddr;190 191 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);192 if (blkaddr < 0)193 return;194 195 offs = rvu_read64(rvu, blkaddr, NIX_PRIV_AF_INT_CFG) & 0x3ff;196 if (!offs)197 return;198 199 rvu_write64(rvu, blkaddr, NIX_AF_RVU_INT_ENA_W1C, ~0ULL);200 rvu_write64(rvu, blkaddr, NIX_AF_GEN_INT_ENA_W1C, ~0ULL);201 rvu_write64(rvu, blkaddr, NIX_AF_ERR_INT_ENA_W1C, ~0ULL);202 rvu_write64(rvu, blkaddr, NIX_AF_RAS_ENA_W1C, ~0ULL);203 204 if (rvu->irq_allocated[offs + NIX_AF_INT_VEC_RVU]) {205 free_irq(pci_irq_vector(rvu->pdev, offs + NIX_AF_INT_VEC_RVU),206 rvu_dl);207 rvu->irq_allocated[offs + NIX_AF_INT_VEC_RVU] = false;208 }209 210 for (i = NIX_AF_INT_VEC_AF_ERR; i < NIX_AF_INT_VEC_CNT; i++)211 if (rvu->irq_allocated[offs + i]) {212 free_irq(pci_irq_vector(rvu->pdev, offs + i), rvu_dl);213 rvu->irq_allocated[offs + i] = false;214 }215}216 217static int rvu_nix_register_interrupts(struct rvu *rvu)218{219 int blkaddr, base;220 bool rc;221 222 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);223 if (blkaddr < 0)224 return blkaddr;225 226 /* Get NIX AF MSIX vectors offset. */227 base = rvu_read64(rvu, blkaddr, NIX_PRIV_AF_INT_CFG) & 0x3ff;228 if (!base) {229 dev_warn(rvu->dev,230 "Failed to get NIX%d NIX_AF_INT vector offsets\n",231 blkaddr - BLKADDR_NIX0);232 return 0;233 }234 /* Register and enable NIX_AF_RVU_INT interrupt */235 rc = rvu_common_request_irq(rvu, base + NIX_AF_INT_VEC_RVU,236 "NIX_AF_RVU_INT",237 rvu_nix_af_rvu_intr_handler);238 if (!rc)239 goto err;240 rvu_write64(rvu, blkaddr, NIX_AF_RVU_INT_ENA_W1S, ~0ULL);241 242 /* Register and enable NIX_AF_GEN_INT interrupt */243 rc = rvu_common_request_irq(rvu, base + NIX_AF_INT_VEC_GEN,244 "NIX_AF_GEN_INT",245 rvu_nix_af_rvu_gen_handler);246 if (!rc)247 goto err;248 rvu_write64(rvu, blkaddr, NIX_AF_GEN_INT_ENA_W1S, ~0ULL);249 250 /* Register and enable NIX_AF_ERR_INT interrupt */251 rc = rvu_common_request_irq(rvu, base + NIX_AF_INT_VEC_AF_ERR,252 "NIX_AF_ERR_INT",253 rvu_nix_af_rvu_err_handler);254 if (!rc)255 goto err;256 rvu_write64(rvu, blkaddr, NIX_AF_ERR_INT_ENA_W1S, ~0ULL);257 258 /* Register and enable NIX_AF_RAS interrupt */259 rc = rvu_common_request_irq(rvu, base + NIX_AF_INT_VEC_POISON,260 "NIX_AF_RAS",261 rvu_nix_af_rvu_ras_handler);262 if (!rc)263 goto err;264 rvu_write64(rvu, blkaddr, NIX_AF_RAS_ENA_W1S, ~0ULL);265 266 return 0;267err:268 rvu_nix_unregister_interrupts(rvu);269 return rc;270}271 272static int rvu_nix_report_show(struct devlink_fmsg *fmsg, void *ctx,273 enum nix_af_rvu_health health_reporter)274{275 struct rvu_nix_event_ctx *nix_event_context;276 u64 intr_val;277 278 nix_event_context = ctx;279 switch (health_reporter) {280 case NIX_AF_RVU_INTR:281 intr_val = nix_event_context->nix_af_rvu_int;282 rvu_report_pair_start(fmsg, "NIX_AF_RVU");283 devlink_fmsg_u64_pair_put(fmsg, "\tNIX RVU Interrupt Reg ",284 nix_event_context->nix_af_rvu_int);285 if (intr_val & BIT_ULL(0))286 devlink_fmsg_string_put(fmsg, "\n\tUnmap Slot Error");287 rvu_report_pair_end(fmsg);288 break;289 case NIX_AF_RVU_GEN:290 intr_val = nix_event_context->nix_af_rvu_gen;291 rvu_report_pair_start(fmsg, "NIX_AF_GENERAL");292 devlink_fmsg_u64_pair_put(fmsg, "\tNIX General Interrupt Reg ",293 nix_event_context->nix_af_rvu_gen);294 if (intr_val & BIT_ULL(0))295 devlink_fmsg_string_put(fmsg, "\n\tRx multicast pkt drop");296 if (intr_val & BIT_ULL(1))297 devlink_fmsg_string_put(fmsg, "\n\tRx mirror pkt drop");298 if (intr_val & BIT_ULL(4))299 devlink_fmsg_string_put(fmsg, "\n\tSMQ flush done");300 rvu_report_pair_end(fmsg);301 break;302 case NIX_AF_RVU_ERR:303 intr_val = nix_event_context->nix_af_rvu_err;304 rvu_report_pair_start(fmsg, "NIX_AF_ERR");305 devlink_fmsg_u64_pair_put(fmsg, "\tNIX Error Interrupt Reg ",306 nix_event_context->nix_af_rvu_err);307 if (intr_val & BIT_ULL(14))308 devlink_fmsg_string_put(fmsg, "\n\tFault on NIX_AQ_INST_S read");309 if (intr_val & BIT_ULL(13))310 devlink_fmsg_string_put(fmsg, "\n\tFault on NIX_AQ_RES_S write");311 if (intr_val & BIT_ULL(12))312 devlink_fmsg_string_put(fmsg, "\n\tAQ Doorbell Error");313 if (intr_val & BIT_ULL(6))314 devlink_fmsg_string_put(fmsg, "\n\tRx on unmapped PF_FUNC");315 if (intr_val & BIT_ULL(5))316 devlink_fmsg_string_put(fmsg, "\n\tRx multicast replication error");317 if (intr_val & BIT_ULL(4))318 devlink_fmsg_string_put(fmsg, "\n\tFault on NIX_RX_MCE_S read");319 if (intr_val & BIT_ULL(3))320 devlink_fmsg_string_put(fmsg, "\n\tFault on multicast WQE read");321 if (intr_val & BIT_ULL(2))322 devlink_fmsg_string_put(fmsg, "\n\tFault on mirror WQE read");323 if (intr_val & BIT_ULL(1))324 devlink_fmsg_string_put(fmsg, "\n\tFault on mirror pkt write");325 if (intr_val & BIT_ULL(0))326 devlink_fmsg_string_put(fmsg, "\n\tFault on multicast pkt write");327 rvu_report_pair_end(fmsg);328 break;329 case NIX_AF_RVU_RAS:330 intr_val = nix_event_context->nix_af_rvu_err;331 rvu_report_pair_start(fmsg, "NIX_AF_RAS");332 devlink_fmsg_u64_pair_put(fmsg, "\tNIX RAS Interrupt Reg ",333 nix_event_context->nix_af_rvu_err);334 devlink_fmsg_string_put(fmsg, "\n\tPoison Data on:");335 if (intr_val & BIT_ULL(34))336 devlink_fmsg_string_put(fmsg, "\n\tNIX_AQ_INST_S");337 if (intr_val & BIT_ULL(33))338 devlink_fmsg_string_put(fmsg, "\n\tNIX_AQ_RES_S");339 if (intr_val & BIT_ULL(32))340 devlink_fmsg_string_put(fmsg, "\n\tHW ctx");341 if (intr_val & BIT_ULL(4))342 devlink_fmsg_string_put(fmsg, "\n\tPacket from mirror buffer");343 if (intr_val & BIT_ULL(3))344 devlink_fmsg_string_put(fmsg, "\n\tPacket from multicast buffer");345 if (intr_val & BIT_ULL(2))346 devlink_fmsg_string_put(fmsg, "\n\tWQE read from mirror buffer");347 if (intr_val & BIT_ULL(1))348 devlink_fmsg_string_put(fmsg, "\n\tWQE read from multicast buffer");349 if (intr_val & BIT_ULL(0))350 devlink_fmsg_string_put(fmsg, "\n\tNIX_RX_MCE_S read");351 rvu_report_pair_end(fmsg);352 break;353 default:354 return -EINVAL;355 }356 357 return 0;358}359 360static int rvu_hw_nix_intr_dump(struct devlink_health_reporter *reporter,361 struct devlink_fmsg *fmsg, void *ctx,362 struct netlink_ext_ack *netlink_extack)363{364 struct rvu *rvu = devlink_health_reporter_priv(reporter);365 struct rvu_devlink *rvu_dl = rvu->rvu_dl;366 struct rvu_nix_event_ctx *nix_ctx;367 368 nix_ctx = rvu_dl->rvu_nix_health_reporter->nix_event_ctx;369 370 return ctx ? rvu_nix_report_show(fmsg, ctx, NIX_AF_RVU_INTR) :371 rvu_nix_report_show(fmsg, nix_ctx, NIX_AF_RVU_INTR);372}373 374static int rvu_hw_nix_intr_recover(struct devlink_health_reporter *reporter,375 void *ctx, struct netlink_ext_ack *netlink_extack)376{377 struct rvu *rvu = devlink_health_reporter_priv(reporter);378 struct rvu_nix_event_ctx *nix_event_ctx = ctx;379 int blkaddr;380 381 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);382 if (blkaddr < 0)383 return blkaddr;384 385 if (nix_event_ctx->nix_af_rvu_int)386 rvu_write64(rvu, blkaddr, NIX_AF_RVU_INT_ENA_W1S, ~0ULL);387 388 return 0;389}390 391static int rvu_hw_nix_gen_dump(struct devlink_health_reporter *reporter,392 struct devlink_fmsg *fmsg, void *ctx,393 struct netlink_ext_ack *netlink_extack)394{395 struct rvu *rvu = devlink_health_reporter_priv(reporter);396 struct rvu_devlink *rvu_dl = rvu->rvu_dl;397 struct rvu_nix_event_ctx *nix_ctx;398 399 nix_ctx = rvu_dl->rvu_nix_health_reporter->nix_event_ctx;400 401 return ctx ? rvu_nix_report_show(fmsg, ctx, NIX_AF_RVU_GEN) :402 rvu_nix_report_show(fmsg, nix_ctx, NIX_AF_RVU_GEN);403}404 405static int rvu_hw_nix_gen_recover(struct devlink_health_reporter *reporter,406 void *ctx, struct netlink_ext_ack *netlink_extack)407{408 struct rvu *rvu = devlink_health_reporter_priv(reporter);409 struct rvu_nix_event_ctx *nix_event_ctx = ctx;410 int blkaddr;411 412 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);413 if (blkaddr < 0)414 return blkaddr;415 416 if (nix_event_ctx->nix_af_rvu_gen)417 rvu_write64(rvu, blkaddr, NIX_AF_GEN_INT_ENA_W1S, ~0ULL);418 419 return 0;420}421 422static int rvu_hw_nix_err_dump(struct devlink_health_reporter *reporter,423 struct devlink_fmsg *fmsg, void *ctx,424 struct netlink_ext_ack *netlink_extack)425{426 struct rvu *rvu = devlink_health_reporter_priv(reporter);427 struct rvu_devlink *rvu_dl = rvu->rvu_dl;428 struct rvu_nix_event_ctx *nix_ctx;429 430 nix_ctx = rvu_dl->rvu_nix_health_reporter->nix_event_ctx;431 432 return ctx ? rvu_nix_report_show(fmsg, ctx, NIX_AF_RVU_ERR) :433 rvu_nix_report_show(fmsg, nix_ctx, NIX_AF_RVU_ERR);434}435 436static int rvu_hw_nix_err_recover(struct devlink_health_reporter *reporter,437 void *ctx, struct netlink_ext_ack *netlink_extack)438{439 struct rvu *rvu = devlink_health_reporter_priv(reporter);440 struct rvu_nix_event_ctx *nix_event_ctx = ctx;441 int blkaddr;442 443 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);444 if (blkaddr < 0)445 return blkaddr;446 447 if (nix_event_ctx->nix_af_rvu_err)448 rvu_write64(rvu, blkaddr, NIX_AF_ERR_INT_ENA_W1S, ~0ULL);449 450 return 0;451}452 453static int rvu_hw_nix_ras_dump(struct devlink_health_reporter *reporter,454 struct devlink_fmsg *fmsg, void *ctx,455 struct netlink_ext_ack *netlink_extack)456{457 struct rvu *rvu = devlink_health_reporter_priv(reporter);458 struct rvu_devlink *rvu_dl = rvu->rvu_dl;459 struct rvu_nix_event_ctx *nix_ctx;460 461 nix_ctx = rvu_dl->rvu_nix_health_reporter->nix_event_ctx;462 463 return ctx ? rvu_nix_report_show(fmsg, ctx, NIX_AF_RVU_RAS) :464 rvu_nix_report_show(fmsg, nix_ctx, NIX_AF_RVU_RAS);465}466 467static int rvu_hw_nix_ras_recover(struct devlink_health_reporter *reporter,468 void *ctx, struct netlink_ext_ack *netlink_extack)469{470 struct rvu *rvu = devlink_health_reporter_priv(reporter);471 struct rvu_nix_event_ctx *nix_event_ctx = ctx;472 int blkaddr;473 474 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);475 if (blkaddr < 0)476 return blkaddr;477 478 if (nix_event_ctx->nix_af_rvu_int)479 rvu_write64(rvu, blkaddr, NIX_AF_RAS_ENA_W1S, ~0ULL);480 481 return 0;482}483 484RVU_REPORTERS(hw_nix_intr);485RVU_REPORTERS(hw_nix_gen);486RVU_REPORTERS(hw_nix_err);487RVU_REPORTERS(hw_nix_ras);488 489static void rvu_nix_health_reporters_destroy(struct rvu_devlink *rvu_dl);490 491static int rvu_nix_register_reporters(struct rvu_devlink *rvu_dl)492{493 struct rvu_nix_health_reporters *rvu_reporters;494 struct rvu_nix_event_ctx *nix_event_context;495 struct rvu *rvu = rvu_dl->rvu;496 497 rvu_reporters = kzalloc(sizeof(*rvu_reporters), GFP_KERNEL);498 if (!rvu_reporters)499 return -ENOMEM;500 501 rvu_dl->rvu_nix_health_reporter = rvu_reporters;502 nix_event_context = kzalloc(sizeof(*nix_event_context), GFP_KERNEL);503 if (!nix_event_context)504 return -ENOMEM;505 506 rvu_reporters->nix_event_ctx = nix_event_context;507 rvu_reporters->rvu_hw_nix_intr_reporter =508 devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_nix_intr_reporter_ops, 0, rvu);509 if (IS_ERR(rvu_reporters->rvu_hw_nix_intr_reporter)) {510 dev_warn(rvu->dev, "Failed to create hw_nix_intr reporter, err=%ld\n",511 PTR_ERR(rvu_reporters->rvu_hw_nix_intr_reporter));512 return PTR_ERR(rvu_reporters->rvu_hw_nix_intr_reporter);513 }514 515 rvu_reporters->rvu_hw_nix_gen_reporter =516 devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_nix_gen_reporter_ops, 0, rvu);517 if (IS_ERR(rvu_reporters->rvu_hw_nix_gen_reporter)) {518 dev_warn(rvu->dev, "Failed to create hw_nix_gen reporter, err=%ld\n",519 PTR_ERR(rvu_reporters->rvu_hw_nix_gen_reporter));520 return PTR_ERR(rvu_reporters->rvu_hw_nix_gen_reporter);521 }522 523 rvu_reporters->rvu_hw_nix_err_reporter =524 devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_nix_err_reporter_ops, 0, rvu);525 if (IS_ERR(rvu_reporters->rvu_hw_nix_err_reporter)) {526 dev_warn(rvu->dev, "Failed to create hw_nix_err reporter, err=%ld\n",527 PTR_ERR(rvu_reporters->rvu_hw_nix_err_reporter));528 return PTR_ERR(rvu_reporters->rvu_hw_nix_err_reporter);529 }530 531 rvu_reporters->rvu_hw_nix_ras_reporter =532 devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_nix_ras_reporter_ops, 0, rvu);533 if (IS_ERR(rvu_reporters->rvu_hw_nix_ras_reporter)) {534 dev_warn(rvu->dev, "Failed to create hw_nix_ras reporter, err=%ld\n",535 PTR_ERR(rvu_reporters->rvu_hw_nix_ras_reporter));536 return PTR_ERR(rvu_reporters->rvu_hw_nix_ras_reporter);537 }538 539 rvu_dl->devlink_wq = create_workqueue("rvu_devlink_wq");540 if (!rvu_dl->devlink_wq)541 return -ENOMEM;542 543 INIT_WORK(&rvu_reporters->intr_work, rvu_nix_intr_work);544 INIT_WORK(&rvu_reporters->gen_work, rvu_nix_gen_work);545 INIT_WORK(&rvu_reporters->err_work, rvu_nix_err_work);546 INIT_WORK(&rvu_reporters->ras_work, rvu_nix_ras_work);547 548 return 0;549}550 551static int rvu_nix_health_reporters_create(struct rvu_devlink *rvu_dl)552{553 struct rvu *rvu = rvu_dl->rvu;554 int err;555 556 err = rvu_nix_register_reporters(rvu_dl);557 if (err) {558 dev_warn(rvu->dev, "Failed to create nix reporter, err =%d\n",559 err);560 return err;561 }562 rvu_nix_register_interrupts(rvu);563 564 return 0;565}566 567static void rvu_nix_health_reporters_destroy(struct rvu_devlink *rvu_dl)568{569 struct rvu_nix_health_reporters *nix_reporters;570 struct rvu *rvu = rvu_dl->rvu;571 572 nix_reporters = rvu_dl->rvu_nix_health_reporter;573 574 if (!nix_reporters->rvu_hw_nix_ras_reporter)575 return;576 if (!IS_ERR_OR_NULL(nix_reporters->rvu_hw_nix_intr_reporter))577 devlink_health_reporter_destroy(nix_reporters->rvu_hw_nix_intr_reporter);578 579 if (!IS_ERR_OR_NULL(nix_reporters->rvu_hw_nix_gen_reporter))580 devlink_health_reporter_destroy(nix_reporters->rvu_hw_nix_gen_reporter);581 582 if (!IS_ERR_OR_NULL(nix_reporters->rvu_hw_nix_err_reporter))583 devlink_health_reporter_destroy(nix_reporters->rvu_hw_nix_err_reporter);584 585 if (!IS_ERR_OR_NULL(nix_reporters->rvu_hw_nix_ras_reporter))586 devlink_health_reporter_destroy(nix_reporters->rvu_hw_nix_ras_reporter);587 588 rvu_nix_unregister_interrupts(rvu);589 kfree(rvu_dl->rvu_nix_health_reporter->nix_event_ctx);590 kfree(rvu_dl->rvu_nix_health_reporter);591}592 593static void rvu_npa_intr_work(struct work_struct *work)594{595 struct rvu_npa_health_reporters *rvu_npa_health_reporter;596 597 rvu_npa_health_reporter = container_of(work, struct rvu_npa_health_reporters, intr_work);598 devlink_health_report(rvu_npa_health_reporter->rvu_hw_npa_intr_reporter,599 "NPA_AF_RVU Error",600 rvu_npa_health_reporter->npa_event_ctx);601}602 603static irqreturn_t rvu_npa_af_rvu_intr_handler(int irq, void *rvu_irq)604{605 struct rvu_npa_event_ctx *npa_event_context;606 struct rvu_devlink *rvu_dl = rvu_irq;607 struct rvu *rvu;608 int blkaddr;609 u64 intr;610 611 rvu = rvu_dl->rvu;612 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);613 if (blkaddr < 0)614 return IRQ_NONE;615 616 npa_event_context = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;617 intr = rvu_read64(rvu, blkaddr, NPA_AF_RVU_INT);618 npa_event_context->npa_af_rvu_int = intr;619 620 /* Clear interrupts */621 rvu_write64(rvu, blkaddr, NPA_AF_RVU_INT, intr);622 rvu_write64(rvu, blkaddr, NPA_AF_RVU_INT_ENA_W1C, ~0ULL);623 queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_npa_health_reporter->intr_work);624 625 return IRQ_HANDLED;626}627 628static void rvu_npa_gen_work(struct work_struct *work)629{630 struct rvu_npa_health_reporters *rvu_npa_health_reporter;631 632 rvu_npa_health_reporter = container_of(work, struct rvu_npa_health_reporters, gen_work);633 devlink_health_report(rvu_npa_health_reporter->rvu_hw_npa_gen_reporter,634 "NPA_AF_GEN Error",635 rvu_npa_health_reporter->npa_event_ctx);636}637 638static irqreturn_t rvu_npa_af_gen_intr_handler(int irq, void *rvu_irq)639{640 struct rvu_npa_event_ctx *npa_event_context;641 struct rvu_devlink *rvu_dl = rvu_irq;642 struct rvu *rvu;643 int blkaddr;644 u64 intr;645 646 rvu = rvu_dl->rvu;647 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);648 if (blkaddr < 0)649 return IRQ_NONE;650 651 npa_event_context = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;652 intr = rvu_read64(rvu, blkaddr, NPA_AF_GEN_INT);653 npa_event_context->npa_af_rvu_gen = intr;654 655 /* Clear interrupts */656 rvu_write64(rvu, blkaddr, NPA_AF_GEN_INT, intr);657 rvu_write64(rvu, blkaddr, NPA_AF_GEN_INT_ENA_W1C, ~0ULL);658 queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_npa_health_reporter->gen_work);659 660 return IRQ_HANDLED;661}662 663static void rvu_npa_err_work(struct work_struct *work)664{665 struct rvu_npa_health_reporters *rvu_npa_health_reporter;666 667 rvu_npa_health_reporter = container_of(work, struct rvu_npa_health_reporters, err_work);668 devlink_health_report(rvu_npa_health_reporter->rvu_hw_npa_err_reporter,669 "NPA_AF_ERR Error",670 rvu_npa_health_reporter->npa_event_ctx);671}672 673static irqreturn_t rvu_npa_af_err_intr_handler(int irq, void *rvu_irq)674{675 struct rvu_npa_event_ctx *npa_event_context;676 struct rvu_devlink *rvu_dl = rvu_irq;677 struct rvu *rvu;678 int blkaddr;679 u64 intr;680 681 rvu = rvu_dl->rvu;682 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);683 if (blkaddr < 0)684 return IRQ_NONE;685 npa_event_context = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;686 intr = rvu_read64(rvu, blkaddr, NPA_AF_ERR_INT);687 npa_event_context->npa_af_rvu_err = intr;688 689 /* Clear interrupts */690 rvu_write64(rvu, blkaddr, NPA_AF_ERR_INT, intr);691 rvu_write64(rvu, blkaddr, NPA_AF_ERR_INT_ENA_W1C, ~0ULL);692 queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_npa_health_reporter->err_work);693 694 return IRQ_HANDLED;695}696 697static void rvu_npa_ras_work(struct work_struct *work)698{699 struct rvu_npa_health_reporters *rvu_npa_health_reporter;700 701 rvu_npa_health_reporter = container_of(work, struct rvu_npa_health_reporters, ras_work);702 devlink_health_report(rvu_npa_health_reporter->rvu_hw_npa_ras_reporter,703 "HW NPA_AF_RAS Error reported",704 rvu_npa_health_reporter->npa_event_ctx);705}706 707static irqreturn_t rvu_npa_af_ras_intr_handler(int irq, void *rvu_irq)708{709 struct rvu_npa_event_ctx *npa_event_context;710 struct rvu_devlink *rvu_dl = rvu_irq;711 struct rvu *rvu;712 int blkaddr;713 u64 intr;714 715 rvu = rvu_dl->rvu;716 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);717 if (blkaddr < 0)718 return IRQ_NONE;719 720 npa_event_context = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;721 intr = rvu_read64(rvu, blkaddr, NPA_AF_RAS);722 npa_event_context->npa_af_rvu_ras = intr;723 724 /* Clear interrupts */725 rvu_write64(rvu, blkaddr, NPA_AF_RAS, intr);726 rvu_write64(rvu, blkaddr, NPA_AF_RAS_ENA_W1C, ~0ULL);727 queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_npa_health_reporter->ras_work);728 729 return IRQ_HANDLED;730}731 732static void rvu_npa_unregister_interrupts(struct rvu *rvu)733{734 struct rvu_devlink *rvu_dl = rvu->rvu_dl;735 int i, offs, blkaddr;736 u64 reg;737 738 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);739 if (blkaddr < 0)740 return;741 742 reg = rvu_read64(rvu, blkaddr, NPA_PRIV_AF_INT_CFG);743 offs = reg & 0x3FF;744 745 rvu_write64(rvu, blkaddr, NPA_AF_RVU_INT_ENA_W1C, ~0ULL);746 rvu_write64(rvu, blkaddr, NPA_AF_GEN_INT_ENA_W1C, ~0ULL);747 rvu_write64(rvu, blkaddr, NPA_AF_ERR_INT_ENA_W1C, ~0ULL);748 rvu_write64(rvu, blkaddr, NPA_AF_RAS_ENA_W1C, ~0ULL);749 750 for (i = 0; i < NPA_AF_INT_VEC_CNT; i++)751 if (rvu->irq_allocated[offs + i]) {752 free_irq(pci_irq_vector(rvu->pdev, offs + i), rvu_dl);753 rvu->irq_allocated[offs + i] = false;754 }755}756 757static int rvu_npa_register_interrupts(struct rvu *rvu)758{759 int blkaddr, base;760 bool rc;761 762 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);763 if (blkaddr < 0)764 return blkaddr;765 766 /* Get NPA AF MSIX vectors offset. */767 base = rvu_read64(rvu, blkaddr, NPA_PRIV_AF_INT_CFG) & 0x3ff;768 if (!base) {769 dev_warn(rvu->dev,770 "Failed to get NPA_AF_INT vector offsets\n");771 return 0;772 }773 774 /* Register and enable NPA_AF_RVU_INT interrupt */775 rc = rvu_common_request_irq(rvu, base + NPA_AF_INT_VEC_RVU,776 "NPA_AF_RVU_INT",777 rvu_npa_af_rvu_intr_handler);778 if (!rc)779 goto err;780 rvu_write64(rvu, blkaddr, NPA_AF_RVU_INT_ENA_W1S, ~0ULL);781 782 /* Register and enable NPA_AF_GEN_INT interrupt */783 rc = rvu_common_request_irq(rvu, base + NPA_AF_INT_VEC_GEN,784 "NPA_AF_RVU_GEN",785 rvu_npa_af_gen_intr_handler);786 if (!rc)787 goto err;788 rvu_write64(rvu, blkaddr, NPA_AF_GEN_INT_ENA_W1S, ~0ULL);789 790 /* Register and enable NPA_AF_ERR_INT interrupt */791 rc = rvu_common_request_irq(rvu, base + NPA_AF_INT_VEC_AF_ERR,792 "NPA_AF_ERR_INT",793 rvu_npa_af_err_intr_handler);794 if (!rc)795 goto err;796 rvu_write64(rvu, blkaddr, NPA_AF_ERR_INT_ENA_W1S, ~0ULL);797 798 /* Register and enable NPA_AF_RAS interrupt */799 rc = rvu_common_request_irq(rvu, base + NPA_AF_INT_VEC_POISON,800 "NPA_AF_RAS",801 rvu_npa_af_ras_intr_handler);802 if (!rc)803 goto err;804 rvu_write64(rvu, blkaddr, NPA_AF_RAS_ENA_W1S, ~0ULL);805 806 return 0;807err:808 rvu_npa_unregister_interrupts(rvu);809 return rc;810}811 812static int rvu_npa_report_show(struct devlink_fmsg *fmsg, void *ctx,813 enum npa_af_rvu_health health_reporter)814{815 struct rvu_npa_event_ctx *npa_event_context;816 unsigned int alloc_dis, free_dis;817 u64 intr_val;818 819 npa_event_context = ctx;820 switch (health_reporter) {821 case NPA_AF_RVU_GEN:822 intr_val = npa_event_context->npa_af_rvu_gen;823 rvu_report_pair_start(fmsg, "NPA_AF_GENERAL");824 devlink_fmsg_u64_pair_put(fmsg, "\tNPA General Interrupt Reg ",825 npa_event_context->npa_af_rvu_gen);826 if (intr_val & BIT_ULL(32))827 devlink_fmsg_string_put(fmsg, "\n\tUnmap PF Error");828 829 free_dis = FIELD_GET(GENMASK(15, 0), intr_val);830 if (free_dis & BIT(NPA_INPQ_NIX0_RX))831 devlink_fmsg_string_put(fmsg, "\n\tNIX0: free disabled RX");832 if (free_dis & BIT(NPA_INPQ_NIX0_TX))833 devlink_fmsg_string_put(fmsg, "\n\tNIX0:free disabled TX");834 if (free_dis & BIT(NPA_INPQ_NIX1_RX))835 devlink_fmsg_string_put(fmsg, "\n\tNIX1: free disabled RX");836 if (free_dis & BIT(NPA_INPQ_NIX1_TX))837 devlink_fmsg_string_put(fmsg, "\n\tNIX1:free disabled TX");838 if (free_dis & BIT(NPA_INPQ_SSO))839 devlink_fmsg_string_put(fmsg, "\n\tFree Disabled for SSO");840 if (free_dis & BIT(NPA_INPQ_TIM))841 devlink_fmsg_string_put(fmsg, "\n\tFree Disabled for TIM");842 if (free_dis & BIT(NPA_INPQ_DPI))843 devlink_fmsg_string_put(fmsg, "\n\tFree Disabled for DPI");844 if (free_dis & BIT(NPA_INPQ_AURA_OP))845 devlink_fmsg_string_put(fmsg, "\n\tFree Disabled for AURA");846 847 alloc_dis = FIELD_GET(GENMASK(31, 16), intr_val);848 if (alloc_dis & BIT(NPA_INPQ_NIX0_RX))849 devlink_fmsg_string_put(fmsg, "\n\tNIX0: alloc disabled RX");850 if (alloc_dis & BIT(NPA_INPQ_NIX0_TX))851 devlink_fmsg_string_put(fmsg, "\n\tNIX0:alloc disabled TX");852 if (alloc_dis & BIT(NPA_INPQ_NIX1_RX))853 devlink_fmsg_string_put(fmsg, "\n\tNIX1: alloc disabled RX");854 if (alloc_dis & BIT(NPA_INPQ_NIX1_TX))855 devlink_fmsg_string_put(fmsg, "\n\tNIX1:alloc disabled TX");856 if (alloc_dis & BIT(NPA_INPQ_SSO))857 devlink_fmsg_string_put(fmsg, "\n\tAlloc Disabled for SSO");858 if (alloc_dis & BIT(NPA_INPQ_TIM))859 devlink_fmsg_string_put(fmsg, "\n\tAlloc Disabled for TIM");860 if (alloc_dis & BIT(NPA_INPQ_DPI))861 devlink_fmsg_string_put(fmsg, "\n\tAlloc Disabled for DPI");862 if (alloc_dis & BIT(NPA_INPQ_AURA_OP))863 devlink_fmsg_string_put(fmsg, "\n\tAlloc Disabled for AURA");864 865 rvu_report_pair_end(fmsg);866 break;867 case NPA_AF_RVU_ERR:868 rvu_report_pair_start(fmsg, "NPA_AF_ERR");869 devlink_fmsg_u64_pair_put(fmsg, "\tNPA Error Interrupt Reg ",870 npa_event_context->npa_af_rvu_err);871 if (npa_event_context->npa_af_rvu_err & BIT_ULL(14))872 devlink_fmsg_string_put(fmsg, "\n\tFault on NPA_AQ_INST_S read");873 if (npa_event_context->npa_af_rvu_err & BIT_ULL(13))874 devlink_fmsg_string_put(fmsg, "\n\tFault on NPA_AQ_RES_S write");875 if (npa_event_context->npa_af_rvu_err & BIT_ULL(12))876 devlink_fmsg_string_put(fmsg, "\n\tAQ Doorbell Error");877 rvu_report_pair_end(fmsg);878 break;879 case NPA_AF_RVU_RAS:880 rvu_report_pair_start(fmsg, "NPA_AF_RVU_RAS");881 devlink_fmsg_u64_pair_put(fmsg, "\tNPA RAS Interrupt Reg ",882 npa_event_context->npa_af_rvu_ras);883 if (npa_event_context->npa_af_rvu_ras & BIT_ULL(34))884 devlink_fmsg_string_put(fmsg, "\n\tPoison data on NPA_AQ_INST_S");885 if (npa_event_context->npa_af_rvu_ras & BIT_ULL(33))886 devlink_fmsg_string_put(fmsg, "\n\tPoison data on NPA_AQ_RES_S");887 if (npa_event_context->npa_af_rvu_ras & BIT_ULL(32))888 devlink_fmsg_string_put(fmsg, "\n\tPoison data on HW context");889 rvu_report_pair_end(fmsg);890 break;891 case NPA_AF_RVU_INTR:892 rvu_report_pair_start(fmsg, "NPA_AF_RVU");893 devlink_fmsg_u64_pair_put(fmsg, "\tNPA RVU Interrupt Reg ",894 npa_event_context->npa_af_rvu_int);895 if (npa_event_context->npa_af_rvu_int & BIT_ULL(0))896 devlink_fmsg_string_put(fmsg, "\n\tUnmap Slot Error");897 rvu_report_pair_end(fmsg);898 break;899 default:900 return -EINVAL;901 }902 903 return 0;904}905 906static int rvu_hw_npa_intr_dump(struct devlink_health_reporter *reporter,907 struct devlink_fmsg *fmsg, void *ctx,908 struct netlink_ext_ack *netlink_extack)909{910 struct rvu *rvu = devlink_health_reporter_priv(reporter);911 struct rvu_devlink *rvu_dl = rvu->rvu_dl;912 struct rvu_npa_event_ctx *npa_ctx;913 914 npa_ctx = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;915 916 return ctx ? rvu_npa_report_show(fmsg, ctx, NPA_AF_RVU_INTR) :917 rvu_npa_report_show(fmsg, npa_ctx, NPA_AF_RVU_INTR);918}919 920static int rvu_hw_npa_intr_recover(struct devlink_health_reporter *reporter,921 void *ctx, struct netlink_ext_ack *netlink_extack)922{923 struct rvu *rvu = devlink_health_reporter_priv(reporter);924 struct rvu_npa_event_ctx *npa_event_ctx = ctx;925 int blkaddr;926 927 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);928 if (blkaddr < 0)929 return blkaddr;930 931 if (npa_event_ctx->npa_af_rvu_int)932 rvu_write64(rvu, blkaddr, NPA_AF_RVU_INT_ENA_W1S, ~0ULL);933 934 return 0;935}936 937static int rvu_hw_npa_gen_dump(struct devlink_health_reporter *reporter,938 struct devlink_fmsg *fmsg, void *ctx,939 struct netlink_ext_ack *netlink_extack)940{941 struct rvu *rvu = devlink_health_reporter_priv(reporter);942 struct rvu_devlink *rvu_dl = rvu->rvu_dl;943 struct rvu_npa_event_ctx *npa_ctx;944 945 npa_ctx = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;946 947 return ctx ? rvu_npa_report_show(fmsg, ctx, NPA_AF_RVU_GEN) :948 rvu_npa_report_show(fmsg, npa_ctx, NPA_AF_RVU_GEN);949}950 951static int rvu_hw_npa_gen_recover(struct devlink_health_reporter *reporter,952 void *ctx, struct netlink_ext_ack *netlink_extack)953{954 struct rvu *rvu = devlink_health_reporter_priv(reporter);955 struct rvu_npa_event_ctx *npa_event_ctx = ctx;956 int blkaddr;957 958 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);959 if (blkaddr < 0)960 return blkaddr;961 962 if (npa_event_ctx->npa_af_rvu_gen)963 rvu_write64(rvu, blkaddr, NPA_AF_GEN_INT_ENA_W1S, ~0ULL);964 965 return 0;966}967 968static int rvu_hw_npa_err_dump(struct devlink_health_reporter *reporter,969 struct devlink_fmsg *fmsg, void *ctx,970 struct netlink_ext_ack *netlink_extack)971{972 struct rvu *rvu = devlink_health_reporter_priv(reporter);973 struct rvu_devlink *rvu_dl = rvu->rvu_dl;974 struct rvu_npa_event_ctx *npa_ctx;975 976 npa_ctx = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;977 978 return ctx ? rvu_npa_report_show(fmsg, ctx, NPA_AF_RVU_ERR) :979 rvu_npa_report_show(fmsg, npa_ctx, NPA_AF_RVU_ERR);980}981 982static int rvu_hw_npa_err_recover(struct devlink_health_reporter *reporter,983 void *ctx, struct netlink_ext_ack *netlink_extack)984{985 struct rvu *rvu = devlink_health_reporter_priv(reporter);986 struct rvu_npa_event_ctx *npa_event_ctx = ctx;987 int blkaddr;988 989 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);990 if (blkaddr < 0)991 return blkaddr;992 993 if (npa_event_ctx->npa_af_rvu_err)994 rvu_write64(rvu, blkaddr, NPA_AF_ERR_INT_ENA_W1S, ~0ULL);995 996 return 0;997}998 999static int rvu_hw_npa_ras_dump(struct devlink_health_reporter *reporter,1000 struct devlink_fmsg *fmsg, void *ctx,1001 struct netlink_ext_ack *netlink_extack)1002{1003 struct rvu *rvu = devlink_health_reporter_priv(reporter);1004 struct rvu_devlink *rvu_dl = rvu->rvu_dl;1005 struct rvu_npa_event_ctx *npa_ctx;1006 1007 npa_ctx = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;1008 1009 return ctx ? rvu_npa_report_show(fmsg, ctx, NPA_AF_RVU_RAS) :1010 rvu_npa_report_show(fmsg, npa_ctx, NPA_AF_RVU_RAS);1011}1012 1013static int rvu_hw_npa_ras_recover(struct devlink_health_reporter *reporter,1014 void *ctx, struct netlink_ext_ack *netlink_extack)1015{1016 struct rvu *rvu = devlink_health_reporter_priv(reporter);1017 struct rvu_npa_event_ctx *npa_event_ctx = ctx;1018 int blkaddr;1019 1020 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);1021 if (blkaddr < 0)1022 return blkaddr;1023 1024 if (npa_event_ctx->npa_af_rvu_ras)1025 rvu_write64(rvu, blkaddr, NPA_AF_RAS_ENA_W1S, ~0ULL);1026 1027 return 0;1028}1029 1030RVU_REPORTERS(hw_npa_intr);1031RVU_REPORTERS(hw_npa_gen);1032RVU_REPORTERS(hw_npa_err);1033RVU_REPORTERS(hw_npa_ras);1034 1035static void rvu_npa_health_reporters_destroy(struct rvu_devlink *rvu_dl);1036 1037static int rvu_npa_register_reporters(struct rvu_devlink *rvu_dl)1038{1039 struct rvu_npa_health_reporters *rvu_reporters;1040 struct rvu_npa_event_ctx *npa_event_context;1041 struct rvu *rvu = rvu_dl->rvu;1042 1043 rvu_reporters = kzalloc(sizeof(*rvu_reporters), GFP_KERNEL);1044 if (!rvu_reporters)1045 return -ENOMEM;1046 1047 rvu_dl->rvu_npa_health_reporter = rvu_reporters;1048 npa_event_context = kzalloc(sizeof(*npa_event_context), GFP_KERNEL);1049 if (!npa_event_context)1050 return -ENOMEM;1051 1052 rvu_reporters->npa_event_ctx = npa_event_context;1053 rvu_reporters->rvu_hw_npa_intr_reporter =1054 devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_npa_intr_reporter_ops, 0, rvu);1055 if (IS_ERR(rvu_reporters->rvu_hw_npa_intr_reporter)) {1056 dev_warn(rvu->dev, "Failed to create hw_npa_intr reporter, err=%ld\n",1057 PTR_ERR(rvu_reporters->rvu_hw_npa_intr_reporter));1058 return PTR_ERR(rvu_reporters->rvu_hw_npa_intr_reporter);1059 }1060 1061 rvu_reporters->rvu_hw_npa_gen_reporter =1062 devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_npa_gen_reporter_ops, 0, rvu);1063 if (IS_ERR(rvu_reporters->rvu_hw_npa_gen_reporter)) {1064 dev_warn(rvu->dev, "Failed to create hw_npa_gen reporter, err=%ld\n",1065 PTR_ERR(rvu_reporters->rvu_hw_npa_gen_reporter));1066 return PTR_ERR(rvu_reporters->rvu_hw_npa_gen_reporter);1067 }1068 1069 rvu_reporters->rvu_hw_npa_err_reporter =1070 devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_npa_err_reporter_ops, 0, rvu);1071 if (IS_ERR(rvu_reporters->rvu_hw_npa_err_reporter)) {1072 dev_warn(rvu->dev, "Failed to create hw_npa_err reporter, err=%ld\n",1073 PTR_ERR(rvu_reporters->rvu_hw_npa_err_reporter));1074 return PTR_ERR(rvu_reporters->rvu_hw_npa_err_reporter);1075 }1076 1077 rvu_reporters->rvu_hw_npa_ras_reporter =1078 devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_npa_ras_reporter_ops, 0, rvu);1079 if (IS_ERR(rvu_reporters->rvu_hw_npa_ras_reporter)) {1080 dev_warn(rvu->dev, "Failed to create hw_npa_ras reporter, err=%ld\n",1081 PTR_ERR(rvu_reporters->rvu_hw_npa_ras_reporter));1082 return PTR_ERR(rvu_reporters->rvu_hw_npa_ras_reporter);1083 }1084 1085 rvu_dl->devlink_wq = create_workqueue("rvu_devlink_wq");1086 if (!rvu_dl->devlink_wq)1087 return -ENOMEM;1088 1089 INIT_WORK(&rvu_reporters->intr_work, rvu_npa_intr_work);1090 INIT_WORK(&rvu_reporters->err_work, rvu_npa_err_work);1091 INIT_WORK(&rvu_reporters->gen_work, rvu_npa_gen_work);1092 INIT_WORK(&rvu_reporters->ras_work, rvu_npa_ras_work);1093 1094 return 0;1095}1096 1097static int rvu_npa_health_reporters_create(struct rvu_devlink *rvu_dl)1098{1099 struct rvu *rvu = rvu_dl->rvu;1100 int err;1101 1102 err = rvu_npa_register_reporters(rvu_dl);1103 if (err) {1104 dev_warn(rvu->dev, "Failed to create npa reporter, err =%d\n",1105 err);1106 return err;1107 }1108 rvu_npa_register_interrupts(rvu);1109 1110 return 0;1111}1112 1113static void rvu_npa_health_reporters_destroy(struct rvu_devlink *rvu_dl)1114{1115 struct rvu_npa_health_reporters *npa_reporters;1116 struct rvu *rvu = rvu_dl->rvu;1117 1118 npa_reporters = rvu_dl->rvu_npa_health_reporter;1119 1120 if (!npa_reporters->rvu_hw_npa_ras_reporter)1121 return;1122 if (!IS_ERR_OR_NULL(npa_reporters->rvu_hw_npa_intr_reporter))1123 devlink_health_reporter_destroy(npa_reporters->rvu_hw_npa_intr_reporter);1124 1125 if (!IS_ERR_OR_NULL(npa_reporters->rvu_hw_npa_gen_reporter))1126 devlink_health_reporter_destroy(npa_reporters->rvu_hw_npa_gen_reporter);1127 1128 if (!IS_ERR_OR_NULL(npa_reporters->rvu_hw_npa_err_reporter))1129 devlink_health_reporter_destroy(npa_reporters->rvu_hw_npa_err_reporter);1130 1131 if (!IS_ERR_OR_NULL(npa_reporters->rvu_hw_npa_ras_reporter))1132 devlink_health_reporter_destroy(npa_reporters->rvu_hw_npa_ras_reporter);1133 1134 rvu_npa_unregister_interrupts(rvu);1135 kfree(rvu_dl->rvu_npa_health_reporter->npa_event_ctx);1136 kfree(rvu_dl->rvu_npa_health_reporter);1137}1138 1139static int rvu_health_reporters_create(struct rvu *rvu)1140{1141 struct rvu_devlink *rvu_dl;1142 int err;1143 1144 rvu_dl = rvu->rvu_dl;1145 err = rvu_npa_health_reporters_create(rvu_dl);1146 if (err)1147 return err;1148 1149 return rvu_nix_health_reporters_create(rvu_dl);1150}1151 1152static void rvu_health_reporters_destroy(struct rvu *rvu)1153{1154 struct rvu_devlink *rvu_dl;1155 1156 if (!rvu->rvu_dl)1157 return;1158 1159 rvu_dl = rvu->rvu_dl;1160 rvu_npa_health_reporters_destroy(rvu_dl);1161 rvu_nix_health_reporters_destroy(rvu_dl);1162}1163 1164/* Devlink Params APIs */1165static int rvu_af_dl_dwrr_mtu_validate(struct devlink *devlink, u32 id,1166 union devlink_param_value val,1167 struct netlink_ext_ack *extack)1168{1169 struct rvu_devlink *rvu_dl = devlink_priv(devlink);1170 struct rvu *rvu = rvu_dl->rvu;1171 int dwrr_mtu = val.vu32;1172 struct nix_txsch *txsch;1173 struct nix_hw *nix_hw;1174 1175 if (!rvu->hw->cap.nix_common_dwrr_mtu) {1176 NL_SET_ERR_MSG_MOD(extack,1177 "Setting DWRR_MTU is not supported on this silicon");1178 return -EOPNOTSUPP;1179 }1180 1181 if ((dwrr_mtu > 65536 || !is_power_of_2(dwrr_mtu)) &&1182 (dwrr_mtu != 9728 && dwrr_mtu != 10240)) {1183 NL_SET_ERR_MSG_MOD(extack,1184 "Invalid, supported MTUs are 0,2,4,8.16,32,64....4K,8K,32K,64K and 9728, 10240");1185 return -EINVAL;1186 }1187 1188 nix_hw = get_nix_hw(rvu->hw, BLKADDR_NIX0);1189 if (!nix_hw)1190 return -ENODEV;1191 1192 txsch = &nix_hw->txsch[NIX_TXSCH_LVL_SMQ];1193 if (rvu_rsrc_free_count(&txsch->schq) != txsch->schq.max) {1194 NL_SET_ERR_MSG_MOD(extack,1195 "Changing DWRR MTU is not supported when there are active NIXLFs");1196 NL_SET_ERR_MSG_MOD(extack,1197 "Make sure none of the PF/VF interfaces are initialized and retry");1198 return -EOPNOTSUPP;1199 }1200 1201 return 0;1202}1203 1204static int rvu_af_dl_dwrr_mtu_set(struct devlink *devlink, u32 id,1205 struct devlink_param_gset_ctx *ctx,1206 struct netlink_ext_ack *extack)1207{1208 struct rvu_devlink *rvu_dl = devlink_priv(devlink);1209 struct rvu *rvu = rvu_dl->rvu;1210 u64 dwrr_mtu;1211 1212 dwrr_mtu = convert_bytes_to_dwrr_mtu(ctx->val.vu32);1213 rvu_write64(rvu, BLKADDR_NIX0,1214 nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM), dwrr_mtu);1215 1216 return 0;1217}1218 1219static int rvu_af_dl_dwrr_mtu_get(struct devlink *devlink, u32 id,1220 struct devlink_param_gset_ctx *ctx)1221{1222 struct rvu_devlink *rvu_dl = devlink_priv(devlink);1223 struct rvu *rvu = rvu_dl->rvu;1224 u64 dwrr_mtu;1225 1226 if (!rvu->hw->cap.nix_common_dwrr_mtu)1227 return -EOPNOTSUPP;1228 1229 dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0,1230 nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM));1231 ctx->val.vu32 = convert_dwrr_mtu_to_bytes(dwrr_mtu);1232 1233 return 0;1234}1235 1236enum rvu_af_dl_param_id {1237 RVU_AF_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,1238 RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU,1239 RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT,1240 RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE,1241 RVU_AF_DEVLINK_PARAM_ID_NIX_MAXLF,1242};1243 1244static int rvu_af_npc_exact_feature_get(struct devlink *devlink, u32 id,1245 struct devlink_param_gset_ctx *ctx)1246{1247 struct rvu_devlink *rvu_dl = devlink_priv(devlink);1248 struct rvu *rvu = rvu_dl->rvu;1249 bool enabled;1250 1251 enabled = rvu_npc_exact_has_match_table(rvu);1252 1253 snprintf(ctx->val.vstr, sizeof(ctx->val.vstr), "%s",1254 enabled ? "enabled" : "disabled");1255 1256 return 0;1257}1258 1259static int rvu_af_npc_exact_feature_disable(struct devlink *devlink, u32 id,1260 struct devlink_param_gset_ctx *ctx,1261 struct netlink_ext_ack *extack)1262{1263 struct rvu_devlink *rvu_dl = devlink_priv(devlink);1264 struct rvu *rvu = rvu_dl->rvu;1265 1266 rvu_npc_exact_disable_feature(rvu);1267 1268 return 0;1269}1270 1271static int rvu_af_npc_exact_feature_validate(struct devlink *devlink, u32 id,1272 union devlink_param_value val,1273 struct netlink_ext_ack *extack)1274{1275 struct rvu_devlink *rvu_dl = devlink_priv(devlink);1276 struct rvu *rvu = rvu_dl->rvu;1277 u64 enable;1278 1279 if (kstrtoull(val.vstr, 10, &enable)) {1280 NL_SET_ERR_MSG_MOD(extack,1281 "Only 1 value is supported");1282 return -EINVAL;1283 }1284 1285 if (enable != 1) {1286 NL_SET_ERR_MSG_MOD(extack,1287 "Only disabling exact match feature is supported");1288 return -EINVAL;1289 }1290 1291 if (rvu_npc_exact_can_disable_feature(rvu))1292 return 0;1293 1294 NL_SET_ERR_MSG_MOD(extack,1295 "Can't disable exact match feature; Please try before any configuration");1296 return -EFAULT;1297}1298 1299static int rvu_af_dl_npc_mcam_high_zone_percent_get(struct devlink *devlink, u32 id,1300 struct devlink_param_gset_ctx *ctx)1301{1302 struct rvu_devlink *rvu_dl = devlink_priv(devlink);1303 struct rvu *rvu = rvu_dl->rvu;1304 struct npc_mcam *mcam;1305 u32 percent;1306 1307 mcam = &rvu->hw->mcam;1308 percent = (mcam->hprio_count * 100) / mcam->bmap_entries;1309 ctx->val.vu8 = (u8)percent;1310 1311 return 0;1312}1313 1314static int rvu_af_dl_npc_mcam_high_zone_percent_set(struct devlink *devlink, u32 id,1315 struct devlink_param_gset_ctx *ctx,1316 struct netlink_ext_ack *extack)1317{1318 struct rvu_devlink *rvu_dl = devlink_priv(devlink);1319 struct rvu *rvu = rvu_dl->rvu;1320 struct npc_mcam *mcam;1321 u32 percent;1322 1323 percent = ctx->val.vu8;1324 mcam = &rvu->hw->mcam;1325 mcam->hprio_count = (mcam->bmap_entries * percent) / 100;1326 mcam->hprio_end = mcam->hprio_count;1327 mcam->lprio_count = (mcam->bmap_entries - mcam->hprio_count) / 2;1328 mcam->lprio_start = mcam->bmap_entries - mcam->lprio_count;1329 1330 return 0;1331}1332 1333static int rvu_af_dl_npc_mcam_high_zone_percent_validate(struct devlink *devlink, u32 id,1334 union devlink_param_value val,1335 struct netlink_ext_ack *extack)1336{1337 struct rvu_devlink *rvu_dl = devlink_priv(devlink);1338 struct rvu *rvu = rvu_dl->rvu;1339 struct npc_mcam *mcam;1340 1341 /* The percent of high prio zone must range from 12% to 100% of unreserved mcam space */1342 if (val.vu8 < 12 || val.vu8 > 100) {1343 NL_SET_ERR_MSG_MOD(extack,1344 "mcam high zone percent must be between 12% to 100%");1345 return -EINVAL;1346 }1347 1348 /* Do not allow user to modify the high priority zone entries while mcam entries1349 * have already been assigned.1350 */1351 mcam = &rvu->hw->mcam;1352 if (mcam->bmap_fcnt < mcam->bmap_entries) {1353 NL_SET_ERR_MSG_MOD(extack,1354 "mcam entries have already been assigned, can't resize");1355 return -EPERM;1356 }1357 1358 return 0;1359}1360 1361static int rvu_af_dl_nix_maxlf_get(struct devlink *devlink, u32 id,1362 struct devlink_param_gset_ctx *ctx)1363{1364 struct rvu_devlink *rvu_dl = devlink_priv(devlink);1365 struct rvu *rvu = rvu_dl->rvu;1366 1367 ctx->val.vu16 = (u16)rvu_get_nixlf_count(rvu);1368 1369 return 0;1370}1371 1372static int rvu_af_dl_nix_maxlf_set(struct devlink *devlink, u32 id,1373 struct devlink_param_gset_ctx *ctx,1374 struct netlink_ext_ack *extack)1375{1376 struct rvu_devlink *rvu_dl = devlink_priv(devlink);1377 struct rvu *rvu = rvu_dl->rvu;1378 struct rvu_block *block;1379 int blkaddr = 0;1380 1381 npc_mcam_rsrcs_deinit(rvu);1382 blkaddr = rvu_get_next_nix_blkaddr(rvu, blkaddr);1383 while (blkaddr) {1384 block = &rvu->hw->block[blkaddr];1385 block->lf.max = ctx->val.vu16;1386 blkaddr = rvu_get_next_nix_blkaddr(rvu, blkaddr);1387 }1388 1389 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);1390 npc_mcam_rsrcs_init(rvu, blkaddr);1391 1392 return 0;1393}1394 1395static int rvu_af_dl_nix_maxlf_validate(struct devlink *devlink, u32 id,1396 union devlink_param_value val,1397 struct netlink_ext_ack *extack)1398{1399 struct rvu_devlink *rvu_dl = devlink_priv(devlink);1400 struct rvu *rvu = rvu_dl->rvu;1401 u16 max_nix0_lf, max_nix1_lf;1402 struct npc_mcam *mcam;1403 u64 cfg;1404 1405 cfg = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_CONST2);1406 max_nix0_lf = cfg & 0xFFF;1407 cfg = rvu_read64(rvu, BLKADDR_NIX1, NIX_AF_CONST2);1408 max_nix1_lf = cfg & 0xFFF;1409 1410 /* Do not allow user to modify maximum NIX LFs while mcam entries1411 * have already been assigned.1412 */1413 mcam = &rvu->hw->mcam;1414 if (mcam->bmap_fcnt < mcam->bmap_entries) {1415 NL_SET_ERR_MSG_MOD(extack,1416 "mcam entries have already been assigned, can't resize");1417 return -EPERM;1418 }1419 1420 if (max_nix0_lf && val.vu16 > max_nix0_lf) {1421 NL_SET_ERR_MSG_MOD(extack,1422 "requested nixlf is greater than the max supported nix0_lf");1423 return -EPERM;1424 }1425 1426 if (max_nix1_lf && val.vu16 > max_nix1_lf) {1427 NL_SET_ERR_MSG_MOD(extack,1428 "requested nixlf is greater than the max supported nix1_lf");1429 return -EINVAL;1430 }1431 1432 return 0;1433}1434 1435static const struct devlink_param rvu_af_dl_params[] = {1436 DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU,1437 "dwrr_mtu", DEVLINK_PARAM_TYPE_U32,1438 BIT(DEVLINK_PARAM_CMODE_RUNTIME),1439 rvu_af_dl_dwrr_mtu_get, rvu_af_dl_dwrr_mtu_set,1440 rvu_af_dl_dwrr_mtu_validate),1441 DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT,1442 "npc_mcam_high_zone_percent", DEVLINK_PARAM_TYPE_U8,1443 BIT(DEVLINK_PARAM_CMODE_RUNTIME),1444 rvu_af_dl_npc_mcam_high_zone_percent_get,1445 rvu_af_dl_npc_mcam_high_zone_percent_set,1446 rvu_af_dl_npc_mcam_high_zone_percent_validate),1447 DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NIX_MAXLF,1448 "nix_maxlf", DEVLINK_PARAM_TYPE_U16,1449 BIT(DEVLINK_PARAM_CMODE_RUNTIME),1450 rvu_af_dl_nix_maxlf_get,1451 rvu_af_dl_nix_maxlf_set,1452 rvu_af_dl_nix_maxlf_validate),1453};1454 1455static const struct devlink_param rvu_af_dl_param_exact_match[] = {1456 DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE,1457 "npc_exact_feature_disable", DEVLINK_PARAM_TYPE_STRING,1458 BIT(DEVLINK_PARAM_CMODE_RUNTIME),1459 rvu_af_npc_exact_feature_get,1460 rvu_af_npc_exact_feature_disable,1461 rvu_af_npc_exact_feature_validate),1462};1463 1464/* Devlink switch mode */1465static int rvu_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)1466{1467 struct rvu_devlink *rvu_dl = devlink_priv(devlink);1468 struct rvu *rvu = rvu_dl->rvu;1469 struct rvu_switch *rswitch;1470 1471 rswitch = &rvu->rswitch;1472 *mode = rswitch->mode;1473 1474 return 0;1475}1476 1477static int rvu_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,1478 struct netlink_ext_ack *extack)1479{1480 struct rvu_devlink *rvu_dl = devlink_priv(devlink);1481 struct rvu *rvu = rvu_dl->rvu;1482 struct rvu_switch *rswitch;1483 1484 rswitch = &rvu->rswitch;1485 switch (mode) {1486 case DEVLINK_ESWITCH_MODE_LEGACY:1487 case DEVLINK_ESWITCH_MODE_SWITCHDEV:1488 if (rswitch->mode == mode)1489 return 0;1490 rswitch->mode = mode;1491 if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV)1492 rvu_switch_enable(rvu);1493 else1494 rvu_switch_disable(rvu);1495 break;1496 default:1497 return -EINVAL;1498 }1499 1500 return 0;1501}1502 1503static const struct devlink_ops rvu_devlink_ops = {1504 .eswitch_mode_get = rvu_devlink_eswitch_mode_get,1505 .eswitch_mode_set = rvu_devlink_eswitch_mode_set,1506};1507 1508int rvu_register_dl(struct rvu *rvu)1509{1510 struct rvu_devlink *rvu_dl;1511 struct devlink *dl;1512 int err;1513 1514 dl = devlink_alloc(&rvu_devlink_ops, sizeof(struct rvu_devlink),1515 rvu->dev);1516 if (!dl) {1517 dev_warn(rvu->dev, "devlink_alloc failed\n");1518 return -ENOMEM;1519 }1520 1521 rvu_dl = devlink_priv(dl);1522 rvu_dl->dl = dl;1523 rvu_dl->rvu = rvu;1524 rvu->rvu_dl = rvu_dl;1525 1526 err = rvu_health_reporters_create(rvu);1527 if (err) {1528 dev_err(rvu->dev,1529 "devlink health reporter creation failed with error %d\n", err);1530 goto err_dl_health;1531 }1532 1533 err = devlink_params_register(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params));1534 if (err) {1535 dev_err(rvu->dev,1536 "devlink params register failed with error %d", err);1537 goto err_dl_health;1538 }1539 1540 /* Register exact match devlink only for CN10K-B */1541 if (!rvu_npc_exact_has_match_table(rvu))1542 goto done;1543 1544 err = devlink_params_register(dl, rvu_af_dl_param_exact_match,1545 ARRAY_SIZE(rvu_af_dl_param_exact_match));1546 if (err) {1547 dev_err(rvu->dev,1548 "devlink exact match params register failed with error %d", err);1549 goto err_dl_exact_match;1550 }1551 1552done:1553 devlink_register(dl);1554 return 0;1555 1556err_dl_exact_match:1557 devlink_params_unregister(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params));1558 1559err_dl_health:1560 rvu_health_reporters_destroy(rvu);1561 devlink_free(dl);1562 return err;1563}1564 1565void rvu_unregister_dl(struct rvu *rvu)1566{1567 struct rvu_devlink *rvu_dl = rvu->rvu_dl;1568 struct devlink *dl = rvu_dl->dl;1569 1570 devlink_unregister(dl);1571 1572 devlink_params_unregister(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params));1573 1574 /* Unregister exact match devlink only for CN10K-B */1575 if (rvu_npc_exact_has_match_table(rvu))1576 devlink_params_unregister(dl, rvu_af_dl_param_exact_match,1577 ARRAY_SIZE(rvu_af_dl_param_exact_match));1578 1579 rvu_health_reporters_destroy(rvu);1580 devlink_free(dl);1581}1582