linux/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
<<
>>
Prefs
   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
  16static 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
  27static 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
  38static 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
  55static void rvu_nix_intr_work(struct work_struct *work)
  56{
  57        struct rvu_nix_health_reporters *rvu_nix_health_reporter;
  58
  59        rvu_nix_health_reporter = container_of(work, struct rvu_nix_health_reporters, intr_work);
  60        devlink_health_report(rvu_nix_health_reporter->rvu_hw_nix_intr_reporter,
  61                              "NIX_AF_RVU Error",
  62                              rvu_nix_health_reporter->nix_event_ctx);
  63}
  64
  65static irqreturn_t rvu_nix_af_rvu_intr_handler(int irq, void *rvu_irq)
  66{
  67        struct rvu_nix_event_ctx *nix_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_NIX, 0);
  75        if (blkaddr < 0)
  76                return IRQ_NONE;
  77
  78        nix_event_context = rvu_dl->rvu_nix_health_reporter->nix_event_ctx;
  79        intr = rvu_read64(rvu, blkaddr, NIX_AF_RVU_INT);
  80        nix_event_context->nix_af_rvu_int = intr;
  81
  82        /* Clear interrupts */
  83        rvu_write64(rvu, blkaddr, NIX_AF_RVU_INT, intr);
  84        rvu_write64(rvu, blkaddr, NIX_AF_RVU_INT_ENA_W1C, ~0ULL);
  85        queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_nix_health_reporter->intr_work);
  86
  87        return IRQ_HANDLED;
  88}
  89
  90static void rvu_nix_gen_work(struct work_struct *work)
  91{
  92        struct rvu_nix_health_reporters *rvu_nix_health_reporter;
  93
  94        rvu_nix_health_reporter = container_of(work, struct rvu_nix_health_reporters, gen_work);
  95        devlink_health_report(rvu_nix_health_reporter->rvu_hw_nix_gen_reporter,
  96                              "NIX_AF_GEN Error",
  97                              rvu_nix_health_reporter->nix_event_ctx);
  98}
  99
 100static irqreturn_t rvu_nix_af_rvu_gen_handler(int irq, void *rvu_irq)
 101{
 102        struct rvu_nix_event_ctx *nix_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_NIX, 0);
 110        if (blkaddr < 0)
 111                return IRQ_NONE;
 112
 113        nix_event_context = rvu_dl->rvu_nix_health_reporter->nix_event_ctx;
 114        intr = rvu_read64(rvu, blkaddr, NIX_AF_GEN_INT);
 115        nix_event_context->nix_af_rvu_gen = intr;
 116
 117        /* Clear interrupts */
 118        rvu_write64(rvu, blkaddr, NIX_AF_GEN_INT, intr);
 119        rvu_write64(rvu, blkaddr, NIX_AF_GEN_INT_ENA_W1C, ~0ULL);
 120        queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_nix_health_reporter->gen_work);
 121
 122        return IRQ_HANDLED;
 123}
 124
 125static void rvu_nix_err_work(struct work_struct *work)
 126{
 127        struct rvu_nix_health_reporters *rvu_nix_health_reporter;
 128
 129        rvu_nix_health_reporter = container_of(work, struct rvu_nix_health_reporters, err_work);
 130        devlink_health_report(rvu_nix_health_reporter->rvu_hw_nix_err_reporter,
 131                              "NIX_AF_ERR Error",
 132                              rvu_nix_health_reporter->nix_event_ctx);
 133}
 134
 135static irqreturn_t rvu_nix_af_rvu_err_handler(int irq, void *rvu_irq)
 136{
 137        struct rvu_nix_event_ctx *nix_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_NIX, 0);
 145        if (blkaddr < 0)
 146                return IRQ_NONE;
 147
 148        nix_event_context = rvu_dl->rvu_nix_health_reporter->nix_event_ctx;
 149        intr = rvu_read64(rvu, blkaddr, NIX_AF_ERR_INT);
 150        nix_event_context->nix_af_rvu_err = intr;
 151
 152        /* Clear interrupts */
 153        rvu_write64(rvu, blkaddr, NIX_AF_ERR_INT, intr);
 154        rvu_write64(rvu, blkaddr, NIX_AF_ERR_INT_ENA_W1C, ~0ULL);
 155        queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_nix_health_reporter->err_work);
 156
 157        return IRQ_HANDLED;
 158}
 159
 160static void rvu_nix_ras_work(struct work_struct *work)
 161{
 162        struct rvu_nix_health_reporters *rvu_nix_health_reporter;
 163
 164        rvu_nix_health_reporter = container_of(work, struct rvu_nix_health_reporters, ras_work);
 165        devlink_health_report(rvu_nix_health_reporter->rvu_hw_nix_ras_reporter,
 166                              "NIX_AF_RAS Error",
 167                              rvu_nix_health_reporter->nix_event_ctx);
 168}
 169
 170static irqreturn_t rvu_nix_af_rvu_ras_handler(int irq, void *rvu_irq)
 171{
 172        struct rvu_nix_event_ctx *nix_event_context;
 173        struct rvu_devlink *rvu_dl = rvu_irq;
 174        struct rvu *rvu;
 175        int blkaddr;
 176        u64 intr;
 177
 178        rvu = rvu_dl->rvu;
 179        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);
 180        if (blkaddr < 0)
 181                return IRQ_NONE;
 182
 183        nix_event_context = rvu_dl->rvu_nix_health_reporter->nix_event_ctx;
 184        intr = rvu_read64(rvu, blkaddr, NIX_AF_ERR_INT);
 185        nix_event_context->nix_af_rvu_ras = intr;
 186
 187        /* Clear interrupts */
 188        rvu_write64(rvu, blkaddr, NIX_AF_RAS, intr);
 189        rvu_write64(rvu, blkaddr, NIX_AF_RAS_ENA_W1C, ~0ULL);
 190        queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_nix_health_reporter->ras_work);
 191
 192        return IRQ_HANDLED;
 193}
 194
 195static void rvu_nix_unregister_interrupts(struct rvu *rvu)
 196{
 197        struct rvu_devlink *rvu_dl = rvu->rvu_dl;
 198        int offs, i, blkaddr;
 199
 200        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);
 201        if (blkaddr < 0)
 202                return;
 203
 204        offs = rvu_read64(rvu, blkaddr, NIX_PRIV_AF_INT_CFG) & 0x3ff;
 205        if (!offs)
 206                return;
 207
 208        rvu_write64(rvu, blkaddr, NIX_AF_RVU_INT_ENA_W1C, ~0ULL);
 209        rvu_write64(rvu, blkaddr, NIX_AF_GEN_INT_ENA_W1C, ~0ULL);
 210        rvu_write64(rvu, blkaddr, NIX_AF_ERR_INT_ENA_W1C, ~0ULL);
 211        rvu_write64(rvu, blkaddr, NIX_AF_RAS_ENA_W1C, ~0ULL);
 212
 213        if (rvu->irq_allocated[offs + NIX_AF_INT_VEC_RVU]) {
 214                free_irq(pci_irq_vector(rvu->pdev, offs + NIX_AF_INT_VEC_RVU),
 215                         rvu_dl);
 216                rvu->irq_allocated[offs + NIX_AF_INT_VEC_RVU] = false;
 217        }
 218
 219        for (i = NIX_AF_INT_VEC_AF_ERR; i < NIX_AF_INT_VEC_CNT; i++)
 220                if (rvu->irq_allocated[offs + i]) {
 221                        free_irq(pci_irq_vector(rvu->pdev, offs + i), rvu_dl);
 222                        rvu->irq_allocated[offs + i] = false;
 223                }
 224}
 225
 226static int rvu_nix_register_interrupts(struct rvu *rvu)
 227{
 228        int blkaddr, base;
 229        bool rc;
 230
 231        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);
 232        if (blkaddr < 0)
 233                return blkaddr;
 234
 235        /* Get NIX AF MSIX vectors offset. */
 236        base = rvu_read64(rvu, blkaddr, NIX_PRIV_AF_INT_CFG) & 0x3ff;
 237        if (!base) {
 238                dev_warn(rvu->dev,
 239                         "Failed to get NIX%d NIX_AF_INT vector offsets\n",
 240                         blkaddr - BLKADDR_NIX0);
 241                return 0;
 242        }
 243        /* Register and enable NIX_AF_RVU_INT interrupt */
 244        rc = rvu_common_request_irq(rvu, base +  NIX_AF_INT_VEC_RVU,
 245                                    "NIX_AF_RVU_INT",
 246                                    rvu_nix_af_rvu_intr_handler);
 247        if (!rc)
 248                goto err;
 249        rvu_write64(rvu, blkaddr, NIX_AF_RVU_INT_ENA_W1S, ~0ULL);
 250
 251        /* Register and enable NIX_AF_GEN_INT interrupt */
 252        rc = rvu_common_request_irq(rvu, base +  NIX_AF_INT_VEC_GEN,
 253                                    "NIX_AF_GEN_INT",
 254                                    rvu_nix_af_rvu_gen_handler);
 255        if (!rc)
 256                goto err;
 257        rvu_write64(rvu, blkaddr, NIX_AF_GEN_INT_ENA_W1S, ~0ULL);
 258
 259        /* Register and enable NIX_AF_ERR_INT interrupt */
 260        rc = rvu_common_request_irq(rvu, base + NIX_AF_INT_VEC_AF_ERR,
 261                                    "NIX_AF_ERR_INT",
 262                                    rvu_nix_af_rvu_err_handler);
 263        if (!rc)
 264                goto err;
 265        rvu_write64(rvu, blkaddr, NIX_AF_ERR_INT_ENA_W1S, ~0ULL);
 266
 267        /* Register and enable NIX_AF_RAS interrupt */
 268        rc = rvu_common_request_irq(rvu, base + NIX_AF_INT_VEC_POISON,
 269                                    "NIX_AF_RAS",
 270                                    rvu_nix_af_rvu_ras_handler);
 271        if (!rc)
 272                goto err;
 273        rvu_write64(rvu, blkaddr, NIX_AF_RAS_ENA_W1S, ~0ULL);
 274
 275        return 0;
 276err:
 277        rvu_nix_unregister_interrupts(rvu);
 278        return rc;
 279}
 280
 281static int rvu_nix_report_show(struct devlink_fmsg *fmsg, void *ctx,
 282                               enum nix_af_rvu_health health_reporter)
 283{
 284        struct rvu_nix_event_ctx *nix_event_context;
 285        u64 intr_val;
 286        int err;
 287
 288        nix_event_context = ctx;
 289        switch (health_reporter) {
 290        case NIX_AF_RVU_INTR:
 291                intr_val = nix_event_context->nix_af_rvu_int;
 292                err = rvu_report_pair_start(fmsg, "NIX_AF_RVU");
 293                if (err)
 294                        return err;
 295                err = devlink_fmsg_u64_pair_put(fmsg, "\tNIX RVU Interrupt Reg ",
 296                                                nix_event_context->nix_af_rvu_int);
 297                if (err)
 298                        return err;
 299                if (intr_val & BIT_ULL(0)) {
 300                        err = devlink_fmsg_string_put(fmsg, "\n\tUnmap Slot Error");
 301                        if (err)
 302                                return err;
 303                }
 304                err = rvu_report_pair_end(fmsg);
 305                if (err)
 306                        return err;
 307                break;
 308        case NIX_AF_RVU_GEN:
 309                intr_val = nix_event_context->nix_af_rvu_gen;
 310                err = rvu_report_pair_start(fmsg, "NIX_AF_GENERAL");
 311                if (err)
 312                        return err;
 313                err = devlink_fmsg_u64_pair_put(fmsg, "\tNIX General Interrupt Reg ",
 314                                                nix_event_context->nix_af_rvu_gen);
 315                if (err)
 316                        return err;
 317                if (intr_val & BIT_ULL(0)) {
 318                        err = devlink_fmsg_string_put(fmsg, "\n\tRx multicast pkt drop");
 319                        if (err)
 320                                return err;
 321                }
 322                if (intr_val & BIT_ULL(1)) {
 323                        err = devlink_fmsg_string_put(fmsg, "\n\tRx mirror pkt drop");
 324                        if (err)
 325                                return err;
 326                }
 327                if (intr_val & BIT_ULL(4)) {
 328                        err = devlink_fmsg_string_put(fmsg, "\n\tSMQ flush done");
 329                        if (err)
 330                                return err;
 331                }
 332                err = rvu_report_pair_end(fmsg);
 333                if (err)
 334                        return err;
 335                break;
 336        case NIX_AF_RVU_ERR:
 337                intr_val = nix_event_context->nix_af_rvu_err;
 338                err = rvu_report_pair_start(fmsg, "NIX_AF_ERR");
 339                if (err)
 340                        return err;
 341                err = devlink_fmsg_u64_pair_put(fmsg, "\tNIX Error Interrupt Reg ",
 342                                                nix_event_context->nix_af_rvu_err);
 343                if (err)
 344                        return err;
 345                if (intr_val & BIT_ULL(14)) {
 346                        err = devlink_fmsg_string_put(fmsg, "\n\tFault on NIX_AQ_INST_S read");
 347                        if (err)
 348                                return err;
 349                }
 350                if (intr_val & BIT_ULL(13)) {
 351                        err = devlink_fmsg_string_put(fmsg, "\n\tFault on NIX_AQ_RES_S write");
 352                        if (err)
 353                                return err;
 354                }
 355                if (intr_val & BIT_ULL(12)) {
 356                        err = devlink_fmsg_string_put(fmsg, "\n\tAQ Doorbell Error");
 357                        if (err)
 358                                return err;
 359                }
 360                if (intr_val & BIT_ULL(6)) {
 361                        err = devlink_fmsg_string_put(fmsg, "\n\tRx on unmapped PF_FUNC");
 362                        if (err)
 363                                return err;
 364                }
 365                if (intr_val & BIT_ULL(5)) {
 366                        err = devlink_fmsg_string_put(fmsg, "\n\tRx multicast replication error");
 367                        if (err)
 368                                return err;
 369                }
 370                if (intr_val & BIT_ULL(4)) {
 371                        err = devlink_fmsg_string_put(fmsg, "\n\tFault on NIX_RX_MCE_S read");
 372                        if (err)
 373                                return err;
 374                }
 375                if (intr_val & BIT_ULL(3)) {
 376                        err = devlink_fmsg_string_put(fmsg, "\n\tFault on multicast WQE read");
 377                        if (err)
 378                                return err;
 379                }
 380                if (intr_val & BIT_ULL(2)) {
 381                        err = devlink_fmsg_string_put(fmsg, "\n\tFault on mirror WQE read");
 382                        if (err)
 383                                return err;
 384                }
 385                if (intr_val & BIT_ULL(1)) {
 386                        err = devlink_fmsg_string_put(fmsg, "\n\tFault on mirror pkt write");
 387                        if (err)
 388                                return err;
 389                }
 390                if (intr_val & BIT_ULL(0)) {
 391                        err = devlink_fmsg_string_put(fmsg, "\n\tFault on multicast pkt write");
 392                        if (err)
 393                                return err;
 394                }
 395                err = rvu_report_pair_end(fmsg);
 396                if (err)
 397                        return err;
 398                break;
 399        case NIX_AF_RVU_RAS:
 400                intr_val = nix_event_context->nix_af_rvu_err;
 401                err = rvu_report_pair_start(fmsg, "NIX_AF_RAS");
 402                if (err)
 403                        return err;
 404                err = devlink_fmsg_u64_pair_put(fmsg, "\tNIX RAS Interrupt Reg ",
 405                                                nix_event_context->nix_af_rvu_err);
 406                if (err)
 407                        return err;
 408                err = devlink_fmsg_string_put(fmsg, "\n\tPoison Data on:");
 409                if (err)
 410                        return err;
 411                if (intr_val & BIT_ULL(34)) {
 412                        err = devlink_fmsg_string_put(fmsg, "\n\tNIX_AQ_INST_S");
 413                        if (err)
 414                                return err;
 415                }
 416                if (intr_val & BIT_ULL(33)) {
 417                        err = devlink_fmsg_string_put(fmsg, "\n\tNIX_AQ_RES_S");
 418                        if (err)
 419                                return err;
 420                }
 421                if (intr_val & BIT_ULL(32)) {
 422                        err = devlink_fmsg_string_put(fmsg, "\n\tHW ctx");
 423                        if (err)
 424                                return err;
 425                }
 426                if (intr_val & BIT_ULL(4)) {
 427                        err = devlink_fmsg_string_put(fmsg, "\n\tPacket from mirror buffer");
 428                        if (err)
 429                                return err;
 430                }
 431                if (intr_val & BIT_ULL(3)) {
 432                        err = devlink_fmsg_string_put(fmsg, "\n\tPacket from multicast buffer");
 433
 434                        if (err)
 435                                return err;
 436                }
 437                if (intr_val & BIT_ULL(2)) {
 438                        err = devlink_fmsg_string_put(fmsg, "\n\tWQE read from mirror buffer");
 439                        if (err)
 440                                return err;
 441                }
 442                if (intr_val & BIT_ULL(1)) {
 443                        err = devlink_fmsg_string_put(fmsg, "\n\tWQE read from multicast buffer");
 444                        if (err)
 445                                return err;
 446                }
 447                if (intr_val & BIT_ULL(0)) {
 448                        err = devlink_fmsg_string_put(fmsg, "\n\tNIX_RX_MCE_S read");
 449                        if (err)
 450                                return err;
 451                }
 452                err = rvu_report_pair_end(fmsg);
 453                if (err)
 454                        return err;
 455                break;
 456        default:
 457                return -EINVAL;
 458        }
 459
 460        return 0;
 461}
 462
 463static int rvu_hw_nix_intr_dump(struct devlink_health_reporter *reporter,
 464                                struct devlink_fmsg *fmsg, void *ctx,
 465                                struct netlink_ext_ack *netlink_extack)
 466{
 467        struct rvu *rvu = devlink_health_reporter_priv(reporter);
 468        struct rvu_devlink *rvu_dl = rvu->rvu_dl;
 469        struct rvu_nix_event_ctx *nix_ctx;
 470
 471        nix_ctx = rvu_dl->rvu_nix_health_reporter->nix_event_ctx;
 472
 473        return ctx ? rvu_nix_report_show(fmsg, ctx, NIX_AF_RVU_INTR) :
 474                     rvu_nix_report_show(fmsg, nix_ctx, NIX_AF_RVU_INTR);
 475}
 476
 477static int rvu_hw_nix_intr_recover(struct devlink_health_reporter *reporter,
 478                                   void *ctx, struct netlink_ext_ack *netlink_extack)
 479{
 480        struct rvu *rvu = devlink_health_reporter_priv(reporter);
 481        struct rvu_nix_event_ctx *nix_event_ctx = ctx;
 482        int blkaddr;
 483
 484        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);
 485        if (blkaddr < 0)
 486                return blkaddr;
 487
 488        if (nix_event_ctx->nix_af_rvu_int)
 489                rvu_write64(rvu, blkaddr, NIX_AF_RVU_INT_ENA_W1S, ~0ULL);
 490
 491        return 0;
 492}
 493
 494static int rvu_hw_nix_gen_dump(struct devlink_health_reporter *reporter,
 495                               struct devlink_fmsg *fmsg, void *ctx,
 496                               struct netlink_ext_ack *netlink_extack)
 497{
 498        struct rvu *rvu = devlink_health_reporter_priv(reporter);
 499        struct rvu_devlink *rvu_dl = rvu->rvu_dl;
 500        struct rvu_nix_event_ctx *nix_ctx;
 501
 502        nix_ctx = rvu_dl->rvu_nix_health_reporter->nix_event_ctx;
 503
 504        return ctx ? rvu_nix_report_show(fmsg, ctx, NIX_AF_RVU_GEN) :
 505                     rvu_nix_report_show(fmsg, nix_ctx, NIX_AF_RVU_GEN);
 506}
 507
 508static int rvu_hw_nix_gen_recover(struct devlink_health_reporter *reporter,
 509                                  void *ctx, struct netlink_ext_ack *netlink_extack)
 510{
 511        struct rvu *rvu = devlink_health_reporter_priv(reporter);
 512        struct rvu_nix_event_ctx *nix_event_ctx = ctx;
 513        int blkaddr;
 514
 515        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);
 516        if (blkaddr < 0)
 517                return blkaddr;
 518
 519        if (nix_event_ctx->nix_af_rvu_gen)
 520                rvu_write64(rvu, blkaddr, NIX_AF_GEN_INT_ENA_W1S, ~0ULL);
 521
 522        return 0;
 523}
 524
 525static int rvu_hw_nix_err_dump(struct devlink_health_reporter *reporter,
 526                               struct devlink_fmsg *fmsg, void *ctx,
 527                               struct netlink_ext_ack *netlink_extack)
 528{
 529        struct rvu *rvu = devlink_health_reporter_priv(reporter);
 530        struct rvu_devlink *rvu_dl = rvu->rvu_dl;
 531        struct rvu_nix_event_ctx *nix_ctx;
 532
 533        nix_ctx = rvu_dl->rvu_nix_health_reporter->nix_event_ctx;
 534
 535        return ctx ? rvu_nix_report_show(fmsg, ctx, NIX_AF_RVU_ERR) :
 536                     rvu_nix_report_show(fmsg, nix_ctx, NIX_AF_RVU_ERR);
 537}
 538
 539static int rvu_hw_nix_err_recover(struct devlink_health_reporter *reporter,
 540                                  void *ctx, struct netlink_ext_ack *netlink_extack)
 541{
 542        struct rvu *rvu = devlink_health_reporter_priv(reporter);
 543        struct rvu_nix_event_ctx *nix_event_ctx = ctx;
 544        int blkaddr;
 545
 546        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);
 547        if (blkaddr < 0)
 548                return blkaddr;
 549
 550        if (nix_event_ctx->nix_af_rvu_err)
 551                rvu_write64(rvu, blkaddr, NIX_AF_ERR_INT_ENA_W1S, ~0ULL);
 552
 553        return 0;
 554}
 555
 556static int rvu_hw_nix_ras_dump(struct devlink_health_reporter *reporter,
 557                               struct devlink_fmsg *fmsg, void *ctx,
 558                               struct netlink_ext_ack *netlink_extack)
 559{
 560        struct rvu *rvu = devlink_health_reporter_priv(reporter);
 561        struct rvu_devlink *rvu_dl = rvu->rvu_dl;
 562        struct rvu_nix_event_ctx *nix_ctx;
 563
 564        nix_ctx = rvu_dl->rvu_nix_health_reporter->nix_event_ctx;
 565
 566        return ctx ? rvu_nix_report_show(fmsg, ctx, NIX_AF_RVU_RAS) :
 567                     rvu_nix_report_show(fmsg, nix_ctx, NIX_AF_RVU_RAS);
 568}
 569
 570static int rvu_hw_nix_ras_recover(struct devlink_health_reporter *reporter,
 571                                  void *ctx, struct netlink_ext_ack *netlink_extack)
 572{
 573        struct rvu *rvu = devlink_health_reporter_priv(reporter);
 574        struct rvu_nix_event_ctx *nix_event_ctx = ctx;
 575        int blkaddr;
 576
 577        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);
 578        if (blkaddr < 0)
 579                return blkaddr;
 580
 581        if (nix_event_ctx->nix_af_rvu_int)
 582                rvu_write64(rvu, blkaddr, NIX_AF_RAS_ENA_W1S, ~0ULL);
 583
 584        return 0;
 585}
 586
 587RVU_REPORTERS(hw_nix_intr);
 588RVU_REPORTERS(hw_nix_gen);
 589RVU_REPORTERS(hw_nix_err);
 590RVU_REPORTERS(hw_nix_ras);
 591
 592static void rvu_nix_health_reporters_destroy(struct rvu_devlink *rvu_dl);
 593
 594static int rvu_nix_register_reporters(struct rvu_devlink *rvu_dl)
 595{
 596        struct rvu_nix_health_reporters *rvu_reporters;
 597        struct rvu_nix_event_ctx *nix_event_context;
 598        struct rvu *rvu = rvu_dl->rvu;
 599
 600        rvu_reporters = kzalloc(sizeof(*rvu_reporters), GFP_KERNEL);
 601        if (!rvu_reporters)
 602                return -ENOMEM;
 603
 604        rvu_dl->rvu_nix_health_reporter = rvu_reporters;
 605        nix_event_context = kzalloc(sizeof(*nix_event_context), GFP_KERNEL);
 606        if (!nix_event_context)
 607                return -ENOMEM;
 608
 609        rvu_reporters->nix_event_ctx = nix_event_context;
 610        rvu_reporters->rvu_hw_nix_intr_reporter =
 611                devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_nix_intr_reporter_ops, 0, rvu);
 612        if (IS_ERR(rvu_reporters->rvu_hw_nix_intr_reporter)) {
 613                dev_warn(rvu->dev, "Failed to create hw_nix_intr reporter, err=%ld\n",
 614                         PTR_ERR(rvu_reporters->rvu_hw_nix_intr_reporter));
 615                return PTR_ERR(rvu_reporters->rvu_hw_nix_intr_reporter);
 616        }
 617
 618        rvu_reporters->rvu_hw_nix_gen_reporter =
 619                devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_nix_gen_reporter_ops, 0, rvu);
 620        if (IS_ERR(rvu_reporters->rvu_hw_nix_gen_reporter)) {
 621                dev_warn(rvu->dev, "Failed to create hw_nix_gen reporter, err=%ld\n",
 622                         PTR_ERR(rvu_reporters->rvu_hw_nix_gen_reporter));
 623                return PTR_ERR(rvu_reporters->rvu_hw_nix_gen_reporter);
 624        }
 625
 626        rvu_reporters->rvu_hw_nix_err_reporter =
 627                devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_nix_err_reporter_ops, 0, rvu);
 628        if (IS_ERR(rvu_reporters->rvu_hw_nix_err_reporter)) {
 629                dev_warn(rvu->dev, "Failed to create hw_nix_err reporter, err=%ld\n",
 630                         PTR_ERR(rvu_reporters->rvu_hw_nix_err_reporter));
 631                return PTR_ERR(rvu_reporters->rvu_hw_nix_err_reporter);
 632        }
 633
 634        rvu_reporters->rvu_hw_nix_ras_reporter =
 635                devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_nix_ras_reporter_ops, 0, rvu);
 636        if (IS_ERR(rvu_reporters->rvu_hw_nix_ras_reporter)) {
 637                dev_warn(rvu->dev, "Failed to create hw_nix_ras reporter, err=%ld\n",
 638                         PTR_ERR(rvu_reporters->rvu_hw_nix_ras_reporter));
 639                return PTR_ERR(rvu_reporters->rvu_hw_nix_ras_reporter);
 640        }
 641
 642        rvu_dl->devlink_wq = create_workqueue("rvu_devlink_wq");
 643        if (!rvu_dl->devlink_wq)
 644                goto err;
 645
 646        INIT_WORK(&rvu_reporters->intr_work, rvu_nix_intr_work);
 647        INIT_WORK(&rvu_reporters->gen_work, rvu_nix_gen_work);
 648        INIT_WORK(&rvu_reporters->err_work, rvu_nix_err_work);
 649        INIT_WORK(&rvu_reporters->ras_work, rvu_nix_ras_work);
 650
 651        return 0;
 652err:
 653        rvu_nix_health_reporters_destroy(rvu_dl);
 654        return -ENOMEM;
 655}
 656
 657static int rvu_nix_health_reporters_create(struct rvu_devlink *rvu_dl)
 658{
 659        struct rvu *rvu = rvu_dl->rvu;
 660        int err;
 661
 662        err = rvu_nix_register_reporters(rvu_dl);
 663        if (err) {
 664                dev_warn(rvu->dev, "Failed to create nix reporter, err =%d\n",
 665                         err);
 666                return err;
 667        }
 668        rvu_nix_register_interrupts(rvu);
 669
 670        return 0;
 671}
 672
 673static void rvu_nix_health_reporters_destroy(struct rvu_devlink *rvu_dl)
 674{
 675        struct rvu_nix_health_reporters *nix_reporters;
 676        struct rvu *rvu = rvu_dl->rvu;
 677
 678        nix_reporters = rvu_dl->rvu_nix_health_reporter;
 679
 680        if (!nix_reporters->rvu_hw_nix_ras_reporter)
 681                return;
 682        if (!IS_ERR_OR_NULL(nix_reporters->rvu_hw_nix_intr_reporter))
 683                devlink_health_reporter_destroy(nix_reporters->rvu_hw_nix_intr_reporter);
 684
 685        if (!IS_ERR_OR_NULL(nix_reporters->rvu_hw_nix_gen_reporter))
 686                devlink_health_reporter_destroy(nix_reporters->rvu_hw_nix_gen_reporter);
 687
 688        if (!IS_ERR_OR_NULL(nix_reporters->rvu_hw_nix_err_reporter))
 689                devlink_health_reporter_destroy(nix_reporters->rvu_hw_nix_err_reporter);
 690
 691        if (!IS_ERR_OR_NULL(nix_reporters->rvu_hw_nix_ras_reporter))
 692                devlink_health_reporter_destroy(nix_reporters->rvu_hw_nix_ras_reporter);
 693
 694        rvu_nix_unregister_interrupts(rvu);
 695        kfree(rvu_dl->rvu_nix_health_reporter->nix_event_ctx);
 696        kfree(rvu_dl->rvu_nix_health_reporter);
 697}
 698
 699static void rvu_npa_intr_work(struct work_struct *work)
 700{
 701        struct rvu_npa_health_reporters *rvu_npa_health_reporter;
 702
 703        rvu_npa_health_reporter = container_of(work, struct rvu_npa_health_reporters, intr_work);
 704        devlink_health_report(rvu_npa_health_reporter->rvu_hw_npa_intr_reporter,
 705                              "NPA_AF_RVU Error",
 706                              rvu_npa_health_reporter->npa_event_ctx);
 707}
 708
 709static irqreturn_t rvu_npa_af_rvu_intr_handler(int irq, void *rvu_irq)
 710{
 711        struct rvu_npa_event_ctx *npa_event_context;
 712        struct rvu_devlink *rvu_dl = rvu_irq;
 713        struct rvu *rvu;
 714        int blkaddr;
 715        u64 intr;
 716
 717        rvu = rvu_dl->rvu;
 718        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
 719        if (blkaddr < 0)
 720                return IRQ_NONE;
 721
 722        npa_event_context = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;
 723        intr = rvu_read64(rvu, blkaddr, NPA_AF_RVU_INT);
 724        npa_event_context->npa_af_rvu_int = intr;
 725
 726        /* Clear interrupts */
 727        rvu_write64(rvu, blkaddr, NPA_AF_RVU_INT, intr);
 728        rvu_write64(rvu, blkaddr, NPA_AF_RVU_INT_ENA_W1C, ~0ULL);
 729        queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_npa_health_reporter->intr_work);
 730
 731        return IRQ_HANDLED;
 732}
 733
 734static void rvu_npa_gen_work(struct work_struct *work)
 735{
 736        struct rvu_npa_health_reporters *rvu_npa_health_reporter;
 737
 738        rvu_npa_health_reporter = container_of(work, struct rvu_npa_health_reporters, gen_work);
 739        devlink_health_report(rvu_npa_health_reporter->rvu_hw_npa_gen_reporter,
 740                              "NPA_AF_GEN Error",
 741                              rvu_npa_health_reporter->npa_event_ctx);
 742}
 743
 744static irqreturn_t rvu_npa_af_gen_intr_handler(int irq, void *rvu_irq)
 745{
 746        struct rvu_npa_event_ctx *npa_event_context;
 747        struct rvu_devlink *rvu_dl = rvu_irq;
 748        struct rvu *rvu;
 749        int blkaddr;
 750        u64 intr;
 751
 752        rvu = rvu_dl->rvu;
 753        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
 754        if (blkaddr < 0)
 755                return IRQ_NONE;
 756
 757        npa_event_context = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;
 758        intr = rvu_read64(rvu, blkaddr, NPA_AF_GEN_INT);
 759        npa_event_context->npa_af_rvu_gen = intr;
 760
 761        /* Clear interrupts */
 762        rvu_write64(rvu, blkaddr, NPA_AF_GEN_INT, intr);
 763        rvu_write64(rvu, blkaddr, NPA_AF_GEN_INT_ENA_W1C, ~0ULL);
 764        queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_npa_health_reporter->gen_work);
 765
 766        return IRQ_HANDLED;
 767}
 768
 769static void rvu_npa_err_work(struct work_struct *work)
 770{
 771        struct rvu_npa_health_reporters *rvu_npa_health_reporter;
 772
 773        rvu_npa_health_reporter = container_of(work, struct rvu_npa_health_reporters, err_work);
 774        devlink_health_report(rvu_npa_health_reporter->rvu_hw_npa_err_reporter,
 775                              "NPA_AF_ERR Error",
 776                              rvu_npa_health_reporter->npa_event_ctx);
 777}
 778
 779static irqreturn_t rvu_npa_af_err_intr_handler(int irq, void *rvu_irq)
 780{
 781        struct rvu_npa_event_ctx *npa_event_context;
 782        struct rvu_devlink *rvu_dl = rvu_irq;
 783        struct rvu *rvu;
 784        int blkaddr;
 785        u64 intr;
 786
 787        rvu = rvu_dl->rvu;
 788        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
 789        if (blkaddr < 0)
 790                return IRQ_NONE;
 791        npa_event_context = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;
 792        intr = rvu_read64(rvu, blkaddr, NPA_AF_ERR_INT);
 793        npa_event_context->npa_af_rvu_err = intr;
 794
 795        /* Clear interrupts */
 796        rvu_write64(rvu, blkaddr, NPA_AF_ERR_INT, intr);
 797        rvu_write64(rvu, blkaddr, NPA_AF_ERR_INT_ENA_W1C, ~0ULL);
 798        queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_npa_health_reporter->err_work);
 799
 800        return IRQ_HANDLED;
 801}
 802
 803static void rvu_npa_ras_work(struct work_struct *work)
 804{
 805        struct rvu_npa_health_reporters *rvu_npa_health_reporter;
 806
 807        rvu_npa_health_reporter = container_of(work, struct rvu_npa_health_reporters, ras_work);
 808        devlink_health_report(rvu_npa_health_reporter->rvu_hw_npa_ras_reporter,
 809                              "HW NPA_AF_RAS Error reported",
 810                              rvu_npa_health_reporter->npa_event_ctx);
 811}
 812
 813static irqreturn_t rvu_npa_af_ras_intr_handler(int irq, void *rvu_irq)
 814{
 815        struct rvu_npa_event_ctx *npa_event_context;
 816        struct rvu_devlink *rvu_dl = rvu_irq;
 817        struct rvu *rvu;
 818        int blkaddr;
 819        u64 intr;
 820
 821        rvu = rvu_dl->rvu;
 822        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
 823        if (blkaddr < 0)
 824                return IRQ_NONE;
 825
 826        npa_event_context = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;
 827        intr = rvu_read64(rvu, blkaddr, NPA_AF_RAS);
 828        npa_event_context->npa_af_rvu_ras = intr;
 829
 830        /* Clear interrupts */
 831        rvu_write64(rvu, blkaddr, NPA_AF_RAS, intr);
 832        rvu_write64(rvu, blkaddr, NPA_AF_RAS_ENA_W1C, ~0ULL);
 833        queue_work(rvu_dl->devlink_wq, &rvu_dl->rvu_npa_health_reporter->ras_work);
 834
 835        return IRQ_HANDLED;
 836}
 837
 838static void rvu_npa_unregister_interrupts(struct rvu *rvu)
 839{
 840        struct rvu_devlink *rvu_dl = rvu->rvu_dl;
 841        int i, offs, blkaddr;
 842        u64 reg;
 843
 844        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
 845        if (blkaddr < 0)
 846                return;
 847
 848        reg = rvu_read64(rvu, blkaddr, NPA_PRIV_AF_INT_CFG);
 849        offs = reg & 0x3FF;
 850
 851        rvu_write64(rvu, blkaddr, NPA_AF_RVU_INT_ENA_W1C, ~0ULL);
 852        rvu_write64(rvu, blkaddr, NPA_AF_GEN_INT_ENA_W1C, ~0ULL);
 853        rvu_write64(rvu, blkaddr, NPA_AF_ERR_INT_ENA_W1C, ~0ULL);
 854        rvu_write64(rvu, blkaddr, NPA_AF_RAS_ENA_W1C, ~0ULL);
 855
 856        for (i = 0; i < NPA_AF_INT_VEC_CNT; i++)
 857                if (rvu->irq_allocated[offs + i]) {
 858                        free_irq(pci_irq_vector(rvu->pdev, offs + i), rvu_dl);
 859                        rvu->irq_allocated[offs + i] = false;
 860                }
 861}
 862
 863static int rvu_npa_register_interrupts(struct rvu *rvu)
 864{
 865        int blkaddr, base;
 866        bool rc;
 867
 868        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
 869        if (blkaddr < 0)
 870                return blkaddr;
 871
 872        /* Get NPA AF MSIX vectors offset. */
 873        base = rvu_read64(rvu, blkaddr, NPA_PRIV_AF_INT_CFG) & 0x3ff;
 874        if (!base) {
 875                dev_warn(rvu->dev,
 876                         "Failed to get NPA_AF_INT vector offsets\n");
 877                return 0;
 878        }
 879
 880        /* Register and enable NPA_AF_RVU_INT interrupt */
 881        rc = rvu_common_request_irq(rvu, base +  NPA_AF_INT_VEC_RVU,
 882                                    "NPA_AF_RVU_INT",
 883                                    rvu_npa_af_rvu_intr_handler);
 884        if (!rc)
 885                goto err;
 886        rvu_write64(rvu, blkaddr, NPA_AF_RVU_INT_ENA_W1S, ~0ULL);
 887
 888        /* Register and enable NPA_AF_GEN_INT interrupt */
 889        rc = rvu_common_request_irq(rvu, base + NPA_AF_INT_VEC_GEN,
 890                                    "NPA_AF_RVU_GEN",
 891                                    rvu_npa_af_gen_intr_handler);
 892        if (!rc)
 893                goto err;
 894        rvu_write64(rvu, blkaddr, NPA_AF_GEN_INT_ENA_W1S, ~0ULL);
 895
 896        /* Register and enable NPA_AF_ERR_INT interrupt */
 897        rc = rvu_common_request_irq(rvu, base + NPA_AF_INT_VEC_AF_ERR,
 898                                    "NPA_AF_ERR_INT",
 899                                    rvu_npa_af_err_intr_handler);
 900        if (!rc)
 901                goto err;
 902        rvu_write64(rvu, blkaddr, NPA_AF_ERR_INT_ENA_W1S, ~0ULL);
 903
 904        /* Register and enable NPA_AF_RAS interrupt */
 905        rc = rvu_common_request_irq(rvu, base + NPA_AF_INT_VEC_POISON,
 906                                    "NPA_AF_RAS",
 907                                    rvu_npa_af_ras_intr_handler);
 908        if (!rc)
 909                goto err;
 910        rvu_write64(rvu, blkaddr, NPA_AF_RAS_ENA_W1S, ~0ULL);
 911
 912        return 0;
 913err:
 914        rvu_npa_unregister_interrupts(rvu);
 915        return rc;
 916}
 917
 918static int rvu_npa_report_show(struct devlink_fmsg *fmsg, void *ctx,
 919                               enum npa_af_rvu_health health_reporter)
 920{
 921        struct rvu_npa_event_ctx *npa_event_context;
 922        unsigned int alloc_dis, free_dis;
 923        u64 intr_val;
 924        int err;
 925
 926        npa_event_context = ctx;
 927        switch (health_reporter) {
 928        case NPA_AF_RVU_GEN:
 929                intr_val = npa_event_context->npa_af_rvu_gen;
 930                err = rvu_report_pair_start(fmsg, "NPA_AF_GENERAL");
 931                if (err)
 932                        return err;
 933                err = devlink_fmsg_u64_pair_put(fmsg, "\tNPA General Interrupt Reg ",
 934                                                npa_event_context->npa_af_rvu_gen);
 935                if (err)
 936                        return err;
 937                if (intr_val & BIT_ULL(32)) {
 938                        err = devlink_fmsg_string_put(fmsg, "\n\tUnmap PF Error");
 939                        if (err)
 940                                return err;
 941                }
 942
 943                free_dis = FIELD_GET(GENMASK(15, 0), intr_val);
 944                if (free_dis & BIT(NPA_INPQ_NIX0_RX)) {
 945                        err = devlink_fmsg_string_put(fmsg, "\n\tNIX0: free disabled RX");
 946                        if (err)
 947                                return err;
 948                }
 949                if (free_dis & BIT(NPA_INPQ_NIX0_TX)) {
 950                        err = devlink_fmsg_string_put(fmsg, "\n\tNIX0:free disabled TX");
 951                        if (err)
 952                                return err;
 953                }
 954                if (free_dis & BIT(NPA_INPQ_NIX1_RX)) {
 955                        err = devlink_fmsg_string_put(fmsg, "\n\tNIX1: free disabled RX");
 956                        if (err)
 957                                return err;
 958                }
 959                if (free_dis & BIT(NPA_INPQ_NIX1_TX)) {
 960                        err = devlink_fmsg_string_put(fmsg, "\n\tNIX1:free disabled TX");
 961                        if (err)
 962                                return err;
 963                }
 964                if (free_dis & BIT(NPA_INPQ_SSO)) {
 965                        err = devlink_fmsg_string_put(fmsg, "\n\tFree Disabled for SSO");
 966                        if (err)
 967                                return err;
 968                }
 969                if (free_dis & BIT(NPA_INPQ_TIM)) {
 970                        err = devlink_fmsg_string_put(fmsg, "\n\tFree Disabled for TIM");
 971                        if (err)
 972                                return err;
 973                }
 974                if (free_dis & BIT(NPA_INPQ_DPI)) {
 975                        err = devlink_fmsg_string_put(fmsg, "\n\tFree Disabled for DPI");
 976                        if (err)
 977                                return err;
 978                }
 979                if (free_dis & BIT(NPA_INPQ_AURA_OP)) {
 980                        err = devlink_fmsg_string_put(fmsg, "\n\tFree Disabled for AURA");
 981                        if (err)
 982                                return err;
 983                }
 984
 985                alloc_dis = FIELD_GET(GENMASK(31, 16), intr_val);
 986                if (alloc_dis & BIT(NPA_INPQ_NIX0_RX)) {
 987                        err = devlink_fmsg_string_put(fmsg, "\n\tNIX0: alloc disabled RX");
 988                        if (err)
 989                                return err;
 990                }
 991                if (alloc_dis & BIT(NPA_INPQ_NIX0_TX)) {
 992                        err = devlink_fmsg_string_put(fmsg, "\n\tNIX0:alloc disabled TX");
 993                        if (err)
 994                                return err;
 995                }
 996                if (alloc_dis & BIT(NPA_INPQ_NIX1_RX)) {
 997                        err = devlink_fmsg_string_put(fmsg, "\n\tNIX1: alloc disabled RX");
 998                        if (err)
 999                                return err;
1000                }
1001                if (alloc_dis & BIT(NPA_INPQ_NIX1_TX)) {
1002                        err = devlink_fmsg_string_put(fmsg, "\n\tNIX1:alloc disabled TX");
1003                        if (err)
1004                                return err;
1005                }
1006                if (alloc_dis & BIT(NPA_INPQ_SSO)) {
1007                        err = devlink_fmsg_string_put(fmsg, "\n\tAlloc Disabled for SSO");
1008                        if (err)
1009                                return err;
1010                }
1011                if (alloc_dis & BIT(NPA_INPQ_TIM)) {
1012                        err = devlink_fmsg_string_put(fmsg, "\n\tAlloc Disabled for TIM");
1013                        if (err)
1014                                return err;
1015                }
1016                if (alloc_dis & BIT(NPA_INPQ_DPI)) {
1017                        err = devlink_fmsg_string_put(fmsg, "\n\tAlloc Disabled for DPI");
1018                        if (err)
1019                                return err;
1020                }
1021                if (alloc_dis & BIT(NPA_INPQ_AURA_OP)) {
1022                        err = devlink_fmsg_string_put(fmsg, "\n\tAlloc Disabled for AURA");
1023                        if (err)
1024                                return err;
1025                }
1026                err = rvu_report_pair_end(fmsg);
1027                if (err)
1028                        return err;
1029                break;
1030        case NPA_AF_RVU_ERR:
1031                err = rvu_report_pair_start(fmsg, "NPA_AF_ERR");
1032                if (err)
1033                        return err;
1034                err = devlink_fmsg_u64_pair_put(fmsg, "\tNPA Error Interrupt Reg ",
1035                                                npa_event_context->npa_af_rvu_err);
1036                if (err)
1037                        return err;
1038
1039                if (npa_event_context->npa_af_rvu_err & BIT_ULL(14)) {
1040                        err = devlink_fmsg_string_put(fmsg, "\n\tFault on NPA_AQ_INST_S read");
1041                        if (err)
1042                                return err;
1043                }
1044                if (npa_event_context->npa_af_rvu_err & BIT_ULL(13)) {
1045                        err = devlink_fmsg_string_put(fmsg, "\n\tFault on NPA_AQ_RES_S write");
1046                        if (err)
1047                                return err;
1048                }
1049                if (npa_event_context->npa_af_rvu_err & BIT_ULL(12)) {
1050                        err = devlink_fmsg_string_put(fmsg, "\n\tAQ Doorbell Error");
1051                        if (err)
1052                                return err;
1053                }
1054                err = rvu_report_pair_end(fmsg);
1055                if (err)
1056                        return err;
1057                break;
1058        case NPA_AF_RVU_RAS:
1059                err = rvu_report_pair_start(fmsg, "NPA_AF_RVU_RAS");
1060                if (err)
1061                        return err;
1062                err = devlink_fmsg_u64_pair_put(fmsg, "\tNPA RAS Interrupt Reg ",
1063                                                npa_event_context->npa_af_rvu_ras);
1064                if (err)
1065                        return err;
1066                if (npa_event_context->npa_af_rvu_ras & BIT_ULL(34)) {
1067                        err = devlink_fmsg_string_put(fmsg, "\n\tPoison data on NPA_AQ_INST_S");
1068                        if (err)
1069                                return err;
1070                }
1071                if (npa_event_context->npa_af_rvu_ras & BIT_ULL(33)) {
1072                        err = devlink_fmsg_string_put(fmsg, "\n\tPoison data on NPA_AQ_RES_S");
1073                        if (err)
1074                                return err;
1075                }
1076                if (npa_event_context->npa_af_rvu_ras & BIT_ULL(32)) {
1077                        err = devlink_fmsg_string_put(fmsg, "\n\tPoison data on HW context");
1078                        if (err)
1079                                return err;
1080                }
1081                err = rvu_report_pair_end(fmsg);
1082                if (err)
1083                        return err;
1084                break;
1085        case NPA_AF_RVU_INTR:
1086                err = rvu_report_pair_start(fmsg, "NPA_AF_RVU");
1087                if (err)
1088                        return err;
1089                err = devlink_fmsg_u64_pair_put(fmsg, "\tNPA RVU Interrupt Reg ",
1090                                                npa_event_context->npa_af_rvu_int);
1091                if (err)
1092                        return err;
1093                if (npa_event_context->npa_af_rvu_int & BIT_ULL(0)) {
1094                        err = devlink_fmsg_string_put(fmsg, "\n\tUnmap Slot Error");
1095                        if (err)
1096                                return err;
1097                }
1098                return rvu_report_pair_end(fmsg);
1099        default:
1100                return -EINVAL;
1101        }
1102
1103        return 0;
1104}
1105
1106static int rvu_hw_npa_intr_dump(struct devlink_health_reporter *reporter,
1107                                struct devlink_fmsg *fmsg, void *ctx,
1108                                struct netlink_ext_ack *netlink_extack)
1109{
1110        struct rvu *rvu = devlink_health_reporter_priv(reporter);
1111        struct rvu_devlink *rvu_dl = rvu->rvu_dl;
1112        struct rvu_npa_event_ctx *npa_ctx;
1113
1114        npa_ctx = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;
1115
1116        return ctx ? rvu_npa_report_show(fmsg, ctx, NPA_AF_RVU_INTR) :
1117                     rvu_npa_report_show(fmsg, npa_ctx, NPA_AF_RVU_INTR);
1118}
1119
1120static int rvu_hw_npa_intr_recover(struct devlink_health_reporter *reporter,
1121                                   void *ctx, struct netlink_ext_ack *netlink_extack)
1122{
1123        struct rvu *rvu = devlink_health_reporter_priv(reporter);
1124        struct rvu_npa_event_ctx *npa_event_ctx = ctx;
1125        int blkaddr;
1126
1127        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
1128        if (blkaddr < 0)
1129                return blkaddr;
1130
1131        if (npa_event_ctx->npa_af_rvu_int)
1132                rvu_write64(rvu, blkaddr, NPA_AF_RVU_INT_ENA_W1S, ~0ULL);
1133
1134        return 0;
1135}
1136
1137static int rvu_hw_npa_gen_dump(struct devlink_health_reporter *reporter,
1138                               struct devlink_fmsg *fmsg, void *ctx,
1139                               struct netlink_ext_ack *netlink_extack)
1140{
1141        struct rvu *rvu = devlink_health_reporter_priv(reporter);
1142        struct rvu_devlink *rvu_dl = rvu->rvu_dl;
1143        struct rvu_npa_event_ctx *npa_ctx;
1144
1145        npa_ctx = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;
1146
1147        return ctx ? rvu_npa_report_show(fmsg, ctx, NPA_AF_RVU_GEN) :
1148                     rvu_npa_report_show(fmsg, npa_ctx, NPA_AF_RVU_GEN);
1149}
1150
1151static int rvu_hw_npa_gen_recover(struct devlink_health_reporter *reporter,
1152                                  void *ctx, struct netlink_ext_ack *netlink_extack)
1153{
1154        struct rvu *rvu = devlink_health_reporter_priv(reporter);
1155        struct rvu_npa_event_ctx *npa_event_ctx = ctx;
1156        int blkaddr;
1157
1158        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
1159        if (blkaddr < 0)
1160                return blkaddr;
1161
1162        if (npa_event_ctx->npa_af_rvu_gen)
1163                rvu_write64(rvu, blkaddr, NPA_AF_GEN_INT_ENA_W1S, ~0ULL);
1164
1165        return 0;
1166}
1167
1168static int rvu_hw_npa_err_dump(struct devlink_health_reporter *reporter,
1169                               struct devlink_fmsg *fmsg, void *ctx,
1170                               struct netlink_ext_ack *netlink_extack)
1171{
1172        struct rvu *rvu = devlink_health_reporter_priv(reporter);
1173        struct rvu_devlink *rvu_dl = rvu->rvu_dl;
1174        struct rvu_npa_event_ctx *npa_ctx;
1175
1176        npa_ctx = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;
1177
1178        return ctx ? rvu_npa_report_show(fmsg, ctx, NPA_AF_RVU_ERR) :
1179                     rvu_npa_report_show(fmsg, npa_ctx, NPA_AF_RVU_ERR);
1180}
1181
1182static int rvu_hw_npa_err_recover(struct devlink_health_reporter *reporter,
1183                                  void *ctx, struct netlink_ext_ack *netlink_extack)
1184{
1185        struct rvu *rvu = devlink_health_reporter_priv(reporter);
1186        struct rvu_npa_event_ctx *npa_event_ctx = ctx;
1187        int blkaddr;
1188
1189        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
1190        if (blkaddr < 0)
1191                return blkaddr;
1192
1193        if (npa_event_ctx->npa_af_rvu_err)
1194                rvu_write64(rvu, blkaddr, NPA_AF_ERR_INT_ENA_W1S, ~0ULL);
1195
1196        return 0;
1197}
1198
1199static int rvu_hw_npa_ras_dump(struct devlink_health_reporter *reporter,
1200                               struct devlink_fmsg *fmsg, void *ctx,
1201                               struct netlink_ext_ack *netlink_extack)
1202{
1203        struct rvu *rvu = devlink_health_reporter_priv(reporter);
1204        struct rvu_devlink *rvu_dl = rvu->rvu_dl;
1205        struct rvu_npa_event_ctx *npa_ctx;
1206
1207        npa_ctx = rvu_dl->rvu_npa_health_reporter->npa_event_ctx;
1208
1209        return ctx ? rvu_npa_report_show(fmsg, ctx, NPA_AF_RVU_RAS) :
1210                     rvu_npa_report_show(fmsg, npa_ctx, NPA_AF_RVU_RAS);
1211}
1212
1213static int rvu_hw_npa_ras_recover(struct devlink_health_reporter *reporter,
1214                                  void *ctx, struct netlink_ext_ack *netlink_extack)
1215{
1216        struct rvu *rvu = devlink_health_reporter_priv(reporter);
1217        struct rvu_npa_event_ctx *npa_event_ctx = ctx;
1218        int blkaddr;
1219
1220        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, 0);
1221        if (blkaddr < 0)
1222                return blkaddr;
1223
1224        if (npa_event_ctx->npa_af_rvu_ras)
1225                rvu_write64(rvu, blkaddr, NPA_AF_RAS_ENA_W1S, ~0ULL);
1226
1227        return 0;
1228}
1229
1230RVU_REPORTERS(hw_npa_intr);
1231RVU_REPORTERS(hw_npa_gen);
1232RVU_REPORTERS(hw_npa_err);
1233RVU_REPORTERS(hw_npa_ras);
1234
1235static void rvu_npa_health_reporters_destroy(struct rvu_devlink *rvu_dl);
1236
1237static int rvu_npa_register_reporters(struct rvu_devlink *rvu_dl)
1238{
1239        struct rvu_npa_health_reporters *rvu_reporters;
1240        struct rvu_npa_event_ctx *npa_event_context;
1241        struct rvu *rvu = rvu_dl->rvu;
1242
1243        rvu_reporters = kzalloc(sizeof(*rvu_reporters), GFP_KERNEL);
1244        if (!rvu_reporters)
1245                return -ENOMEM;
1246
1247        rvu_dl->rvu_npa_health_reporter = rvu_reporters;
1248        npa_event_context = kzalloc(sizeof(*npa_event_context), GFP_KERNEL);
1249        if (!npa_event_context)
1250                return -ENOMEM;
1251
1252        rvu_reporters->npa_event_ctx = npa_event_context;
1253        rvu_reporters->rvu_hw_npa_intr_reporter =
1254                devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_npa_intr_reporter_ops, 0, rvu);
1255        if (IS_ERR(rvu_reporters->rvu_hw_npa_intr_reporter)) {
1256                dev_warn(rvu->dev, "Failed to create hw_npa_intr reporter, err=%ld\n",
1257                         PTR_ERR(rvu_reporters->rvu_hw_npa_intr_reporter));
1258                return PTR_ERR(rvu_reporters->rvu_hw_npa_intr_reporter);
1259        }
1260
1261        rvu_reporters->rvu_hw_npa_gen_reporter =
1262                devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_npa_gen_reporter_ops, 0, rvu);
1263        if (IS_ERR(rvu_reporters->rvu_hw_npa_gen_reporter)) {
1264                dev_warn(rvu->dev, "Failed to create hw_npa_gen reporter, err=%ld\n",
1265                         PTR_ERR(rvu_reporters->rvu_hw_npa_gen_reporter));
1266                return PTR_ERR(rvu_reporters->rvu_hw_npa_gen_reporter);
1267        }
1268
1269        rvu_reporters->rvu_hw_npa_err_reporter =
1270                devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_npa_err_reporter_ops, 0, rvu);
1271        if (IS_ERR(rvu_reporters->rvu_hw_npa_err_reporter)) {
1272                dev_warn(rvu->dev, "Failed to create hw_npa_err reporter, err=%ld\n",
1273                         PTR_ERR(rvu_reporters->rvu_hw_npa_err_reporter));
1274                return PTR_ERR(rvu_reporters->rvu_hw_npa_err_reporter);
1275        }
1276
1277        rvu_reporters->rvu_hw_npa_ras_reporter =
1278                devlink_health_reporter_create(rvu_dl->dl, &rvu_hw_npa_ras_reporter_ops, 0, rvu);
1279        if (IS_ERR(rvu_reporters->rvu_hw_npa_ras_reporter)) {
1280                dev_warn(rvu->dev, "Failed to create hw_npa_ras reporter, err=%ld\n",
1281                         PTR_ERR(rvu_reporters->rvu_hw_npa_ras_reporter));
1282                return PTR_ERR(rvu_reporters->rvu_hw_npa_ras_reporter);
1283        }
1284
1285        rvu_dl->devlink_wq = create_workqueue("rvu_devlink_wq");
1286        if (!rvu_dl->devlink_wq)
1287                goto err;
1288
1289        INIT_WORK(&rvu_reporters->intr_work, rvu_npa_intr_work);
1290        INIT_WORK(&rvu_reporters->err_work, rvu_npa_err_work);
1291        INIT_WORK(&rvu_reporters->gen_work, rvu_npa_gen_work);
1292        INIT_WORK(&rvu_reporters->ras_work, rvu_npa_ras_work);
1293
1294        return 0;
1295err:
1296        rvu_npa_health_reporters_destroy(rvu_dl);
1297        return -ENOMEM;
1298}
1299
1300static int rvu_npa_health_reporters_create(struct rvu_devlink *rvu_dl)
1301{
1302        struct rvu *rvu = rvu_dl->rvu;
1303        int err;
1304
1305        err = rvu_npa_register_reporters(rvu_dl);
1306        if (err) {
1307                dev_warn(rvu->dev, "Failed to create npa reporter, err =%d\n",
1308                         err);
1309                return err;
1310        }
1311        rvu_npa_register_interrupts(rvu);
1312
1313        return 0;
1314}
1315
1316static void rvu_npa_health_reporters_destroy(struct rvu_devlink *rvu_dl)
1317{
1318        struct rvu_npa_health_reporters *npa_reporters;
1319        struct rvu *rvu = rvu_dl->rvu;
1320
1321        npa_reporters = rvu_dl->rvu_npa_health_reporter;
1322
1323        if (!npa_reporters->rvu_hw_npa_ras_reporter)
1324                return;
1325        if (!IS_ERR_OR_NULL(npa_reporters->rvu_hw_npa_intr_reporter))
1326                devlink_health_reporter_destroy(npa_reporters->rvu_hw_npa_intr_reporter);
1327
1328        if (!IS_ERR_OR_NULL(npa_reporters->rvu_hw_npa_gen_reporter))
1329                devlink_health_reporter_destroy(npa_reporters->rvu_hw_npa_gen_reporter);
1330
1331        if (!IS_ERR_OR_NULL(npa_reporters->rvu_hw_npa_err_reporter))
1332                devlink_health_reporter_destroy(npa_reporters->rvu_hw_npa_err_reporter);
1333
1334        if (!IS_ERR_OR_NULL(npa_reporters->rvu_hw_npa_ras_reporter))
1335                devlink_health_reporter_destroy(npa_reporters->rvu_hw_npa_ras_reporter);
1336
1337        rvu_npa_unregister_interrupts(rvu);
1338        kfree(rvu_dl->rvu_npa_health_reporter->npa_event_ctx);
1339        kfree(rvu_dl->rvu_npa_health_reporter);
1340}
1341
1342static int rvu_health_reporters_create(struct rvu *rvu)
1343{
1344        struct rvu_devlink *rvu_dl;
1345        int err;
1346
1347        rvu_dl = rvu->rvu_dl;
1348        err = rvu_npa_health_reporters_create(rvu_dl);
1349        if (err)
1350                return err;
1351
1352        return rvu_nix_health_reporters_create(rvu_dl);
1353}
1354
1355static void rvu_health_reporters_destroy(struct rvu *rvu)
1356{
1357        struct rvu_devlink *rvu_dl;
1358
1359        if (!rvu->rvu_dl)
1360                return;
1361
1362        rvu_dl = rvu->rvu_dl;
1363        rvu_npa_health_reporters_destroy(rvu_dl);
1364        rvu_nix_health_reporters_destroy(rvu_dl);
1365}
1366
1367static int rvu_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
1368                                struct netlink_ext_ack *extack)
1369{
1370        return devlink_info_driver_name_put(req, DRV_NAME);
1371}
1372
1373static const struct devlink_ops rvu_devlink_ops = {
1374        .info_get = rvu_devlink_info_get,
1375};
1376
1377int rvu_register_dl(struct rvu *rvu)
1378{
1379        struct rvu_devlink *rvu_dl;
1380        struct devlink *dl;
1381        int err;
1382
1383        rvu_dl = kzalloc(sizeof(*rvu_dl), GFP_KERNEL);
1384        if (!rvu_dl)
1385                return -ENOMEM;
1386
1387        dl = devlink_alloc(&rvu_devlink_ops, sizeof(struct rvu_devlink));
1388        if (!dl) {
1389                dev_warn(rvu->dev, "devlink_alloc failed\n");
1390                kfree(rvu_dl);
1391                return -ENOMEM;
1392        }
1393
1394        err = devlink_register(dl, rvu->dev);
1395        if (err) {
1396                dev_err(rvu->dev, "devlink register failed with error %d\n", err);
1397                devlink_free(dl);
1398                kfree(rvu_dl);
1399                return err;
1400        }
1401
1402        rvu_dl->dl = dl;
1403        rvu_dl->rvu = rvu;
1404        rvu->rvu_dl = rvu_dl;
1405
1406        return rvu_health_reporters_create(rvu);
1407}
1408
1409void rvu_unregister_dl(struct rvu *rvu)
1410{
1411        struct rvu_devlink *rvu_dl = rvu->rvu_dl;
1412        struct devlink *dl = rvu_dl->dl;
1413
1414        if (!dl)
1415                return;
1416
1417        rvu_health_reporters_destroy(rvu);
1418        devlink_unregister(dl);
1419        devlink_free(dl);
1420        kfree(rvu_dl);
1421}
1422