Skip to content

Commit

Permalink
scsi: qedf: Wait for stag work during unload
Browse files Browse the repository at this point in the history
If stag work is already scheduled and unload is called, it can lead to
issues as unload cleans up the work element. Wait for stag work to get
completed before cleanup during unload.

Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://lore.kernel.org/r/20240515091101.18754-3-skashyap@marvell.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
  • Loading branch information
Saurav Kashyap authored and Martin K. Petersen committed May 15, 2024
1 parent 51071f0 commit 78e8847
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 3 deletions.
1 change: 1 addition & 0 deletions drivers/scsi/qedf/qedf.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ struct qedf_ctx {
#define QEDF_IN_RECOVERY 5
#define QEDF_DBG_STOP_IO 6
#define QEDF_PROBING 8
#define QEDF_STAG_IN_PROGRESS 9
unsigned long flags; /* Miscellaneous state flags */
int fipvlan_retries;
u8 num_queues;
Expand Down
30 changes: 27 additions & 3 deletions drivers/scsi/qedf/qedf_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,11 +318,18 @@ static struct fc_seq *qedf_elsct_send(struct fc_lport *lport, u32 did,
*/
if (resp == fc_lport_flogi_resp) {
qedf->flogi_cnt++;
qedf->flogi_pending++;

if (test_bit(QEDF_UNLOADING, &qedf->flags)) {
QEDF_ERR(&qedf->dbg_ctx, "Driver unloading\n");
qedf->flogi_pending = 0;
}

if (qedf->flogi_pending >= QEDF_FLOGI_RETRY_CNT) {
schedule_delayed_work(&qedf->stag_work, 2);
return NULL;
}
qedf->flogi_pending++;

return fc_elsct_send(lport, did, fp, op, qedf_flogi_resp,
arg, timeout);
}
Expand Down Expand Up @@ -912,13 +919,14 @@ void qedf_ctx_soft_reset(struct fc_lport *lport)
struct qedf_ctx *qedf;
struct qed_link_output if_link;

qedf = lport_priv(lport);

if (lport->vport) {
clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags);
printk_ratelimited("Cannot issue host reset on NPIV port.\n");
return;
}

qedf = lport_priv(lport);

qedf->flogi_pending = 0;
/* For host reset, essentially do a soft link up/down */
atomic_set(&qedf->link_state, QEDF_LINK_DOWN);
Expand All @@ -938,6 +946,7 @@ void qedf_ctx_soft_reset(struct fc_lport *lport)
if (!if_link.link_up) {
QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC,
"Physical link is not up.\n");
clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags);
return;
}
/* Flush and wait to make sure link down is processed */
Expand All @@ -950,6 +959,7 @@ void qedf_ctx_soft_reset(struct fc_lport *lport)
"Queue link up work.\n");
queue_delayed_work(qedf->link_update_wq, &qedf->link_update,
0);
clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags);
}

/* Reset the host by gracefully logging out and then logging back in */
Expand Down Expand Up @@ -3721,6 +3731,7 @@ static void __qedf_remove(struct pci_dev *pdev, int mode)
{
struct qedf_ctx *qedf;
int rc;
int cnt = 0;

if (!pdev) {
QEDF_ERR(NULL, "pdev is NULL.\n");
Expand All @@ -3738,6 +3749,17 @@ static void __qedf_remove(struct pci_dev *pdev, int mode)
return;
}

stag_in_prog:
if (test_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags)) {
QEDF_ERR(&qedf->dbg_ctx, "Stag in progress, cnt=%d.\n", cnt);
cnt++;

if (cnt < 5) {
msleep(500);
goto stag_in_prog;
}
}

if (mode != QEDF_MODE_RECOVERY)
set_bit(QEDF_UNLOADING, &qedf->flags);

Expand Down Expand Up @@ -4013,6 +4035,8 @@ void qedf_stag_change_work(struct work_struct *work)
return;
}

set_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags);

printk_ratelimited("[%s]:[%s:%d]:%d: Performing software context reset.",
dev_name(&qedf->pdev->dev), __func__, __LINE__,
qedf->dbg_ctx.host_no);
Expand Down

0 comments on commit 78e8847

Please sign in to comment.