mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-19 03:31:26 +00:00
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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user