@@ -14,6 +14,7 @@
#include "bnxt.h"
#include "bnxt_hwrm.h"
#include "bnxt_coredump.h"
+#include "bnxt_ulp.h"
static const u16 bnxt_bstore_to_seg_id[] = {
[BNXT_CTX_QP] = BNXT_CTX_MEM_SEG_QP,
@@ -414,13 +415,20 @@ static int __bnxt_get_coredump(struct bnxt *bp, u16 dump_type, void *buf,
}
if (dump_type == BNXT_DUMP_DRIVER) {
- u32 drv_len, segs = 0;
+ u32 drv_len, drv_segs, segs = 0;
+ void *drv_buf = NULL;
drv_len = bnxt_get_ctx_coredump(bp, buf, offset, &segs);
+ drv_segs = segs;
+ segs = 0;
+ if (buf)
+ drv_buf = buf + offset + drv_len;
+ drv_len += bnxt_get_ulp_dump(bp, dump_type, drv_buf, &segs);
+ drv_segs += segs;
*dump_len += drv_len;
offset += drv_len;
if (buf)
- coredump.total_segs += segs;
+ coredump.total_segs += drv_segs;
goto err;
}
@@ -25,6 +25,7 @@
#include "bnxt.h"
#include "bnxt_hwrm.h"
#include "bnxt_ulp.h"
+#include "bnxt_coredump.h"
static DEFINE_IDA(bnxt_aux_dev_ids);
@@ -393,6 +394,62 @@ void bnxt_register_async_events(struct bnxt_en_dev *edev,
}
EXPORT_SYMBOL(bnxt_register_async_events);
+static void bnxt_ulp_fill_dump_hdr(struct bnxt *bp, void *buf, u32 seg_id,
+ u32 seg_len)
+{
+ struct bnxt_coredump_segment_hdr seg_hdr;
+
+ bnxt_fill_coredump_seg_hdr(bp, &seg_hdr, NULL, seg_len, 0, 0, 0,
+ BNXT_DRV_COMP_ID, seg_id);
+ memcpy(buf, &seg_hdr, sizeof(seg_hdr));
+}
+
+u32 bnxt_get_ulp_dump(struct bnxt *bp, u32 dump_flag, void *buf, u32 *segs)
+{
+ struct bnxt_en_dev *edev = bp->edev;
+ struct bnxt_ulp_dump *dump;
+ struct bnxt_ulp_ops *ops;
+ struct bnxt_ulp *ulp;
+ u32 i, dump_len = 0;
+
+ *segs = 0;
+ if (!edev || !bnxt_ulp_registered(edev))
+ return 0;
+
+ ulp = edev->ulp_tbl;
+ ops = rtnl_dereference(ulp->ulp_ops);
+ if (!ops || !ops->ulp_get_dump_info || !ops->ulp_get_dump_data)
+ return 0;
+
+ dump = &ulp->ulp_dump;
+ if (!buf) {
+ memset(dump, 0, sizeof(*dump));
+ ops->ulp_get_dump_info(ulp->handle, dump_flag, dump);
+ if (dump->segs > BNXT_ULP_MAX_DUMP_SEGS)
+ return 0;
+ for (i = 0; i < dump->segs; i++) {
+ dump_len += dump->seg_tbl[i].seg_len;
+ dump_len += BNXT_SEG_HDR_LEN;
+ }
+ } else {
+ for (i = 0; i < dump->segs; i++) {
+ struct bnxt_ulp_dump_tbl *tbl = &dump->seg_tbl[i];
+ u32 seg_len = tbl->seg_len;
+ u32 seg_id = tbl->seg_id;
+
+ bnxt_ulp_fill_dump_hdr(bp, buf, seg_id, seg_len);
+ buf += BNXT_SEG_HDR_LEN;
+ dump_len += BNXT_SEG_HDR_LEN;
+ ops->ulp_get_dump_data(ulp->handle, seg_id, buf,
+ seg_len);
+ buf += seg_len;
+ dump_len += seg_len;
+ }
+ }
+ *segs = dump->segs;
+ return dump_len;
+}
+
void bnxt_rdma_aux_device_uninit(struct bnxt *bp)
{
struct bnxt_aux_priv *aux_priv;
@@ -29,11 +29,31 @@ struct bnxt_msix_entry {
u32 db_offset;
};
+#define BNXT_ULP_MAX_DUMP_SEGS 8
+
+/**
+ * struct bnxt_ulp_dump - bnxt ULP aux device coredump info
+ * @segs: number of coredump segments with info in the seg_tbl
+ * @seg_tbl: coredump segment table
+ * @seg_tbl.seg_id: coredump segment ID
+ * @seg_tbl.seg_len: coredump segment len
+ */
+struct bnxt_ulp_dump {
+ u32 segs;
+ struct bnxt_ulp_dump_tbl {
+ u32 seg_id;
+ u32 seg_len;
+ } seg_tbl[BNXT_ULP_MAX_DUMP_SEGS];
+};
+
struct bnxt_ulp_ops {
/* async_notifier() cannot sleep (in BH context) */
void (*ulp_async_notifier)(void *, struct hwrm_async_event_cmpl *);
void (*ulp_irq_stop)(void *, bool);
void (*ulp_irq_restart)(void *, struct bnxt_msix_entry *);
+ void (*ulp_get_dump_info)(void *handle, u32 dump_flags,
+ struct bnxt_ulp_dump *dump);
+ void (*ulp_get_dump_data)(void *handle, u32 seg_id, void *buf, u32 len);
};
struct bnxt_fw_msg {
@@ -51,6 +71,7 @@ struct bnxt_ulp {
u16 max_async_event_id;
u16 msix_requested;
atomic_t ref_count;
+ struct bnxt_ulp_dump ulp_dump;
};
struct bnxt_en_dev {
@@ -119,6 +140,7 @@ void bnxt_ulp_start(struct bnxt *bp, int err);
void bnxt_ulp_sriov_cfg(struct bnxt *bp, int num_vfs);
void bnxt_ulp_irq_stop(struct bnxt *bp);
void bnxt_ulp_irq_restart(struct bnxt *bp, int err);
+u32 bnxt_get_ulp_dump(struct bnxt *bp, u32 dump_flag, void *buf, u32 *segs);
void bnxt_ulp_async_events(struct bnxt *bp, struct hwrm_async_event_cmpl *cmpl);
void bnxt_rdma_aux_device_uninit(struct bnxt *bp);
void bnxt_rdma_aux_device_del(struct bnxt *bp);