[PATCH rdma-next 1/2] qedr: Add doorbell overflow recovery support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Ariel Elior <ariel.elior@xxxxxxxxxxx>

Use the doorbell recovery mechanism to register rdma related doorbells
that will be restored in case there is a doorbell overflow attention.

Signed-off-by: Ariel Elior <ariel.elior@xxxxxxxxxxx>
Signed-off-by: Michal Kalderon <michal.kalderon@xxxxxxxxxxx>
---
 drivers/infiniband/hw/qedr/qedr.h  |   6 +
 drivers/infiniband/hw/qedr/verbs.c | 289 ++++++++++++++++++++++++++++++-------
 include/uapi/rdma/qedr-abi.h       |  15 ++
 3 files changed, 261 insertions(+), 49 deletions(-)

diff --git a/drivers/infiniband/hw/qedr/qedr.h b/drivers/infiniband/hw/qedr/qedr.h
index 53bbe6b4e6e6..5cff124aeed4 100644
--- a/drivers/infiniband/hw/qedr/qedr.h
+++ b/drivers/infiniband/hw/qedr/qedr.h
@@ -268,6 +268,12 @@ struct qedr_userq {
 	struct qedr_pbl *pbl_tbl;
 	u64 buf_addr;
 	size_t buf_len;
+
+	/* doorbell recovery */
+	void __iomem *db_addr;
+	struct ib_umem *db_rec_umem;
+	u64 db_rec_addr;
+	struct qedr_user_db_rec *db_rec_virt;
 };
 
 struct qedr_cq {
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
index e1ccf32b1c3d..1fa9320d5f72 100644
--- a/drivers/infiniband/hw/qedr/verbs.c
+++ b/drivers/infiniband/hw/qedr/verbs.c
@@ -699,15 +699,43 @@ static void qedr_populate_pbls(struct qedr_dev *dev, struct ib_umem *umem,
 	}
 }
 
+static int qedr_db_recovery_add(struct qedr_dev *dev,
+				void __iomem *db_addr,
+				void *db_data,
+				enum qed_db_rec_width db_width,
+				enum qed_db_rec_space db_space)
+{
+	if (!db_data) {
+		DP_DEBUG(dev, QEDR_MSG_INIT, "avoiding db rec since old lib\n");
+		return 0;
+	}
+
+	return dev->ops->common->db_recovery_add(dev->cdev, db_addr, db_data,
+						 db_width, db_space);
+}
+
+static int qedr_db_recovery_del(struct qedr_dev *dev,
+				void __iomem *db_addr,
+				void *db_data)
+{
+	if (!db_data) {
+		DP_DEBUG(dev, QEDR_MSG_INIT, "avoiding db rec since old lib\n");
+		return 0;
+	}
+
+	return dev->ops->common->db_recovery_del(dev->cdev, db_addr, db_data);
+}
+
 static int qedr_copy_cq_uresp(struct qedr_dev *dev,
-			      struct qedr_cq *cq, struct ib_udata *udata)
+			      struct qedr_cq *cq, struct ib_udata *udata,
+			      u32 db_offset)
 {
 	struct qedr_create_cq_uresp uresp;
 	int rc;
 
 	memset(&uresp, 0, sizeof(uresp));
 
-	uresp.db_offset = DB_ADDR_SHIFT(DQ_PWM_OFFSET_UCM_RDMA_CQ_CONS_32BIT);
+	uresp.db_offset = db_offset;
 	uresp.icid = cq->icid;
 
 	rc = qedr_ib_copy_to_udata(udata, &uresp, sizeof(uresp));
@@ -736,12 +764,37 @@ static inline int qedr_align_cq_entries(int entries)
 	return aligned_size / QEDR_CQE_SIZE;
 }
 
-static inline int qedr_init_user_queue(struct ib_ucontext *ib_ctx,
-				       struct qedr_dev *dev,
-				       struct qedr_userq *q,
-				       u64 buf_addr, size_t buf_len,
-				       int access, int dmasync,
-				       int alloc_and_init)
+static int qedr_init_user_db_rec(struct ib_ucontext *ib_ctx,
+				 struct qedr_dev *dev, struct qedr_userq *q,
+				 u64 db_rec_addr, int access, int dmasync)
+{
+	/* Aborting for non doorbell userqueue (SRQ) */
+	if (db_rec_addr == 0)
+		return 0;
+
+	q->db_rec_addr = db_rec_addr;
+	q->db_rec_umem = ib_umem_get(ib_ctx, q->db_rec_addr, PAGE_SIZE,
+				     access, dmasync);
+
+	if (IS_ERR(q->db_rec_umem)) {
+		DP_ERR(dev,
+		       "create user queue: failed db_rec ib_umem_get, error was %ld, db_rec_addr was %llx\n",
+		       PTR_ERR(q->db_rec_umem), db_rec_addr);
+		return PTR_ERR(q->db_rec_umem);
+	}
+
+	q->db_rec_virt = sg_virt(q->db_rec_umem->sg_head.sgl);
+
+	return 0;
+}
+
+static int qedr_init_user_queue(struct ib_ucontext *ib_ctx,
+				struct qedr_dev *dev,
+				struct qedr_userq *q,
+				u64 buf_addr, size_t buf_len,
+				u64 db_rec_addr,
+				int access, int dmasync,
+				int alloc_and_init)
 {
 	u32 fw_pages;
 	int rc;
@@ -778,7 +831,9 @@ static inline int qedr_init_user_queue(struct ib_ucontext *ib_ctx,
 		}
 	}
 
-	return 0;
+	/* mmap the user address used to store doorbell data for recovery */
+	return qedr_init_user_db_rec(ib_ctx, dev, q, db_rec_addr, access,
+				     dmasync);
 
 err0:
 	ib_umem_release(q->umem);
@@ -866,6 +921,7 @@ struct ib_cq *qedr_create_cq(struct ib_device *ibdev,
 	int entries = attr->cqe;
 	struct qedr_cq *cq;
 	int chain_entries;
+	u32 db_offset;
 	int page_cnt;
 	u64 pbl_ptr;
 	u16 icid;
@@ -889,9 +945,13 @@ struct ib_cq *qedr_create_cq(struct ib_device *ibdev,
 	if (!cq)
 		return ERR_PTR(-ENOMEM);
 
+	/* calc db offset. user will add DPI base, kernel will add db addr */
+	db_offset = DB_ADDR_SHIFT(DQ_PWM_OFFSET_UCM_RDMA_CQ_CONS_32BIT);
+
 	if (udata) {
 		memset(&ureq, 0, sizeof(ureq));
-		if (ib_copy_from_udata(&ureq, udata, sizeof(ureq))) {
+		if (ib_copy_from_udata(&ureq, udata, min(sizeof(ureq),
+							 udata->inlen))) {
 			DP_ERR(dev,
 			       "create cq: problem copying data from user space\n");
 			goto err0;
@@ -906,8 +966,8 @@ struct ib_cq *qedr_create_cq(struct ib_device *ibdev,
 		cq->cq_type = QEDR_CQ_TYPE_USER;
 
 		rc = qedr_init_user_queue(ib_ctx, dev, &cq->q, ureq.addr,
-					  ureq.len, IB_ACCESS_LOCAL_WRITE,
-					  1, 1);
+					  ureq.len, ureq.db_rec_addr,
+					  IB_ACCESS_LOCAL_WRITE, 1, 1);
 		if (rc)
 			goto err0;
 
@@ -915,6 +975,8 @@ struct ib_cq *qedr_create_cq(struct ib_device *ibdev,
 		page_cnt = cq->q.pbl_info.num_pbes;
 
 		cq->ibcq.cqe = chain_entries;
+		cq->q.db_addr = (void __iomem *)(uintptr_t)ctx->dpi_addr +
+			db_offset;
 	} else {
 		cq->cq_type = QEDR_CQ_TYPE_KERNEL;
 
@@ -945,14 +1007,21 @@ struct ib_cq *qedr_create_cq(struct ib_device *ibdev,
 	spin_lock_init(&cq->cq_lock);
 
 	if (ib_ctx) {
-		rc = qedr_copy_cq_uresp(dev, cq, udata);
+		rc = qedr_copy_cq_uresp(dev, cq, udata, db_offset);
 		if (rc)
 			goto err3;
+
+		rc = qedr_db_recovery_add(dev, cq->q.db_addr,
+					  &cq->q.db_rec_virt->db_data,
+					  DB_REC_WIDTH_64B,
+					  DB_REC_USER);
+		if (rc)
+			goto err3;
+
 	} else {
 		/* Generate doorbell address. */
-		cq->db_addr = dev->db_addr +
-		    DB_ADDR_SHIFT(DQ_PWM_OFFSET_UCM_RDMA_CQ_CONS_32BIT);
-		cq->db.data.icid = cq->icid;
+		cq->db_addr = dev->db_addr + db_offset;
+		cq->db.data.icid = cpu_to_le16(cq->icid);
 		cq->db.data.params = DB_AGG_CMD_SET <<
 		    RDMA_PWM_VAL32_DATA_AGG_CMD_SHIFT;
 
@@ -962,6 +1031,11 @@ struct ib_cq *qedr_create_cq(struct ib_device *ibdev,
 		cq->latest_cqe = NULL;
 		consume_cqe(cq);
 		cq->cq_cons = qed_chain_get_cons_idx_u32(&cq->pbl);
+
+		rc = qedr_db_recovery_add(dev, cq->db_addr, &cq->db.data,
+					  DB_REC_WIDTH_64B, DB_REC_KERNEL);
+		if (rc)
+			goto err3;
 	}
 
 	DP_DEBUG(dev, QEDR_MSG_CQ,
@@ -980,8 +1054,22 @@ struct ib_cq *qedr_create_cq(struct ib_device *ibdev,
 	else
 		dev->ops->common->chain_free(dev->cdev, &cq->pbl);
 err1:
-	if (udata)
+	if (udata) {
 		ib_umem_release(cq->q.umem);
+
+		ib_umem_release(cq->q.db_rec_umem);
+
+		/* Not checking for return value since we are in error path
+		 * anyway
+		 */
+		qedr_db_recovery_del(dev, cq->q.db_addr,
+				     &cq->q.db_rec_virt->db_data);
+	} else {
+		/* Not checking for return value since we are in error path
+		 * anyway
+		 */
+		qedr_db_recovery_del(dev, cq->db_addr, &cq->db.data);
+	}
 err0:
 	kfree(cq);
 	return ERR_PTR(-EINVAL);
@@ -1014,8 +1102,12 @@ int qedr_destroy_cq(struct ib_cq *ibcq)
 	cq->destroyed = 1;
 
 	/* GSIs CQs are handled by driver, so they don't exist in the FW */
-	if (cq->cq_type == QEDR_CQ_TYPE_GSI)
+	if (cq->cq_type == QEDR_CQ_TYPE_GSI) {
+		rc = qedr_db_recovery_del(dev, cq->db_addr, &cq->db.data);
+		if (rc)
+			return rc;
 		goto done;
+	}
 
 	iparams.icid = cq->icid;
 	rc = dev->ops->rdma_destroy_cq(dev->rdma_ctx, &iparams, &oparams);
@@ -1027,6 +1119,17 @@ int qedr_destroy_cq(struct ib_cq *ibcq)
 	if (ibcq->uobject && ibcq->uobject->context) {
 		qedr_free_pbl(dev, &cq->q.pbl_info, cq->q.pbl_tbl);
 		ib_umem_release(cq->q.umem);
+
+		rc = qedr_db_recovery_del(dev, cq->q.db_addr,
+					  &cq->q.db_rec_virt->db_data);
+		if (rc)
+			return rc;
+		if (cq->q.db_rec_umem)
+			ib_umem_release(cq->q.db_rec_umem);
+	} else {
+		rc = qedr_db_recovery_del(dev, cq->db_addr, &cq->db.data);
+		if (rc)
+			return rc;
 	}
 
 	/* We don't want the IRQ handler to handle a non-existing CQ so we
@@ -1234,19 +1337,19 @@ static void qedr_copy_sq_uresp(struct qedr_dev *dev,
 }
 
 static int qedr_copy_qp_uresp(struct qedr_dev *dev,
-			      struct qedr_qp *qp, struct ib_udata *udata)
+			      struct qedr_qp *qp, struct ib_udata *udata,
+			      struct qedr_create_qp_uresp *uresp)
 {
-	struct qedr_create_qp_uresp uresp;
 	int rc;
 
-	memset(&uresp, 0, sizeof(uresp));
-	qedr_copy_sq_uresp(dev, &uresp, qp);
-	qedr_copy_rq_uresp(dev, &uresp, qp);
+	memset(uresp, 0, sizeof(*uresp));
+	qedr_copy_sq_uresp(dev, uresp, qp);
+	qedr_copy_rq_uresp(dev, uresp, qp);
 
-	uresp.atomic_supported = dev->atomic_cap != IB_ATOMIC_NONE;
-	uresp.qp_id = qp->qp_id;
+	uresp->atomic_supported = dev->atomic_cap != IB_ATOMIC_NONE;
+	uresp->qp_id = qp->qp_id;
 
-	rc = qedr_ib_copy_to_udata(udata, &uresp, sizeof(uresp));
+	rc = qedr_ib_copy_to_udata(udata, uresp, sizeof(*uresp));
 	if (rc)
 		DP_ERR(dev,
 		       "create qp: failed a copy to user space with qp icid=0x%x.\n",
@@ -1290,16 +1393,35 @@ static void qedr_set_common_qp_params(struct qedr_dev *dev,
 		 qp->sq.max_sges, qp->sq_cq->icid);
 }
 
-static void qedr_set_roce_db_info(struct qedr_dev *dev, struct qedr_qp *qp)
+static int qedr_set_roce_db_info(struct qedr_dev *dev, struct qedr_qp *qp)
 {
+	int rc;
+
 	qp->sq.db = dev->db_addr +
 		    DB_ADDR_SHIFT(DQ_PWM_OFFSET_XCM_RDMA_SQ_PROD);
-	qp->sq.db_data.data.icid = qp->icid + 1;
+	qp->sq.db_data.data.icid = cpu_to_le16(qp->icid + 1);
+	rc = qedr_db_recovery_add(dev, qp->sq.db,
+				  &qp->sq.db_data,
+				  DB_REC_WIDTH_32B,
+				  DB_REC_KERNEL);
+	if (rc)
+		return rc;
+
 	if (!qp->srq) {
 		qp->rq.db = dev->db_addr +
 			    DB_ADDR_SHIFT(DQ_PWM_OFFSET_TCM_ROCE_RQ_PROD);
-		qp->rq.db_data.data.icid = qp->icid;
+		qp->rq.db_data.data.icid = cpu_to_le16(qp->icid);
+
+		rc = qedr_db_recovery_add(dev, qp->rq.db,
+					  &qp->rq.db_data,
+					  DB_REC_WIDTH_32B,
+					  DB_REC_KERNEL);
+		if (rc)
+			qedr_db_recovery_del(dev, qp->sq.db,
+					     &qp->sq.db_data);
 	}
+
+	return rc;
 }
 
 static int qedr_check_srq_params(struct ib_pd *ibpd, struct qedr_dev *dev,
@@ -1353,7 +1475,7 @@ static int qedr_init_srq_user_params(struct ib_ucontext *ib_ctx,
 	int rc;
 
 	rc = qedr_init_user_queue(ib_ctx, srq->dev, &srq->usrq, ureq->srq_addr,
-				  ureq->srq_len, access, dmasync, 1);
+				  ureq->srq_len, 0,  access, dmasync, 1);
 	if (rc)
 		return rc;
 
@@ -1462,7 +1584,8 @@ struct ib_srq *qedr_create_srq(struct ib_pd *ibpd,
 	if (udata && ibpd->uobject && ibpd->uobject->context) {
 		ib_ctx = ibpd->uobject->context;
 
-		if (ib_copy_from_udata(&ureq, udata, sizeof(ureq))) {
+		if (ib_copy_from_udata(&ureq, udata, min(sizeof(ureq),
+							 udata->inlen))) {
 			DP_ERR(dev,
 			       "create srq: problem copying data from user space\n");
 			goto err0;
@@ -1679,8 +1802,10 @@ qedr_iwarp_populate_user_qp(struct qedr_dev *dev,
 			   &qp->urq.pbl_info, FW_PAGE_SHIFT);
 }
 
-static void qedr_cleanup_user(struct qedr_dev *dev, struct qedr_qp *qp)
+static int qedr_cleanup_user(struct qedr_dev *dev, struct qedr_qp *qp)
 {
+	int rc;
+
 	if (qp->usq.umem)
 		ib_umem_release(qp->usq.umem);
 	qp->usq.umem = NULL;
@@ -1688,6 +1813,22 @@ static void qedr_cleanup_user(struct qedr_dev *dev, struct qedr_qp *qp)
 	if (qp->urq.umem)
 		ib_umem_release(qp->urq.umem);
 	qp->urq.umem = NULL;
+
+	if (qp->usq.db_rec_umem)
+		ib_umem_release(qp->usq.db_rec_umem);
+	qp->usq.db_rec_umem = NULL;
+	if (qp->urq.db_rec_umem)
+		ib_umem_release(qp->urq.db_rec_umem);
+	qp->urq.db_rec_umem = NULL;
+
+	rc = qedr_db_recovery_del(dev, qp->usq.db_addr,
+				  &qp->usq.db_rec_virt->db_data);
+	if (rc)
+		return rc;
+
+	rc = qedr_db_recovery_del(dev, qp->urq.db_addr,
+				  &qp->urq.db_rec_virt->db_data);
+	return rc;
 }
 
 static int qedr_create_user_qp(struct qedr_dev *dev,
@@ -1700,14 +1841,17 @@ static int qedr_create_user_qp(struct qedr_dev *dev,
 	struct qed_rdma_create_qp_out_params out_params;
 	struct qedr_pd *pd = get_qedr_pd(ibpd);
 	struct ib_ucontext *ib_ctx = NULL;
+	struct qedr_create_qp_uresp uresp;
+	struct qedr_ucontext *ctx = NULL;
 	struct qedr_create_qp_ureq ureq;
 	int alloc_and_init = rdma_protocol_roce(&dev->ibdev, 1);
 	int rc = -EINVAL;
 
 	ib_ctx = ibpd->uobject->context;
+	ctx = get_qedr_ucontext(ib_ctx);
 
 	memset(&ureq, 0, sizeof(ureq));
-	rc = ib_copy_from_udata(&ureq, udata, sizeof(ureq));
+	rc = ib_copy_from_udata(&ureq, udata, min(sizeof(ureq), udata->inlen));
 	if (rc) {
 		DP_ERR(dev, "Problem copying data from user space\n");
 		return rc;
@@ -1715,14 +1859,16 @@ static int qedr_create_user_qp(struct qedr_dev *dev,
 
 	/* SQ - read access only (0), dma sync not required (0) */
 	rc = qedr_init_user_queue(ib_ctx, dev, &qp->usq, ureq.sq_addr,
-				  ureq.sq_len, 0, 0, alloc_and_init);
+				  ureq.sq_len, ureq.sq_db_rec_addr, 0, 0,
+				  alloc_and_init);
 	if (rc)
 		return rc;
 
 	if (!qp->srq) {
 		/* RQ - read access only (0), dma sync not required (0) */
 		rc = qedr_init_user_queue(ib_ctx, dev, &qp->urq, ureq.rq_addr,
-					  ureq.rq_len, 0, 0, alloc_and_init);
+					  ureq.rq_len, ureq.rq_db_rec_addr,
+					  0, 0, alloc_and_init);
 		if (rc)
 			return rc;
 	}
@@ -1752,13 +1898,30 @@ static int qedr_create_user_qp(struct qedr_dev *dev,
 	qp->qp_id = out_params.qp_id;
 	qp->icid = out_params.icid;
 
-	rc = qedr_copy_qp_uresp(dev, qp, udata);
+	rc = qedr_copy_qp_uresp(dev, qp, udata, &uresp);
 	if (rc)
 		goto err;
 
+	/* db offset was calculated in copy_qp_uresp, now set in the user q */
+	qp->usq.db_addr = (void __iomem *)(uintptr_t)ctx->dpi_addr +
+		uresp.sq_db_offset;
+	qp->urq.db_addr = (void __iomem *)(uintptr_t)ctx->dpi_addr +
+		uresp.rq_db_offset;
+
+	rc = qedr_db_recovery_add(dev, qp->usq.db_addr,
+				  &qp->usq.db_rec_virt->db_data,
+				  DB_REC_WIDTH_32B,
+				  DB_REC_USER);
+	if (rc)
+		return rc;
+
+	rc = qedr_db_recovery_add(dev, qp->urq.db_addr,
+				  &qp->urq.db_rec_virt->db_data,
+				  DB_REC_WIDTH_32B,
+				  DB_REC_USER);
 	qedr_qp_user_print(dev, qp);
 
-	return 0;
+	return rc;
 err:
 	rc = dev->ops->rdma_destroy_qp(dev->rdma_ctx, qp->qed_qp);
 	if (rc)
@@ -1769,19 +1932,35 @@ static int qedr_create_user_qp(struct qedr_dev *dev,
 	return rc;
 }
 
-static void qedr_set_iwarp_db_info(struct qedr_dev *dev, struct qedr_qp *qp)
+static int qedr_set_iwarp_db_info(struct qedr_dev *dev, struct qedr_qp *qp)
 {
+	int rc;
+
 	qp->sq.db = dev->db_addr +
 	    DB_ADDR_SHIFT(DQ_PWM_OFFSET_XCM_RDMA_SQ_PROD);
-	qp->sq.db_data.data.icid = qp->icid;
+	qp->sq.db_data.data.icid = cpu_to_le16(qp->icid);
+
+	rc = qedr_db_recovery_add(dev, qp->sq.db,
+				  &qp->sq.db_data,
+				  DB_REC_WIDTH_32B,
+				  DB_REC_KERNEL);
+	if (rc)
+		return rc;
 
 	qp->rq.db = dev->db_addr +
 		    DB_ADDR_SHIFT(DQ_PWM_OFFSET_TCM_IWARP_RQ_PROD);
-	qp->rq.db_data.data.icid = qp->icid;
+	qp->rq.db_data.data.icid = cpu_to_le16(qp->icid);
 	qp->rq.iwarp_db2 = dev->db_addr +
 			   DB_ADDR_SHIFT(DQ_PWM_OFFSET_TCM_FLAGS);
 	qp->rq.iwarp_db2_data.data.icid = qp->icid;
 	qp->rq.iwarp_db2_data.data.value = DQ_TCM_IWARP_POST_RQ_CF_CMD;
+
+	rc = qedr_db_recovery_add(dev, qp->rq.db,
+				  &qp->rq.db_data,
+				  DB_REC_WIDTH_32B,
+				  DB_REC_KERNEL);
+
+	return rc;
 }
 
 static int
@@ -1829,8 +2008,7 @@ qedr_roce_create_kernel_qp(struct qedr_dev *dev,
 	qp->qp_id = out_params.qp_id;
 	qp->icid = out_params.icid;
 
-	qedr_set_roce_db_info(dev, qp);
-	return rc;
+	return qedr_set_roce_db_info(dev, qp);
 }
 
 static int
@@ -1888,8 +2066,7 @@ qedr_iwarp_create_kernel_qp(struct qedr_dev *dev,
 	qp->qp_id = out_params.qp_id;
 	qp->icid = out_params.icid;
 
-	qedr_set_iwarp_db_info(dev, qp);
-	return rc;
+	return qedr_set_iwarp_db_info(dev, qp);
 
 err:
 	dev->ops->rdma_destroy_qp(dev->rdma_ctx, qp->qed_qp);
@@ -1897,13 +2074,27 @@ qedr_iwarp_create_kernel_qp(struct qedr_dev *dev,
 	return rc;
 }
 
-static void qedr_cleanup_kernel(struct qedr_dev *dev, struct qedr_qp *qp)
+static int qedr_cleanup_kernel(struct qedr_dev *dev, struct qedr_qp *qp)
 {
+	int rc = 0;
+
 	dev->ops->common->chain_free(dev->cdev, &qp->sq.pbl);
 	kfree(qp->wqe_wr_id);
 
 	dev->ops->common->chain_free(dev->cdev, &qp->rq.pbl);
 	kfree(qp->rqe_wr_id);
+
+	/* GSI qp is not registered to db mechanism so no need to delete */
+	if (qp->qp_type == IB_QPT_GSI)
+		return rc;
+
+	rc = qedr_db_recovery_del(dev, qp->sq.db, &qp->sq.db_data);
+	if (rc)
+		return rc;
+
+	if (!qp->srq)
+		rc = qedr_db_recovery_del(dev, qp->rq.db, &qp->rq.db_data);
+	return rc;
 }
 
 static int qedr_create_kernel_qp(struct qedr_dev *dev,
@@ -2544,7 +2735,7 @@ int qedr_query_qp(struct ib_qp *ibqp,
 
 static int qedr_free_qp_resources(struct qedr_dev *dev, struct qedr_qp *qp)
 {
-	int rc = 0;
+	int rc;
 
 	if (qp->qp_type != IB_QPT_GSI) {
 		rc = dev->ops->rdma_destroy_qp(dev->rdma_ctx, qp->qed_qp);
@@ -2553,11 +2744,11 @@ static int qedr_free_qp_resources(struct qedr_dev *dev, struct qedr_qp *qp)
 	}
 
 	if (qp->ibqp.uobject && qp->ibqp.uobject->context)
-		qedr_cleanup_user(dev, qp);
+		rc = qedr_cleanup_user(dev, qp);
 	else
-		qedr_cleanup_kernel(dev, qp);
+		rc = qedr_cleanup_kernel(dev, qp);
 
-	return 0;
+	return rc;
 }
 
 int qedr_destroy_qp(struct ib_qp *ibqp)
diff --git a/include/uapi/rdma/qedr-abi.h b/include/uapi/rdma/qedr-abi.h
index 7a10b3a325fa..d60e6acb8a09 100644
--- a/include/uapi/rdma/qedr-abi.h
+++ b/include/uapi/rdma/qedr-abi.h
@@ -68,6 +68,7 @@ struct qedr_alloc_pd_uresp {
 struct qedr_create_cq_ureq {
 	__aligned_u64 addr;
 	__aligned_u64 len;
+	__aligned_u64 db_rec_addr;
 };
 
 struct qedr_create_cq_uresp {
@@ -93,6 +94,12 @@ struct qedr_create_qp_ureq {
 
 	/* length of RQ buffer */
 	__aligned_u64 rq_len;
+
+	/* address of SQ doorbell recovery user entry */
+	__aligned_u64 sq_db_rec_addr;
+
+	/* address of RQ doorbell recovery user entry */
+	__aligned_u64 rq_db_rec_addr;
 };
 
 struct qedr_create_qp_uresp {
@@ -128,4 +135,12 @@ struct qedr_create_srq_uresp {
 	__u32 reserved1;
 };
 
+/* doorbell recovery entry allocated and populated by userspace doorbelling
+ * entities and mapped to kernel. Kernel uses this to register doorbell
+ * information with doorbell drop recovery mechanism.
+ */
+struct qedr_user_db_rec {
+	__aligned_u64 db_data; /* doorbell data */
+};
+
 #endif /* __QEDR_USER_H__ */
-- 
2.14.5




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux