From 64918c69a29f8a199645a876596a325b4cc6b202 Mon Sep 17 00:00:00 2001 From: Tony Battersby Date: Tue, 14 Oct 2025 12:26:06 +0300 Subject: [PATCH] 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 --- qla2x00t-32gbit/qla2x00-target/scst_qla2xxx.c | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/qla2x00t-32gbit/qla2x00-target/scst_qla2xxx.c b/qla2x00t-32gbit/qla2x00-target/scst_qla2xxx.c index 1a7c472a8..3fca87ff0 100644 --- a/qla2x00t-32gbit/qla2x00-target/scst_qla2xxx.c +++ b/qla2x00t-32gbit/qla2x00-target/scst_qla2xxx.c @@ -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