bnxt_en: add support for retrieving crash dump using ethtool
authorVikas Gupta <vikas.gupta@broadcom.com>
Wed, 28 Aug 2024 18:32:28 +0000 (11:32 -0700)
committerJakub Kicinski <kuba@kernel.org>
Thu, 29 Aug 2024 22:33:24 +0000 (15:33 -0700)
Add support for retrieving crash dump using ethtool -w on the
supported interface.

Reviewed-by: Somnath Kotur <somnath.kotur@broadcom.com>
Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Vikas Gupta <vikas.gupta@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Link: https://patch.msgid.link/20240828183235.128948-3-michael.chan@broadcom.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c

index ebbad9c..4e2b938 100644 (file)
@@ -372,14 +372,75 @@ err:
        return rc;
 }
 
+static u32 bnxt_copy_crash_data(struct bnxt_ring_mem_info *rmem, void *buf,
+                               u32 dump_len)
+{
+       u32 data_copied = 0;
+       u32 data_len;
+       int i;
+
+       for (i = 0; i < rmem->nr_pages; i++) {
+               data_len = rmem->page_size;
+               if (data_copied + data_len > dump_len)
+                       data_len = dump_len - data_copied;
+               memcpy(buf + data_copied, rmem->pg_arr[i], data_len);
+               data_copied += data_len;
+               if (data_copied >= dump_len)
+                       break;
+       }
+       return data_copied;
+}
+
+static int bnxt_copy_crash_dump(struct bnxt *bp, void *buf, u32 dump_len)
+{
+       struct bnxt_ring_mem_info *rmem;
+       u32 offset = 0;
+
+       if (!bp->fw_crash_mem)
+               return -ENOENT;
+
+       rmem = &bp->fw_crash_mem->ring_mem;
+
+       if (rmem->depth > 1) {
+               int i;
+
+               for (i = 0; i < rmem->nr_pages; i++) {
+                       struct bnxt_ctx_pg_info *pg_tbl;
+
+                       pg_tbl = bp->fw_crash_mem->ctx_pg_tbl[i];
+                       offset += bnxt_copy_crash_data(&pg_tbl->ring_mem,
+                                                      buf + offset,
+                                                      dump_len - offset);
+                       if (offset >= dump_len)
+                               break;
+               }
+       } else {
+               bnxt_copy_crash_data(rmem, buf, dump_len);
+       }
+
+       return 0;
+}
+
+static bool bnxt_crash_dump_avail(struct bnxt *bp)
+{
+       u32 sig = 0;
+
+       /* First 4 bytes(signature) of crash dump is always non-zero */
+       bnxt_copy_crash_dump(bp, &sig, sizeof(sig));
+       return !!sig;
+}
+
 int bnxt_get_coredump(struct bnxt *bp, u16 dump_type, void *buf, u32 *dump_len)
 {
        if (dump_type == BNXT_DUMP_CRASH) {
+               if (bp->fw_dbg_cap & DBG_QCAPS_RESP_FLAGS_CRASHDUMP_HOST_DDR)
+                       return bnxt_copy_crash_dump(bp, buf, *dump_len);
 #ifdef CONFIG_TEE_BNXT_FW
-               return tee_bnxt_copy_coredump(buf, 0, *dump_len);
-#else
-               return -EOPNOTSUPP;
+               else if (bp->fw_dbg_cap & DBG_QCAPS_RESP_FLAGS_CRASHDUMP_SOC_DDR)
+                       return tee_bnxt_copy_coredump(buf, 0, *dump_len);
 #endif
+               else
+                       return -EOPNOTSUPP;
        } else {
                return __bnxt_get_coredump(bp, buf, dump_len);
        }
@@ -442,10 +503,17 @@ u32 bnxt_get_coredump_length(struct bnxt *bp, u16 dump_type)
 {
        u32 len = 0;
 
+       if (dump_type == BNXT_DUMP_CRASH &&
+           bp->fw_dbg_cap & DBG_QCAPS_RESP_FLAGS_CRASHDUMP_HOST_DDR &&
+           bp->fw_crash_mem) {
+               if (!bnxt_crash_dump_avail(bp))
+                       return 0;
+
+               return bp->fw_crash_len;
+       }
+
        if (bnxt_hwrm_get_dump_len(bp, dump_type, &len)) {
-               if (dump_type == BNXT_DUMP_CRASH)
-                       len = BNXT_CRASH_DUMP_LEN;
-               else
+               if (dump_type != BNXT_DUMP_CRASH)
                        __bnxt_get_coredump(bp, NULL, &len);
        }
        return len;
index 194f473..7392a71 100644 (file)
@@ -4989,9 +4989,16 @@ static int bnxt_set_dump(struct net_device *dev, struct ethtool_dump *dump)
                return -EINVAL;
        }
 
-       if (!IS_ENABLED(CONFIG_TEE_BNXT_FW) && dump->flag == BNXT_DUMP_CRASH) {
-               netdev_info(dev, "Cannot collect crash dump as TEE_BNXT_FW config option is not enabled.\n");
-               return -EOPNOTSUPP;
+       if (dump->flag == BNXT_DUMP_CRASH) {
+               if (bp->fw_dbg_cap & DBG_QCAPS_RESP_FLAGS_CRASHDUMP_SOC_DDR &&
+                   (!IS_ENABLED(CONFIG_TEE_BNXT_FW))) {
+                       netdev_info(dev,
+                                   "Cannot collect crash dump as TEE_BNXT_FW config option is not enabled.\n");
+                       return -EOPNOTSUPP;
+               } else if (!(bp->fw_dbg_cap & DBG_QCAPS_RESP_FLAGS_CRASHDUMP_HOST_DDR)) {
+                       netdev_info(dev, "Crash dump collection from host memory is not supported on this interface.\n");
+                       return -EOPNOTSUPP;
+               }
        }
 
        bp->dump_flag = dump->flag;