diff --git a/iscsi-scst/kernel/iscsi.c b/iscsi-scst/kernel/iscsi.c index b7c6a2e03..31763f851 100644 --- a/iscsi-scst/kernel/iscsi.c +++ b/iscsi-scst/kernel/iscsi.c @@ -240,7 +240,8 @@ void cmnd_done(struct iscsi_cmnd *cmnd) switch (cmnd->scst_state) { case ISCSI_CMD_STATE_PROCESSED: TRACE_DBG("cmd %p PROCESSED", cmnd); - scst_tgt_cmd_done(cmnd->scst_cmd); + scst_tgt_cmd_done(cmnd->scst_cmd, + SCST_CONTEXT_DIRECT); break; case ISCSI_CMD_STATE_AFTER_PREPROC: { @@ -1148,12 +1149,6 @@ static int iscsi_pre_exec(struct scst_cmd *scst_cmd) EXTRACHECKS_BUG_ON(scst_cmd_atomic(scst_cmd)); if (scst_cmd_get_data_direction(scst_cmd) == SCST_DATA_READ) { - if (!(req->conn->ddigest_type & DIGEST_NONE)) - scst_set_long_xmit(scst_cmd); -#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) - else if (cmnd_hdr(req)->data_length > 8*1024) - scst_set_long_xmit(scst_cmd); -#endif EXTRACHECKS_BUG_ON(!list_empty(&req->rx_ddigest_cmd_list)); goto out; } @@ -2504,8 +2499,7 @@ static void iscsi_preprocessing_done(struct scst_cmd *scst_cmd) * upon entrance in this function, because otherwise it could be destroyed * inside as a result of iscsi_send(), which releases sent commands. */ -static void iscsi_try_local_processing(struct iscsi_conn *conn, - bool single_only) +static void iscsi_try_local_processing(struct iscsi_conn *conn) { int local; @@ -2532,11 +2526,9 @@ static void iscsi_try_local_processing(struct iscsi_conn *conn, if (local) { int rc = 1; - while (test_write_ready(conn)) { + + if (test_write_ready(conn)) rc = iscsi_send(conn); - if ((rc <= 0) || single_only) - break; - } spin_lock_bh(&iscsi_wr_lock); #ifdef CONFIG_SCST_EXTRACHECKS @@ -2565,11 +2557,6 @@ static int iscsi_xmit_response(struct scst_cmd *scst_cmd) u8 *sense = scst_cmd_get_sense_buffer(scst_cmd); int sense_len = scst_cmd_get_sense_buffer_len(scst_cmd); int old_state = req->scst_state; -#if 0 /* temp. ToDo */ - bool single_only = !scst_get_long_xmit(scst_cmd); -#else - bool single_only = 0; -#endif if (scst_cmd_atomic(scst_cmd)) return SCST_TGT_RES_NEED_THREAD_CTX; @@ -2678,7 +2665,7 @@ static int iscsi_xmit_response(struct scst_cmd *scst_cmd) conn_get_ordered(conn); req_cmnd_release(req); - iscsi_try_local_processing(conn, single_only); + iscsi_try_local_processing(conn); conn_put(conn); out: diff --git a/mpt/mpt_scst.c b/mpt/mpt_scst.c index 1853f757e..4b284e320 100644 --- a/mpt/mpt_scst.c +++ b/mpt/mpt_scst.c @@ -280,7 +280,8 @@ static void mpt_on_free_cmd(struct scst_cmd *scst_cmd); static void mpt_task_mgmt_fn_done(struct scst_mgmt_cmd *mcmd); static int mpt_handle_task_mgmt(MPT_STM_PRIV * priv, u32 reply_word, int task_mgmt, int lun); -static int mpt_send_cmd_to_scst(struct mpt_cmd *cmd, int context); +static int mpt_send_cmd_to_scst(struct mpt_cmd *cmd, + enum scst_exec_context context); static struct scst_tgt_template tgt_template = { .name = MYNAM, @@ -634,7 +635,7 @@ mpt_alloc_session_done(struct scst_session *scst_sess, void *data, int result) } static int -mpt_send_cmd_to_scst(struct mpt_cmd *cmd, int context) +mpt_send_cmd_to_scst(struct mpt_cmd *cmd, enum scst_exec_context context) { int res = 0; @@ -708,14 +709,20 @@ void stm_tgt_reply(MPT_ADAPTER *ioc, u32 reply_word) { MPT_STM_PRIV *priv = mpt_stm_priv[ioc->id]; - int index; - int init_index; + int index, init_index; + enum scst_exec_context context; struct scst_cmd *scst_cmd; struct mpt_cmd *cmd; volatile int *io_state; TRACE_ENTRY(); +#ifdef DEBUG_WORK_IN_THREAD + context = SCST_CONTEXT_THREAD; +#else + context = SCST_CONTEXT_TASKLET; +#endif + index = GET_IO_INDEX(reply_word); init_index = GET_INITIATOR_INDEX(reply_word); scst_cmd = priv->scst_cmd[index]; @@ -742,14 +749,10 @@ stm_tgt_reply(MPT_ADAPTER *ioc, u32 reply_word) scst_cmd, index, cmd, mpt_state_string[cmd->state]); if (cmd->state == MPT_STATE_NEED_DATA) { - int context = SCST_CONTEXT_TASKLET; int rx_status = SCST_RX_STATUS_SUCCESS; cmd->state = MPT_STATE_DATA_IN; -#ifdef DEBUG_WORK_IN_THREAD - context = SCST_CONTEXT_THREAD; -#endif TRACE_DBG("Data received, context %x, rx_status %d", context, rx_status); @@ -804,7 +807,7 @@ stm_tgt_reply(MPT_ADAPTER *ioc, u32 reply_word) atomic_set(&priv->pending_sense[init_index], MPT_STATUS_SENSE_IDLE); /* ToDo: check and set scst_set_delivery_status(), if necessary */ - scst_tgt_cmd_done(scst_cmd); + scst_tgt_cmd_done(scst_cmd, context); break; /* we tried to send status and sense @@ -815,7 +818,7 @@ stm_tgt_reply(MPT_ADAPTER *ioc, u32 reply_word) atomic_set(&priv->pending_sense[init_index], MPT_STATUS_SENSE_HANDLE_RQ); /* ToDo: check and set scst_set_delivery_status(), if necessary */ - scst_tgt_cmd_done(scst_cmd); + scst_tgt_cmd_done(scst_cmd, context); break; /* we've handled REQUEST_SENSE ourselves and @@ -834,12 +837,12 @@ stm_tgt_reply(MPT_ADAPTER *ioc, u32 reply_word) /* nothing much to do here, we aren't * handling cached sense/status */ /* ToDo: check and set scst_set_delivery_status(), if necessary */ - scst_tgt_cmd_done(scst_cmd); + scst_tgt_cmd_done(scst_cmd, context); break; } } else { /* ToDo: check and set scst_set_delivery_status(), if necessary */ - scst_tgt_cmd_done(scst_cmd); + scst_tgt_cmd_done(scst_cmd, context); } goto out; @@ -1686,7 +1689,7 @@ mpt_xmit_response(struct scst_cmd *scst_cmd) out_tgt_free: /* ToDo: check and set scst_set_delivery_status(), if necessary */ - scst_tgt_cmd_done(scst_cmd); + scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_SAME); goto out; } @@ -1769,7 +1772,7 @@ static int mpt_rdy_to_xfer(struct scst_cmd *scst_cmd) TRACE_DBG("cmd %p while session %p is shutting down", prm.cmd, sess); scst_rx_data(scst_cmd, SCST_RX_STATUS_ERROR_FATAL, - SCST_CONTEXT_THREAD); + SCST_CONTEXT_SAME); res = SCST_TGT_RES_SUCCESS; goto out; } diff --git a/qla2x00t/qla2x00-target/qla2x00t.c b/qla2x00t/qla2x00-target/qla2x00t.c index a0632dbc3..3ef2d107e 100644 --- a/qla2x00t/qla2x00-target/qla2x00t.c +++ b/qla2x00t/qla2x00-target/qla2x00t.c @@ -954,9 +954,11 @@ out_unlock: spin_unlock_irqrestore(&ha->hardware_lock, flags); if (do_tgt_cmd_done) { - if (!in_interrupt()) + if (!in_interrupt()) { msleep(250); - scst_tgt_cmd_done(cmd->scst_cmd); + scst_tgt_cmd_done(cmd->scst_cmd, SCST_CONTEXT_DIRECT); + } else + scst_tgt_cmd_done(cmd->scst_cmd, SCST_CONTEXT_TASKLET); /* !! At this point cmd could be already freed !! */ } @@ -1004,10 +1006,17 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, struct scst_cmd *scst_cmd; struct q2t_cmd *cmd; uint16_t loop_id = -1; + enum scst_exec_context context; int err = 0; TRACE_ENTRY(); +#ifdef CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD + context = SCST_CONTEXT_THREAD; +#else + context = SCST_CONTEXT_TASKLET; +#endif + if (ctio != NULL) loop_id = GET_TARGET_ID(ha, ctio); @@ -1109,7 +1118,6 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, } goto out_free; } else if (cmd->state == Q2T_STATE_NEED_DATA) { - int context = SCST_CONTEXT_TASKLET; int rx_status = SCST_RX_STATUS_SUCCESS; cmd->state = Q2T_STATE_DATA_IN; @@ -1117,10 +1125,6 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, if (status != CTIO_SUCCESS) rx_status = SCST_RX_STATUS_ERROR; -#ifdef CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD - context = SCST_CONTEXT_THREAD; -#endif - TRACE_DBG("Data received, context %x, rx_status %d", context, rx_status); @@ -1148,7 +1152,7 @@ out_free: TRACE_MGMT_DBG("%s", "Finishing failed CTIO"); scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_FAILED); } - scst_tgt_cmd_done(scst_cmd); + scst_tgt_cmd_done(scst_cmd, context); goto out; } @@ -1209,7 +1213,7 @@ static int q2t_do_send_cmd_to_scst(scsi_qla_host_t *ha, struct q2t_cmd *cmd) struct q2t_sess *sess = cmd->sess; uint16_t lun; scst_data_direction dir = SCST_DATA_NONE; - int context; + enum scst_exec_context context; TRACE_ENTRY(); diff --git a/qla_isp/linux/isp_scst.c b/qla_isp/linux/isp_scst.c index f725daab7..1355f6c5b 100644 --- a/qla_isp/linux/isp_scst.c +++ b/qla_isp/linux/isp_scst.c @@ -642,7 +642,7 @@ scsi_target_done_cmd(tmd_cmd_t *tmd) if (unlikely(xact->td_error)) { scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_FAILED); } - scst_tgt_cmd_done(scst_cmd); + scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_TASKLET); return; } @@ -658,7 +658,7 @@ scsi_target_done_cmd(tmd_cmd_t *tmd) if (unlikely(xact->td_error)) { scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_FAILED); } - scst_tgt_cmd_done(scst_cmd); + scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_TASKLET); } } else { ; /* we don't have all data, do nothing */ @@ -669,7 +669,7 @@ scsi_target_done_cmd(tmd_cmd_t *tmd) if (unlikely(xact->td_error)) { scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_FAILED); } - scst_tgt_cmd_done(scst_cmd); + scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_TASKLET); } else { Eprintk("don't know what to do with TMD_DONE[%llx] cdb0 %x hf %x lf %x xfrlen %d totlen %d moved %d\n", tmd->cd_tagval, tmd->cd_cdb[0], xact->td_hflags, xact->td_lflags, xact->td_xfrlen, tmd->cd_totlen, tmd->cd_moved); @@ -1106,7 +1106,7 @@ isp_rdy_to_xfer(struct scst_cmd *scst_cmd) if (unlikely(bc->enable == 0)) { SDprintk("%s: TMD[%llx] Chan %d not enabled\n", __FUNCTION__, tmd->cd_tagval, tmd->cd_channel); up_read(&bc->disable_sem); - scst_rx_data(scst_cmd, SCST_RX_STATUS_ERROR, SCST_CONTEXT_TASKLET); + scst_rx_data(scst_cmd, SCST_RX_STATUS_ERROR, SCST_CONTEXT_SAME); return (0); } @@ -1128,7 +1128,7 @@ isp_xmit_response(struct scst_cmd *scst_cmd) if (unlikely(scst_cmd_aborted(scst_cmd))) { scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_ABORTED); - scst_tgt_cmd_done(scst_cmd); + scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_SAME); return (0); } @@ -1205,7 +1205,7 @@ out: if (unlikely(bc->enable == 0)) { SDprintk("%s: TMD[%llx] Chan %d not enabled\n", __FUNCTION__, tmd->cd_tagval, tmd->cd_channel); up_read(&bc->disable_sem); - scst_tgt_cmd_done(scst_cmd); + scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_SAME); return (0); } diff --git a/scst/include/scst.h b/scst/include/scst.h index f7c122d19..fd4d5ab5b 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -173,35 +173,40 @@ typedef _Bool bool; #define SCST_ATOMIC 1 /************************************************************* - ** Values for pref_context parameter of scst_cmd_init_done() and - ** scst_rx_data() + ** Values for pref_context parameter of scst_cmd_init_done(), + ** scst_rx_data(), scst_restart_cmd(), scst_tgt_cmd_done() + ** and scst_cmd_done() *************************************************************/ -/* - * Direct cmd's processing (i.e. regular function calls in the current - * context) sleeping is not allowed - */ -#define SCST_CONTEXT_DIRECT_ATOMIC 0 +enum scst_exec_context { + /* + * Direct cmd's processing (i.e. regular function calls in the current + * context) sleeping is not allowed + */ + SCST_CONTEXT_DIRECT_ATOMIC, -/* - * Direct cmd's processing (i.e. regular function calls in the current - * context), sleeping is allowed, no restrictions - */ -#define SCST_CONTEXT_DIRECT 1 + /* + * Direct cmd's processing (i.e. regular function calls in the current + * context), sleeping is allowed, no restrictions + */ + SCST_CONTEXT_DIRECT, -/* Tasklet or thread context required for cmd's processing */ -#define SCST_CONTEXT_TASKLET 2 + /* Tasklet or thread context required for cmd's processing */ + SCST_CONTEXT_TASKLET, -/* Thread context required for cmd's processing */ -#define SCST_CONTEXT_THREAD 3 + /* Thread context required for cmd's processing */ + SCST_CONTEXT_THREAD, -/* - * SCST internal flag, which specifies that context is processable, i.e. the - * next command in the active list will be processed after the current one. - * - * Target drivers must never use it!! - */ -#define SCST_CONTEXT_PROCESSABLE 0x100 + /* + * Context is the same as it was in previous call of the corresponding + * callback. For example, if dev handler's exec() does sync. data + * reading this value should be used for scst_cmd_done(). The same is + * true if scst_tgt_cmd_done() called directly from target driver's + * xmit_response(). Not allowed in scst_cmd_init_done() and + * scst_cmd_init_stage1_done(). + */ + SCST_CONTEXT_SAME +}; /************************************************************* ** Values for status parameter of scst_rx_data() @@ -705,7 +710,10 @@ struct scst_dev_type { /* Set, if no /proc files should be automatically created by SCST */ unsigned no_proc:1; - /* Set, if exec() is synchronous */ + /* + * Should be set, if exec() is synchronous. This is a hint to SCST core + * to optimize commands order management. + */ unsigned exec_sync:1; /* @@ -742,8 +750,8 @@ struct scst_dev_type { * by scst_cmd_atomic(): it is true if the function called in the * atomic (non-sleeping) context. * - * If this function provides sync execution, you must set above - * exec_sync flag and should consider to setup dedicated threads by + * If this function provides sync execution, you should set + * exec_sync flag and consider to setup dedicated threads by * setting threads_num > 0. * * !! If this function is implemented, scst_check_local_events() !! @@ -1001,6 +1009,7 @@ struct scst_cmd { /************************************************************* ** Cmd's flags *************************************************************/ + /* * Set if expected_sn should be incremented, i.e. cmd was sent * for execution @@ -1022,12 +1031,6 @@ struct scst_cmd { /* Set if this command contains status */ unsigned int is_send_status:1; - /* - * Set if the cmd is being processed in the processable context. See - * comment for SCST_CONTEXT_PROCESSABLE for what it means. - */ - unsigned int context_processable:1; - /* Set if cmd is being retried */ unsigned int retry:1; @@ -1110,16 +1113,6 @@ struct scst_cmd { /* Set if increment expected_sn in cmd->scst_cmd_done() */ unsigned int inc_expected_sn_on_done:1; - /* - * Set if xmit_response() is going to need a considerable processing - * time. Processing time is considerable, if it's > context switch time - * (about 1 usec on modern systems). It's needed to trigger other - * threads to start processing other outstanding commands without - * waiting XMIT for the current one to finish. E.g., it should be set - * if iSCSI data digest used and cmd has READ direction. - */ - unsigned int long_xmit:1; - /* Set if tgt_sn field is valid */ unsigned int tgt_sn_set:1; @@ -1197,7 +1190,8 @@ struct scst_cmd { int data_len; /* Completition routine */ - void (*scst_cmd_done) (struct scst_cmd *cmd, int next_state); + void (*scst_cmd_done) (struct scst_cmd *cmd, int next_state, + enum scst_exec_context pref_context); struct sgv_pool_obj *sgv; /* sgv object */ @@ -1778,7 +1772,8 @@ struct scst_cmd *scst_rx_cmd(struct scst_session *sess, * with multiple connections per session seems to be an exception. For it, some * mutex/lock shall be used for the serialization. */ -void scst_cmd_init_done(struct scst_cmd *cmd, int pref_context); +void scst_cmd_init_done(struct scst_cmd *cmd, + enum scst_exec_context pref_context); /* * Notifies SCST that the driver finished the first stage of the command @@ -1790,7 +1785,7 @@ void scst_cmd_init_done(struct scst_cmd *cmd, int pref_context); * See also scst_cmd_init_done() comment for the serialization requirements. */ static inline void scst_cmd_init_stage1_done(struct scst_cmd *cmd, - int pref_context, int set_sn) + enum scst_exec_context pref_context, int set_sn) { cmd->preprocessing_only = 1; cmd->set_sn_on_restart_cmd = !set_sn; @@ -1807,7 +1802,8 @@ static inline void scst_cmd_init_stage1_done(struct scst_cmd *cmd, * * See also scst_cmd_init_done() comment for the serialization requirements. */ -void scst_restart_cmd(struct scst_cmd *cmd, int status, int pref_context); +void scst_restart_cmd(struct scst_cmd *cmd, int status, + enum scst_exec_context pref_context); /* * Notifies SCST that the driver received all the necessary data @@ -1817,15 +1813,18 @@ void scst_restart_cmd(struct scst_cmd *cmd, int status, int pref_context); * The third argument sets preferred command execition context * (see SCST_CONTEXT_* constants for details) */ -void scst_rx_data(struct scst_cmd *cmd, int status, int pref_context); +void scst_rx_data(struct scst_cmd *cmd, int status, + enum scst_exec_context pref_context); /* * Notifies SCST that the driver sent the response and the command * can be freed now. Don't forget to set the delivery status, if it * isn't success, using scst_set_delivery_status() before calling - * this function. + * this function. The third argument sets preferred command execition + * context (see SCST_CONTEXT_* constants for details) */ -void scst_tgt_cmd_done(struct scst_cmd *cmd); +void scst_tgt_cmd_done(struct scst_cmd *cmd, + enum scst_exec_context pref_context); /* * Creates new management command sends it for execution. @@ -2295,24 +2294,6 @@ static inline void scst_set_delivery_status(struct scst_cmd *cmd, cmd->delivery_status = delivery_status; } -/* - * Get/set/clear functions for cmd's long XMIT flag. - */ -static inline int scst_get_long_xmit(struct scst_cmd *cmd) -{ - return cmd->long_xmit; -} - -static inline void scst_set_long_xmit(struct scst_cmd *cmd) -{ - cmd->long_xmit = 1; -} - -static inline void scst_clear_long_xmit(struct scst_cmd *cmd) -{ - cmd->long_xmit = 0; -} - /* * Get/Set function for mgmt cmd's target private data */ @@ -2464,11 +2445,9 @@ void scst_resume_activity(void); /* * Main SCST commands processing routing. Must be used only by dev handlers. - * Argument context sets the execution context, only SCST_CONTEXT_DIRECT and - * SCST_CONTEXT_DIRECT_ATOMIC with optional SCST_CONTEXT_PROCESSABLE flag - * are allowed. + * Argument atomic is true if function called in atomic context. */ -void scst_process_active_cmd(struct scst_cmd *cmd, int context); +void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic); /* * Checks if command can be executed (reservations, etc.) or there are local diff --git a/scst/src/dev_handlers/scst_disk.c b/scst/src/dev_handlers/scst_disk.c index 4fd907683..e7c5fd662 100644 --- a/scst/src/dev_handlers/scst_disk.c +++ b/scst/src/dev_handlers/scst_disk.c @@ -374,7 +374,7 @@ out: out_done: res = SCST_EXEC_COMPLETED; - cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); goto out; } diff --git a/scst/src/dev_handlers/scst_modisk.c b/scst/src/dev_handlers/scst_modisk.c index 0d8439e82..0a24cdc7a 100644 --- a/scst/src/dev_handlers/scst_modisk.c +++ b/scst/src/dev_handlers/scst_modisk.c @@ -396,7 +396,7 @@ out: out_done: res = SCST_EXEC_COMPLETED; - cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); goto out; } diff --git a/scst/src/dev_handlers/scst_tape.c b/scst/src/dev_handlers/scst_tape.c index 0422e5d0c..0430c906b 100644 --- a/scst/src/dev_handlers/scst_tape.c +++ b/scst/src/dev_handlers/scst_tape.c @@ -420,7 +420,7 @@ out: out_done: res = SCST_EXEC_COMPLETED; - cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); goto out; } diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index e1c9daacf..a2b2d6798 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -1148,7 +1148,7 @@ static int dev_user_process_reply_alloc(struct scst_user_cmd *ucmd, } out_process: - scst_process_active_cmd(cmd, SCST_CONTEXT_DIRECT); + scst_process_active_cmd(cmd, false); TRACE_EXIT_RES(res); return res; @@ -1196,7 +1196,7 @@ static int dev_user_process_reply_parse(struct scst_user_cmd *ucmd, cmd->data_len = preply->data_len; out_process: - scst_process_active_cmd(cmd, SCST_CONTEXT_DIRECT); + scst_process_active_cmd(cmd, false); TRACE_EXIT_RES(res); return res; @@ -1326,7 +1326,7 @@ static int dev_user_process_reply_exec(struct scst_user_cmd *ucmd, out_compl: cmd->completed = 1; - cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_DIRECT); /* !! At this point cmd can be already freed !! */ out: @@ -1520,8 +1520,7 @@ static int dev_user_process_scst_commands(struct scst_user_dev *dev) TRACE_DBG("Deleting cmd %p from active cmd list", cmd); list_del(&cmd->cmd_list_entry); spin_unlock_irq(&dev->cmd_lists.cmd_list_lock); - scst_process_active_cmd(cmd, SCST_CONTEXT_DIRECT | - SCST_CONTEXT_PROCESSABLE); + scst_process_active_cmd(cmd, false); spin_lock_irq(&dev->cmd_lists.cmd_list_lock); res++; } @@ -1558,7 +1557,8 @@ again: rc = scst_check_local_events(u->cmd); if (unlikely(rc != 0)) { u->cmd->scst_cmd_done(u->cmd, - SCST_CMD_STATE_DEFAULT); + SCST_CMD_STATE_DEFAULT, + SCST_CONTEXT_DIRECT); /* * !! At this point cmd & u can be !! * !! already freed !! @@ -1884,7 +1884,7 @@ static void dev_user_unjam_cmd(struct scst_user_cmd *ucmd, int busy, TRACE_MGMT_DBG("EXEC: unjamming ucmd %p", ucmd); - if (test_bit(SCST_CMD_ABORTED, &ucmd->cmd->cmd_flags)) + if (test_bit(SCST_CMD_ABORTED, &ucmd->cmd->cmd_flags)) ucmd->aborted = 1; else { if (busy) @@ -1894,7 +1894,8 @@ static void dev_user_unjam_cmd(struct scst_user_cmd *ucmd, int busy, SCST_LOAD_SENSE(scst_sense_hardw_error)); } - ucmd->cmd->scst_cmd_done(ucmd->cmd, SCST_CMD_STATE_DEFAULT); + ucmd->cmd->scst_cmd_done(ucmd->cmd, SCST_CMD_STATE_DEFAULT, + SCST_CONTEXT_DIRECT); /* !! At this point cmd and ucmd can be already freed !! */ if (flags != NULL) diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index 471a4c3e0..3ecb03e4b 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -931,7 +931,8 @@ static int vdisk_do_job(struct scst_cmd *cmd) if (immed) { scst_cmd_get(cmd); cmd->completed = 1; - cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, + SCST_CONTEXT_SAME); vdisk_fsync(thr, loff, data_len, NULL); /* ToDo: vdisk_fsync() error processing */ scst_cmd_put(cmd); @@ -1000,7 +1001,7 @@ out_compl: cmd->completed = 1; out_done: - cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); out_thr: if (likely(thr != NULL)) @@ -1104,7 +1105,7 @@ out: return res; out_done: - cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); goto out; } @@ -2282,9 +2283,10 @@ static inline void blockio_check_finish(struct blockio_work *blockio_work) if (atomic_dec_and_test(&blockio_work->bios_inflight)) { blockio_work->cmd->completed = 1; blockio_work->cmd->scst_cmd_done(blockio_work->cmd, - SCST_CMD_STATE_DEFAULT); + SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_DIRECT_ATOMIC); kfree(blockio_work); } + return; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 9ede83570..20eb0979a 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -2480,7 +2480,6 @@ int scst_obtain_device_parameters(struct scst_device *dev) TRACE_ENTRY(); - sBUG_ON(in_interrupt() || in_atomic()); EXTRACHECKS_BUG_ON(dev->scsi_dev == NULL); for (i = 0; i < 5; i++) { diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index 21f82619d..391ced37b 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -125,22 +125,6 @@ extern unsigned long scst_trace_flag; #define SCST_TGT_RETRY_TIMEOUT (3/2*HZ) -static inline int scst_get_context(void) -{ - if (in_irq()) - return SCST_CONTEXT_TASKLET; - if (irqs_disabled()) - return SCST_CONTEXT_THREAD; - if (in_softirq() || in_atomic()) - return SCST_CONTEXT_DIRECT_ATOMIC; - return SCST_CONTEXT_DIRECT; -} - -static inline bool scst_is_context_gfp_atomic(void) -{ - return irqs_disabled() || in_atomic() || in_interrupt(); -} - extern unsigned int scst_max_cmd_mem; extern unsigned int scst_max_dev_cmd_mem; @@ -246,10 +230,7 @@ static inline void scst_make_deferred_commands_active( spin_lock_irq(&c->cmd_lists->cmd_list_lock); list_add_tail(&c->cmd_list_entry, &c->cmd_lists->active_cmd_list); -#if 0 /* temp. ToDo */ - if (!curr_cmd->context_processable || curr_cmd->long_xmit) -#endif - wake_up(&c->cmd_lists->cmd_list_waitQ); + wake_up(&c->cmd_lists->cmd_list_waitQ); spin_unlock_irq(&c->cmd_lists->cmd_list_lock); } @@ -316,8 +297,8 @@ static inline void scst_destroy_cmd(struct scst_cmd *cmd) return; } -void scst_proccess_redirect_cmd(struct scst_cmd *cmd, int context, - int check_retries); +void scst_proccess_redirect_cmd(struct scst_cmd *cmd, + enum scst_exec_context context, int check_retries); void scst_check_retries(struct scst_tgt *tgt); void scst_tgt_retry_timer_fn(unsigned long arg); diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 48740d9b1..9afbbbf9c 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -99,9 +99,13 @@ out: } EXPORT_SYMBOL(scst_rx_cmd); -static int scst_init_cmd(struct scst_cmd *cmd, int context) +/* + * No locks, but might be on IRQ. Returns 0 on success, <0 if processing of + * this command should be stopped. + */ +static int scst_init_cmd(struct scst_cmd *cmd, enum scst_exec_context *context) { - int rc; + int rc, res = 0; TRACE_ENTRY(); @@ -122,23 +126,24 @@ static int scst_init_cmd(struct scst_cmd *cmd, int context) goto out; /* Small context optimization */ - if (((context == SCST_CONTEXT_TASKLET) || - (context == SCST_CONTEXT_DIRECT_ATOMIC)) && - scst_cmd_is_expected_set(cmd)) { + if (((*context == SCST_CONTEXT_TASKLET) || + (*context == SCST_CONTEXT_DIRECT_ATOMIC) || + ((*context == SCST_CONTEXT_SAME) && scst_cmd_atomic(cmd))) && + scst_cmd_is_expected_set(cmd)) { if (cmd->expected_data_direction == SCST_DATA_WRITE) { if (!test_bit(SCST_TGT_DEV_AFTER_INIT_WR_ATOMIC, &cmd->tgt_dev->tgt_dev_flags)) - context = SCST_CONTEXT_THREAD; + *context = SCST_CONTEXT_THREAD; } else { if (!test_bit(SCST_TGT_DEV_AFTER_INIT_OTH_ATOMIC, &cmd->tgt_dev->tgt_dev_flags)) - context = SCST_CONTEXT_THREAD; + *context = SCST_CONTEXT_THREAD; } } out: - TRACE_EXIT_RES(context); - return context; + TRACE_EXIT_RES(res); + return res; out_redirect: if (cmd->preprocessing_only) { @@ -146,14 +151,11 @@ out_redirect: * Poor man solution for single threaded targets, where * blocking receiver at least sometimes means blocking all. */ - sBUG_ON(context != SCST_CONTEXT_DIRECT); + sBUG_ON(*context != SCST_CONTEXT_DIRECT); scst_set_busy(cmd); scst_set_cmd_abnormal_done_state(cmd); /* Keep initiator away from too many BUSY commands */ - if (!in_interrupt() && !in_atomic()) - msleep(50); - else - WARN_ON_ONCE(1); + msleep(50); } else { unsigned long flags; spin_lock_irqsave(&scst_init_lock, flags); @@ -164,7 +166,7 @@ out_redirect: scst_init_poll_cnt++; spin_unlock_irqrestore(&scst_init_lock, flags); wake_up(&scst_init_cmd_list_waitQ); - context = -1; + res = -1; } goto out; } @@ -176,10 +178,12 @@ static inline uint64_t scst_sec_to_nsec(time_t sec) } #endif -void scst_cmd_init_done(struct scst_cmd *cmd, int pref_context) +void scst_cmd_init_done(struct scst_cmd *cmd, + enum scst_exec_context pref_context) { unsigned long flags; struct scst_session *sess = cmd->sess; + int rc; TRACE_ENTRY(); @@ -276,8 +280,8 @@ void scst_cmd_init_done(struct scst_cmd *cmd, int pref_context) cmd->state = SCST_CMD_STATE_INIT; /* cmd must be inited here to preserve the order */ - pref_context = scst_init_cmd(cmd, pref_context); - if (unlikely(pref_context < 0)) + rc = scst_init_cmd(cmd, &pref_context); + if (unlikely(rc < 0)) goto out; active: @@ -288,8 +292,12 @@ active: break; case SCST_CONTEXT_DIRECT: + scst_process_active_cmd(cmd, false); + /* For *NEED_THREAD wake_up() is already done */ + break; + case SCST_CONTEXT_DIRECT_ATOMIC: - scst_process_active_cmd(cmd, pref_context); + scst_process_active_cmd(cmd, true); /* For *NEED_THREAD wake_up() is already done */ break; @@ -772,7 +780,8 @@ out_error: goto out; } -void scst_restart_cmd(struct scst_cmd *cmd, int status, int pref_context) +void scst_restart_cmd(struct scst_cmd *cmd, int status, + enum scst_exec_context pref_context) { TRACE_ENTRY(); @@ -805,7 +814,9 @@ void scst_restart_cmd(struct scst_cmd *cmd, int status, int pref_context) scst_cmd_set_sn(cmd); /* Small context optimization */ if ((pref_context == SCST_CONTEXT_TASKLET) || - (pref_context == SCST_CONTEXT_DIRECT_ATOMIC)) { + (pref_context == SCST_CONTEXT_DIRECT_ATOMIC) || + ((pref_context == SCST_CONTEXT_SAME) && + scst_cmd_atomic(cmd))) { if (cmd->data_direction == SCST_DATA_WRITE) { if (!test_bit(SCST_TGT_DEV_AFTER_RESTART_WR_ATOMIC, &cmd->tgt_dev->tgt_dev_flags)) @@ -976,8 +987,8 @@ out_dev_done: } /* No locks, but might be in IRQ */ -void scst_proccess_redirect_cmd(struct scst_cmd *cmd, int context, - int check_retries) +void scst_proccess_redirect_cmd(struct scst_cmd *cmd, + enum scst_exec_context context, int check_retries) { unsigned long flags; @@ -985,14 +996,19 @@ void scst_proccess_redirect_cmd(struct scst_cmd *cmd, int context, TRACE_DBG("Context: %x", context); - switch (context & ~SCST_CONTEXT_PROCESSABLE) { + if (context == SCST_CONTEXT_SAME) + context = scst_cmd_atomic(cmd) ? SCST_CONTEXT_DIRECT_ATOMIC : + SCST_CONTEXT_DIRECT; + + switch (context) { case SCST_CONTEXT_DIRECT_ATOMIC: - context &= ~SCST_CONTEXT_PROCESSABLE; - /* go through */ + scst_process_active_cmd(cmd, true); + break; + case SCST_CONTEXT_DIRECT: if (check_retries) scst_check_retries(cmd->tgt); - scst_process_active_cmd(cmd, context); + scst_process_active_cmd(cmd, false); break; default: @@ -1025,7 +1041,8 @@ void scst_proccess_redirect_cmd(struct scst_cmd *cmd, int context, return; } -void scst_rx_data(struct scst_cmd *cmd, int status, int pref_context) +void scst_rx_data(struct scst_cmd *cmd, int status, + enum scst_exec_context pref_context) { TRACE_ENTRY(); @@ -1049,7 +1066,9 @@ void scst_rx_data(struct scst_cmd *cmd, int status, int pref_context) cmd->state = SCST_CMD_STATE_TGT_PRE_EXEC; /* Small context optimization */ if ((pref_context == SCST_CONTEXT_TASKLET) || - (pref_context == SCST_CONTEXT_DIRECT_ATOMIC)) { + (pref_context == SCST_CONTEXT_DIRECT_ATOMIC) || + ((pref_context == SCST_CONTEXT_SAME) && + scst_cmd_atomic(cmd))) { if (!test_bit(SCST_TGT_DEV_AFTER_RX_DATA_ATOMIC, &cmd->tgt_dev->tgt_dev_flags)) pref_context = SCST_CONTEXT_THREAD; @@ -1165,8 +1184,7 @@ static void scst_do_cmd_done(struct scst_cmd *cmd, int result, cmd->dbl_ua_orig_resp_data_len = cmd->resp_data_len; cmd->dbl_ua_orig_data_direction = cmd->data_direction; - scst_alloc_set_sense(cmd, scst_is_context_gfp_atomic(), - rq_sense, rq_sense_len); + scst_alloc_set_sense(cmd, 1, rq_sense, rq_sense_len); } TRACE(TRACE_SCSI, "cmd%p, result=%x, cmd->status=%x, resid=%d, " @@ -1181,10 +1199,11 @@ static void scst_do_cmd_done(struct scst_cmd *cmd, int result, } /* For small context optimization */ -static inline int scst_optimize_post_exec_context(struct scst_cmd *cmd, - int context) +static inline enum scst_exec_context scst_optimize_post_exec_context( + struct scst_cmd *cmd, enum scst_exec_context context) { - if ((context == SCST_CONTEXT_TASKLET) || + if (((context == SCST_CONTEXT_SAME) && scst_cmd_atomic(cmd)) || + (context == SCST_CONTEXT_TASKLET) || (context == SCST_CONTEXT_DIRECT_ATOMIC)) { if (!test_bit(SCST_TGT_DEV_AFTER_EXEC_ATOMIC, &cmd->tgt_dev->tgt_dev_flags)) @@ -1215,6 +1234,7 @@ static void scst_cmd_done(struct scsi_cmnd *scsi_cmd) { struct scsi_request *req = NULL; struct scst_cmd *cmd; + enum scst_exec_context context; TRACE_ENTRY(); @@ -1237,8 +1257,15 @@ static void scst_cmd_done(struct scsi_cmnd *scsi_cmd) cmd->state = SCST_CMD_STATE_PRE_DEV_DONE; + if (in_irq()) + context = SCST_CONTEXT_TASKLET; + else if (irqs_disabled()) + context = SCST_CONTEXT_THREAD; + else + context = SCST_CONTEXT_DIRECT_ATOMIC; + scst_proccess_redirect_cmd(cmd, - scst_optimize_post_exec_context(cmd, scst_get_context()), 0); + scst_optimize_post_exec_context(cmd, context), 0); out: TRACE_EXIT(); @@ -1248,6 +1275,7 @@ out: static void scst_cmd_done(void *data, char *sense, int result, int resid) { struct scst_cmd *cmd; + enum scst_exec_context context; TRACE_ENTRY(); @@ -1259,8 +1287,15 @@ static void scst_cmd_done(void *data, char *sense, int result, int resid) cmd->state = SCST_CMD_STATE_PRE_DEV_DONE; + if (in_irq()) + context = SCST_CONTEXT_TASKLET; + else if (irqs_disabled()) + context = SCST_CONTEXT_THREAD; + else + context = SCST_CONTEXT_DIRECT_ATOMIC; + scst_proccess_redirect_cmd(cmd, - scst_optimize_post_exec_context(cmd, scst_get_context()), 0); + scst_optimize_post_exec_context(cmd, context), 0); out: TRACE_EXIT(); @@ -1268,10 +1303,9 @@ out: } #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) */ -static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state) +static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state, + enum scst_exec_context pref_context) { - int context; - TRACE_ENTRY(); #ifdef CONFIG_SCST_MEASURE_LATENCY @@ -1317,10 +1351,8 @@ static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state) scst_set_cmd_abnormal_done_state(cmd); } #endif - context = scst_optimize_post_exec_context(cmd, scst_get_context()); - if (cmd->context_processable) - context |= SCST_CONTEXT_PROCESSABLE; - scst_proccess_redirect_cmd(cmd, context, 0); + pref_context = scst_optimize_post_exec_context(cmd, pref_context); + scst_proccess_redirect_cmd(cmd, pref_context, 0); TRACE_EXIT(); return; @@ -1427,7 +1459,7 @@ out_compl: out_done: /* Report the result */ - cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); TRACE_EXIT(); return SCST_EXEC_COMPLETED; @@ -1520,7 +1552,7 @@ out: out_done: /* Report the result */ - cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); res = SCST_EXEC_COMPLETED; goto out; } @@ -1583,7 +1615,7 @@ out: out_done: res = SCST_EXEC_COMPLETED; /* Report the result */ - cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); goto out; } @@ -1764,9 +1796,6 @@ static int scst_do_real_exec(struct scst_cmd *cmd) cmd->state = SCST_CMD_STATE_REAL_EXECUTING; - if (!handler->exec_sync) - cmd->context_processable = 0; - if (handler->exec) { if (unlikely(!dev->handler->exec_atomic && scst_cmd_atomic(cmd))) { @@ -1876,7 +1905,7 @@ out_busy: out_done: res = SCST_EXEC_COMPLETED; /* Report the result */ - cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); goto out_complete; } @@ -1966,7 +1995,7 @@ out: out_done: /* Report the result */ - cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); res = SCST_EXEC_COMPLETED; goto out; } @@ -2794,14 +2823,15 @@ out_error: goto out; } -void scst_tgt_cmd_done(struct scst_cmd *cmd) +void scst_tgt_cmd_done(struct scst_cmd *cmd, + enum scst_exec_context pref_context) { TRACE_ENTRY(); sBUG_ON(cmd->state != SCST_CMD_STATE_XMIT_WAIT); cmd->state = SCST_CMD_STATE_FINISHED; - scst_proccess_redirect_cmd(cmd, scst_get_context(), 1); + scst_proccess_redirect_cmd(cmd, pref_context, 1); TRACE_EXIT(); return; @@ -3238,7 +3268,7 @@ int scst_init_cmd_thread(void *arg) } /* Called with no locks held */ -void scst_process_active_cmd(struct scst_cmd *cmd, int context) +void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic) { int res; @@ -3246,12 +3276,9 @@ void scst_process_active_cmd(struct scst_cmd *cmd, int context) EXTRACHECKS_BUG_ON(in_irq()); - cmd->context_processable = context | SCST_CONTEXT_PROCESSABLE; - context &= ~SCST_CONTEXT_PROCESSABLE; - cmd->atomic = (context == SCST_CONTEXT_DIRECT_ATOMIC); + cmd->atomic = atomic; - TRACE_DBG("cmd %p, context_processable %d, atomic %d", cmd, - cmd->context_processable, cmd->atomic); + TRACE_DBG("cmd %p, atomic %d", cmd, atomic); do { switch (cmd->state) { @@ -3397,25 +3424,17 @@ EXPORT_SYMBOL(scst_process_active_cmd); /* Called under cmd_list_lock and IRQs disabled */ static void scst_do_job_active(struct list_head *cmd_list, - spinlock_t *cmd_list_lock, int context) + spinlock_t *cmd_list_lock, bool atomic) { TRACE_ENTRY(); -#ifdef CONFIG_SCST_EXTRACHECKS - { - int c = context & ~SCST_CONTEXT_PROCESSABLE; - sBUG_ON((c != SCST_CONTEXT_DIRECT_ATOMIC) && - (c != SCST_CONTEXT_DIRECT)); - } -#endif - while (!list_empty(cmd_list)) { struct scst_cmd *cmd = list_entry(cmd_list->next, typeof(*cmd), cmd_list_entry); TRACE_DBG("Deleting cmd %p from active cmd list", cmd); list_del(&cmd->cmd_list_entry); spin_unlock_irq(cmd_list_lock); - scst_process_active_cmd(cmd, context); + scst_process_active_cmd(cmd, atomic); spin_lock_irq(cmd_list_lock); } @@ -3471,8 +3490,7 @@ int scst_cmd_thread(void *arg) } scst_do_job_active(&p_cmd_lists->active_cmd_list, - &p_cmd_lists->cmd_list_lock, SCST_CONTEXT_DIRECT | - SCST_CONTEXT_PROCESSABLE); + &p_cmd_lists->cmd_list_lock, false); } spin_unlock_irq(&p_cmd_lists->cmd_list_lock); @@ -3501,8 +3519,7 @@ void scst_cmd_tasklet(long p) TRACE_ENTRY(); spin_lock_irq(&t->tasklet_lock); - scst_do_job_active(&t->tasklet_cmd_list, &t->tasklet_lock, - SCST_CONTEXT_DIRECT_ATOMIC); + scst_do_job_active(&t->tasklet_cmd_list, &t->tasklet_lock, true); spin_unlock_irq(&t->tasklet_lock); TRACE_EXIT(); diff --git a/scst_local/scst_local.c b/scst_local/scst_local.c index d7ab5f8a1..af0e8acee 100644 --- a/scst_local/scst_local.c +++ b/scst_local/scst_local.c @@ -928,7 +928,7 @@ static int scst_local_targ_xmit_response(struct scst_cmd *scst_cmd) if (unlikely(scst_cmd_aborted(scst_cmd))) { scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_ABORTED); - scst_tgt_cmd_done(scst_cmd); + scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_SAME); printk(KERN_INFO "%s aborted command handled\n", __func__); return SCST_TGT_RES_SUCCESS; } @@ -947,7 +947,7 @@ static int scst_local_targ_xmit_response(struct scst_cmd *scst_cmd) /* * Now tell SCST that the command is done ... */ - scst_tgt_cmd_done(scst_cmd); + scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_SAME); TRACE_EXIT(); diff --git a/srpt/src/ib_srpt.c b/srpt/src/ib_srpt.c index f534179d0..998fef447 100644 --- a/srpt/src/ib_srpt.c +++ b/srpt/src/ib_srpt.c @@ -654,7 +654,8 @@ static void srpt_handle_err_comp(struct srpt_rdma_ch *ch, struct ib_wc *wc) dir = scst_cmd_get_data_direction(scmnd); if (dir == SCST_DATA_NONE) - scst_tgt_cmd_done(scmnd); + scst_tgt_cmd_done(scmnd, + SCST_CONTEXT_DIRECT_ATOMIC); else { dma_unmap_sg(sdev->device->dma_device, scst_cmd_get_sg(scmnd), @@ -674,7 +675,8 @@ static void srpt_handle_err_comp(struct srpt_rdma_ch *ch, struct ib_wc *wc) SCST_CONTEXT_THREAD); else if (scmnd->state == SCST_CMD_STATE_XMIT_WAIT) - scst_tgt_cmd_done(scmnd); + scst_tgt_cmd_done(scmnd, + SCST_CONTEXT_DIRECT_ATOMIC); } } else srpt_reset_ioctx(ch, ioctx); @@ -683,7 +685,8 @@ static void srpt_handle_err_comp(struct srpt_rdma_ch *ch, struct ib_wc *wc) } static void srpt_handle_send_comp(struct srpt_rdma_ch *ch, - struct srpt_ioctx *ioctx) + struct srpt_ioctx *ioctx, + enum scst_exec_context context) { if (ioctx->scmnd) { scst_data_direction dir = @@ -702,7 +705,7 @@ static void srpt_handle_send_comp(struct srpt_rdma_ch *ch, ioctx->scmnd->sg_cnt = 0; } - scst_tgt_cmd_done(ioctx->scmnd); + scst_tgt_cmd_done(ioctx->scmnd, context); } else srpt_reset_ioctx(ch, ioctx); } @@ -1041,7 +1044,8 @@ static void srpt_completion(struct ib_cq *cq, void *ctx) } else { switch (wc.opcode) { case IB_WC_SEND: - srpt_handle_send_comp(ch, ioctx); + srpt_handle_send_comp(ch, ioctx, + SCST_CONTEXT_DIRECT_ATOMIC); break; case IB_WC_RDMA_WRITE: case IB_WC_RDMA_READ: @@ -1833,11 +1837,8 @@ static int srpt_xmit_response(struct scst_cmd *scmnd) else if (ch->state == RDMA_CHANNEL_CONNECTING) ret = SCST_TGT_RES_QUEUE_FULL; - if (unlikely(scst_cmd_aborted(scmnd))) { - scst_set_delivery_status(scmnd, - SCST_CMD_DELIVERY_ABORTED); - ret = SCST_TGT_RES_SUCCESS; - } + if (unlikely(scst_cmd_aborted(scmnd))) + goto out_aborted; goto out; } @@ -1851,10 +1852,7 @@ static int srpt_xmit_response(struct scst_cmd *scmnd) printk(KERN_ERR PFX "%s: tag= %lld already get aborted\n", __func__, (unsigned long long)tag); - scst_set_delivery_status(ioctx->scmnd, - SCST_CMD_DELIVERY_ABORTED); - scst_tgt_cmd_done(ioctx->scmnd); - goto out; + goto out_aborted; } dir = scst_cmd_get_data_direction(scmnd); @@ -1903,6 +1901,12 @@ static int srpt_xmit_response(struct scst_cmd *scmnd) out: return ret; + +out_aborted: + ret = SCST_TGT_RES_SUCCESS; + scst_set_delivery_status(scmnd, SCST_CMD_DELIVERY_ABORTED); + scst_tgt_cmd_done(scmnd, SCST_CONTEXT_SAME); + goto out; } static void srpt_tsk_mgmt_done(struct scst_mgmt_cmd *mcmnd) @@ -2070,7 +2074,8 @@ static int srpt_ioctx_thread(void *arg) spin_unlock_irq(&srpt_thread.thread_lock); switch (ioctx->op) { case IB_WC_SEND: - srpt_handle_send_comp(ioctx->ch, ioctx); + srpt_handle_send_comp(ioctx->ch, ioctx, + SCST_CONTEXT_DIRECT); break; case IB_WC_RDMA_WRITE: case IB_WC_RDMA_READ: