ib_srpt: Avoid delay when unloading during I/O (merged r3899 and r3900 from trunk)

git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/2.1.0.x@3912 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Bart Van Assche
2011-11-06 10:45:25 +00:00
parent fe6c9a0a32
commit 65c0b7ea2e
+10 -32
View File
@@ -1969,19 +1969,16 @@ static void srpt_process_send_completion(struct ib_cq *cq,
}
}
static bool srpt_process_completion(struct ib_cq *cq,
static void srpt_process_completion(struct ib_cq *cq,
struct srpt_rdma_ch *ch,
enum scst_exec_context context)
{
struct ib_wc *const wc = ch->wc;
int i, n;
bool keep_going;
EXTRACHECKS_WARN_ON(cq != ch->cq);
keep_going = atomic_read(&ch->state) <= CH_LIVE;
if (keep_going)
ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
while ((n = ib_poll_cq(cq, ARRAY_SIZE(ch->wc), wc)) > 0) {
for (i = 0; i < n; i++) {
if (opcode_from_wr_id(wc[i].wr_id) == SRPT_RECV)
@@ -1992,8 +1989,6 @@ static bool srpt_process_completion(struct ib_cq *cq,
&wc[i]);
}
}
return keep_going;
}
/**
@@ -2028,49 +2023,32 @@ 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;
ch = arg;
BUG_ON(!ch);
while (!kthread_should_stop()) {
while (!kthread_should_stop() && !ch->last_wqe_received) {
set_current_state(TASK_INTERRUPTIBLE);
if (!srpt_process_completion(ch->cq, ch, SCST_CONTEXT_THREAD))
break;
srpt_process_completion(ch->cq, ch, SCST_CONTEXT_THREAD);
schedule();
}
set_current_state(TASK_RUNNING);
WARN_ON(atomic_read(&ch->state) <= CH_LIVE);
ret = wait_event_timeout(ch->state_wq,
atomic_read(&ch->state) >= CH_DRAINING,
RDMA_COMPL_TIMEOUT_S * HZ);
WARN_ON(ret < 0);
if (!ret) {
PRINT_ERROR("%s: DREP message has not been received in time.",
ch->sess_name);
srpt_drain_channel(ch->cm_id);
}
ret = wait_event_timeout(ch->state_wq,
atomic_read(&ch->state) == CH_RELEASING,
RDMA_COMPL_TIMEOUT_S * HZ);
WARN_ON(ret < 0);
if (!ret) {
PRINT_ERROR("%s: Last WQE event has not been received in time.",
ch->sess_name);
atomic_set(&ch->state, CH_RELEASING);
}
srpt_process_completion(ch->cq, ch, SCST_CONTEXT_THREAD);
/*
* Note: scst_unregister_session() must only be invoked after the last
* WQE event has been received.
*/
TRACE_DBG("ch %s: about to invoke scst_unregister_session()",
ch->sess_name);
scst_unregister_session(ch->scst_sess, false, srpt_free_ch);
while (!kthread_should_stop()) {
set_current_state(TASK_INTERRUPTIBLE);
srpt_process_completion(ch->cq, ch, SCST_CONTEXT_THREAD);
schedule();
}