summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSaurav Kashyap <skashyap@marvell.com>2022-02-08 01:39:46 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-04-08 13:58:59 +0200
commita6c5d48769592f47d0aaf6ff2c1a289c130736aa (patch)
treef99f86dd62e1285cd2f5a92cf86f84c5f420b947
parent66db8488b9b9e5454a9519dc5a546b83360c82ea (diff)
downloadlinux-rt-a6c5d48769592f47d0aaf6ff2c1a289c130736aa.tar.gz
scsi: qla2xxx: Add qla2x00_async_done() for async routines
commit 49b729f58e7a98a006a8a0c1dcca8a1a4f58d2a8 upstream. This done routine will delete the timer and check for its return value and decrease the reference count accordingly. This prevents boot hangs reported after commit 31e6cdbe0eae ("scsi: qla2xxx: Implement ref count for SRB") was merged. Link: https://lore.kernel.org/r/20220208093946.4471-1-njavali@marvell.com Fixes: 31e6cdbe0eae ("scsi: qla2xxx: Implement ref count for SRB") Reported-by: Ewan Milne <emilne@redhat.com> Tested-by: Ewan D. Milne <emilne@redhat.com> Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> Signed-off-by: Saurav Kashyap <skashyap@marvell.com> Signed-off-by: Nilesh Javali <njavali@marvell.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 85cccc7b9f83..e0fe9ddb4bd2 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -2560,6 +2560,20 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
}
}
+static void
+qla2x00_async_done(struct srb *sp, int res)
+{
+ if (del_timer(&sp->u.iocb_cmd.timer)) {
+ /*
+ * Successfully cancelled the timeout handler
+ * ref: TMR
+ */
+ if (kref_put(&sp->cmd_kref, qla2x00_sp_release))
+ return;
+ }
+ sp->async_done(sp, res);
+}
+
void
qla2x00_sp_release(struct kref *kref)
{
@@ -2573,7 +2587,8 @@ qla2x00_init_async_sp(srb_t *sp, unsigned long tmo,
void (*done)(struct srb *sp, int res))
{
timer_setup(&sp->u.iocb_cmd.timer, qla2x00_sp_timeout, 0);
- sp->done = done;
+ sp->done = qla2x00_async_done;
+ sp->async_done = done;
sp->free = qla2x00_sp_free;
sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ;