From: Mustafa Ismail <mustafa.ismail@xxxxxxxxx> Running fio can occasionally cause a hang when sbitmap_queue_get() fails to return a tag in iscsit_allocate_cmd() and iscsit_wait_for_tag() is called and will never return from the schedule(). This is because the polling thread of the CQ is suspended, and will not poll for a SQ completion which would free up a tag. Fix this by creating a separate CQ for the SQ so that send completions are processed on a separate thread and are not blocked when the RQ CQ is stalled. Fixes: 10e9cbb6b531 ("scsi: target: Convert target drivers to use sbitmap") Reviewed-by: Mike Marciniszyn <mike.marciniszyn@xxxxxxxxx> Signed-off-by: Mustafa Ismail <mustafa.ismail@xxxxxxxxx> Signed-off-by: Shiraz Saleem <shiraz.saleem@xxxxxxxxx> --- drivers/infiniband/ulp/isert/ib_isert.c | 33 +++++++++++++++++++++++---------- drivers/infiniband/ulp/isert/ib_isert.h | 3 ++- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 7540488..f827b91 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -109,19 +109,27 @@ static int isert_sg_tablesize_set(const char *val, const struct kernel_param *kp struct ib_qp_init_attr attr; int ret, factor; - isert_conn->cq = ib_cq_pool_get(ib_dev, cq_size, -1, IB_POLL_WORKQUEUE); - if (IS_ERR(isert_conn->cq)) { - isert_err("Unable to allocate cq\n"); - ret = PTR_ERR(isert_conn->cq); + isert_conn->snd_cq = ib_cq_pool_get(ib_dev, cq_size, -1, + IB_POLL_WORKQUEUE); + if (IS_ERR(isert_conn->snd_cq)) { + isert_err("Unable to allocate send cq\n"); + ret = PTR_ERR(isert_conn->snd_cq); return ERR_PTR(ret); } + isert_conn->rcv_cq = ib_cq_pool_get(ib_dev, cq_size, -1, + IB_POLL_WORKQUEUE); + if (IS_ERR(isert_conn->rcv_cq)) { + isert_err("Unable to allocate receive cq\n"); + ret = PTR_ERR(isert_conn->rcv_cq); + goto create_cq_err; + } isert_conn->cq_size = cq_size; memset(&attr, 0, sizeof(struct ib_qp_init_attr)); attr.event_handler = isert_qp_event_callback; attr.qp_context = isert_conn; - attr.send_cq = isert_conn->cq; - attr.recv_cq = isert_conn->cq; + attr.send_cq = isert_conn->snd_cq; + attr.recv_cq = isert_conn->rcv_cq; attr.cap.max_send_wr = ISERT_QP_MAX_REQ_DTOS + 1; attr.cap.max_recv_wr = ISERT_QP_MAX_RECV_DTOS + 1; factor = rdma_rw_mr_factor(device->ib_device, cma_id->port_num, @@ -137,12 +145,16 @@ static int isert_sg_tablesize_set(const char *val, const struct kernel_param *kp ret = rdma_create_qp(cma_id, device->pd, &attr); if (ret) { isert_err("rdma_create_qp failed for cma_id %d\n", ret); - ib_cq_pool_put(isert_conn->cq, isert_conn->cq_size); - - return ERR_PTR(ret); + goto create_qp_err; } return cma_id->qp; +create_qp_err: + ib_cq_pool_put(isert_conn->rcv_cq, isert_conn->cq_size); +create_cq_err: + ib_cq_pool_put(isert_conn->snd_cq, isert_conn->cq_size); + + return ERR_PTR(ret); } static int @@ -409,7 +421,8 @@ static int isert_sg_tablesize_set(const char *val, const struct kernel_param *kp isert_destroy_qp(struct isert_conn *isert_conn) { ib_destroy_qp(isert_conn->qp); - ib_cq_pool_put(isert_conn->cq, isert_conn->cq_size); + ib_cq_pool_put(isert_conn->snd_cq, isert_conn->cq_size); + ib_cq_pool_put(isert_conn->rcv_cq, isert_conn->cq_size); } static int diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h index 0b2dfd6..0cd43af 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.h +++ b/drivers/infiniband/ulp/isert/ib_isert.h @@ -180,7 +180,8 @@ struct isert_conn { struct iser_tx_desc login_tx_desc; struct rdma_cm_id *cm_id; struct ib_qp *qp; - struct ib_cq *cq; + struct ib_cq *snd_cq; + struct ib_cq *rcv_cq; u32 cq_size; struct isert_device *device; struct mutex mutex; -- 1.8.3.1