RDMA/core: Inject Completion Queue errors

Reducing the size of a CQ provokes an overrun.

Suggested-by: HÃ¥kon Bugge <haakon.bugge@oracle.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 7982430..64afd26 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -389,6 +389,7 @@
 	bool			ignore_flush;
 	bool			ignore_alloc_mr;
 	bool			ignore_modify_qp;
+	bool			ignore_cq_errors;
 };
 
 extern struct fail_rdma_verbs_attr fail_rdma_verbs;
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index e7de41a..f2246f6 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -353,6 +353,8 @@
 			    &fail_rdma_verbs.ignore_alloc_mr);
 	debugfs_create_bool("ignore-modify-qp", S_IFREG | 0600, dir,
 			    &fail_rdma_verbs.ignore_modify_qp);
+	debugfs_create_bool("ignore-cq-errors", S_IFREG | 0600, dir,
+			    &fail_rdma_verbs.ignore_cq_errors);
 }
 
 #else /* CONFIG_FAIL_RDMA_VERBS */
@@ -2964,6 +2966,13 @@
 	}
 }
 
+static noinline void
+ib_maybe_fail_cq_error(struct ib_cq *cq)
+{
+	if (should_fail(&fail_rdma_verbs.attr, 1))
+		ib_resize_cq(cq, 2);
+}
+
 static noinline int
 ib_maybe_fail_post_send(struct ib_qp *qp, const struct ib_send_wr *send_wr,
 			const struct ib_send_wr **bad_wr)
@@ -3022,6 +3031,8 @@
 	const struct ib_send_wr *dummy;
 	const struct ib_send_wr **bad_wr = bad_send_wr ? : &dummy;
 
+	if (!fail_rdma_verbs.ignore_cq_errors)
+		ib_maybe_fail_cq_error(qp->send_cq);
 	if (!fail_rdma_verbs.ignore_post_send)
 		return ib_maybe_fail_post_send(qp, send_wr, bad_wr);
 	return qp->device->ops.post_send(qp, send_wr, bad_wr);
@@ -3081,6 +3092,8 @@
 	const struct ib_recv_wr *dummy;
 	const struct ib_recv_wr **bad_wr = bad_recv_wr ? : &dummy;
 
+	if (!fail_rdma_verbs.ignore_cq_errors)
+		ib_maybe_fail_cq_error(qp->recv_cq);
 	if (!fail_rdma_verbs.ignore_post_recv)
 		return ib_maybe_fail_post_recv(qp, recv_wr, bad_wr);
 	return qp->device->ops.post_recv(qp, recv_wr, bad_wr);