ib_srpt: Restore the "connecting" channel state

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4827 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Bart Van Assche
2013-03-28 15:17:13 +00:00
parent 0763baaad6
commit 210b5d466e
2 changed files with 40 additions and 12 deletions

View File

@@ -193,6 +193,7 @@ 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);
@@ -213,6 +214,7 @@ 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;
@@ -227,6 +229,29 @@ 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.
*
@@ -347,6 +372,8 @@ 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:
@@ -1834,7 +1861,7 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
DMA_FROM_DEVICE);
srp_cmd = recv_ioctx->ioctx.buf;
if (unlikely(!ch->rts)) {
if (unlikely(ch->state == CH_CONNECTING)) {
list_add_tail(&recv_ioctx->wait_list, &ch->cmd_wait_list);
goto out;
}
@@ -1971,7 +1998,8 @@ static void srpt_process_send_completion(struct ib_cq *cq,
}
}
if (unlikely(ch->rts && !list_empty(&ch->cmd_wait_list)))
if (unlikely(!list_empty(&ch->cmd_wait_list) &&
ch->state != CH_CONNECTING))
srpt_process_wait_list(ch);
}
@@ -2086,7 +2114,7 @@ static int srpt_compl_thread(void *arg)
barrier();
#endif
#endif
while (!ch->last_wqe_received && ch->state == CH_LIVE) {
while (!ch->last_wqe_received && ch->state <= CH_LIVE) {
srpt_process_completion(ch);
schedule();
set_current_state(TASK_INTERRUPTIBLE);
@@ -2225,7 +2253,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_LIVE into CH_DISCONNECTING.
* CH_CONNECTING or CH_LIVE into CH_DISCONNECTING.
*/
static bool __srpt_close_ch(struct srpt_rdma_ch *ch)
__releases(&ch->srpt_tgt->spinlock)
@@ -2245,6 +2273,7 @@ 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;
@@ -2508,7 +2537,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_LIVE;
ch->state = CH_CONNECTING;
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 **)
@@ -2670,7 +2699,7 @@ restart:
rep_param->initiator_depth = 4;
spin_lock_irq(&srpt_tgt->spinlock);
if (ch->state == CH_LIVE)
if (ch->state == CH_CONNECTING)
ret = ib_send_cm_rep(cm_id, rep_param);
else
ret = -ECONNABORTED;
@@ -2771,9 +2800,8 @@ static void srpt_cm_rtu_recv(struct ib_cm_id *cm_id)
int ret;
ret = srpt_ch_qp_rts(ch, ch->qp);
if (ret == 0) {
smp_mb();
ch->rts = true;
if (ret == 0 && srpt_test_and_set_ch_state(ch, CH_CONNECTING,
CH_LIVE)) {
WARN_ON(srpt_zerolength_write(ch) < 0);
} else {
srpt_close_ch(ch);

View File

@@ -269,13 +269,15 @@ struct srpt_send_ioctx {
/**
* enum rdma_ch_state - SRP channel state.
* @CH_LIVE: QP is in RTR, RTU or RTS state.
* @CH_CONNECTING: QP is in RTR state; waiting for RTU.
* @CH_LIVE: QP is in 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,
@@ -308,7 +310,6 @@ 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.
* @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
@@ -340,7 +341,6 @@ struct srpt_rdma_ch {
enum rdma_ch_state state;
struct list_head list;
struct list_head cmd_wait_list;
bool rts;
bool dreq_received;
bool last_wqe_received;