diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index 2de101d..060143e 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -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);
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.h b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
index fbb16a4..8d82066 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.h
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
@@ -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)
 {
diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c
index 87fdf69..67d2bf0 100644
--- a/drivers/infiniband/hw/bnxt_re/main.c
+++ b/drivers/infiniband/hw/bnxt_re/main.c
@@ -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)) {
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
index 0d9487c..d1acb01 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
@@ -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;
