From 86cf7130a58bd2cdd09da72cdadae0dcd5f5db19 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Fri, 9 Sep 2016 16:30:17 -0500 Subject: scsi: hpsa: Determine device external status earlier Currently we are checking for external status before we are determining if a device is an external device. Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 030d0023e1d2..332ff1ab7491 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -4270,6 +4270,11 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position, i, nphysicals, nlogicals, physdev_list, logdev_list); + /* Determine if this is a lun from an external target array */ + tmpdevice->external = + figure_external_status(h, raid_ctlr_position, i, + nphysicals, nlocal_logicals); + /* * Skip over some devices such as a spare. */ @@ -4295,11 +4300,6 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) continue; } - /* Determine if this is a lun from an external target array */ - tmpdevice->external = - figure_external_status(h, raid_ctlr_position, i, - nphysicals, nlocal_logicals); - figure_bus_target_lun(h, lunaddrbytes, tmpdevice); hpsa_update_device_supports_aborts(h, tmpdevice, lunaddrbytes); this_device = currentsd[ncurrent]; -- cgit v1.2.3 From d49c2077c03d70a59e3063c7d33f00172491ae31 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Fri, 9 Sep 2016 16:30:23 -0500 Subject: scsi: hpsa: Check for null device pointers A device can be deleted causing NULL pointer issues. Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers/scsi/hpsa.c') 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 -- cgit v1.2.3 From 8383278d28b9bc598225f163b6644b8b09f2733d Mon Sep 17 00:00:00 2001 From: Scott Teel Date: Fri, 9 Sep 2016 16:30:29 -0500 Subject: scsi: hpsa: Check for vpd support before sending Before using vendor-specific VPD pages for getting raid_level and device_id, check for page support. If page isn't supported, don't try to use it. Also, pay attention to return status on hpsa_get_device_id. [mkp: fix boolean return warnings reported by kbuild test robot] Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 50 ++++++++++++++++++++++++++++++++++++------------- drivers/scsi/hpsa_cmd.h | 1 + 2 files changed, 38 insertions(+), 13 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 97f50c71b7c9..5d25e8db281c 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -293,6 +293,8 @@ static int detect_controller_lockup(struct ctlr_info *h); static void hpsa_disable_rld_caching(struct ctlr_info *h); static inline int hpsa_scsi_do_report_phys_luns(struct ctlr_info *h, struct ReportExtendedLUNdata *buf, int bufsize); +static bool hpsa_vpd_page_supported(struct ctlr_info *h, + unsigned char scsi3addr[], u8 page); static int hpsa_luns_changed(struct ctlr_info *h); static bool hpsa_cmd_dev_match(struct ctlr_info *h, struct CommandList *c, struct hpsa_scsi_dev_t *dev, @@ -3088,11 +3090,19 @@ static void hpsa_get_raid_level(struct ctlr_info *h, buf = kzalloc(64, GFP_KERNEL); if (!buf) return; - rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | 0xC1, buf, 64); + + if (!hpsa_vpd_page_supported(h, scsi3addr, + HPSA_VPD_LV_DEVICE_GEOMETRY)) + goto exit; + + rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | + HPSA_VPD_LV_DEVICE_GEOMETRY, buf, 64); + if (rc == 0) *raid_level = buf[8]; if (*raid_level > RAID_UNKNOWN) *raid_level = RAID_UNKNOWN; +exit: kfree(buf); return; } @@ -3450,7 +3460,7 @@ static void hpsa_get_sas_address(struct ctlr_info *h, unsigned char *scsi3addr, } /* Get a device id from inquiry page 0x83 */ -static int hpsa_vpd_page_supported(struct ctlr_info *h, +static bool hpsa_vpd_page_supported(struct ctlr_info *h, unsigned char scsi3addr[], u8 page) { int rc; @@ -3460,7 +3470,7 @@ static int hpsa_vpd_page_supported(struct ctlr_info *h, buf = kzalloc(256, GFP_KERNEL); if (!buf) - return 0; + return false; /* Get the size of the page list first */ rc = hpsa_scsi_do_inquiry(h, scsi3addr, @@ -3487,10 +3497,10 @@ static int hpsa_vpd_page_supported(struct ctlr_info *h, goto exit_supported; exit_unsupported: kfree(buf); - return 0; + return false; exit_supported: kfree(buf); - return 1; + return true; } static void hpsa_get_ioaccel_status(struct ctlr_info *h, @@ -3539,18 +3549,25 @@ static int hpsa_get_device_id(struct ctlr_info *h, unsigned char *scsi3addr, int rc; unsigned char *buf; - if (buflen > 16) - buflen = 16; + /* Does controller have VPD for device id? */ + if (!hpsa_vpd_page_supported(h, scsi3addr, HPSA_VPD_LV_DEVICE_ID)) + return 1; /* not supported */ + buf = kzalloc(64, GFP_KERNEL); if (!buf) return -ENOMEM; - rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | 0x83, buf, 64); - if (rc == 0) - memcpy(device_id, &buf[index], buflen); + + rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | + HPSA_VPD_LV_DEVICE_ID, buf, 64); + if (rc == 0) { + if (buflen > 16) + buflen = 16; + memcpy(device_id, &buf[8], buflen); + } kfree(buf); - return rc != 0; + return rc; /*0 - got id, otherwise, didn't */ } static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical, @@ -3821,8 +3838,15 @@ static int hpsa_update_device_info(struct ctlr_info *h, sizeof(this_device->model)); memset(this_device->device_id, 0, sizeof(this_device->device_id)); - hpsa_get_device_id(h, scsi3addr, this_device->device_id, 8, - sizeof(this_device->device_id)); + if (hpsa_get_device_id(h, scsi3addr, this_device->device_id, 8, + sizeof(this_device->device_id))) + dev_err(&h->pdev->dev, + "hpsa%d: %s: can't get device id for host %d:C0:T%d:L%d\t%s\t%.16s\n", + h->ctlr, __func__, + h->scsi_host->host_no, + this_device->target, this_device->lun, + scsi_device_type(this_device->devtype), + this_device->model); if ((this_device->devtype == TYPE_DISK || this_device->devtype == TYPE_ZBC) && diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index a5be153d92d4..a584cdf07058 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h @@ -157,6 +157,7 @@ /* VPD Inquiry types */ #define HPSA_VPD_SUPPORTED_PAGES 0x00 +#define HPSA_VPD_LV_DEVICE_ID 0x83 #define HPSA_VPD_LV_DEVICE_GEOMETRY 0xC1 #define HPSA_VPD_LV_IOACCEL_STATUS 0xC2 #define HPSA_VPD_LV_STATUS 0xC3 -- cgit v1.2.3 From 4b6e5597f4c9ae545a1bd18e830d9f6b4465cadd Mon Sep 17 00:00:00 2001 From: Scott Teel Date: Fri, 9 Sep 2016 16:30:36 -0500 Subject: scsi: hpsa: Prevent sending bmic commands to externals Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 5d25e8db281c..82b277be6bf1 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -4072,7 +4072,17 @@ static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h, struct bmic_identify_physical_device *id_phys) { int rc; - struct ext_report_lun_entry *rle = &rlep->LUN[rle_index]; + struct ext_report_lun_entry *rle; + + /* + * external targets don't support BMIC + */ + if (dev->external) { + dev->queue_depth = 7; + return; + } + + rle = &rlep->LUN[rle_index]; dev->ioaccel_handle = rle->ioaccel_handle; if ((rle->device_flags & 0x08) && dev->ioaccel_handle) -- cgit v1.2.3 From 45e596cd6ead1c4ada74b03067595d7f4502fa6a Mon Sep 17 00:00:00 2001 From: Don Brace Date: Fri, 9 Sep 2016 16:30:42 -0500 Subject: scsi: hpsa: Check for null devices in ioaccel submission patch Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 82b277be6bf1..e5c02d7cb34b 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -2499,6 +2499,10 @@ static void complete_scsi_command(struct CommandList *cp) } dev = cmd->device->hostdata; + if (!dev) { + cmd->result = DID_NO_CONNECT << 16; + return hpsa_cmd_free_and_done(h, cp, cmd); + } c2 = &h->ioaccel2_cmd_pool[cp->cmdindex]; scsi_dma_unmap(cmd); /* undo the DMA mappings */ @@ -4686,6 +4690,9 @@ static int hpsa_scsi_ioaccel_direct_map(struct ctlr_info *h, struct scsi_cmnd *cmd = c->scsi_cmd; struct hpsa_scsi_dev_t *dev = cmd->device->hostdata; + if (!dev) + return -1; + c->phys_disk = dev; return hpsa_scsi_ioaccel_queue_command(h, c, dev->ioaccel_handle, @@ -4762,6 +4769,12 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h, u32 len; u32 total_len = 0; + if (!cmd->device) + return -1; + + if (!cmd->device->hostdata) + return -1; + BUG_ON(scsi_sg_count(cmd) > h->maxsgentries); if (fixup_ioaccel_cdb(cdb, &cdb_len)) { @@ -4870,6 +4883,12 @@ static int hpsa_scsi_ioaccel_queue_command(struct ctlr_info *h, struct CommandList *c, u32 ioaccel_handle, u8 *cdb, int cdb_len, u8 *scsi3addr, struct hpsa_scsi_dev_t *phys_disk) { + if (!c->scsi_cmd->device) + return -1; + + if (!c->scsi_cmd->device->hostdata) + return -1; + /* Try to honor the device's queue depth */ if (atomic_inc_return(&phys_disk->ioaccel_cmds_out) > phys_disk->queue_depth) { @@ -4950,6 +4969,9 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h, #endif int offload_to_mirror; + if (!dev) + return -1; + /* check for valid opcode, get LBA and block count */ switch (cmd->cmnd[0]) { case WRITE_6: @@ -5362,6 +5384,9 @@ static int hpsa_ioaccel_submit(struct ctlr_info *h, struct hpsa_scsi_dev_t *dev = cmd->device->hostdata; int rc = IO_ACCEL_INELIGIBLE; + if (!dev) + return SCSI_MLQUEUE_HOST_BUSY; + cmd->host_scribble = (unsigned char *) c; if (dev->offload_enabled) { @@ -5900,6 +5925,9 @@ static void setup_ioaccel2_abort_cmd(struct CommandList *c, struct ctlr_info *h, struct scsi_cmnd *scmd = command_to_abort->scsi_cmd; struct hpsa_scsi_dev_t *dev = scmd->device->hostdata; + if (!dev) + return; + /* * We're overlaying struct hpsa_tmf_struct on top of something which * was allocated as a struct io_accel2_cmd, so we better be sure it @@ -6020,6 +6048,9 @@ static int hpsa_send_abort_ioaccel2(struct ctlr_info *h, struct io_accel2_cmd *c2; dev = abort->scsi_cmd->device->hostdata; + if (!dev) + return -1; + if (!dev->offload_enabled && !dev->hba_ioaccel_enabled) return -1; -- cgit v1.2.3 From abbada7175999fbd6500b8144e985b779588962f Mon Sep 17 00:00:00 2001 From: Mahesh Rajashekhara Date: Fri, 16 Sep 2016 14:54:23 -0500 Subject: scsi: hpsa: correct scsi 6byte lba calculation Missing 5 bits of byte 1 in the LBA issued by SML. Reported-by: Mahesh Rajashekhara Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Mahesh Rajashekhara Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index e5c02d7cb34b..261b9bba1f0f 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -4565,7 +4565,9 @@ static int fixup_ioaccel_cdb(u8 *cdb, int *cdb_len) case READ_6: case READ_12: if (*cdb_len == 6) { - block = get_unaligned_be16(&cdb[2]); + block = (((cdb[1] & 0x1F) << 16) | + (cdb[2] << 8) | + cdb[3]); block_cnt = cdb[4]; if (block_cnt == 0) block_cnt = 256; @@ -4725,9 +4727,11 @@ static void set_encrypt_ioaccel2(struct ctlr_info *h, */ switch (cmd->cmnd[0]) { /* Required? 6-byte cdbs eliminated by fixup_ioaccel_cdb */ - case WRITE_6: case READ_6: - first_block = get_unaligned_be16(&cmd->cmnd[2]); + case WRITE_6: + first_block = (((cmd->cmnd[1] & 0x1F) << 16) | + (cmd->cmnd[2] << 8) | + cmd->cmnd[3]); break; case WRITE_10: case READ_10: @@ -4977,7 +4981,9 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h, case WRITE_6: is_write = 1; case READ_6: - first_block = get_unaligned_be16(&cmd->cmnd[2]); + first_block = (((cmd->cmnd[1] & 0x1F) << 16) | + (cmd->cmnd[2] << 8) | + cmd->cmnd[3]); block_cnt = cmd->cmnd[4]; if (block_cnt == 0) block_cnt = 256; -- cgit v1.2.3 From b32ece0ff70c30e59f16e9a8ffd05acc27298ba3 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Tue, 20 Sep 2016 15:42:30 -0500 Subject: scsi: hpsa: correct call to hpsa_do_reset calling fill_cmd() using a MACRO definition not handled in switch statement causes BUG() to be called. Signed-off-by: Don Brace Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 2 +- drivers/scsi/hpsa.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 261b9bba1f0f..d007ec18179a 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -6017,7 +6017,7 @@ static int hpsa_send_reset_as_abort_ioaccel2(struct ctlr_info *h, "Reset as abort: Resetting physical device at scsi3addr 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", psa[0], psa[1], psa[2], psa[3], psa[4], psa[5], psa[6], psa[7]); - rc = hpsa_do_reset(h, dev, psa, HPSA_RESET_TYPE_TARGET, reply_queue); + rc = hpsa_do_reset(h, dev, psa, HPSA_PHYS_TARGET_RESET, reply_queue); if (rc != 0) { dev_warn(&h->pdev->dev, "Reset as abort: Failed on physical device at scsi3addr 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index a1487e67f7a1..82cdfad874f3 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -312,7 +312,6 @@ struct offline_device_entry { #define HPSA_DEVICE_RESET_MSG 1 #define HPSA_RESET_TYPE_CONTROLLER 0x00 #define HPSA_RESET_TYPE_BUS 0x01 -#define HPSA_RESET_TYPE_TARGET 0x03 #define HPSA_RESET_TYPE_LUN 0x04 #define HPSA_PHYS_TARGET_RESET 0x99 /* not defined by cciss spec */ #define HPSA_MSG_SEND_RETRY_LIMIT 10 -- cgit v1.2.3