From c57dc1b9f050978084dbe2854d99d99f295787f1 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 17 Sep 2011 16:00:12 +0000 Subject: [PATCH] ib_srpt: Merge r3854..3859 from trunk git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/2.1.0.x@3860 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- srpt/src/ib_srpt.c | 36 ++++++++++++++++++++++++++++++------ srpt/src/ib_srpt.h | 1 + 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/srpt/src/ib_srpt.c b/srpt/src/ib_srpt.c index 4dae12381..773e96941 100644 --- a/srpt/src/ib_srpt.c +++ b/srpt/src/ib_srpt.c @@ -172,6 +172,7 @@ static void srpt_unregister_procfs_entry(struct scst_tgt_template *tgt); #endif /*CONFIG_SCST_PROC*/ static void srpt_unmap_sg_to_ib_sge(struct srpt_rdma_ch *ch, struct srpt_send_ioctx *ioctx); +static void srpt_drain_channel(struct ib_cm_id *cm_id); static void srpt_free_ch(struct scst_session *sess); static struct ib_client srpt_client = { @@ -327,9 +328,9 @@ static void srpt_qp_event(struct ib_event *event, struct srpt_rdma_ch *ch) ch->sess_name); if (srpt_test_and_set_channel_state(ch, CH_DRAINING, CH_RELEASING)) - wake_up_process(ch->thread); + wake_up(&ch->last_wqe); else - TRACE_DBG("%s: state %d - ignored LAST_WQE.", + TRACE_DBG("%s: state %d - ignored Last WQE event.", ch->sess_name, atomic_read(&ch->state)); break; default: @@ -1991,6 +1992,7 @@ static void srpt_completion(struct ib_cq *cq, void *ctx) static int srpt_compl_thread(void *arg) { struct srpt_rdma_ch *ch; + int ret; /* Hibernation / freezing of the SRPT kernel thread is not supported. */ current->flags |= PF_NOFREEZE; @@ -2005,9 +2007,25 @@ static int srpt_compl_thread(void *arg) } set_current_state(TASK_RUNNING); + WARN_ON(atomic_read(&ch->state) <= CH_LIVE); + + ret = wait_event_timeout(ch->last_wqe, + atomic_read(&ch->state) == CH_RELEASING, + 2 * RDMA_COMPL_TIMEOUT_S * HZ); + WARN_ON(ret < 0); + if (!ret) { + PRINT_ERROR("%s: %s has not been received in time.", + ch->sess_name, + atomic_read(&ch->state) == CH_DISCONNECTING ? + "DREP message" : + atomic_read(&ch->state) == CH_DRAINING ? + "Last WQE event" : "(?)"); + srpt_drain_channel(ch->cm_id); + atomic_set(&ch->state, CH_RELEASING); + } + TRACE_DBG("ch %s: about to invoke scst_unregister_session()", ch->sess_name); - WARN_ON(atomic_read(&ch->state) != CH_RELEASING); scst_unregister_session(ch->scst_sess, false, srpt_free_ch); while (!kthread_should_stop()) { @@ -2146,6 +2164,7 @@ static bool __srpt_close_ch(struct srpt_rdma_ch *ch) /* fall through */ case CH_LIVE: was_live = true; + wake_up_process(ch->thread); if (ib_send_cm_dreq(ch->cm_id, NULL, 0) < 0) PRINT_ERROR("%s", "sending CM DREQ failed."); break; @@ -2437,6 +2456,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, INIT_LIST_HEAD(&ch->cmd_wait_list); spin_lock_init(&ch->spinlock); + init_waitqueue_head(&ch->last_wqe); ch->ioctx_ring = (struct srpt_send_ioctx **) srpt_alloc_ioctx_ring(ch->sport->sdev, ch->rq_size, sizeof(*ch->ioctx_ring[0]), @@ -3416,10 +3436,13 @@ static int srpt_release_sdev(struct srpt_device *sdev) PRINT_INFO("%s: waiting for session unregistration ...", sdev->device->name); spin_lock_irq(&sdev->spinlock); - list_for_each_entry_safe(ch, next_ch, &sdev->rch_list, list) - PRINT_INFO("%s: %d commands in progress", + list_for_each_entry_safe(ch, next_ch, &sdev->rch_list, list) { + PRINT_INFO("%s: state %d; %d commands in progress", ch->sess_name, + atomic_read(&ch->state), atomic_read(&ch->scst_sess->sess_cmd_count)); + __srpt_close_ch(ch); + } spin_unlock_irq(&sdev->spinlock); } @@ -3759,7 +3782,8 @@ static void srpt_add_one(struct ib_device *device) sdev->srq_size, sdev->dev_attr.max_srq_wr, device->name); if (!srpt_service_guid) - srpt_service_guid = be64_to_cpu(device->node_guid); + srpt_service_guid = be64_to_cpu(device->node_guid) & + ~be64_to_cpu(IB_SERVICE_ID_AGN_MASK); sdev->cm_id = ib_create_cm_id(device, srpt_cm_handler, sdev); if (IS_ERR(sdev->cm_id)) diff --git a/srpt/src/ib_srpt.h b/srpt/src/ib_srpt.h index 1998609d0..eb62623b2 100644 --- a/srpt/src/ib_srpt.h +++ b/srpt/src/ib_srpt.h @@ -305,6 +305,7 @@ struct srpt_rdma_ch { atomic_t state; struct list_head list; struct list_head cmd_wait_list; + wait_queue_head_t last_wqe; struct scst_session *scst_sess; u8 sess_name[36];