Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: qedf: Wait for stag work during unload

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>

authored by

Saurav Kashyap and committed by
Martin K. Petersen
78e88472 51071f08

+28 -3
+1
drivers/scsi/qedf/qedf.h
··· 363 363 #define QEDF_IN_RECOVERY 5 364 364 #define QEDF_DBG_STOP_IO 6 365 365 #define QEDF_PROBING 8 366 + #define QEDF_STAG_IN_PROGRESS 9 366 367 unsigned long flags; /* Miscellaneous state flags */ 367 368 int fipvlan_retries; 368 369 u8 num_queues;
+27 -3
drivers/scsi/qedf/qedf_main.c
··· 318 318 */ 319 319 if (resp == fc_lport_flogi_resp) { 320 320 qedf->flogi_cnt++; 321 + qedf->flogi_pending++; 322 + 323 + if (test_bit(QEDF_UNLOADING, &qedf->flags)) { 324 + QEDF_ERR(&qedf->dbg_ctx, "Driver unloading\n"); 325 + qedf->flogi_pending = 0; 326 + } 327 + 321 328 if (qedf->flogi_pending >= QEDF_FLOGI_RETRY_CNT) { 322 329 schedule_delayed_work(&qedf->stag_work, 2); 323 330 return NULL; 324 331 } 325 - qedf->flogi_pending++; 332 + 326 333 return fc_elsct_send(lport, did, fp, op, qedf_flogi_resp, 327 334 arg, timeout); 328 335 } ··· 919 912 struct qedf_ctx *qedf; 920 913 struct qed_link_output if_link; 921 914 915 + qedf = lport_priv(lport); 916 + 922 917 if (lport->vport) { 918 + clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags); 923 919 printk_ratelimited("Cannot issue host reset on NPIV port.\n"); 924 920 return; 925 921 } 926 - 927 - qedf = lport_priv(lport); 928 922 929 923 qedf->flogi_pending = 0; 930 924 /* For host reset, essentially do a soft link up/down */ ··· 946 938 if (!if_link.link_up) { 947 939 QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC, 948 940 "Physical link is not up.\n"); 941 + clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags); 949 942 return; 950 943 } 951 944 /* Flush and wait to make sure link down is processed */ ··· 959 950 "Queue link up work.\n"); 960 951 queue_delayed_work(qedf->link_update_wq, &qedf->link_update, 961 952 0); 953 + clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags); 962 954 } 963 955 964 956 /* Reset the host by gracefully logging out and then logging back in */ ··· 3731 3721 { 3732 3722 struct qedf_ctx *qedf; 3733 3723 int rc; 3724 + int cnt = 0; 3734 3725 3735 3726 if (!pdev) { 3736 3727 QEDF_ERR(NULL, "pdev is NULL.\n"); ··· 3747 3736 if (test_bit(QEDF_UNLOADING, &qedf->flags)) { 3748 3737 QEDF_ERR(&qedf->dbg_ctx, "Already removing PCI function.\n"); 3749 3738 return; 3739 + } 3740 + 3741 + stag_in_prog: 3742 + if (test_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags)) { 3743 + QEDF_ERR(&qedf->dbg_ctx, "Stag in progress, cnt=%d.\n", cnt); 3744 + cnt++; 3745 + 3746 + if (cnt < 5) { 3747 + msleep(500); 3748 + goto stag_in_prog; 3749 + } 3750 3750 } 3751 3751 3752 3752 if (mode != QEDF_MODE_RECOVERY) ··· 4034 4012 QEDF_ERR(&qedf->dbg_ctx, "Driver unloading\n"); 4035 4013 return; 4036 4014 } 4015 + 4016 + set_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags); 4037 4017 4038 4018 printk_ratelimited("[%s]:[%s:%d]:%d: Performing software context reset.", 4039 4019 dev_name(&qedf->pdev->dev), __func__, __LINE__,