@@ -272,14 +272,14 @@ int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid,
esas2r_log(ESAS2R_LOG_CRIT,
"tried to init invalid adapter index %u!",
index);
- return 0;
+ goto error_exit;
}
if (esas2r_adapters[index]) {
esas2r_log(ESAS2R_LOG_CRIT,
"tried to init existing adapter index %u!",
index);
- return 0;
+ goto error_exit;
}
a = (struct esas2r_adapter *)host->hostdata;
@@ -294,8 +294,7 @@ int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid,
if (!dma64 && dma_set_mask_and_coherent(&pcid->dev, DMA_BIT_MASK(32))) {
esas2r_log(ESAS2R_LOG_CRIT, "failed to set DMA mask");
- esas2r_kill_adapter(index);
- return 0;
+ goto error_kill_adapter;
}
esas2r_log_dev(ESAS2R_LOG_INFO, &pcid->dev,
@@ -314,6 +313,10 @@ int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid,
snprintf(a->fw_event_q_name, ESAS2R_KOBJ_NAME_LEN, "esas2r/%d",
a->index);
a->fw_event_q = create_singlethread_workqueue(a->fw_event_q_name);
+ if (!a->fw_event_q) {
+ esas2r_log(ESAS2R_LOG_CRIT, "failed to allocate workqueue");
+ goto error_kill_adapter;
+ }
init_waitqueue_head(&a->buffered_ioctl_waiter);
init_waitqueue_head(&a->nvram_waiter);
@@ -338,8 +341,7 @@ int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid,
if (!alloc_vda_req(a, last_request)) {
esas2r_log(ESAS2R_LOG_CRIT,
"failed to allocate a VDA request!");
- esas2r_kill_adapter(index);
- return 0;
+ goto error_destroy_workqueue;
}
}
@@ -350,8 +352,7 @@ int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid,
if (esas2r_map_regions(a) != 0) {
esas2r_log(ESAS2R_LOG_CRIT, "could not map PCI regions!");
- esas2r_kill_adapter(index);
- return 0;
+ goto error_destroy_workqueue;
}
a->index = index;
@@ -379,8 +380,7 @@ int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid,
esas2r_log(ESAS2R_LOG_CRIT,
"failed to allocate %d bytes of consistent memory!",
a->uncached_size);
- esas2r_kill_adapter(index);
- return 0;
+ goto error_destroy_workqueue;
}
a->uncached_phys = bus_addr;
@@ -397,8 +397,7 @@ int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid,
&next_uncached)) {
esas2r_log(ESAS2R_LOG_CRIT,
"failed to initialize adapter structure (2)!");
- esas2r_kill_adapter(index);
- return 0;
+ goto error_destroy_workqueue;
}
tasklet_init(&a->tasklet,
@@ -430,6 +429,13 @@ int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid,
a, a->disable_cnt);
return 1;
+
+error_destroy_workqueue:
+ destroy_workqueue(a->fw_event_q);
+error_kill_adapter:
+ esas2r_kill_adapter(index);
+error_exit:
+ return 0;
}
static void esas2r_adapter_power_down(struct esas2r_adapter *a,
Add the check for the return value of the create_singlethread_workqueue in order to avoid NULL pointer dereference. Moreover, the allocated "a->fw_event_q" should be destroyed when esas2r_init_adapter fails later in order to avoid memory leak. It is better to use goto label to remove duplicate error handling code. Fixes: 26780d9e12ed ("[SCSI] esas2r: ATTO Technology ExpressSAS 6G SAS/SATA RAID Adapter Driver") Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn> --- drivers/scsi/esas2r/esas2r_init.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-)