ib_srpt: Process cmd_wait_list after QP RTS transition

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4825 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Bart Van Assche
2013-03-27 15:31:42 +00:00
parent a6a71c8248
commit 546073cfb4
2 changed files with 15 additions and 66 deletions

View File

@@ -193,7 +193,6 @@ static enum rdma_ch_state srpt_set_ch_state_to_disc(struct srpt_rdma_ch *ch)
spin_lock_irqsave(&ch->spinlock, flags);
prev = ch->state;
switch (prev) {
case CH_CONNECTING:
case CH_LIVE:
ch->state = CH_DISCONNECTING;
wake_up_process(ch->thread);
@@ -214,7 +213,6 @@ static bool srpt_set_ch_state_to_draining(struct srpt_rdma_ch *ch)
spin_lock_irqsave(&ch->spinlock, flags);
switch (ch->state) {
case CH_CONNECTING:
case CH_LIVE:
case CH_DISCONNECTING:
ch->state = CH_DRAINING;
@@ -229,29 +227,6 @@ static bool srpt_set_ch_state_to_draining(struct srpt_rdma_ch *ch)
return changed;
}
/**
* srpt_test_and_set_ch_state() - Test and set the channel state.
*
* Returns true if and only if the channel state has been set to the new state.
*/
static bool srpt_test_and_set_ch_state(struct srpt_rdma_ch *ch,
enum rdma_ch_state old,
enum rdma_ch_state new)
{
unsigned long flags;
bool changed = false;
spin_lock_irqsave(&ch->spinlock, flags);
if (ch->state == old) {
ch->state = new;
wake_up_process(ch->thread);
changed = true;
}
spin_unlock_irqrestore(&ch->spinlock, flags);
return changed;
}
/**
* srpt_adjust_req_lim() - Adjust ch->req_lim and ch->req_lim_delta atomically.
*
@@ -372,8 +347,6 @@ static void srpt_srq_event(struct ib_event *event, void *ctx)
static const char *get_ch_state_name(enum rdma_ch_state s)
{
switch (s) {
case CH_CONNECTING:
return "connecting";
case CH_LIVE:
return "live";
case CH_DISCONNECTING:
@@ -1861,7 +1834,7 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
DMA_FROM_DEVICE);
srp_cmd = recv_ioctx->ioctx.buf;
if (unlikely(!ch->rtu_received)) {
if (unlikely(!ch->rts)) {
list_add_tail(&recv_ioctx->wait_list, &ch->cmd_wait_list);
goto out;
}
@@ -1995,9 +1968,7 @@ static void srpt_process_send_completion(struct ib_cq *cq,
}
}
if (unlikely(opcode == SRPT_SEND &&
ch->rtu_received &&
!list_empty(&ch->cmd_wait_list)))
if (unlikely(ch->rts && !list_empty(&ch->cmd_wait_list)))
srpt_process_wait_list(ch);
}
@@ -2111,23 +2082,6 @@ static int srpt_compl_thread(void *arg)
/* See also http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52925. */
barrier();
#endif
#endif
while (ch->state < CH_LIVE) {
srpt_process_completion(ch);
schedule();
set_current_state(TASK_INTERRUPTIBLE);
}
set_current_state(TASK_RUNNING);
srpt_process_wait_list(ch);
ch->rtu_received = true;
set_current_state(TASK_INTERRUPTIBLE);
#if defined(__GNUC__)
#if (__GNUC__ * 100 + __GNUC_MINOR__) <= 406
/* See also http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52925. */
barrier();
#endif
#endif
while (!ch->last_wqe_received && ch->state == CH_LIVE) {
srpt_process_completion(ch);
@@ -2268,7 +2222,7 @@ static void srpt_destroy_ch_ib(struct srpt_rdma_ch *ch)
* an appropriate time.
*
* Returns true if and only if the channel state has been modified from
* CH_CONNECTING or CH_LIVE into CH_DISCONNECTING.
* CH_LIVE into CH_DISCONNECTING.
*/
static bool __srpt_close_ch(struct srpt_rdma_ch *ch)
__releases(&ch->srpt_tgt->spinlock)
@@ -2288,7 +2242,6 @@ static bool __srpt_close_ch(struct srpt_rdma_ch *ch)
prev_state = srpt_set_ch_state_to_disc(ch);
switch (prev_state) {
case CH_CONNECTING:
case CH_LIVE:
was_live = true;
break;
@@ -2552,7 +2505,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
*/
ch->rq_size = min(SRPT_RQ_SIZE, scst_get_max_lun_commands(NULL, 0));
spin_lock_init(&ch->spinlock);
ch->state = CH_CONNECTING;
ch->state = CH_LIVE;
INIT_LIST_HEAD(&ch->cmd_wait_list);
ch->max_rsp_size = max_t(uint32_t, srp_max_rsp_size, MIN_MAX_RSP_SIZE);
ch->ioctx_ring = (struct srpt_send_ioctx **)
@@ -2714,7 +2667,7 @@ restart:
rep_param->initiator_depth = 4;
spin_lock_irq(&srpt_tgt->spinlock);
if (ch->state == CH_CONNECTING)
if (ch->state == CH_LIVE)
ret = ib_send_cm_rep(cm_id, rep_param);
else
ret = -ECONNABORTED;
@@ -2792,16 +2745,15 @@ static void srpt_cm_rej_recv(struct ib_cm_id *cm_id)
*/
static void srpt_cm_rtu_recv(struct ib_cm_id *cm_id)
{
struct srpt_rdma_ch *ch;
struct srpt_rdma_ch *ch = cm_id->context;
int ret;
ch = cm_id->context;
BUG_ON(!ch);
if (srpt_test_and_set_ch_state(ch, CH_CONNECTING, CH_LIVE)) {
ret = srpt_ch_qp_rts(ch, ch->qp);
if (ret)
srpt_close_ch(ch);
ret = srpt_ch_qp_rts(ch, ch->qp);
if (ret == 0) {
smp_mb();
ch->rts = true;
} else {
srpt_close_ch(ch);
}
}

View File

@@ -268,15 +268,13 @@ struct srpt_send_ioctx {
/**
* enum rdma_ch_state - SRP channel state.
* @CH_CONNECTING: QP is in RTR state; waiting for RTU.
* @CH_LIVE: QP is in RTS state.
* @CH_LIVE: QP is in RTR, RTU or RTS state.
* @CH_DISCONNECTING: DREQ has been received and waiting for DREP or DREQ has
* been sent and waiting for DREP or channel is being closed
* for another reason.
* @CH_DRAINING: QP is in ERR state.
*/
enum rdma_ch_state {
CH_CONNECTING,
CH_LIVE,
CH_DISCONNECTING,
CH_DRAINING,
@@ -309,8 +307,7 @@ enum rdma_ch_state {
* @wc: Work completion array.
* @state: channel state. See also enum rdma_ch_state.
* @dreq_received: Whether an IB CM DREQ event has been received.
* @rtu_received: Whether an IB CM RTU event has been received and the
* requests received before that event have been processed.
* @rts: Whether the QP is in the RTS state.
* @list: node for insertion in the srpt_device.rch_list list.
* @cmd_wait_list: list of SCST commands that arrived before the RTU event. This
* list contains struct srpt_ioctx elements and is protected
@@ -342,7 +339,7 @@ struct srpt_rdma_ch {
enum rdma_ch_state state;
struct list_head list;
struct list_head cmd_wait_list;
bool rtu_received;
bool rts;
bool dreq_received;
bool last_wqe_received;