@@ -41,6 +41,7 @@
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
+#include <linux/vmalloc.h>
#include <net/addrconf.h>
#include <rdma/ib_verbs.h>
@@ -954,6 +955,71 @@ static int bnxt_re_destroy_gsi_sqp(struct bnxt_re_qp *qp)
return rc;
}
+static struct qdump_array *bnxt_re_get_next_qpdump(struct bnxt_re_dev *rdev)
+{
+ struct qdump_array *qdump;
+ u32 index;
+
+ index = rdev->qdump_head.index;
+ qdump = &rdev->qdump_head.qdump[index];
+ memset(qdump, 0, sizeof(*qdump));
+
+ index++;
+ index %= rdev->qdump_head.max_elements;
+ rdev->qdump_head.index = index;
+
+ return qdump;
+}
+
+/*
+ * bnxt_re_capture_qpdump - Capture snapshot of various queues of a QP.
+ * @qp - Pointer to QP for which data has to be collected
+ *
+ * This function will capture info about SQ/RQ/SCQ/RCQ of a QP which
+ * can be used to debug any issue
+ *
+ */
+void bnxt_re_capture_qpdump(struct bnxt_re_qp *qp)
+{
+ struct bnxt_qplib_qp *qpl = &qp->qplib_qp;
+ struct bnxt_re_dev *rdev = qp->rdev;
+ struct qdump_qpinfo *qpinfo;
+ struct qdump_array *qdump;
+ bool capture_snapdump;
+
+ if (rdev->snapdump_dbg_lvl == BNXT_RE_SNAPDUMP_NONE)
+ return;
+
+ capture_snapdump = test_bit(QP_FLAGS_CAPTURE_SNAPDUMP, &qpl->flags);
+ if (rdev->snapdump_dbg_lvl == BNXT_RE_SNAPDUMP_ERR &&
+ !capture_snapdump)
+ return;
+
+ if (qp->is_snapdump_captured || !rdev->qdump_head.qdump)
+ return;
+
+ mutex_lock(&rdev->qdump_head.lock);
+ qdump = bnxt_re_get_next_qpdump(rdev);
+
+ qpinfo = &qdump->qpinfo;
+ qpinfo->id = qpl->id;
+ qpinfo->dest_qpid = qpl->dest_qpn;
+ qpinfo->is_user = qpl->is_user;
+ qpinfo->mtu = qpl->mtu;
+ qpinfo->state = qpl->state;
+ qpinfo->type = qpl->type;
+ qpinfo->wqe_mode = qpl->wqe_mode;
+ qpinfo->qp_handle = qpl->qp_handle;
+ qpinfo->scq_handle = qp->scq->qplib_cq.cq_handle;
+ qpinfo->rcq_handle = qp->rcq->qplib_cq.cq_handle;
+ qpinfo->scq_id = qp->scq->qplib_cq.id;
+ qpinfo->rcq_id = qp->rcq->qplib_cq.id;
+
+ qdump->valid = true;
+ qp->is_snapdump_captured = true;
+ mutex_unlock(&rdev->qdump_head.lock);
+}
+
/* Queue Pairs */
int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
{
@@ -965,6 +1031,7 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
unsigned int flags;
int rc;
+ bnxt_re_capture_qpdump(qp);
bnxt_re_debug_rem_qpinfo(rdev, qp);
bnxt_qplib_flush_cqn_wq(&qp->qplib_qp);
@@ -96,6 +96,7 @@ struct bnxt_re_qp {
struct bnxt_re_cq *scq;
struct bnxt_re_cq *rcq;
struct dentry *dentry;
+ bool is_snapdump_captured;
};
struct bnxt_re_cq {
@@ -113,6 +114,7 @@ struct bnxt_re_cq {
int resize_cqe;
void *uctx_cq_page;
struct hlist_node hash_entry;
+ bool is_snapdump_captured;
};
struct bnxt_re_mr {
@@ -267,6 +269,46 @@ int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata);
void bnxt_re_dealloc_ucontext(struct ib_ucontext *context);
int bnxt_re_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
void bnxt_re_mmap_free(struct rdma_user_mmap_entry *rdma_entry);
+void bnxt_re_capture_qpdump(struct bnxt_re_qp *qp);
+
+static inline const char *__to_qp_type_str(u8 type)
+{
+ switch (type) {
+ case CMDQ_CREATE_QP1_TYPE_GSI:
+ case CMDQ_CREATE_QP_TYPE_GSI:
+ return "GSI";
+ case CMDQ_CREATE_QP_TYPE_RC:
+ return "RC";
+ case CMDQ_CREATE_QP_TYPE_UD:
+ return "UD";
+ case CMDQ_CREATE_QP_TYPE_RAW_ETHERTYPE:
+ return "RAW_ETH";
+ default:
+ return "NotSupp";
+ }
+}
+
+static inline const char *__to_qp_state_str(u8 state)
+{
+ switch (state) {
+ case CMDQ_MODIFY_QP_NEW_STATE_RESET:
+ return "RESET";
+ case CMDQ_MODIFY_QP_NEW_STATE_INIT:
+ return "INIT";
+ case CMDQ_MODIFY_QP_NEW_STATE_RTR:
+ return "RTR";
+ case CMDQ_MODIFY_QP_NEW_STATE_RTS:
+ return "RTS";
+ case CMDQ_MODIFY_QP_NEW_STATE_SQD:
+ return "SQD";
+ case CMDQ_MODIFY_QP_NEW_STATE_SQE:
+ return "SQE";
+ case CMDQ_MODIFY_QP_NEW_STATE_ERR:
+ return "ERR";
+ default:
+ return "NotSupp";
+ }
+}
static inline u32 __to_ib_port_num(u16 port_id)
{
@@ -1420,9 +1420,15 @@ static int bnxt_re_handle_qp_async_event(struct creq_qp_event *qp_event,
struct ib_event event = {};
unsigned int flags;
- if (qp->qplib_qp.srq)
+ if (qp->qplib_qp.srq) {
srq = container_of(qp->qplib_qp.srq, struct bnxt_re_srq,
qplib_srq);
+ set_bit(SRQ_FLAGS_CAPTURE_SNAPDUMP, &srq->qplib_srq.flags);
+ }
+
+ set_bit(QP_FLAGS_CAPTURE_SNAPDUMP, &qp->qplib_qp.flags);
+ set_bit(CQ_FLAGS_CAPTURE_SNAPDUMP, &qp->scq->qplib_cq.flags);
+ set_bit(CQ_FLAGS_CAPTURE_SNAPDUMP, &qp->rcq->qplib_cq.flags);
if (qp->qplib_qp.state == CMDQ_MODIFY_QP_NEW_STATE_ERR &&
rdma_is_kernel_res(&qp->ib_qp.res)) {
@@ -106,6 +106,8 @@ struct bnxt_qplib_srq {
u16 eventq_hw_ring_id;
spinlock_t lock; /* protect SRQE link list */
u8 toggle;
+ unsigned long flags;
+#define SRQ_FLAGS_CAPTURE_SNAPDUMP 1
};
struct bnxt_qplib_sge {
@@ -279,6 +281,8 @@ struct bnxt_qplib_qp {
u8 wqe_mode;
u8 state;
u8 cur_qp_state;
+ u16 ctx_size_sb;
+ u8 is_user;
u64 modify_flags;
u32 max_inline_data;
u32 mtu;
@@ -344,6 +348,8 @@ struct bnxt_qplib_qp {
u32 msn_tbl_sz;
bool is_host_msn_tbl;
u8 tos_dscp;
+ unsigned long flags;
+#define QP_FLAGS_CAPTURE_SNAPDUMP 1
};
#define BNXT_QPLIB_MAX_CQE_ENTRY_SIZE sizeof(struct cq_base)
@@ -448,6 +454,7 @@ struct bnxt_qplib_cq {
#define CQ_RESIZE_WAIT_TIME_MS 500
unsigned long flags;
#define CQ_FLAGS_RESIZE_IN_PROG 1
+#define CQ_FLAGS_CAPTURE_SNAPDUMP 2
wait_queue_head_t waitq;
struct list_head sqf_head, rqf_head;
atomic_t arm_state;