diff mbox series

scsi: qedf: Add missing checks for create_workqueue

Message ID 20230208020646.36294-1-jiasheng@iscas.ac.cn (mailing list archive)
State Deferred
Headers show
Series scsi: qedf: Add missing checks for create_workqueue | expand

Commit Message

Jiasheng Jiang Feb. 8, 2023, 2:06 a.m. UTC
Add the checks for the return value of the create_workqueue in order to
avoid NULL pointer dereference.
Moreover, the allocated "qedf->link_update_wq" should be destroyed when
__qedf_probe fails later in order to avoid memory leak.

Fixes: 61d8658b4a43 ("scsi: qedf: Add QLogic FastLinQ offload FCoE driver framework.")
Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
---
 drivers/scsi/qedf/qedf_main.c | 56 ++++++++++++++++++++++-------------
 1 file changed, 35 insertions(+), 21 deletions(-)
diff mbox series

Patch

diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
index 35e16600fc63..ff90291530a7 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -3360,6 +3360,11 @@  static int __qedf_probe(struct pci_dev *pdev, int mode)
 	sprintf(host_buf, "qedf_%u_link",
 	    qedf->lport->host->host_no);
 	qedf->link_update_wq = create_workqueue(host_buf);
+	if (!qedf->link_update_wq) {
+		QEDF_ERR(&(qedf->dbg_ctx), "Failed to link workqueue.\n");
+		rc = -ENOMEM;
+		goto err1;
+	}
 	INIT_DELAYED_WORK(&qedf->link_update, qedf_handle_link_update);
 	INIT_DELAYED_WORK(&qedf->link_recovery, qedf_link_recovery);
 	INIT_DELAYED_WORK(&qedf->grcdump_work, qedf_wq_grcdump);
@@ -3394,14 +3399,14 @@  static int __qedf_probe(struct pci_dev *pdev, int mode)
 		}
 		QEDF_ERR(&qedf->dbg_ctx, "common probe failed.\n");
 		rc = -ENODEV;
-		goto err1;
+		goto err2;
 	}
 
 	/* Learn information crucial for qedf to progress */
 	rc = qed_ops->fill_dev_info(qedf->cdev, &qedf->dev_info);
 	if (rc) {
 		QEDF_ERR(&(qedf->dbg_ctx), "Failed to dev info.\n");
-		goto err1;
+		goto err2;
 	}
 
 	QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC,
@@ -3420,7 +3425,7 @@  static int __qedf_probe(struct pci_dev *pdev, int mode)
 	rc = qedf_set_fcoe_pf_param(qedf);
 	if (rc) {
 		QEDF_ERR(&(qedf->dbg_ctx), "Cannot set fcoe pf param.\n");
-		goto err2;
+		goto err3;
 	}
 	qed_ops->common->update_pf_params(qedf->cdev, &qedf->pf_params);
 
@@ -3428,7 +3433,7 @@  static int __qedf_probe(struct pci_dev *pdev, int mode)
 	rc = qed_ops->fill_dev_info(qedf->cdev, &qedf->dev_info);
 	if (rc) {
 		QEDF_ERR(&qedf->dbg_ctx, "Failed to fill dev info.\n");
-		goto err2;
+		goto err3;
 	}
 
 	if (mode != QEDF_MODE_RECOVERY) {
@@ -3437,7 +3442,7 @@  static int __qedf_probe(struct pci_dev *pdev, int mode)
 			QEDF_ERR(&qedf->dbg_ctx, "Cannot register devlink\n");
 			rc = PTR_ERR(qedf->devlink);
 			qedf->devlink = NULL;
-			goto err2;
+			goto err3;
 		}
 	}
 
@@ -3454,7 +3459,7 @@  static int __qedf_probe(struct pci_dev *pdev, int mode)
 	if (rc) {
 
 		QEDF_ERR(&(qedf->dbg_ctx), "Cannot start slowpath.\n");
-		goto err2;
+		goto err3;
 	}
 
 	/* Start the Slowpath-process */
@@ -3467,7 +3472,7 @@  static int __qedf_probe(struct pci_dev *pdev, int mode)
 	rc = qed_ops->common->slowpath_start(qedf->cdev, &slowpath_params);
 	if (rc) {
 		QEDF_ERR(&(qedf->dbg_ctx), "Cannot start slowpath.\n");
-		goto err2;
+		goto err3;
 	}
 
 	/*
@@ -3480,13 +3485,13 @@  static int __qedf_probe(struct pci_dev *pdev, int mode)
 	rc = qedf_setup_int(qedf);
 	if (rc) {
 		QEDF_ERR(&qedf->dbg_ctx, "Setup interrupts failed.\n");
-		goto err3;
+		goto err4;
 	}
 
 	rc = qed_ops->start(qedf->cdev, &qedf->tasks);
 	if (rc) {
 		QEDF_ERR(&(qedf->dbg_ctx), "Cannot start FCoE function.\n");
-		goto err4;
+		goto err5;
 	}
 	task_start = qedf_get_task_mem(&qedf->tasks, 0);
 	task_end = qedf_get_task_mem(&qedf->tasks, MAX_TID_BLOCKS_FCOE - 1);
@@ -3546,7 +3551,7 @@  static int __qedf_probe(struct pci_dev *pdev, int mode)
 	if (!qedf->cmd_mgr) {
 		QEDF_ERR(&(qedf->dbg_ctx), "Failed to allocate cmd mgr.\n");
 		rc = -ENOMEM;
-		goto err5;
+		goto err6;
 	}
 
 	if (mode != QEDF_MODE_RECOVERY) {
@@ -3559,7 +3564,7 @@  static int __qedf_probe(struct pci_dev *pdev, int mode)
 		if (rc) {
 			QEDF_WARN(&qedf->dbg_ctx,
 				  "Error adding Scsi_Host rc=0x%x.\n", rc);
-			goto err6;
+			goto err7;
 		}
 	}
 
@@ -3574,7 +3579,7 @@  static int __qedf_probe(struct pci_dev *pdev, int mode)
 	if (!qedf->ll2_recv_wq) {
 		QEDF_ERR(&(qedf->dbg_ctx), "Failed to LL2 workqueue.\n");
 		rc = -ENOMEM;
-		goto err7;
+		goto err8;
 	}
 
 #ifdef CONFIG_DEBUG_FS
@@ -3587,7 +3592,7 @@  static int __qedf_probe(struct pci_dev *pdev, int mode)
 	rc = qed_ops->ll2->start(qedf->cdev, &params);
 	if (rc) {
 		QEDF_ERR(&(qedf->dbg_ctx), "Could not start Light L2.\n");
-		goto err7;
+		goto err8;
 	}
 	set_bit(QEDF_LL2_STARTED, &qedf->flags);
 
@@ -3607,7 +3612,7 @@  static int __qedf_probe(struct pci_dev *pdev, int mode)
 		if (rc) {
 			QEDF_ERR(&(qedf->dbg_ctx),
 			    "qedf_lport_setup failed.\n");
-			goto err7;
+			goto err8;
 		}
 	}
 
@@ -3618,7 +3623,7 @@  static int __qedf_probe(struct pci_dev *pdev, int mode)
 		QEDF_ERR(&(qedf->dbg_ctx), "Failed to start timer "
 			  "workqueue.\n");
 		rc = -ENOMEM;
-		goto err7;
+		goto err8;
 	}
 
 	/* DPC workqueue is not reaped during recovery unload */
@@ -3626,6 +3631,11 @@  static int __qedf_probe(struct pci_dev *pdev, int mode)
 		sprintf(host_buf, "qedf_%u_dpc",
 		    qedf->lport->host->host_no);
 		qedf->dpc_wq = create_workqueue(host_buf);
+		if (!qedf->dpc_wq) {
+			QEDF_ERR(&(qedf->dbg_ctx), "Failed to dpc workqueue.\n");
+			rc = -ENOMEM;
+			goto err9;
+		}
 	}
 	INIT_DELAYED_WORK(&qedf->recovery_work, qedf_recovery_handler);
 
@@ -3682,7 +3692,9 @@  static int __qedf_probe(struct pci_dev *pdev, int mode)
 	/* All good */
 	return 0;
 
-err7:
+err9:
+	destroy_workqueue(qedf->timer_work_queue);
+err8:
 	if (qedf->ll2_recv_wq)
 		destroy_workqueue(qedf->ll2_recv_wq);
 	fc_remove_host(qedf->lport->host);
@@ -3690,17 +3702,19 @@  static int __qedf_probe(struct pci_dev *pdev, int mode)
 #ifdef CONFIG_DEBUG_FS
 	qedf_dbg_host_exit(&(qedf->dbg_ctx));
 #endif
-err6:
+err7:
 	qedf_cmd_mgr_free(qedf->cmd_mgr);
-err5:
+err6:
 	qed_ops->stop(qedf->cdev);
-err4:
+err5:
 	qedf_free_fcoe_pf_param(qedf);
 	qedf_sync_free_irqs(qedf);
-err3:
+err4:
 	qed_ops->common->slowpath_stop(qedf->cdev);
-err2:
+err3:
 	qed_ops->common->remove(qedf->cdev);
+err2:
+	destroy_workqueue(qedf->link_update_wq);
 err1:
 	scsi_host_put(lport->host);
 err0: