diff --git a/providers/cxgb4/qp.c b/providers/cxgb4/qp.c
index af04e3a1..46806341 100644
--- a/providers/cxgb4/qp.c
+++ b/providers/cxgb4/qp.c
@@ -488,44 +488,49 @@ static void update_qp_state(struct c4iw_qp *qhp)
 		qhp->ibv_qp.state = attr.qp_state;
 }
 
-/*
- * Assumes qhp lock is held.
- */
 void c4iw_flush_qp(struct c4iw_qp *qhp)
 {
 	struct c4iw_cq *rchp, *schp;
 	int count;
 
-	if (qhp->wq.flushed)
-		return;
-
-	update_qp_state(qhp);
-
 	rchp = to_c4iw_cq(qhp->ibv_qp.recv_cq);
 	schp = to_c4iw_cq(qhp->ibv_qp.send_cq);
 
 	PDBG("%s qhp %p rchp %p schp %p\n", __func__, qhp, rchp, schp);
-	qhp->wq.flushed = 1;
-	pthread_spin_unlock(&qhp->lock);
 
 	/* locking heirarchy: cq lock first, then qp lock. */
 	pthread_spin_lock(&rchp->lock);
+	if (schp != rchp)
+		pthread_spin_lock(&schp->lock);
 	pthread_spin_lock(&qhp->lock);
+
+	if (qhp->wq.flushed) {
+		pthread_spin_unlock(&qhp->lock);
+		if (rchp != schp)
+			pthread_spin_unlock(&schp->lock);
+		pthread_spin_unlock(&rchp->lock);
+		return;
+	}
+
+	qhp->wq.flushed = 1;
+	t4_set_wq_in_error(&qhp->wq);
+
+	update_qp_state(qhp);
+
 	c4iw_flush_hw_cq(rchp);
 	c4iw_count_rcqes(&rchp->cq, &qhp->wq, &count);
 	c4iw_flush_rq(&qhp->wq, &rchp->cq, count);
-	pthread_spin_unlock(&qhp->lock);
-	pthread_spin_unlock(&rchp->lock);
 
-	/* locking heirarchy: cq lock first, then qp lock. */
-	pthread_spin_lock(&schp->lock);
-	pthread_spin_lock(&qhp->lock);
 	if (schp != rchp)
 		c4iw_flush_hw_cq(schp);
+
 	c4iw_flush_sq(qhp);
+
 	pthread_spin_unlock(&qhp->lock);
-	pthread_spin_unlock(&schp->lock);
-	pthread_spin_lock(&qhp->lock);
+	if (schp != rchp)
+		pthread_spin_unlock(&schp->lock);
+	pthread_spin_unlock(&rchp->lock);
+
 }
 
 void c4iw_flush_qps(struct c4iw_dev *dev)
@@ -537,9 +542,7 @@ void c4iw_flush_qps(struct c4iw_dev *dev)
 		struct c4iw_qp *qhp = dev->qpid2ptr[i];
 		if (qhp) {
 			if (!qhp->wq.flushed && t4_wq_in_error(&qhp->wq)) {
-				pthread_spin_lock(&qhp->lock);
 				c4iw_flush_qp(qhp);
-				pthread_spin_unlock(&qhp->lock);
 			}
 		}
 	}
diff --git a/providers/cxgb4/verbs.c b/providers/cxgb4/verbs.c
index 3c493697..988b62a7 100644
--- a/providers/cxgb4/verbs.c
+++ b/providers/cxgb4/verbs.c
@@ -584,9 +584,9 @@ int c4iw_modify_qp(struct ibv_qp *ibqp, struct ibv_qp_attr *attr,
 	int ret;
 
 	PDBG("%s enter qp %p new state %d\n", __func__, ibqp, attr_mask & IBV_QP_STATE ? attr->qp_state : -1);
-	pthread_spin_lock(&qhp->lock);
 	if (t4_wq_in_error(&qhp->wq))
 		c4iw_flush_qp(qhp);
+	pthread_spin_lock(&qhp->lock);
 	ret = ibv_cmd_modify_qp(ibqp, attr, attr_mask, &cmd, sizeof cmd);
 	if (!ret && (attr_mask & IBV_QP_STATE) && attr->qp_state == IBV_QPS_RESET)
 		reset_qp(qhp);
@@ -601,9 +601,7 @@ int c4iw_destroy_qp(struct ibv_qp *ibqp)
 	struct c4iw_dev *dev = to_c4iw_dev(ibqp->context->device);
 
 	PDBG("%s enter qp %p\n", __func__, ibqp);
-	pthread_spin_lock(&qhp->lock);
 	c4iw_flush_qp(qhp);
-	pthread_spin_unlock(&qhp->lock);
 
 	ret = ibv_cmd_destroy_qp(ibqp);
 	if (ret) {
@@ -635,9 +633,9 @@ int c4iw_query_qp(struct ibv_qp *ibqp, struct ibv_qp_attr *attr,
 	struct c4iw_qp *qhp = to_c4iw_qp(ibqp);
 	int ret;
 
-	pthread_spin_lock(&qhp->lock);
 	if (t4_wq_in_error(&qhp->wq))
 		c4iw_flush_qp(qhp);
+	pthread_spin_lock(&qhp->lock);
 	ret = ibv_cmd_query_qp(ibqp, attr, attr_mask, init_attr, &cmd, sizeof cmd);
 	pthread_spin_unlock(&qhp->lock);
 	return ret;
@@ -659,9 +657,9 @@ int c4iw_attach_mcast(struct ibv_qp *ibqp, const union ibv_gid *gid,
 	struct c4iw_qp *qhp = to_c4iw_qp(ibqp);
 	int ret;
 
-	pthread_spin_lock(&qhp->lock);
 	if (t4_wq_in_error(&qhp->wq))
 		c4iw_flush_qp(qhp);
+	pthread_spin_lock(&qhp->lock);
 	ret = ibv_cmd_attach_mcast(ibqp, gid, lid);
 	pthread_spin_unlock(&qhp->lock);
 	return ret;
@@ -673,9 +671,9 @@ int c4iw_detach_mcast(struct ibv_qp *ibqp, const union ibv_gid *gid,
 	struct c4iw_qp *qhp = to_c4iw_qp(ibqp);
 	int ret;
 
-	pthread_spin_lock(&qhp->lock);
 	if (t4_wq_in_error(&qhp->wq))
 		c4iw_flush_qp(qhp);
+	pthread_spin_lock(&qhp->lock);
 	ret = ibv_cmd_detach_mcast(ibqp, gid, lid);
 	pthread_spin_unlock(&qhp->lock);
 	return ret;
@@ -694,9 +692,7 @@ void c4iw_async_event(struct ibv_async_event *event)
 	case IBV_EVENT_QP_ACCESS_ERR:
 	case IBV_EVENT_PATH_MIG_ERR: {
 		struct c4iw_qp *qhp = to_c4iw_qp(event->element.qp);
-		pthread_spin_lock(&qhp->lock);
 		c4iw_flush_qp(qhp);
-		pthread_spin_unlock(&qhp->lock);
 		break;
 	}
 	case IBV_EVENT_SQ_DRAINED:
