summary refs log tree commit diff
path: root/drivers/scsi/hpsa.c
diff options
context:
space:
mode:
authorDon Brace <don.brace@microsemi.com>2016-09-09 16:30:23 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2016-09-14 14:14:40 -0400
commitd49c2077c03d70a59e3063c7d33f00172491ae31 (patch)
tree841167e2f2a4c87f44bb496bf0564d3de139dcb2 /drivers/scsi/hpsa.c
parent86cf7130a58bd2cdd09da72cdadae0dcd5f5db19 (diff)
downloadlinux-d49c2077c03d70a59e3063c7d33f00172491ae31.tar.gz
scsi: hpsa: Check for null device pointers
A device can be deleted causing NULL pointer issues.

Reviewed-by: Scott Benesh <scott.benesh@microsemi.com>
Reviewed-by: Scott Teel <scott.teel@microsemi.com>
Reviewed-by: Kevin Barnett <kevin.barnett@microsemi.com>
Signed-off-by: Don Brace <don.brace@microsemi.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/hpsa.c')
-rw-r--r--drivers/scsi/hpsa.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 332ff1ab7491..97f50c71b7c9 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -2388,7 +2388,8 @@ static void hpsa_cmd_free_and_done(struct ctlr_info *h,
 		struct CommandList *c, struct scsi_cmnd *cmd)
 {
 	hpsa_cmd_resolve_and_free(h, c);
-	cmd->scsi_done(cmd);
+	if (cmd && cmd->scsi_done)
+		cmd->scsi_done(cmd);
 }
 
 static void hpsa_retry_cmd(struct ctlr_info *h, struct CommandList *c)
@@ -2489,6 +2490,12 @@ static void complete_scsi_command(struct CommandList *cp)
 	ei = cp->err_info;
 	cmd = cp->scsi_cmd;
 	h = cp->h;
+
+	if (!cmd->device) {
+		cmd->result = DID_NO_CONNECT << 16;
+		return hpsa_cmd_free_and_done(h, cp, cmd);
+	}
+
 	dev = cmd->device->hostdata;
 	c2 = &h->ioaccel2_cmd_pool[cp->cmdindex];
 
@@ -2504,8 +2511,15 @@ static void complete_scsi_command(struct CommandList *cp)
 	cmd->result = (DID_OK << 16); 		/* host byte */
 	cmd->result |= (COMMAND_COMPLETE << 8);	/* msg byte */
 
-	if (cp->cmd_type == CMD_IOACCEL2 || cp->cmd_type == CMD_IOACCEL1)
-		atomic_dec(&cp->phys_disk->ioaccel_cmds_out);
+	if (cp->cmd_type == CMD_IOACCEL2 || cp->cmd_type == CMD_IOACCEL1) {
+		if (dev->physical_device && dev->expose_device &&
+			dev->removed) {
+			cmd->result = DID_NO_CONNECT << 16;
+			return hpsa_cmd_free_and_done(h, cp, cmd);
+		}
+		if (likely(cp->phys_disk != NULL))
+			atomic_dec(&cp->phys_disk->ioaccel_cmds_out);
+	}
 
 	/*
 	 * We check for lockup status here as it may be set for