mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-22 05:01:27 +00:00
qla2x00t-32gbit: target: Add on_abort_cmd callback
This enables the initiator to abort commands that are stuck pending in the HW without waiting for a timeout. Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
This commit is contained in:
committed by
Gleb Chesnokov
parent
f4b52771b6
commit
64918c69a2
@@ -83,6 +83,7 @@ static int sqa_xmit_response(struct scst_cmd *scst_cmd);
|
||||
static int sqa_rdy_to_xfer(struct scst_cmd *scst_cmd);
|
||||
static void sqa_on_free_cmd(struct scst_cmd *scst_cmd);
|
||||
static void sqa_task_mgmt_fn_done(struct scst_mgmt_cmd *mcmd);
|
||||
static void sqa_on_abort_cmd(struct scst_cmd *scst_cmd);
|
||||
static int sqa_get_initiator_port_transport_id(struct scst_tgt *tgt,
|
||||
struct scst_session *scst_sess,
|
||||
uint8_t **transport_id);
|
||||
@@ -1273,6 +1274,7 @@ static struct scst_tgt_template sqa_scst_template = {
|
||||
|
||||
.on_free_cmd = sqa_on_free_cmd,
|
||||
.task_mgmt_fn_done = sqa_task_mgmt_fn_done,
|
||||
.on_abort_cmd = sqa_on_abort_cmd,
|
||||
.close_session = sqa_close_session,
|
||||
|
||||
.get_initiator_port_transport_id = sqa_get_initiator_port_transport_id,
|
||||
@@ -2034,6 +2036,46 @@ out_unlock:
|
||||
TRACE_EXIT();
|
||||
}
|
||||
|
||||
struct sqa_abort_work {
|
||||
struct scst_cmd *scst_cmd;
|
||||
struct work_struct abort_work;
|
||||
};
|
||||
|
||||
static void sqa_on_abort_cmd_work(struct work_struct *work)
|
||||
{
|
||||
struct sqa_abort_work *abort_work =
|
||||
container_of(work, struct sqa_abort_work, abort_work);
|
||||
struct scst_cmd *scst_cmd = abort_work->scst_cmd;
|
||||
struct qla_tgt_cmd *cmd = scst_cmd_get_tgt_priv(scst_cmd);
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
kfree(abort_work);
|
||||
qlt_abort_cmd(cmd);
|
||||
scst_cmd_put(scst_cmd);
|
||||
|
||||
TRACE_EXIT();
|
||||
}
|
||||
|
||||
static void sqa_on_abort_cmd(struct scst_cmd *scst_cmd)
|
||||
{
|
||||
struct sqa_abort_work *abort_work;
|
||||
|
||||
/*
|
||||
* The caller holds sess->sess_list_lock, but qlt_abort_cmd() needs to
|
||||
* acquire qpair->qp_lock_ptr (ha->hardware_lock); these locks are
|
||||
* acquired in the reverse order elsewhere. Use a workqueue to avoid
|
||||
* acquiring the locks in the wrong order here.
|
||||
*/
|
||||
abort_work = kmalloc(sizeof(*abort_work), GFP_ATOMIC);
|
||||
if (!abort_work)
|
||||
return;
|
||||
scst_cmd_get(scst_cmd);
|
||||
abort_work->scst_cmd = scst_cmd;
|
||||
INIT_WORK(&abort_work->abort_work, sqa_on_abort_cmd_work);
|
||||
schedule_work(&abort_work->abort_work);
|
||||
}
|
||||
|
||||
/*
|
||||
* The following structure defines the callbacks which will be executed
|
||||
* from functions in the qla_target.c file back to this interface
|
||||
|
||||
Reference in New Issue
Block a user