Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'add-devlink-and-devlink-health-reporters-to'

George Cherian says:

====================
Add devlink and devlink health reporters to octeontx2

Add basic devlink and devlink health reporters.
Devlink health reporters are added for NPA block.

Address Jakub's comment to add devlink support for error reporting.
https://www.spinics.net/lists/netdev/msg670712.html

For now, I have dropped the NIX block health reporters.
This series attempts to add health reporters only for the NPA block.
As per Jakub's suggestion separate reporters per event is used and also
got rid of the counters.
====================

Link: https://lore.kernel.org/r/20201211062526.2302643-1-george.cherian@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

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