From 8aa60681dbc0a501697663af0cd9c31df046d709 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 4 Nov 2015 15:50:01 -0600 Subject: hpsa: remove unused parameter hostno This parameter was once used before scan_start was defined but now it is no longer used. Signed-off-by: Don Brace Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 40669f8dd0df..815dc7f65079 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -243,7 +243,7 @@ static int hpsa_slave_alloc(struct scsi_device *sdev); static int hpsa_slave_configure(struct scsi_device *sdev); static void hpsa_slave_destroy(struct scsi_device *sdev); -static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno); +static void hpsa_update_scsi_devices(struct ctlr_info *h); static int check_for_unit_attention(struct ctlr_info *h, struct CommandList *c); static void check_ioctl_unit_attention(struct ctlr_info *h, @@ -1152,7 +1152,7 @@ static inline void hpsa_show_dev_msg(const char *level, struct ctlr_info *h, } /* Add an entry into h->dev[] array. */ -static int hpsa_scsi_add_entry(struct ctlr_info *h, int hostno, +static int hpsa_scsi_add_entry(struct ctlr_info *h, struct hpsa_scsi_dev_t *device, struct hpsa_scsi_dev_t *added[], int *nadded) { @@ -1228,7 +1228,7 @@ lun_assigned: } /* Update an entry in h->dev[] array. */ -static void hpsa_scsi_update_entry(struct ctlr_info *h, int hostno, +static void hpsa_scsi_update_entry(struct ctlr_info *h, int entry, struct hpsa_scsi_dev_t *new_entry) { int offload_enabled; @@ -1276,7 +1276,7 @@ static void hpsa_scsi_update_entry(struct ctlr_info *h, int hostno, } /* Replace an entry from h->dev[] array. */ -static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno, +static void hpsa_scsi_replace_entry(struct ctlr_info *h, int entry, struct hpsa_scsi_dev_t *new_entry, struct hpsa_scsi_dev_t *added[], int *nadded, struct hpsa_scsi_dev_t *removed[], int *nremoved) @@ -1304,7 +1304,7 @@ static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno, } /* Remove an entry from h->dev[] array. */ -static void hpsa_scsi_remove_entry(struct ctlr_info *h, int hostno, int entry, +static void hpsa_scsi_remove_entry(struct ctlr_info *h, int entry, struct hpsa_scsi_dev_t *removed[], int *nremoved) { /* assumes h->devlock is held */ @@ -1638,7 +1638,7 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h, } } -static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, +static void adjust_hpsa_scsi_table(struct ctlr_info *h, struct hpsa_scsi_dev_t *sd[], int nsds) { /* sd contains scsi3 addresses and devtypes, and inquiry @@ -1678,19 +1678,18 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, device_change = hpsa_scsi_find_entry(csd, sd, nsds, &entry); if (device_change == DEVICE_NOT_FOUND) { changes++; - hpsa_scsi_remove_entry(h, hostno, i, - removed, &nremoved); + hpsa_scsi_remove_entry(h, i, removed, &nremoved); continue; /* remove ^^^, hence i not incremented */ } else if (device_change == DEVICE_CHANGED) { changes++; - hpsa_scsi_replace_entry(h, hostno, i, sd[entry], + hpsa_scsi_replace_entry(h, i, sd[entry], added, &nadded, removed, &nremoved); /* Set it to NULL to prevent it from being freed * at the bottom of hpsa_update_scsi_devices() */ sd[entry] = NULL; } else if (device_change == DEVICE_UPDATED) { - hpsa_scsi_update_entry(h, hostno, i, sd[entry]); + hpsa_scsi_update_entry(h, i, sd[entry]); } i++; } @@ -1718,8 +1717,7 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, h->ndevices, &entry); if (device_change == DEVICE_NOT_FOUND) { changes++; - if (hpsa_scsi_add_entry(h, hostno, sd[i], - added, &nadded) != 0) + if (hpsa_scsi_add_entry(h, sd[i], added, &nadded) != 0) break; sd[i] = NULL; /* prevent from being freed later. */ } else if (device_change == DEVICE_CHANGED) { @@ -1755,7 +1753,7 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, * (or if there are no changes) scsi_scan_host will do it later the * first time through. */ - if (hostno == -1 || !changes) + if (!changes) goto free_and_out; sh = h->scsi_host; @@ -3702,7 +3700,7 @@ static void hpsa_get_path_info(struct hpsa_scsi_dev_t *this_device, sizeof(this_device->bay)); } -static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) +static void hpsa_update_scsi_devices(struct ctlr_info *h) { /* the idea here is we could get notified * that some devices have changed, so we do a report @@ -3865,7 +3863,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) if (ncurrent >= HPSA_MAX_DEVICES) break; } - adjust_hpsa_scsi_table(h, hostno, currentsd, ncurrent); + adjust_hpsa_scsi_table(h, currentsd, ncurrent); out: kfree(tmpdevice); for (i = 0; i < ndev_allocated; i++) @@ -4947,7 +4945,7 @@ static void hpsa_scan_start(struct Scsi_Host *sh) if (unlikely(lockup_detected(h))) return hpsa_scan_complete(h); - hpsa_update_scsi_devices(h, h->scsi_host->host_no); + hpsa_update_scsi_devices(h); hpsa_scan_complete(h); } -- cgit v1.2.3 From 55d95d39b70fa391d609927242f55307d5536b17 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 4 Nov 2015 15:50:07 -0600 Subject: hpsa: stop zeroing reset_cmds_out and ioaccel_cmds_out during rescan pulling the rug out from under the reset handler likewise for ioaccel_cmds_out Reviewed-by: Hannes Reinecke Reviewed-by: Tomas Henzl Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 815dc7f65079..4085401c97d8 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3671,8 +3671,6 @@ static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h, DRIVE_CMDS_RESERVED_FOR_FW; else dev->queue_depth = DRIVE_QUEUE_DEPTH; /* conservative */ - atomic_set(&dev->ioaccel_cmds_out, 0); - atomic_set(&dev->reset_cmds_out, 0); } static void hpsa_get_path_info(struct hpsa_scsi_dev_t *this_device, -- cgit v1.2.3 From b48d9804281957ea35340076c2492c924ceb3ef0 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 4 Nov 2015 15:50:13 -0600 Subject: hpsa: remove unused hpsa_tag_discard_error_bits This function is no longer used. Reviewed-by: Tomas Henzl Reviewed-by: Hannes Reinecke Signed-off-by: Don Brace Reviewed-by: Manoj Kumar Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 4085401c97d8..5a99627368a3 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -230,6 +230,7 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, int cmd_type); static void hpsa_free_cmd_pool(struct ctlr_info *h); #define VPD_PAGE (1 << 8) +#define HPSA_SIMPLE_ERROR_BITS 0x03 static int hpsa_scsi_queue_command(struct Scsi_Host *h, struct scsi_cmnd *cmd); static void hpsa_scan_start(struct Scsi_Host *); @@ -6436,16 +6437,6 @@ static inline void finish_cmd(struct CommandList *c) complete(c->waiting); } - -static inline u32 hpsa_tag_discard_error_bits(struct ctlr_info *h, u32 tag) -{ -#define HPSA_PERF_ERROR_BITS ((1 << DIRECT_LOOKUP_SHIFT) - 1) -#define HPSA_SIMPLE_ERROR_BITS 0x03 - if (unlikely(!(h->transMethod & CFGTBL_Trans_Performant))) - return tag & ~HPSA_SIMPLE_ERROR_BITS; - return tag & ~HPSA_PERF_ERROR_BITS; -} - /* process completion of an indexed ("direct lookup") command */ static inline void process_indexed_cmd(struct ctlr_info *h, u32 raw_tag) -- cgit v1.2.3 From 9975ec9dbeb1775d29faaae50b31e2c19f740bf8 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 4 Nov 2015 15:50:25 -0600 Subject: hpsa: check for null arguments to dev_printk Check for NULLs. Reviewed-by: Tomas Henzl Reviewed-by: Manoj Kumar Signed-off-by: Don Brace Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 5a99627368a3..b64913f9d880 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1138,6 +1138,9 @@ static int hpsa_find_target_lun(struct ctlr_info *h, static inline void hpsa_show_dev_msg(const char *level, struct ctlr_info *h, struct hpsa_scsi_dev_t *dev, char *description) { + if (h == NULL || h->pdev == NULL || h->scsi_host == NULL) + return; + dev_printk(level, &h->pdev->dev, "scsi %d:%d:%d:%d: %s %s %.8s %.16s RAID-%s SSDSmartPathCap%c En%c Exp=%d\n", h->scsi_host->host_no, dev->bus, dev->target, dev->lun, -- cgit v1.2.3 From 1d33d85d4e51d85ee986b603de90be4f0b2faf2c Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 4 Nov 2015 15:50:31 -0600 Subject: hpsa: fix null device issues Reviewed-by: Tomas Henzl Reviewed-by: Manoj Kumar Signed-off-by: Don Brace Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index b64913f9d880..446816664335 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1135,7 +1135,7 @@ static int hpsa_find_target_lun(struct ctlr_info *h, return !found; } -static inline void hpsa_show_dev_msg(const char *level, struct ctlr_info *h, +static void hpsa_show_dev_msg(const char *level, struct ctlr_info *h, struct hpsa_scsi_dev_t *dev, char *description) { if (h == NULL || h->pdev == NULL || h->scsi_host == NULL) @@ -1419,6 +1419,9 @@ static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle, #define DEVICE_CHANGED 1 #define DEVICE_SAME 2 #define DEVICE_UPDATED 3 + if (needle == NULL) + return DEVICE_NOT_FOUND; + for (i = 0; i < haystack_size; i++) { if (haystack[i] == NULL) /* previously removed. */ continue; @@ -1581,6 +1584,8 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h, if (!logical_drive->offload_config) continue; for (j = 0; j < ndevices; j++) { + if (dev[j] == NULL) + continue; if (dev[j]->devtype != TYPE_DISK) continue; if (is_logical_dev_addr_mode(dev[j]->scsi3addr)) @@ -1624,6 +1629,8 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h, int i; for (i = 0; i < ndevices; i++) { + if (dev[i] == NULL) + continue; if (dev[i]->devtype != TYPE_DISK) continue; if (!is_logical_dev_addr_mode(dev[i]->scsi3addr)) @@ -1737,8 +1744,11 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, /* Now that h->dev[]->phys_disk[] is coherent, we can enable * any logical drives that need it enabled. */ - for (i = 0; i < h->ndevices; i++) + for (i = 0; i < h->ndevices; i++) { + if (h->dev[i] == NULL) + continue; h->dev[i]->offload_enabled = h->dev[i]->offload_to_be_enabled; + } spin_unlock_irqrestore(&h->devlock, flags); @@ -1763,6 +1773,8 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, sh = h->scsi_host; /* Notify scsi mid layer of any removed devices */ for (i = 0; i < nremoved; i++) { + if (removed[i] == NULL) + continue; if (removed[i]->expose_state & HPSA_SCSI_ADD) { struct scsi_device *sdev = scsi_device_lookup(sh, removed[i]->bus, @@ -1786,18 +1798,18 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, /* Notify scsi mid layer of any added devices */ for (i = 0; i < nadded; i++) { + if (added[i] == NULL) + continue; if (!(added[i]->expose_state & HPSA_SCSI_ADD)) continue; if (scsi_add_device(sh, added[i]->bus, added[i]->target, added[i]->lun) == 0) continue; - hpsa_show_dev_msg(KERN_WARNING, h, added[i], - "addition failed, device not added."); + dev_warn(&h->pdev->dev, "addition failed, device not added."); /* now we have to remove it from h->dev, * since it didn't get added to scsi mid layer */ fixup_botched_add(h, added[i]); - added[i] = NULL; } free_and_out: -- cgit v1.2.3 From 853633e85996cb661e7aed5b3ae8823b12f265cf Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 4 Nov 2015 15:50:37 -0600 Subject: hpsa: allow driver requested rescans Reviewed-by: Scott Teel Reviewed-by: Justin Lindley Reviewed-by: Kevin Barnett Reviewed-by: Tomas Henzl Reviewed-by; Hannes Reinecke Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 446816664335..f010b8ec1a20 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1810,6 +1810,7 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, * since it didn't get added to scsi mid layer */ fixup_botched_add(h, added[i]); + h->drv_req_rescan = 1; } free_and_out: @@ -3751,9 +3752,13 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) } memset(lunzerobits, 0, sizeof(lunzerobits)); + h->drv_req_rescan = 0; /* cancel scheduled rescan - we're doing it. */ + if (hpsa_gather_lun_info(h, physdev_list, &nphysicals, - logdev_list, &nlogicals)) + logdev_list, &nlogicals)) { + h->drv_req_rescan = 1; goto out; + } /* We might see up to the maximum number of logical and physical disks * plus external target devices, and a device for the local RAID @@ -3774,6 +3779,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) if (!currentsd[i]) { dev_warn(&h->pdev->dev, "out of memory at %s:%d\n", __FILE__, __LINE__); + h->drv_req_rescan = 1; goto out; } ndev_allocated++; @@ -3801,8 +3807,10 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) /* Get device type, vendor, model, device id */ if (hpsa_update_device_info(h, lunaddrbytes, tmpdevice, - &is_OBDR)) + &is_OBDR)) { + h->drv_req_rescan = 1; continue; /* skip it if we can't talk to it. */ + } figure_bus_target_lun(h, lunaddrbytes, tmpdevice); hpsa_update_device_supports_aborts(h, tmpdevice, lunaddrbytes); this_device = currentsd[ncurrent]; @@ -7862,6 +7870,11 @@ static void hpsa_ack_ctlr_events(struct ctlr_info *h) */ static int hpsa_ctlr_needs_rescan(struct ctlr_info *h) { + if (h->drv_req_rescan) { + h->drv_req_rescan = 0; + return 1; + } + if (!(h->fw_support & MISC_FW_EVENT_NOTIFY)) return 0; -- cgit v1.2.3 From 683fc444697a388f17cbc3bd7e64191ce000b6b4 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 4 Nov 2015 15:50:44 -0600 Subject: hpsa: abandon rescans on memory alloaction failures. Abandon and reschedule rescan process only if device inquiries fail due to mem alloc failures, which are likely to occur for all devices. Otherwise, skip device if inquiry fails for other reasons, and continue rescanning process for other devices. Reviewed-by: Scott Teel Reviewed-by: Justin Lindley Reviewed-by: Kevin Barnett Reviewed-by: Tomas Henzl Signed-off-by: Don Brace Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index f010b8ec1a20..ce0341a178fd 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3366,10 +3366,13 @@ static int hpsa_update_device_info(struct ctlr_info *h, unsigned char *inq_buff; unsigned char *obdr_sig; + int rc = 0; inq_buff = kzalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL); - if (!inq_buff) + if (!inq_buff) { + rc = -ENOMEM; goto bail_out; + } /* Do an inquiry to the device to see what it is. */ if (hpsa_scsi_do_inquiry(h, scsi3addr, 0, inq_buff, @@ -3377,6 +3380,7 @@ static int hpsa_update_device_info(struct ctlr_info *h, /* Inquiry failed (msg printed already) */ dev_err(&h->pdev->dev, "hpsa_update_device_info: inquiry failed\n"); + rc = -EIO; goto bail_out; } @@ -3426,7 +3430,7 @@ static int hpsa_update_device_info(struct ctlr_info *h, bail_out: kfree(inq_buff); - return 1; + return rc; } static void hpsa_update_device_supports_aborts(struct ctlr_info *h, @@ -3794,6 +3798,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) n_ext_target_devs = 0; for (i = 0; i < nphysicals + nlogicals + 1; i++) { u8 *lunaddrbytes, is_OBDR = 0; + int rc = 0; /* Figure out where the LUN ID info is coming from */ lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position, @@ -3806,11 +3811,20 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) continue; /* Get device type, vendor, model, device id */ - if (hpsa_update_device_info(h, lunaddrbytes, tmpdevice, - &is_OBDR)) { + rc = hpsa_update_device_info(h, lunaddrbytes, tmpdevice, + &is_OBDR); + if (rc == -ENOMEM) { + dev_warn(&h->pdev->dev, + "Out of memory, rescan deferred.\n"); h->drv_req_rescan = 1; - continue; /* skip it if we can't talk to it. */ + goto out; } + if (rc) { + dev_warn(&h->pdev->dev, + "Inquiry failed, skipping device.\n"); + continue; + } + figure_bus_target_lun(h, lunaddrbytes, tmpdevice); hpsa_update_device_supports_aborts(h, tmpdevice, lunaddrbytes); this_device = currentsd[ncurrent]; -- cgit v1.2.3 From c8a6c9a6b41367d147990756b311ed5a67f19005 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 4 Nov 2015 15:50:50 -0600 Subject: hpsa: correct transfer length for 6 byte read/write commands handle block counts of 0. Cleanup block and block count calculations. Reviewed-by: Scott Teel Reviewed-by: Justin Lindley Reviewed-by: Kevin Barnett Reviewed-by: Tomas Henzl Reviewed-by: Hannes Reinecke Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index ce0341a178fd..ae9968b4f766 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -4012,19 +4012,14 @@ static int fixup_ioaccel_cdb(u8 *cdb, int *cdb_len) case READ_6: case READ_12: if (*cdb_len == 6) { - block = (((u32) cdb[2]) << 8) | cdb[3]; + block = get_unaligned_be16(&cdb[2]); block_cnt = cdb[4]; + if (block_cnt == 0) + block_cnt = 256; } else { BUG_ON(*cdb_len != 12); - block = (((u32) cdb[2]) << 24) | - (((u32) cdb[3]) << 16) | - (((u32) cdb[4]) << 8) | - cdb[5]; - block_cnt = - (((u32) cdb[6]) << 24) | - (((u32) cdb[7]) << 16) | - (((u32) cdb[8]) << 8) | - cdb[9]; + block = get_unaligned_be32(&cdb[2]); + block_cnt = get_unaligned_be32(&cdb[6]); } if (block_cnt > 0xffff) return IO_ACCEL_INELIGIBLE; @@ -4410,9 +4405,7 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h, case WRITE_6: is_write = 1; case READ_6: - first_block = - (((u64) cmd->cmnd[2]) << 8) | - cmd->cmnd[3]; + first_block = get_unaligned_be16(&cmd->cmnd[2]); block_cnt = cmd->cmnd[4]; if (block_cnt == 0) block_cnt = 256; -- cgit v1.2.3 From da03ded045b6249261e6c82d942e6d0298dabc9b Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 4 Nov 2015 15:50:56 -0600 Subject: hpsa: fix hpsa_adjust_hpsa_scsi_table Fix a NULL pointer issue in the driver when devices are removed during a reset. Signed-off-by: Don Brace Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index ae9968b4f766..382cb5d428c7 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1663,6 +1663,15 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int nadded, nremoved; struct Scsi_Host *sh = NULL; + /* + * A reset can cause a device status to change + * re-schedule the scan to see what happened. + */ + if (h->reset_in_progress) { + h->drv_req_rescan = 1; + return; + } + added = kzalloc(sizeof(*added) * HPSA_MAX_DEVICES, GFP_KERNEL); removed = kzalloc(sizeof(*removed) * HPSA_MAX_DEVICES, GFP_KERNEL); @@ -1771,6 +1780,10 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, goto free_and_out; sh = h->scsi_host; + if (sh == NULL) { + dev_warn(&h->pdev->dev, "%s: scsi_host is null\n", __func__); + goto free_and_out; + } /* Notify scsi mid layer of any removed devices */ for (i = 0; i < nremoved; i++) { if (removed[i] == NULL) @@ -5234,12 +5247,15 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd) hpsa_show_dev_msg(KERN_WARNING, h, dev, "resetting"); + h->reset_in_progress = 1; + /* send a reset to the SCSI LUN which the command was sent to */ rc = hpsa_do_reset(h, dev, dev->scsi3addr, HPSA_RESET_TYPE_LUN, DEFAULT_REPLY_QUEUE); snprintf(msg, sizeof(msg), "reset %s", rc == 0 ? "completed successfully" : "failed"); hpsa_show_dev_msg(KERN_WARNING, h, dev, msg); + h->reset_in_progress = 0; return rc == 0 ? SUCCESS : FAILED; } -- cgit v1.2.3 From 0b9b7b6eecad03e0ba4290af7145e2c5d1f8ff13 Mon Sep 17 00:00:00 2001 From: Scott Teel Date: Wed, 4 Nov 2015 15:51:02 -0600 Subject: hpsa: fix physical target reset Set reset type in device_reset_handler to do either logical unit reset for logical devices, or physical target reset, for physical devices. Reviewed-by: Scott Teel Reviewed-by: Justin Lindley Reviewed-by: Kevin Barnett Reviewed-by: Tomas Henzl Reviewed-by: Hannes Reinecke Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 382cb5d428c7..1607b6d01852 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -2737,9 +2737,8 @@ static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr, /* fill_cmd can't fail here, no data buffer to map. */ - (void) fill_cmd(c, HPSA_DEVICE_RESET_MSG, h, NULL, 0, 0, + (void) fill_cmd(c, reset_type, h, NULL, 0, 0, scsi3addr, TYPE_MSG); - c->Request.CDB[1] = reset_type; /* fill_cmd defaults to LUN reset */ rc = hpsa_scsi_do_simple_cmd(h, c, reply_queue, NO_TIMEOUT); if (rc) { dev_warn(&h->pdev->dev, "Failed to send reset command\n"); @@ -5207,6 +5206,7 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd) int rc; struct ctlr_info *h; struct hpsa_scsi_dev_t *dev; + u8 reset_type; char msg[48]; /* find the controller to which the command to be aborted was sent */ @@ -5245,15 +5245,23 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd) if (is_hba_lunid(dev->scsi3addr)) return SUCCESS; - hpsa_show_dev_msg(KERN_WARNING, h, dev, "resetting"); + if (is_logical_dev_addr_mode(dev->scsi3addr)) + reset_type = HPSA_DEVICE_RESET_MSG; + else + reset_type = HPSA_PHYS_TARGET_RESET; + + sprintf(msg, "resetting %s", + reset_type == HPSA_DEVICE_RESET_MSG ? "logical " : "physical "); + hpsa_show_dev_msg(KERN_WARNING, h, dev, msg); h->reset_in_progress = 1; /* send a reset to the SCSI LUN which the command was sent to */ - rc = hpsa_do_reset(h, dev, dev->scsi3addr, HPSA_RESET_TYPE_LUN, + rc = hpsa_do_reset(h, dev, dev->scsi3addr, reset_type, DEFAULT_REPLY_QUEUE); - snprintf(msg, sizeof(msg), "reset %s", - rc == 0 ? "completed successfully" : "failed"); + sprintf(msg, "reset %s %s", + reset_type == HPSA_DEVICE_RESET_MSG ? "logical " : "physical ", + rc == 0 ? "completed successfully" : "failed"); hpsa_show_dev_msg(KERN_WARNING, h, dev, msg); h->reset_in_progress = 0; return rc == 0 ? SUCCESS : FAILED; @@ -6370,6 +6378,20 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, } else if (cmd_type == TYPE_MSG) { switch (cmd) { + case HPSA_PHYS_TARGET_RESET: + c->Request.CDBLen = 16; + c->Request.type_attr_dir = + TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_NONE); + c->Request.Timeout = 0; /* Don't time out */ + memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB)); + c->Request.CDB[0] = HPSA_RESET; + c->Request.CDB[1] = HPSA_TARGET_RESET_TYPE; + /* Physical target reset needs no control bytes 4-7*/ + c->Request.CDB[4] = 0x00; + c->Request.CDB[5] = 0x00; + c->Request.CDB[6] = 0x00; + c->Request.CDB[7] = 0x00; + break; case HPSA_DEVICE_RESET_MSG: c->Request.CDBLen = 16; c->Request.type_attr_dir = -- cgit v1.2.3 From f2039b03290b3b1e0556b85b7018273e116d17c3 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 4 Nov 2015 15:51:08 -0600 Subject: hpsa: correct check for non-disk devices The driver is using two MACROs which seemingly are looking in the wrong location for the device_flags returned from CISS_REPORT_PHYS. Both MACROs, NON_DISK_PHYS_DEV and PHYS_IOACCEL, are using the pointer returned from figure_lunaddrbytes which is the address of the LUN.lunid element in the extended CISS_REPORT_PHYS. But the MACROS are using offsets beyond the range of the element (offset 17 of an 8 byte element). These MACROs actually are looking at the correct location but they fail static checker analysis. It also will not work if any new elements are added to the extended LUN structure. Change the code to use the structure elements directly since this MACRO is only used in one location. Reported-by: Dan Carpenter Reviewed-by: Scott Teel Reviewed-by: Justin Lindley Reviewed-by: Kevin Barnett Reviewed-by: Tomas Henzl Reviewed-by: Hannes Reinecke Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 1607b6d01852..9cf551b1fa9a 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3681,19 +3681,18 @@ static u8 *figure_lunaddrbytes(struct ctlr_info *h, int raid_ctlr_position, /* get physical drive ioaccel handle and queue depth */ static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h, struct hpsa_scsi_dev_t *dev, - u8 *lunaddrbytes, + struct ReportExtendedLUNdata *rlep, int rle_index, struct bmic_identify_physical_device *id_phys) { int rc; - struct ext_report_lun_entry *rle = - (struct ext_report_lun_entry *) lunaddrbytes; + struct ext_report_lun_entry *rle = &rlep->LUN[rle_index]; dev->ioaccel_handle = rle->ioaccel_handle; - if (PHYS_IOACCEL(lunaddrbytes) && dev->ioaccel_handle) + if ((rle->device_flags & 0x08) && dev->ioaccel_handle) dev->hba_ioaccel_enabled = 1; memset(id_phys, 0, sizeof(*id_phys)); - rc = hpsa_bmic_id_physical_device(h, lunaddrbytes, - GET_BMIC_DRIVE_NUMBER(lunaddrbytes), id_phys, + rc = hpsa_bmic_id_physical_device(h, &rle->lunid[0], + GET_BMIC_DRIVE_NUMBER(&rle->lunid[0]), id_phys, sizeof(*id_phys)); if (!rc) /* Reserve space for FW operations */ @@ -3707,11 +3706,12 @@ static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h, } static void hpsa_get_path_info(struct hpsa_scsi_dev_t *this_device, - u8 *lunaddrbytes, + struct ReportExtendedLUNdata *rlep, int rle_index, struct bmic_identify_physical_device *id_phys) { - if (PHYS_IOACCEL(lunaddrbytes) - && this_device->ioaccel_handle) + struct ext_report_lun_entry *rle = &rlep->LUN[rle_index]; + + if ((rle->device_flags & 0x08) && this_device->ioaccel_handle) this_device->hba_ioaccel_enabled = 1; memcpy(&this_device->active_path_index, @@ -3811,6 +3811,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) for (i = 0; i < nphysicals + nlogicals + 1; i++) { u8 *lunaddrbytes, is_OBDR = 0; int rc = 0; + int phys_dev_index = i - (raid_ctlr_position == 0); /* Figure out where the LUN ID info is coming from */ lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position, @@ -3819,7 +3820,8 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) /* skip masked non-disk devices */ if (MASKED_DEVICE(lunaddrbytes)) if (i < nphysicals + (raid_ctlr_position == 0) && - NON_DISK_PHYS_DEV(lunaddrbytes)) + (physdev_list-> + LUN[phys_dev_index].device_flags & 0x01)) continue; /* Get device type, vendor, model, device id */ @@ -3884,9 +3886,9 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) /* Never use RAID mapper in HBA mode. */ this_device->offload_enabled = 0; hpsa_get_ioaccel_drive_info(h, this_device, - lunaddrbytes, id_phys); - hpsa_get_path_info(this_device, lunaddrbytes, - id_phys); + physdev_list, phys_dev_index, id_phys); + hpsa_get_path_info(this_device, + physdev_list, phys_dev_index, id_phys); } ncurrent++; break; -- cgit v1.2.3 From a736e9b6a03283a2e0fc8190b748b3a672f289c1 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 4 Nov 2015 15:51:14 -0600 Subject: hpsa: correct ioaccel2 sg chain len Reviewed-by: Scott Teel Reviewed-by: Justin Lindley Reviewed-by: Kevin Barnett Reviewed-by: Tomas Henzl Reviewed-by: Hannes Reinecke Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 9cf551b1fa9a..61992c08787c 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1983,7 +1983,7 @@ static int hpsa_map_ioaccel2_sg_chain_block(struct ctlr_info *h, u32 chain_size; chain_block = h->ioaccel2_cmd_sg_list[c->cmdindex]; - chain_size = le32_to_cpu(cp->data_len); + chain_size = le32_to_cpu(cp->sg[0].length); temp64 = pci_map_single(h->pdev, chain_block, chain_size, PCI_DMA_TODEVICE); if (dma_mapping_error(&h->pdev->dev, temp64)) { @@ -2004,7 +2004,7 @@ static void hpsa_unmap_ioaccel2_sg_chain_block(struct ctlr_info *h, chain_sg = cp->sg; temp64 = le64_to_cpu(chain_sg->address); - chain_size = le32_to_cpu(cp->data_len); + chain_size = le32_to_cpu(cp->sg[0].length); pci_unmap_single(h->pdev, temp64, chain_size, PCI_DMA_TODEVICE); } @@ -4315,6 +4315,7 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h, /* fill in sg elements */ if (use_sg > h->ioaccel_maxsg) { cp->sg_count = 1; + cp->sg[0].length = cpu_to_le32(use_sg * sizeof(cp->sg[0])); if (hpsa_map_ioaccel2_sg_chain_block(h, cp, c)) { atomic_dec(&phys_disk->ioaccel_cmds_out); scsi_dma_unmap(cmd); -- cgit v1.2.3 From 2a168208a35515b8ca54fbf1a17581ad2a852a3f Mon Sep 17 00:00:00 2001 From: Kevin Barnett Date: Wed, 4 Nov 2015 15:51:21 -0600 Subject: hpsa: simplify check for device exposure remove macros and cleanup device exposure checking Reviewed-by: Scott Teel Reviewed-by: Justin Lindley Reviewed-by: Kevin Barnett Reviewed-by: Tomas Henzl Reviewed-by: Hannes Reinecke Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 61992c08787c..77c14aeb43eb 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -792,8 +792,7 @@ static ssize_t path_info_show(struct device *dev, PATH_STRING_LEN, "PORT: %.2s ", phys_connector); - if (hdev->devtype == TYPE_DISK && - hdev->expose_state != HPSA_DO_NOT_EXPOSE) { + if (hdev->devtype == TYPE_DISK && hdev->expose_device) { if (box == 0 || box == 0xFF) { output_len += snprintf(path[i] + output_len, PATH_STRING_LEN, @@ -1152,7 +1151,7 @@ static void hpsa_show_dev_msg(const char *level, struct ctlr_info *h, "RAID-?" : raid_label[dev->raid_level], dev->offload_config ? '+' : '-', dev->offload_enabled ? '+' : '-', - dev->expose_state); + dev->expose_device); } /* Add an entry into h->dev[] array. */ @@ -1225,7 +1224,7 @@ lun_assigned: added[*nadded] = device; (*nadded)++; hpsa_show_dev_msg(KERN_INFO, h, device, - device->expose_state & HPSA_SCSI_ADD ? "added" : "masked"); + device->expose_device ? "added" : "masked"); device->offload_to_be_enabled = device->offload_enabled; device->offload_enabled = 0; return 0; @@ -1788,7 +1787,7 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, for (i = 0; i < nremoved; i++) { if (removed[i] == NULL) continue; - if (removed[i]->expose_state & HPSA_SCSI_ADD) { + if (removed[i]->expose_device) { struct scsi_device *sdev = scsi_device_lookup(sh, removed[i]->bus, removed[i]->target, removed[i]->lun); @@ -1813,7 +1812,7 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, for (i = 0; i < nadded; i++) { if (added[i] == NULL) continue; - if (!(added[i]->expose_state & HPSA_SCSI_ADD)) + if (!(added[i]->expose_device)) continue; if (scsi_add_device(sh, added[i]->bus, added[i]->target, added[i]->lun) == 0) @@ -1861,7 +1860,7 @@ static int hpsa_slave_alloc(struct scsi_device *sdev) sdev_id(sdev), sdev->lun); if (likely(sd)) { atomic_set(&sd->ioaccel_cmds_out, 0); - sdev->hostdata = (sd->expose_state & HPSA_SCSI_ADD) ? sd : NULL; + sdev->hostdata = sd->expose_device ? sd : NULL; } else sdev->hostdata = NULL; spin_unlock_irqrestore(&h->devlock, flags); @@ -1875,7 +1874,7 @@ static int hpsa_slave_configure(struct scsi_device *sdev) int queue_depth; sd = sdev->hostdata; - sdev->no_uld_attach = !sd || !(sd->expose_state & HPSA_ULD_ATTACH); + sdev->no_uld_attach = !sd || !sd->expose_device; if (sd) queue_depth = sd->queue_depth != 0 ? @@ -3861,12 +3860,10 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) /* do not expose masked devices */ if (MASKED_DEVICE(lunaddrbytes) && - i < nphysicals + (raid_ctlr_position == 0)) { - this_device->expose_state = HPSA_DO_NOT_EXPOSE; - } else { - this_device->expose_state = - HPSA_SG_ATTACH | HPSA_ULD_ATTACH; - } + i < nphysicals + (raid_ctlr_position == 0)) + this_device->expose_device = 0; + else + this_device->expose_device = 1; switch (this_device->devtype) { case TYPE_ROM: -- cgit v1.2.3 From 04fa2f44461dd90a00b514cd75ce82f829924826 Mon Sep 17 00:00:00 2001 From: Kevin Barnett Date: Wed, 4 Nov 2015 15:51:27 -0600 Subject: hpsa: simplify update scsi devices remove repeated calculation that checks for physical or logical devices. Reviewed-by: Scott Teel Reviewed-by: Justin Lindley Reviewed-by: Kevin Barnett Reviewed-by: Tomas Henzl Reviewed-by: Matthew R. Ochs Reviewed-by: Hannes Reinecke Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 77c14aeb43eb..62df4808119c 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3752,6 +3752,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) int ncurrent = 0; int i, n_ext_target_devs, ndevs_to_allocate; int raid_ctlr_position; + bool physical_device; DECLARE_BITMAP(lunzerobits, MAX_EXT_TARGETS); currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_DEVICES, GFP_KERNEL); @@ -3812,16 +3813,16 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) int rc = 0; int phys_dev_index = i - (raid_ctlr_position == 0); + physical_device = i < nphysicals + (raid_ctlr_position == 0); + /* Figure out where the LUN ID info is coming from */ lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position, i, nphysicals, nlogicals, physdev_list, logdev_list); /* skip masked non-disk devices */ - if (MASKED_DEVICE(lunaddrbytes)) - if (i < nphysicals + (raid_ctlr_position == 0) && - (physdev_list-> - LUN[phys_dev_index].device_flags & 0x01)) - continue; + if (MASKED_DEVICE(lunaddrbytes) && physical_device && + (physdev_list->LUN[phys_dev_index].device_flags & 0x01)) + continue; /* Get device type, vendor, model, device id */ rc = hpsa_update_device_info(h, lunaddrbytes, tmpdevice, @@ -3857,10 +3858,13 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) } *this_device = *tmpdevice; + this_device->physical_device = physical_device; - /* do not expose masked devices */ - if (MASKED_DEVICE(lunaddrbytes) && - i < nphysicals + (raid_ctlr_position == 0)) + /* + * Expose all devices except for physical devices that + * are masked. + */ + if (MASKED_DEVICE(lunaddrbytes) && this_device->physical_device) this_device->expose_device = 0; else this_device->expose_device = 1; @@ -3878,7 +3882,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) ncurrent++; break; case TYPE_DISK: - if (i < nphysicals + (raid_ctlr_position == 0)) { + if (this_device->physical_device) { /* The disk is in HBA mode. */ /* Never use RAID mapper in HBA mode. */ this_device->offload_enabled = 0; -- cgit v1.2.3 From f3f017305d4da61b64098f3d89cb64563c95087a Mon Sep 17 00:00:00 2001 From: Kevin Barnett Date: Wed, 4 Nov 2015 15:51:33 -0600 Subject: hpsa: add function is_logical_device simplify checking for logical/physical devices Reviewed-by: Scott Teel Reviewed-by: Justin Lindley Reviewed-by: Kevin Barnett Reviewed-by: Tomas Henzl Reviewed-by: Matthew R. Ochs Reviewed-by: Hannes Reinecke Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 62df4808119c..21892c155b01 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -618,6 +618,11 @@ static const char * const raid_label[] = { "0", "4", "1(+0)", "5", "5+1", "6", #define HPSA_RAID_ADM 6 /* also used for RAID 1+0 ADM */ #define RAID_UNKNOWN (ARRAY_SIZE(raid_label) - 1) +static inline bool is_logical_device(struct hpsa_scsi_dev_t *device) +{ + return !device->physical_device; +} + static ssize_t raid_level_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -638,7 +643,7 @@ static ssize_t raid_level_show(struct device *dev, } /* Is this even a logical drive? */ - if (!is_logical_dev_addr_mode(hdev->scsi3addr)) { + if (!is_logical_device(hdev)) { spin_unlock_irqrestore(&h->lock, flags); l = snprintf(buf, PAGE_SIZE, "N/A\n"); return l; @@ -772,8 +777,8 @@ static ssize_t path_info_show(struct device *dev, scsi_device_type(hdev->devtype)); if (is_ext_target(h, hdev) || - (hdev->devtype == TYPE_RAID) || - is_logical_dev_addr_mode(hdev->scsi3addr)) { + hdev->devtype == TYPE_RAID || + is_logical_device(hdev)) { output_len += snprintf(path[i] + output_len, PATH_STRING_LEN, "%s\n", active); @@ -1587,7 +1592,7 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h, continue; if (dev[j]->devtype != TYPE_DISK) continue; - if (is_logical_dev_addr_mode(dev[j]->scsi3addr)) + if (is_logical_device(dev[j])) continue; if (dev[j]->ioaccel_handle != dd[i].ioaccel_handle) continue; @@ -1632,7 +1637,7 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h, continue; if (dev[i]->devtype != TYPE_DISK) continue; - if (!is_logical_dev_addr_mode(dev[i]->scsi3addr)) + if (!is_logical_device(dev[i])) continue; /* @@ -2237,7 +2242,7 @@ static void process_ioaccel2_completion(struct ctlr_info *h, * the normal I/O path so the controller can handle whatever's * wrong. */ - if (is_logical_dev_addr_mode(dev->scsi3addr) && + if (is_logical_device(dev) && c2->error_data.serv_response == IOACCEL2_SERV_RESPONSE_FAILURE) { if (c2->error_data.status == @@ -2357,7 +2362,7 @@ static void complete_scsi_command(struct CommandList *cp) * the normal I/O path so the controller can handle whatever's * wrong. */ - if (is_logical_dev_addr_mode(dev->scsi3addr)) { + if (is_logical_device(dev)) { if (ei->CommandStatus == CMD_IOACCEL_DISABLED) dev->offload_enabled = 0; return hpsa_retry_cmd(h, cp); -- cgit v1.2.3 From 75d23d894a4054dea2912e8ccad3134b8b90f1f1 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 4 Nov 2015 15:51:39 -0600 Subject: hpsa: enhance hpsa_get_device_id use an index into vpd data for SAS/SATA drives Reviewed-by: Scott Teel Reviewed-by: Justin Lindley Reviewed-by: Kevin Barnett Reviewed-by: Tomas Henzl Reviewed-by: Matthew R. Ochs Signed-off-by: Don Brace Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 21892c155b01..80d64acc2991 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3128,7 +3128,7 @@ out: /* Get the device id from inquiry page 0x83 */ static int hpsa_get_device_id(struct ctlr_info *h, unsigned char *scsi3addr, - unsigned char *device_id, int buflen) + unsigned char *device_id, int index, int buflen) { int rc; unsigned char *buf; @@ -3140,8 +3140,10 @@ static int hpsa_get_device_id(struct ctlr_info *h, unsigned char *scsi3addr, return -ENOMEM; rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | 0x83, buf, 64); if (rc == 0) - memcpy(device_id, &buf[8], buflen); + memcpy(device_id, &buf[index], buflen); + kfree(buf); + return rc != 0; } @@ -3370,6 +3372,18 @@ static int hpsa_device_supports_aborts(struct ctlr_info *h, return rc; } +static void sanitize_inquiry_string(unsigned char *s, int len) +{ + bool terminated = false; + + for (; len > 0; (--len, ++s)) { + if (*s == 0) + terminated = true; + if (terminated || *s < 0x20 || *s > 0x7e) + *s = ' '; + } +} + static int hpsa_update_device_info(struct ctlr_info *h, unsigned char scsi3addr[], struct hpsa_scsi_dev_t *this_device, unsigned char *is_OBDR_device) @@ -3400,6 +3414,9 @@ static int hpsa_update_device_info(struct ctlr_info *h, goto bail_out; } + sanitize_inquiry_string(&inq_buff[8], 8); + sanitize_inquiry_string(&inq_buff[16], 16); + this_device->devtype = (inq_buff[0] & 0x1f); memcpy(this_device->scsi3addr, scsi3addr, 8); memcpy(this_device->vendor, &inq_buff[8], @@ -3408,7 +3425,7 @@ 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, + hpsa_get_device_id(h, scsi3addr, this_device->device_id, 8, sizeof(this_device->device_id)); if (this_device->devtype == TYPE_DISK && -- cgit v1.2.3 From c795505a742807fe6ba81d6c63b57c7d2737df3d Mon Sep 17 00:00:00 2001 From: Kevin Barnett Date: Wed, 4 Nov 2015 15:51:45 -0600 Subject: hpsa: refactor hpsa_figure_bus_target_lun setup for sas transport. Need to set the bus and target accordingly. Reviewed-by: Scott Teel Reviewed-by: Justin Lindley Reviewed-by: Kevin Barnett Reviewed-by: Hannes Reinecke Signed-off-by: Don Brace Reviewed-by: Matthew R. Ochs Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 80d64acc2991..c95ff8cfe00a 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3512,38 +3512,37 @@ static int is_ext_target(struct ctlr_info *h, struct hpsa_scsi_dev_t *device) return 0; } -/* Helper function to assign bus, target, lun mapping of devices. - * Puts non-external target logical volumes on bus 0, external target logical - * volumes on bus 1, physical devices on bus 2. and the hba on bus 3. +/* + * Helper function to assign bus, target, lun mapping of devices. * Logical drive target and lun are assigned at this time, but * physical device lun and target assignment are deferred (assigned * in hpsa_find_target_lun, called by hpsa_scsi_add_entry.) - */ +*/ static void figure_bus_target_lun(struct ctlr_info *h, u8 *lunaddrbytes, struct hpsa_scsi_dev_t *device) { - u32 lunid = le32_to_cpu(*((__le32 *) lunaddrbytes)); + u32 lunid = get_unaligned_le32(lunaddrbytes); if (!is_logical_dev_addr_mode(lunaddrbytes)) { /* physical device, target and lun filled in later */ if (is_hba_lunid(lunaddrbytes)) - hpsa_set_bus_target_lun(device, 3, 0, lunid & 0x3fff); + hpsa_set_bus_target_lun(device, + HPSA_HBA_BUS, 0, lunid & 0x3fff); else /* defer target, lun assignment for physical devices */ - hpsa_set_bus_target_lun(device, 2, -1, -1); + hpsa_set_bus_target_lun(device, + HPSA_PHYSICAL_DEVICE_BUS, -1, -1); return; } /* It's a logical device */ if (is_ext_target(h, device)) { - /* external target way, put logicals on bus 1 - * and match target/lun numbers box - * reports, other smart array, bus 0, target 0, match lunid - */ hpsa_set_bus_target_lun(device, - 1, (lunid >> 16) & 0x3fff, lunid & 0x00ff); + HPSA_EXTERNAL_RAID_VOLUME_BUS, (lunid >> 16) & 0x3fff, + lunid & 0x00ff); return; } - hpsa_set_bus_target_lun(device, 0, 0, lunid & 0x3fff); + hpsa_set_bus_target_lun(device, HPSA_RAID_VOLUME_BUS, + 0, lunid & 0x3fff); } /* -- cgit v1.2.3 From 096ccff47e152aef8e9ef318c02781daedc433b7 Mon Sep 17 00:00:00 2001 From: Kevin Barnett Date: Wed, 4 Nov 2015 15:51:51 -0600 Subject: hpsa: move scsi_add_device and scsi_remove_device calls to new function preparation for adding the sas transport class Reviewed-by: Scott Teel Reviewed-by: Justin Lindley Reviewed-by: Kevin Barnett Reviewed-by: Tomas Henzl Reviewed-by: Hannes Reinecke Reviewed-by: Matthew R. Ochs Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 71 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 26 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index c95ff8cfe00a..0af4c670c7cd 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1653,6 +1653,43 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h, } } +static int hpsa_add_device(struct ctlr_info *h, struct hpsa_scsi_dev_t *device) +{ + int rc = 0; + + if (!h->scsi_host) + return 1; + + rc = scsi_add_device(h->scsi_host, device->bus, + device->target, device->lun); + return rc; +} + +static void hpsa_remove_device(struct ctlr_info *h, + struct hpsa_scsi_dev_t *device) +{ + struct scsi_device *sdev = NULL; + + if (!h->scsi_host) + return; + + sdev = scsi_device_lookup(h->scsi_host, device->bus, + device->target, device->lun); + + if (sdev) { + scsi_remove_device(sdev); + scsi_device_put(sdev); + } else { + /* + * We don't expect to get here. Future commands + * to this device will get a selection timeout as + * if the device were gone. + */ + hpsa_show_dev_msg(KERN_WARNING, h, device, + "didn't find device for removal."); + } +} + static void adjust_hpsa_scsi_table(struct ctlr_info *h, struct hpsa_scsi_dev_t *sd[], int nsds) { @@ -1665,7 +1702,6 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, unsigned long flags; struct hpsa_scsi_dev_t **added, **removed; int nadded, nremoved; - struct Scsi_Host *sh = NULL; /* * A reset can cause a device status to change @@ -1783,46 +1819,29 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, if (!changes) goto free_and_out; - sh = h->scsi_host; - if (sh == NULL) { - dev_warn(&h->pdev->dev, "%s: scsi_host is null\n", __func__); - goto free_and_out; - } /* Notify scsi mid layer of any removed devices */ for (i = 0; i < nremoved; i++) { if (removed[i] == NULL) continue; - if (removed[i]->expose_device) { - struct scsi_device *sdev = - scsi_device_lookup(sh, removed[i]->bus, - removed[i]->target, removed[i]->lun); - if (sdev != NULL) { - scsi_remove_device(sdev); - scsi_device_put(sdev); - } else { - /* - * We don't expect to get here. - * future cmds to this device will get selection - * timeout as if the device was gone. - */ - hpsa_show_dev_msg(KERN_WARNING, h, removed[i], - "didn't find device for removal."); - } - } + if (removed[i]->expose_device) + hpsa_remove_device(h, removed[i]); kfree(removed[i]); removed[i] = NULL; } /* Notify scsi mid layer of any added devices */ for (i = 0; i < nadded; i++) { + int rc = 0; + if (added[i] == NULL) continue; if (!(added[i]->expose_device)) continue; - if (scsi_add_device(sh, added[i]->bus, - added[i]->target, added[i]->lun) == 0) + rc = hpsa_add_device(h, added[i]); + if (!rc) continue; - dev_warn(&h->pdev->dev, "addition failed, device not added."); + dev_warn(&h->pdev->dev, + "addition failed %d, device not added.", rc); /* now we have to remove it from h->dev, * since it didn't get added to scsi mid layer */ -- cgit v1.2.3 From 66749d0d617a9cda967f168802f1fb1a6e598a92 Mon Sep 17 00:00:00 2001 From: Scott Teel Date: Wed, 4 Nov 2015 15:51:57 -0600 Subject: hpsa: generalize external arrays External array LUNs must use target and lun numbers assigned by the external array. So the driver must treat these differently from local LUNs when assigning lun/target. LUN's 'model' field has been used to detect Lun types that need special treatment, but the desire is to eliminate the need to reference specific array models, and support any external array. Pass-through RAID (PTRAID) luns are not luns of the local controller, so they are not reported in LUN count of command 'ID controller'. However, they ARE reported in "Report logical Luns" command. Local luns are listed first, then PTRAID LUNs. The number of luns from "Report LUNs" in excess of those reported by 'ID controller' are therefore the PTRAID LUNS. We can now remove function is_ext_target, and the 'white list' array of supported model names. Reviewed-by: Scott Teel Reviewed-by: Justin Lindley Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Reviewed-by: Matthew R. Ochs Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 139 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 113 insertions(+), 26 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 0af4c670c7cd..1a67d63d5585 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -275,7 +275,6 @@ static int hpsa_scsi_ioaccel_queue_command(struct ctlr_info *h, static void hpsa_command_resubmit_worker(struct work_struct *work); static u32 lockup_detected(struct ctlr_info *h); static int detect_controller_lockup(struct ctlr_info *h); -static int is_ext_target(struct ctlr_info *h, struct hpsa_scsi_dev_t *device); static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev) { @@ -776,7 +775,7 @@ static ssize_t path_info_show(struct device *dev, hdev->bus, hdev->target, hdev->lun, scsi_device_type(hdev->devtype)); - if (is_ext_target(h, hdev) || + if (hdev->external || hdev->devtype == TYPE_RAID || is_logical_device(hdev)) { output_len += snprintf(path[i] + output_len, @@ -3034,6 +3033,35 @@ out: return rc; } +static int hpsa_bmic_id_controller(struct ctlr_info *h, + struct bmic_identify_controller *buf, size_t bufsize) +{ + int rc = IO_OK; + struct CommandList *c; + struct ErrorInfo *ei; + + c = cmd_alloc(h); + + rc = fill_cmd(c, BMIC_IDENTIFY_CONTROLLER, h, buf, bufsize, + 0, RAID_CTLR_LUNID, TYPE_CMD); + if (rc) + goto out; + + rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, + PCI_DMA_FROMDEVICE, NO_TIMEOUT); + if (rc) + goto out; + ei = c->err_info; + if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) { + hpsa_scsi_interpret_error(h, c); + rc = -1; + } +out: + cmd_free(h, c); + return rc; +} + + static int hpsa_bmic_id_physical_device(struct ctlr_info *h, unsigned char scsi3addr[], u16 bmic_device_index, struct bmic_identify_physical_device *buf, size_t bufsize) @@ -3510,27 +3538,6 @@ static void hpsa_update_device_supports_aborts(struct ctlr_info *h, } } -static unsigned char *ext_target_model[] = { - "MSA2012", - "MSA2024", - "MSA2312", - "MSA2324", - "P2000 G3 SAS", - "MSA 2040 SAS", - NULL, -}; - -static int is_ext_target(struct ctlr_info *h, struct hpsa_scsi_dev_t *device) -{ - int i; - - for (i = 0; ext_target_model[i]; i++) - if (strncmp(device->model, ext_target_model[i], - strlen(ext_target_model[i])) == 0) - return 1; - return 0; -} - /* * Helper function to assign bus, target, lun mapping of devices. * Logical drive target and lun are assigned at this time, but @@ -3554,7 +3561,7 @@ static void figure_bus_target_lun(struct ctlr_info *h, return; } /* It's a logical device */ - if (is_ext_target(h, device)) { + if (device->external) { hpsa_set_bus_target_lun(device, HPSA_EXTERNAL_RAID_VOLUME_BUS, (lunid >> 16) & 0x3fff, lunid & 0x00ff); @@ -3588,7 +3595,7 @@ static int add_ext_target_dev(struct ctlr_info *h, if (!is_logical_dev_addr_mode(lunaddrbytes)) return 0; /* It's the logical targets that may lack lun 0. */ - if (!is_ext_target(h, tmpdevice)) + if (!tmpdevice->external) return 0; /* Only external target devices have this problem. */ if (tmpdevice->lun == 0) /* if lun is 0, then we have a lun 0. */ @@ -3647,6 +3654,27 @@ static int hpsa_get_pdisk_of_ioaccel2(struct ctlr_info *h, return 0; } +static int figure_external_status(struct ctlr_info *h, int raid_ctlr_position, + int i, int nphysicals, int nlocal_logicals) +{ + /* In report logicals, local logicals are listed first, + * then any externals. + */ + int logicals_start = nphysicals + (raid_ctlr_position == 0); + + if (i == raid_ctlr_position) + return 0; + + if (i < logicals_start) + return 0; + + /* i is in logicals range, but still within local logicals */ + if ((i - nphysicals - (raid_ctlr_position == 0)) < nlocal_logicals) + return 0; + + return 1; /* it's an external lun */ +} + /* * Do CISS_REPORT_PHYS and CISS_REPORT_LOG. Data is returned in physdev, * logdev. The number of luns in physdev and logdev are returned in @@ -3770,6 +3798,32 @@ static void hpsa_get_path_info(struct hpsa_scsi_dev_t *this_device, sizeof(this_device->bay)); } +/* get number of local logical disks. */ +static int hpsa_set_local_logical_count(struct ctlr_info *h, + struct bmic_identify_controller *id_ctlr, + u32 *nlocals) +{ + int rc; + + if (!id_ctlr) { + dev_warn(&h->pdev->dev, "%s: id_ctlr buffer is NULL.\n", + __func__); + return -ENOMEM; + } + memset(id_ctlr, 0, sizeof(*id_ctlr)); + rc = hpsa_bmic_id_controller(h, id_ctlr, sizeof(*id_ctlr)); + if (!rc) + if (id_ctlr->configured_logical_drive_count < 256) + *nlocals = id_ctlr->configured_logical_drive_count; + else + *nlocals = le16_to_cpu( + id_ctlr->extended_logical_unit_count); + else + *nlocals = -1; + return rc; +} + + static void hpsa_update_scsi_devices(struct ctlr_info *h) { /* the idea here is we could get notified @@ -3785,8 +3839,10 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) struct ReportExtendedLUNdata *physdev_list = NULL; struct ReportLUNdata *logdev_list = NULL; struct bmic_identify_physical_device *id_phys = NULL; + struct bmic_identify_controller *id_ctlr = NULL; u32 nphysicals = 0; u32 nlogicals = 0; + u32 nlocal_logicals = 0; u32 ndev_allocated = 0; struct hpsa_scsi_dev_t **currentsd, *this_device, *tmpdevice; int ncurrent = 0; @@ -3800,9 +3856,10 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) logdev_list = kzalloc(sizeof(*logdev_list), GFP_KERNEL); tmpdevice = kzalloc(sizeof(*tmpdevice), GFP_KERNEL); id_phys = kzalloc(sizeof(*id_phys), GFP_KERNEL); + id_ctlr = kzalloc(sizeof(*id_ctlr), GFP_KERNEL); if (!currentsd || !physdev_list || !logdev_list || - !tmpdevice || !id_phys) { + !tmpdevice || !id_phys || !id_ctlr) { dev_err(&h->pdev->dev, "out of memory\n"); goto out; } @@ -3816,6 +3873,13 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) goto out; } + /* Set number of local logicals (non PTRAID) */ + if (hpsa_set_local_logical_count(h, id_ctlr, &nlocal_logicals)) { + dev_warn(&h->pdev->dev, + "%s: Can't determine number of local logical devices.\n", + __func__); + } + /* We might see up to the maximum number of logical and physical disks * plus external target devices, and a device for the local RAID * controller. @@ -3879,6 +3943,11 @@ 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]; @@ -3962,6 +4031,7 @@ out: kfree(currentsd); kfree(physdev_list); kfree(logdev_list); + kfree(id_ctlr); kfree(id_phys); } @@ -6414,6 +6484,23 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, c->Request.CDB[7] = (size >> 16) & 0xFF; c->Request.CDB[8] = (size >> 8) & 0XFF; break; + case BMIC_IDENTIFY_CONTROLLER: + c->Request.CDBLen = 10; + c->Request.type_attr_dir = + TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ); + c->Request.Timeout = 0; + c->Request.CDB[0] = BMIC_READ; + c->Request.CDB[1] = 0; + c->Request.CDB[2] = 0; + c->Request.CDB[3] = 0; + c->Request.CDB[4] = 0; + c->Request.CDB[5] = 0; + c->Request.CDB[6] = BMIC_IDENTIFY_CONTROLLER; + c->Request.CDB[7] = (size >> 16) & 0xFF; + c->Request.CDB[8] = (size >> 8) & 0XFF; + c->Request.CDB[9] = 0; + break; + default: dev_warn(&h->pdev->dev, "unknown command 0x%c\n", cmd); BUG(); -- cgit v1.2.3 From 2d62a33e05d471bef6b2e5478f57d05b9baded85 Mon Sep 17 00:00:00 2001 From: Scott Teel Date: Wed, 4 Nov 2015 15:52:03 -0600 Subject: hpsa: eliminate fake lun0 enclosures We don't need to create fake enclosure devices at Lun0 in external target array configurations anymore. This was done to support Pre-SCSI rev 5 controllers that didn't suppoprt report luns commands, so the SCSI layer had to scan targets. If there was no LUN at LUN 0, then the target scan would stop, and move to the next target. Lun0 enclosure device was added to prevent sparsely-numbered LUNs from being missed. Reviewed-by: Scott Teel Reviewed-by: Justin Lindley Reviewed-by: Kevin Barnett Reviewed-by: Matthew R. Ochs Reviewed-by: Hannes Reinecke Reviewed-by: Tomas Henzl Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 68 ----------------------------------------------------- 1 file changed, 68 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 1a67d63d5585..c843dd288a4e 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3571,60 +3571,6 @@ static void figure_bus_target_lun(struct ctlr_info *h, 0, lunid & 0x3fff); } -/* - * If there is no lun 0 on a target, linux won't find any devices. - * For the external targets (arrays), we have to manually detect the enclosure - * which is at lun zero, as CCISS_REPORT_PHYSICAL_LUNS doesn't report - * it for some reason. *tmpdevice is the target we're adding, - * this_device is a pointer into the current element of currentsd[] - * that we're building up in update_scsi_devices(), below. - * lunzerobits is a bitmap that tracks which targets already have a - * lun 0 assigned. - * Returns 1 if an enclosure was added, 0 if not. - */ -static int add_ext_target_dev(struct ctlr_info *h, - struct hpsa_scsi_dev_t *tmpdevice, - struct hpsa_scsi_dev_t *this_device, u8 *lunaddrbytes, - unsigned long lunzerobits[], int *n_ext_target_devs) -{ - unsigned char scsi3addr[8]; - - if (test_bit(tmpdevice->target, lunzerobits)) - return 0; /* There is already a lun 0 on this target. */ - - if (!is_logical_dev_addr_mode(lunaddrbytes)) - return 0; /* It's the logical targets that may lack lun 0. */ - - if (!tmpdevice->external) - return 0; /* Only external target devices have this problem. */ - - if (tmpdevice->lun == 0) /* if lun is 0, then we have a lun 0. */ - return 0; - - memset(scsi3addr, 0, 8); - scsi3addr[3] = tmpdevice->target; - if (is_hba_lunid(scsi3addr)) - return 0; /* Don't add the RAID controller here. */ - - if (is_scsi_rev_5(h)) - return 0; /* p1210m doesn't need to do this. */ - - if (*n_ext_target_devs >= MAX_EXT_TARGETS) { - dev_warn(&h->pdev->dev, "Maximum number of external " - "target devices exceeded. Check your hardware " - "configuration."); - return 0; - } - - if (hpsa_update_device_info(h, scsi3addr, this_device, NULL)) - return 0; - (*n_ext_target_devs)++; - hpsa_set_bus_target_lun(this_device, - tmpdevice->bus, tmpdevice->target, 0); - hpsa_update_device_supports_aborts(h, this_device, scsi3addr); - set_bit(tmpdevice->target, lunzerobits); - return 1; -} /* * Get address of physical disk used for an ioaccel2 mode command: @@ -3952,20 +3898,6 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) hpsa_update_device_supports_aborts(h, tmpdevice, lunaddrbytes); this_device = currentsd[ncurrent]; - /* - * For external target devices, we have to insert a LUN 0 which - * doesn't show up in CCISS_REPORT_PHYSICAL data, but there - * is nonetheless an enclosure device there. We have to - * present that otherwise linux won't find anything if - * there is no lun 0. - */ - if (add_ext_target_dev(h, tmpdevice, this_device, - lunaddrbytes, lunzerobits, - &n_ext_target_devs)) { - ncurrent++; - this_device = currentsd[ncurrent]; - } - *this_device = *tmpdevice; this_device->physical_device = physical_device; -- cgit v1.2.3 From 34592254c13324add1972e6a7d5f6636d95ade33 Mon Sep 17 00:00:00 2001 From: Scott Teel Date: Wed, 4 Nov 2015 15:52:09 -0600 Subject: hpsa: add discovery polling for PT RAID devices. There are problems with getting configuration change notification in pass-through RAID environments. So, activate flag h->discovery_polling when one of these devices is detected in update_scsi_devices. After discovery_polling is set, execute a report luns from rescan_controller_worker (every 30 seconds). If the data from report_luns is different than last time (binary compare), execute a full rescan via update_scsi_devices. Reviewed-by: Scott Teel Reviewed-by: Justin Lindley Reviewed-by: Kevin Barnett Reviewed-by: Hannes Reinecke Reviewed-by: Matthew R. Ochs Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index c843dd288a4e..acfbbb2a3e7a 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -275,6 +275,7 @@ static int hpsa_scsi_ioaccel_queue_command(struct ctlr_info *h, static void hpsa_command_resubmit_worker(struct work_struct *work); static u32 lockup_detected(struct ctlr_info *h); static int detect_controller_lockup(struct ctlr_info *h); +static int hpsa_luns_changed(struct ctlr_info *h); static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev) { @@ -3898,6 +3899,18 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) hpsa_update_device_supports_aborts(h, tmpdevice, lunaddrbytes); this_device = currentsd[ncurrent]; + /* Turn on discovery_polling if there are ext target devices. + * Event-based change notification is unreliable for those. + */ + if (!h->discovery_polling) { + if (tmpdevice->external) { + h->discovery_polling = 1; + dev_info(&h->pdev->dev, + "External target, activate discovery polling.\n"); + } + } + + *this_device = *tmpdevice; this_device->physical_device = physical_device; @@ -8016,6 +8029,41 @@ static int hpsa_offline_devices_ready(struct ctlr_info *h) return 0; } +static int hpsa_luns_changed(struct ctlr_info *h) +{ + int rc = 1; /* assume there are changes */ + struct ReportLUNdata *logdev = NULL; + + /* if we can't find out if lun data has changed, + * assume that it has. + */ + + if (!h->lastlogicals) + goto out; + + logdev = kzalloc(sizeof(*logdev), GFP_KERNEL); + if (!logdev) { + dev_warn(&h->pdev->dev, + "Out of memory, can't track lun changes.\n"); + goto out; + } + if (hpsa_scsi_do_report_luns(h, 1, logdev, sizeof(*logdev), 0)) { + dev_warn(&h->pdev->dev, + "report luns failed, can't track lun changes.\n"); + goto out; + } + if (memcmp(logdev, h->lastlogicals, sizeof(*logdev))) { + dev_info(&h->pdev->dev, + "Lun changes detected.\n"); + memcpy(h->lastlogicals, logdev, sizeof(*logdev)); + goto out; + } else + rc = 0; /* no changes detected. */ +out: + kfree(logdev); + return rc; +} + static void hpsa_rescan_ctlr_worker(struct work_struct *work) { unsigned long flags; @@ -8031,6 +8079,18 @@ static void hpsa_rescan_ctlr_worker(struct work_struct *work) hpsa_ack_ctlr_events(h); hpsa_scan_start(h->scsi_host); scsi_host_put(h->scsi_host); + } else if (h->discovery_polling) { + if (hpsa_luns_changed(h)) { + struct Scsi_Host *sh = NULL; + + dev_info(&h->pdev->dev, + "driver discovery polling rescan.\n"); + sh = scsi_host_get(h->scsi_host); + if (sh != NULL) { + hpsa_scan_start(sh); + scsi_host_put(sh); + } + } } spin_lock_irqsave(&h->lock, flags); if (!h->remove_in_progress) @@ -8271,6 +8331,8 @@ reinit_after_soft_reset: /* Enable Accelerated IO path at driver layer */ h->acciopath_status = 1; + /* Disable discovery polling.*/ + h->discovery_polling = 0; /* Turn the interrupts on so we can service requests */ @@ -8278,6 +8340,11 @@ reinit_after_soft_reset: hpsa_hba_inquiry(h); + h->lastlogicals = kzalloc(sizeof(*(h->lastlogicals)), GFP_KERNEL); + if (!h->lastlogicals) + dev_info(&h->pdev->dev, + "Can't track change to report lun data\n"); + /* Monitor the controller for firmware lockups */ h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL; INIT_DELAYED_WORK(&h->monitor_ctlr_work, hpsa_monitor_ctlr_worker); @@ -8415,6 +8482,7 @@ static void hpsa_remove_one(struct pci_dev *pdev) hpsa_free_performant_mode(h); /* init_one 7 */ hpsa_free_sg_chain_blocks(h); /* init_one 6 */ hpsa_free_cmd_pool(h); /* init_one 5 */ + kfree(h->lastlogicals); /* hpsa_free_irqs already called via hpsa_shutdown init_one 4 */ -- cgit v1.2.3 From c2adae44e9161612c89e52d233c83086195f454c Mon Sep 17 00:00:00 2001 From: Scott Teel Date: Wed, 4 Nov 2015 15:52:16 -0600 Subject: hpsa: disable report lun data caching When external target arrays are present, disable the firmware's normal behavior of returning a cached copy of the report lun data, and force it to collect new data each time we request a report luns. This is necessary for external arrays, since there may be no reliable signal from the external array to the smart array when lun configuration changes, and thus when driver requests report luns, it may be stale data. Use diag options to turn off RPL data caching. Reviewed-by: Scott Teel Reviewed-by: Justin Lindley Reviewed-by: Kevin Barnett Reviewed-by: Hannes Reinecke Reviewed-by: Matthew R. Ochs Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index acfbbb2a3e7a..91e7005811d6 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -275,6 +275,7 @@ static int hpsa_scsi_ioaccel_queue_command(struct ctlr_info *h, static void hpsa_command_resubmit_worker(struct work_struct *work); static u32 lockup_detected(struct ctlr_info *h); static int detect_controller_lockup(struct ctlr_info *h); +static void hpsa_disable_rld_caching(struct ctlr_info *h); static int hpsa_luns_changed(struct ctlr_info *h); static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev) @@ -6380,6 +6381,24 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, c->Request.CDB[8] = (size >> 8) & 0xFF; c->Request.CDB[9] = size & 0xFF; break; + case BMIC_SENSE_DIAG_OPTIONS: + c->Request.CDBLen = 16; + c->Request.type_attr_dir = + TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ); + c->Request.Timeout = 0; + /* Spec says this should be BMIC_WRITE */ + c->Request.CDB[0] = BMIC_READ; + c->Request.CDB[6] = BMIC_SENSE_DIAG_OPTIONS; + break; + case BMIC_SET_DIAG_OPTIONS: + c->Request.CDBLen = 16; + c->Request.type_attr_dir = + TYPE_ATTR_DIR(cmd_type, + ATTR_SIMPLE, XFER_WRITE); + c->Request.Timeout = 0; + c->Request.CDB[0] = BMIC_WRITE; + c->Request.CDB[6] = BMIC_SET_DIAG_OPTIONS; + break; case HPSA_CACHE_FLUSH: c->Request.CDBLen = 12; c->Request.type_attr_dir = @@ -8080,6 +8099,7 @@ static void hpsa_rescan_ctlr_worker(struct work_struct *work) hpsa_scan_start(h->scsi_host); scsi_host_put(h->scsi_host); } else if (h->discovery_polling) { + hpsa_disable_rld_caching(h); if (hpsa_luns_changed(h)) { struct Scsi_Host *sh = NULL; @@ -8417,6 +8437,71 @@ out: kfree(flush_buf); } +/* Make controller gather fresh report lun data each time we + * send down a report luns request + */ +static void hpsa_disable_rld_caching(struct ctlr_info *h) +{ + u32 *options; + struct CommandList *c; + int rc; + + /* Don't bother trying to set diag options if locked up */ + if (unlikely(h->lockup_detected)) + return; + + options = kzalloc(sizeof(*options), GFP_KERNEL); + if (!options) { + dev_err(&h->pdev->dev, + "Error: failed to disable rld caching, during alloc.\n"); + return; + } + + c = cmd_alloc(h); + + /* first, get the current diag options settings */ + if (fill_cmd(c, BMIC_SENSE_DIAG_OPTIONS, h, options, 4, 0, + RAID_CTLR_LUNID, TYPE_CMD)) + goto errout; + + rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, + PCI_DMA_FROMDEVICE, NO_TIMEOUT); + if ((rc != 0) || (c->err_info->CommandStatus != 0)) + goto errout; + + /* Now, set the bit for disabling the RLD caching */ + *options |= HPSA_DIAG_OPTS_DISABLE_RLD_CACHING; + + if (fill_cmd(c, BMIC_SET_DIAG_OPTIONS, h, options, 4, 0, + RAID_CTLR_LUNID, TYPE_CMD)) + goto errout; + + rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, + PCI_DMA_TODEVICE, NO_TIMEOUT); + if ((rc != 0) || (c->err_info->CommandStatus != 0)) + goto errout; + + /* Now verify that it got set: */ + if (fill_cmd(c, BMIC_SENSE_DIAG_OPTIONS, h, options, 4, 0, + RAID_CTLR_LUNID, TYPE_CMD)) + goto errout; + + rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, + PCI_DMA_FROMDEVICE, NO_TIMEOUT); + if ((rc != 0) || (c->err_info->CommandStatus != 0)) + goto errout; + + if (*options && HPSA_DIAG_OPTS_DISABLE_RLD_CACHING) + goto out; + +errout: + dev_err(&h->pdev->dev, + "Error: failed to disable report lun data caching.\n"); +out: + cmd_free(h, c); + kfree(options); +} + static void hpsa_shutdown(struct pci_dev *pdev) { struct ctlr_info *h; -- cgit v1.2.3 From 7c59a0d46125d8c47c840e874d2cc9dd082afdf7 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 4 Nov 2015 15:52:22 -0600 Subject: hpsa: enhance device messages Reviewed-by: Justin Lindley Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Reviewed-by: Tomas Henzl Reviewed-by: Hannes Reinecke Reviewed-by: Matthew R. Ochs Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 91e7005811d6..64638d56fb65 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -608,7 +608,7 @@ static inline int is_logical_dev_addr_mode(unsigned char scsi3addr[]) } static const char * const raid_label[] = { "0", "4", "1(+0)", "5", "5+1", "6", - "1(+0)ADM", "UNKNOWN" + "1(+0)ADM", "UNKNOWN", "PHYS DRV" }; #define HPSA_RAID_0 0 #define HPSA_RAID_4 1 @@ -617,7 +617,8 @@ static const char * const raid_label[] = { "0", "4", "1(+0)", "5", "5+1", "6", #define HPSA_RAID_51 4 #define HPSA_RAID_6 5 /* also used for RAID 60 */ #define HPSA_RAID_ADM 6 /* also used for RAID 1+0 ADM */ -#define RAID_UNKNOWN (ARRAY_SIZE(raid_label) - 1) +#define RAID_UNKNOWN (ARRAY_SIZE(raid_label) - 2) +#define PHYSICAL_DRIVE (ARRAY_SIZE(raid_label) - 1) static inline bool is_logical_device(struct hpsa_scsi_dev_t *device) { @@ -1143,18 +1144,52 @@ static int hpsa_find_target_lun(struct ctlr_info *h, static void hpsa_show_dev_msg(const char *level, struct ctlr_info *h, struct hpsa_scsi_dev_t *dev, char *description) { +#define LABEL_SIZE 25 + char label[LABEL_SIZE]; + if (h == NULL || h->pdev == NULL || h->scsi_host == NULL) return; + switch (dev->devtype) { + case TYPE_RAID: + snprintf(label, LABEL_SIZE, "controller"); + break; + case TYPE_ENCLOSURE: + snprintf(label, LABEL_SIZE, "enclosure"); + break; + case TYPE_DISK: + if (dev->external) + snprintf(label, LABEL_SIZE, "external"); + else if (!is_logical_dev_addr_mode(dev->scsi3addr)) + snprintf(label, LABEL_SIZE, "%s", + raid_label[PHYSICAL_DRIVE]); + else + snprintf(label, LABEL_SIZE, "RAID-%s", + dev->raid_level > RAID_UNKNOWN ? "?" : + raid_label[dev->raid_level]); + break; + case TYPE_ROM: + snprintf(label, LABEL_SIZE, "rom"); + break; + case TYPE_TAPE: + snprintf(label, LABEL_SIZE, "tape"); + break; + case TYPE_MEDIUM_CHANGER: + snprintf(label, LABEL_SIZE, "changer"); + break; + default: + snprintf(label, LABEL_SIZE, "UNKNOWN"); + break; + } + dev_printk(level, &h->pdev->dev, - "scsi %d:%d:%d:%d: %s %s %.8s %.16s RAID-%s SSDSmartPathCap%c En%c Exp=%d\n", + "scsi %d:%d:%d:%d: %s %s %.8s %.16s %s SSDSmartPathCap%c En%c Exp=%d\n", h->scsi_host->host_no, dev->bus, dev->target, dev->lun, description, scsi_device_type(dev->devtype), dev->vendor, dev->model, - dev->raid_level > RAID_UNKNOWN ? - "RAID-?" : raid_label[dev->raid_level], + label, dev->offload_config ? '+' : '-', dev->offload_enabled ? '+' : '-', dev->expose_device); -- cgit v1.2.3 From 1faf072c0e3ab0bc41fc1d343883dac704b82946 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Wed, 4 Nov 2015 15:52:28 -0600 Subject: hpsa: fix multiple issues in path_info_show path_info_show() seems to be broken in multiple ways. First, there's 817 return snprintf(buf, output_len+1, "%s%s%s%s%s%s%s%s", 818 path[0], path[1], path[2], path[3], 819 path[4], path[5], path[6], path[7]); so hopefully output_len contains the combined length of the eight strings. Otherwise, snprintf will stop copying to the output buffer, but still end up reporting that combined length - which in turn would result in user-space getting a bunch of useless nul bytes (thankfully the upper sysfs layer seems to clear the output buffer before passing it to the various ->show routines). But we have 767 output_len = snprintf(path[i], 768 PATH_STRING_LEN, "[%d:%d:%d:%d] %20.20s ", 769 h->scsi_host->host_no, 770 hdev->bus, hdev->target, hdev->lun, 771 scsi_device_type(hdev->devtype)); so output_len at best contains the length of the last string printed. Inside the loop, we then otherwise add to output_len. By magic, we still have PATH_STRING_LEN available every time... This wouldn't really be a problem if the bean-counting has been done properly and each line actually does fit in 50 bytes, and maybe it does, but I don't immediately see why. Suppose we end up taking this branch: 802 output_len += snprintf(path[i] + output_len, 803 PATH_STRING_LEN, 804 "BOX: %hhu BAY: %hhu %s\n", 805 box, bay, active); An optimistic estimate says this uses strlen("BOX: 1 BAY: 2 Active\n") which is 21. Now add the 20 bytes guaranteed by the %20.20s and then some for the rest of that format string, and we're easily over 50 bytes. I don't think we can get over 100 bytes even being pessimistic, so this just means we'll scribble into the next path[i+1] and maybe get that overwritten later, leading to some garbled output (in fact, since we'd overwrite the previous string's 0-terminator, we could end up with one very long string and then print various suffixes of that, leading to much more than 400 bytes of output). Except of course when we're filling path[7], where overrunning it means writing random stuff to the kernel stack, which is usually a lot of fun. We can fix all of that and get rid of the 400 byte stack buffer by simply writing directly to the given output buffer, which the upper layer guarantees is at least PAGE_SIZE. s[c]nprintf doesn't care where it is writing to, so this doesn't make the spin lock hold time any longer. Using scnprintf ensures that output_len always represents the number of bytes actually written to the buffer, so we'll report the proper amount to the upper layer. Reviewed-by: Hannes Reinecke Reviewed-by: Tomas Henzl Reviewed-by: Matthew R. Ochs Signed-off-by: Rasmus Villemoes Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 64638d56fb65..910b2d1513c0 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -734,7 +734,6 @@ static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev, } #define MAX_PATHS 8 -#define PATH_STRING_LEN 50 static ssize_t path_info_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -750,9 +749,7 @@ static ssize_t path_info_show(struct device *dev, u8 path_map_index = 0; char *active; unsigned char phys_connector[2]; - unsigned char path[MAX_PATHS][PATH_STRING_LEN]; - memset(path, 0, MAX_PATHS * PATH_STRING_LEN); sdev = to_scsi_device(dev); h = sdev_to_hba(sdev); spin_lock_irqsave(&h->devlock, flags); @@ -772,8 +769,9 @@ static ssize_t path_info_show(struct device *dev, else continue; - output_len = snprintf(path[i], - PATH_STRING_LEN, "[%d:%d:%d:%d] %20.20s ", + output_len += scnprintf(buf + output_len, + PAGE_SIZE - output_len, + "[%d:%d:%d:%d] %20.20s ", h->scsi_host->host_no, hdev->bus, hdev->target, hdev->lun, scsi_device_type(hdev->devtype)); @@ -781,9 +779,9 @@ static ssize_t path_info_show(struct device *dev, if (hdev->external || hdev->devtype == TYPE_RAID || is_logical_device(hdev)) { - output_len += snprintf(path[i] + output_len, - PATH_STRING_LEN, "%s\n", - active); + output_len += snprintf(buf + output_len, + PAGE_SIZE - output_len, + "%s\n", active); continue; } @@ -795,35 +793,33 @@ static ssize_t path_info_show(struct device *dev, if (phys_connector[1] < '0') phys_connector[1] = '0'; if (hdev->phys_connector[i] > 0) - output_len += snprintf(path[i] + output_len, - PATH_STRING_LEN, + output_len += snprintf(buf + output_len, + PAGE_SIZE - output_len, "PORT: %.2s ", phys_connector); if (hdev->devtype == TYPE_DISK && hdev->expose_device) { if (box == 0 || box == 0xFF) { - output_len += snprintf(path[i] + output_len, - PATH_STRING_LEN, + output_len += snprintf(buf + output_len, + PAGE_SIZE - output_len, "BAY: %hhu %s\n", bay, active); } else { - output_len += snprintf(path[i] + output_len, - PATH_STRING_LEN, + output_len += snprintf(buf + output_len, + PAGE_SIZE - output_len, "BOX: %hhu BAY: %hhu %s\n", box, bay, active); } } else if (box != 0 && box != 0xFF) { - output_len += snprintf(path[i] + output_len, - PATH_STRING_LEN, "BOX: %hhu %s\n", + output_len += snprintf(buf + output_len, + PAGE_SIZE - output_len, "BOX: %hhu %s\n", box, active); } else - output_len += snprintf(path[i] + output_len, - PATH_STRING_LEN, "%s\n", active); + output_len += snprintf(buf + output_len, + PAGE_SIZE - output_len, "%s\n", active); } spin_unlock_irqrestore(&h->devlock, flags); - return snprintf(buf, output_len+1, "%s%s%s%s%s%s%s%s", - path[0], path[1], path[2], path[3], - path[4], path[5], path[6], path[7]); + return output_len; } static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL); -- cgit v1.2.3 From d04e62b9d63a7498735761dc40eaed88b7fd9d80 Mon Sep 17 00:00:00 2001 From: Kevin Barnett Date: Wed, 4 Nov 2015 15:52:34 -0600 Subject: hpsa: add in sas transport class Reviewed-by: Scott Teel Reviewed-by: Justin Lindley Reviewed-by: Kevin Barnett Reviewed-by: Hannes Reinecke Reviewed-by: Tomas Henzl Reviewed-by: Matthew R. Ochs Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 550 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 529 insertions(+), 21 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 910b2d1513c0..5f02a603eb4d 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -205,6 +206,16 @@ static struct board_type products[] = { {0xFFFF103C, "Unknown Smart Array", &SA5_access}, }; +static struct scsi_transport_template *hpsa_sas_transport_template; +static int hpsa_add_sas_host(struct ctlr_info *h); +static void hpsa_delete_sas_host(struct ctlr_info *h); +static int hpsa_add_sas_device(struct hpsa_sas_node *hpsa_sas_node, + struct hpsa_scsi_dev_t *device); +static void hpsa_remove_sas_device(struct hpsa_scsi_dev_t *device); +static struct hpsa_scsi_dev_t + *hpsa_find_device_by_sas_rphy(struct ctlr_info *h, + struct sas_rphy *rphy); + #define SCSI_CMD_BUSY ((struct scsi_cmnd *)&hpsa_cmd_busy) static const struct scsi_cmnd hpsa_cmd_busy; #define SCSI_CMD_IDLE ((struct scsi_cmnd *)&hpsa_cmd_idle) @@ -276,6 +287,8 @@ static void hpsa_command_resubmit_worker(struct work_struct *work); static u32 lockup_detected(struct ctlr_info *h); 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 int hpsa_luns_changed(struct ctlr_info *h); static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev) @@ -1692,8 +1705,12 @@ static int hpsa_add_device(struct ctlr_info *h, struct hpsa_scsi_dev_t *device) if (!h->scsi_host) return 1; - rc = scsi_add_device(h->scsi_host, device->bus, + if (is_logical_device(device)) /* RAID */ + rc = scsi_add_device(h->scsi_host, device->bus, device->target, device->lun); + else /* HBA */ + rc = hpsa_add_sas_device(h->sas_host, device); + return rc; } @@ -1705,21 +1722,23 @@ static void hpsa_remove_device(struct ctlr_info *h, if (!h->scsi_host) return; - sdev = scsi_device_lookup(h->scsi_host, device->bus, + if (is_logical_device(device)) { /* RAID */ + sdev = scsi_device_lookup(h->scsi_host, device->bus, device->target, device->lun); - - if (sdev) { - scsi_remove_device(sdev); - scsi_device_put(sdev); - } else { - /* - * We don't expect to get here. Future commands - * to this device will get a selection timeout as - * if the device were gone. - */ - hpsa_show_dev_msg(KERN_WARNING, h, device, + if (sdev) { + scsi_remove_device(sdev); + scsi_device_put(sdev); + } else { + /* + * We don't expect to get here. Future commands + * to this device will get a selection timeout as + * if the device were gone. + */ + hpsa_show_dev_msg(KERN_WARNING, h, device, "didn't find device for removal."); - } + } + } else /* HBA */ + hpsa_remove_sas_device(device); } static void adjust_hpsa_scsi_table(struct ctlr_info *h, @@ -1912,11 +1931,24 @@ static int hpsa_slave_alloc(struct scsi_device *sdev) h = sdev_to_hba(sdev); spin_lock_irqsave(&h->devlock, flags); - sd = lookup_hpsa_scsi_dev(h, sdev_channel(sdev), - sdev_id(sdev), sdev->lun); - if (likely(sd)) { + if (sdev_channel(sdev) == HPSA_PHYSICAL_DEVICE_BUS) { + struct scsi_target *starget; + struct sas_rphy *rphy; + + starget = scsi_target(sdev); + rphy = target_to_rphy(starget); + sd = hpsa_find_device_by_sas_rphy(h, rphy); + if (sd) { + sd->target = sdev_id(sdev); + sd->lun = sdev->lun; + } + } else + sd = lookup_hpsa_scsi_dev(h, sdev_channel(sdev), + sdev_id(sdev), sdev->lun); + + if (sd && sd->expose_device) { atomic_set(&sd->ioaccel_cmds_out, 0); - sdev->hostdata = sd->expose_device ? sd : NULL; + sdev->hostdata = sd; } else sdev->hostdata = NULL; spin_unlock_irqrestore(&h->devlock, flags); @@ -3066,6 +3098,38 @@ out: return rc; } +static int hpsa_bmic_sense_subsystem_information(struct ctlr_info *h, + unsigned char scsi3addr[], u16 bmic_device_index, + struct bmic_sense_subsystem_info *buf, size_t bufsize) +{ + int rc = IO_OK; + struct CommandList *c; + struct ErrorInfo *ei; + + c = cmd_alloc(h); + + rc = fill_cmd(c, BMIC_SENSE_SUBSYSTEM_INFORMATION, h, buf, bufsize, + 0, RAID_CTLR_LUNID, TYPE_CMD); + if (rc) + goto out; + + c->Request.CDB[2] = bmic_device_index & 0xff; + c->Request.CDB[9] = (bmic_device_index >> 8) & 0xff; + + rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, + PCI_DMA_FROMDEVICE, NO_TIMEOUT); + if (rc) + goto out; + ei = c->err_info; + if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) { + hpsa_scsi_interpret_error(h, c); + rc = -1; + } +out: + cmd_free(h, c); + return rc; +} + static int hpsa_bmic_id_controller(struct ctlr_info *h, struct bmic_identify_controller *buf, size_t bufsize) { @@ -3094,7 +3158,6 @@ out: return rc; } - static int hpsa_bmic_id_physical_device(struct ctlr_info *h, unsigned char scsi3addr[], u16 bmic_device_index, struct bmic_identify_physical_device *buf, size_t bufsize) @@ -3121,9 +3184,71 @@ static int hpsa_bmic_id_physical_device(struct ctlr_info *h, } out: cmd_free(h, c); + return rc; } +static u64 hpsa_get_sas_address_from_report_physical(struct ctlr_info *h, + unsigned char *scsi3addr) +{ + struct ReportExtendedLUNdata *physdev; + u32 nphysicals; + u64 sa = 0; + int i; + + physdev = kzalloc(sizeof(*physdev), GFP_KERNEL); + if (!physdev) + return 0; + + if (hpsa_scsi_do_report_phys_luns(h, physdev, sizeof(*physdev))) { + dev_err(&h->pdev->dev, "report physical LUNs failed.\n"); + kfree(physdev); + return 0; + } + nphysicals = get_unaligned_be32(physdev->LUNListLength) / 24; + + for (i = 0; i < nphysicals; i++) + if (!memcmp(&physdev->LUN[i].lunid[0], scsi3addr, 8)) { + sa = get_unaligned_be64(&physdev->LUN[i].wwid[0]); + break; + } + + kfree(physdev); + + return sa; +} + +static void hpsa_get_sas_address(struct ctlr_info *h, unsigned char *scsi3addr, + struct hpsa_scsi_dev_t *dev) +{ + int rc; + u64 sa = 0; + + if (is_hba_lunid(scsi3addr)) { + struct bmic_sense_subsystem_info *ssi; + + ssi = kzalloc(sizeof(*ssi), GFP_KERNEL); + if (ssi == NULL) { + dev_warn(&h->pdev->dev, + "%s: out of memory\n", __func__); + return; + } + + rc = hpsa_bmic_sense_subsystem_information(h, + scsi3addr, 0, ssi, sizeof(*ssi)); + if (rc == 0) { + sa = get_unaligned_be64(ssi->primary_world_wide_id); + h->sas_address = sa; + } + + kfree(ssi); + } else + sa = hpsa_get_sas_address_from_report_physical(h, scsi3addr); + + dev->sas_address = sa; +} + +/* Get a device id from inquiry page 0x83 */ static int hpsa_vpd_page_supported(struct ctlr_info *h, unsigned char scsi3addr[], u8 page) { @@ -3955,6 +4080,13 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) else this_device->expose_device = 1; + + /* + * Get the SAS address for physical devices that are exposed. + */ + if (this_device->physical_device && this_device->expose_device) + hpsa_get_sas_address(h, lunaddrbytes, this_device); + switch (this_device->devtype) { case TYPE_ROM: /* We don't *really* support actual CD-ROM devices, @@ -4000,6 +4132,18 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) if (ncurrent >= HPSA_MAX_DEVICES) break; } + + if (h->sas_host == NULL) { + int rc = 0; + + rc = hpsa_add_sas_host(h); + if (rc) { + dev_warn(&h->pdev->dev, + "Could not add sas host %d\n", rc); + goto out; + } + } + adjust_hpsa_scsi_table(h, currentsd, ncurrent); out: kfree(tmpdevice); @@ -5131,6 +5275,7 @@ static int hpsa_scsi_host_alloc(struct ctlr_info *h) sh->can_queue = h->nr_cmds - HPSA_NRESERVED_CMDS; sh->cmd_per_lun = sh->can_queue; sh->sg_tablesize = h->maxsgentries; + sh->transportt = hpsa_sas_transport_template; sh->hostdata[0] = (unsigned long) h; sh->irq = h->intr[h->intr_mode]; sh->unique_id = sh->irq; @@ -6479,6 +6624,16 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, c->Request.CDB[7] = (size >> 16) & 0xFF; c->Request.CDB[8] = (size >> 8) & 0XFF; break; + case BMIC_SENSE_SUBSYSTEM_INFORMATION: + c->Request.CDBLen = 10; + c->Request.type_attr_dir = + TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ); + c->Request.Timeout = 0; + c->Request.CDB[0] = BMIC_READ; + c->Request.CDB[6] = BMIC_SENSE_SUBSYSTEM_INFORMATION; + c->Request.CDB[7] = (size >> 16) & 0xFF; + c->Request.CDB[8] = (size >> 8) & 0XFF; + break; case BMIC_IDENTIFY_CONTROLLER: c->Request.CDBLen = 10; c->Request.type_attr_dir = @@ -6495,7 +6650,6 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, c->Request.CDB[8] = (size >> 8) & 0XFF; c->Request.CDB[9] = 0; break; - default: dev_warn(&h->pdev->dev, "unknown command 0x%c\n", cmd); BUG(); @@ -8611,6 +8765,9 @@ static void hpsa_remove_one(struct pci_dev *pdev) free_percpu(h->lockup_detected); /* init_one 2 */ h->lockup_detected = NULL; /* init_one 2 */ /* (void) pci_disable_pcie_error_reporting(pdev); */ /* init_one 1 */ + + hpsa_delete_sas_host(h); + kfree(h); /* init_one 1 */ } @@ -9073,18 +9230,369 @@ static void hpsa_drain_accel_commands(struct ctlr_info *h) } while (1); } +static struct hpsa_sas_phy *hpsa_alloc_sas_phy( + struct hpsa_sas_port *hpsa_sas_port) +{ + struct hpsa_sas_phy *hpsa_sas_phy; + struct sas_phy *phy; + + hpsa_sas_phy = kzalloc(sizeof(*hpsa_sas_phy), GFP_KERNEL); + if (!hpsa_sas_phy) + return NULL; + + phy = sas_phy_alloc(hpsa_sas_port->parent_node->parent_dev, + hpsa_sas_port->next_phy_index); + if (!phy) { + kfree(hpsa_sas_phy); + return NULL; + } + + hpsa_sas_port->next_phy_index++; + hpsa_sas_phy->phy = phy; + hpsa_sas_phy->parent_port = hpsa_sas_port; + + return hpsa_sas_phy; +} + +static void hpsa_free_sas_phy(struct hpsa_sas_phy *hpsa_sas_phy) +{ + struct sas_phy *phy = hpsa_sas_phy->phy; + + sas_port_delete_phy(hpsa_sas_phy->parent_port->port, phy); + sas_phy_free(phy); + if (hpsa_sas_phy->added_to_port) + list_del(&hpsa_sas_phy->phy_list_entry); + kfree(hpsa_sas_phy); +} + +static int hpsa_sas_port_add_phy(struct hpsa_sas_phy *hpsa_sas_phy) +{ + int rc; + struct hpsa_sas_port *hpsa_sas_port; + struct sas_phy *phy; + struct sas_identify *identify; + + hpsa_sas_port = hpsa_sas_phy->parent_port; + phy = hpsa_sas_phy->phy; + + identify = &phy->identify; + memset(identify, 0, sizeof(*identify)); + identify->sas_address = hpsa_sas_port->sas_address; + identify->device_type = SAS_END_DEVICE; + identify->initiator_port_protocols = SAS_PROTOCOL_STP; + identify->target_port_protocols = SAS_PROTOCOL_STP; + phy->minimum_linkrate_hw = SAS_LINK_RATE_UNKNOWN; + phy->maximum_linkrate_hw = SAS_LINK_RATE_UNKNOWN; + phy->minimum_linkrate = SAS_LINK_RATE_UNKNOWN; + phy->maximum_linkrate = SAS_LINK_RATE_UNKNOWN; + phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN; + + rc = sas_phy_add(hpsa_sas_phy->phy); + if (rc) + return rc; + + sas_port_add_phy(hpsa_sas_port->port, hpsa_sas_phy->phy); + list_add_tail(&hpsa_sas_phy->phy_list_entry, + &hpsa_sas_port->phy_list_head); + hpsa_sas_phy->added_to_port = true; + + return 0; +} + +static int + hpsa_sas_port_add_rphy(struct hpsa_sas_port *hpsa_sas_port, + struct sas_rphy *rphy) +{ + struct sas_identify *identify; + + identify = &rphy->identify; + identify->sas_address = hpsa_sas_port->sas_address; + identify->initiator_port_protocols = SAS_PROTOCOL_STP; + identify->target_port_protocols = SAS_PROTOCOL_STP; + + return sas_rphy_add(rphy); +} + +static struct hpsa_sas_port + *hpsa_alloc_sas_port(struct hpsa_sas_node *hpsa_sas_node, + u64 sas_address) +{ + int rc; + struct hpsa_sas_port *hpsa_sas_port; + struct sas_port *port; + + hpsa_sas_port = kzalloc(sizeof(*hpsa_sas_port), GFP_KERNEL); + if (!hpsa_sas_port) + return NULL; + + INIT_LIST_HEAD(&hpsa_sas_port->phy_list_head); + hpsa_sas_port->parent_node = hpsa_sas_node; + + port = sas_port_alloc_num(hpsa_sas_node->parent_dev); + if (!port) + goto free_hpsa_port; + + rc = sas_port_add(port); + if (rc) + goto free_sas_port; + + hpsa_sas_port->port = port; + hpsa_sas_port->sas_address = sas_address; + list_add_tail(&hpsa_sas_port->port_list_entry, + &hpsa_sas_node->port_list_head); + + return hpsa_sas_port; + +free_sas_port: + sas_port_free(port); +free_hpsa_port: + kfree(hpsa_sas_port); + + return NULL; +} + +static void hpsa_free_sas_port(struct hpsa_sas_port *hpsa_sas_port) +{ + struct hpsa_sas_phy *hpsa_sas_phy; + struct hpsa_sas_phy *next; + + list_for_each_entry_safe(hpsa_sas_phy, next, + &hpsa_sas_port->phy_list_head, phy_list_entry) + hpsa_free_sas_phy(hpsa_sas_phy); + + sas_port_delete(hpsa_sas_port->port); + list_del(&hpsa_sas_port->port_list_entry); + kfree(hpsa_sas_port); +} + +static struct hpsa_sas_node *hpsa_alloc_sas_node(struct device *parent_dev) +{ + struct hpsa_sas_node *hpsa_sas_node; + + hpsa_sas_node = kzalloc(sizeof(*hpsa_sas_node), GFP_KERNEL); + if (hpsa_sas_node) { + hpsa_sas_node->parent_dev = parent_dev; + INIT_LIST_HEAD(&hpsa_sas_node->port_list_head); + } + + return hpsa_sas_node; +} + +static void hpsa_free_sas_node(struct hpsa_sas_node *hpsa_sas_node) +{ + struct hpsa_sas_port *hpsa_sas_port; + struct hpsa_sas_port *next; + + if (!hpsa_sas_node) + return; + + list_for_each_entry_safe(hpsa_sas_port, next, + &hpsa_sas_node->port_list_head, port_list_entry) + hpsa_free_sas_port(hpsa_sas_port); + + kfree(hpsa_sas_node); +} + +static struct hpsa_scsi_dev_t + *hpsa_find_device_by_sas_rphy(struct ctlr_info *h, + struct sas_rphy *rphy) +{ + int i; + struct hpsa_scsi_dev_t *device; + + for (i = 0; i < h->ndevices; i++) { + device = h->dev[i]; + if (!device->sas_port) + continue; + if (device->sas_port->rphy == rphy) + return device; + } + + return NULL; +} + +static int hpsa_add_sas_host(struct ctlr_info *h) +{ + int rc; + struct device *parent_dev; + struct hpsa_sas_node *hpsa_sas_node; + struct hpsa_sas_port *hpsa_sas_port; + struct hpsa_sas_phy *hpsa_sas_phy; + + parent_dev = &h->scsi_host->shost_gendev; + + hpsa_sas_node = hpsa_alloc_sas_node(parent_dev); + if (!hpsa_sas_node) + return -ENOMEM; + + hpsa_sas_port = hpsa_alloc_sas_port(hpsa_sas_node, h->sas_address); + if (!hpsa_sas_port) { + rc = -ENODEV; + goto free_sas_node; + } + + hpsa_sas_phy = hpsa_alloc_sas_phy(hpsa_sas_port); + if (!hpsa_sas_phy) { + rc = -ENODEV; + goto free_sas_port; + } + + rc = hpsa_sas_port_add_phy(hpsa_sas_phy); + if (rc) + goto free_sas_phy; + + h->sas_host = hpsa_sas_node; + + return 0; + +free_sas_phy: + hpsa_free_sas_phy(hpsa_sas_phy); +free_sas_port: + hpsa_free_sas_port(hpsa_sas_port); +free_sas_node: + hpsa_free_sas_node(hpsa_sas_node); + + return rc; +} + +static void hpsa_delete_sas_host(struct ctlr_info *h) +{ + hpsa_free_sas_node(h->sas_host); +} + +static int hpsa_add_sas_device(struct hpsa_sas_node *hpsa_sas_node, + struct hpsa_scsi_dev_t *device) +{ + int rc; + struct hpsa_sas_port *hpsa_sas_port; + struct sas_rphy *rphy; + + hpsa_sas_port = hpsa_alloc_sas_port(hpsa_sas_node, device->sas_address); + if (!hpsa_sas_port) + return -ENOMEM; + + rphy = sas_end_device_alloc(hpsa_sas_port->port); + if (!rphy) { + rc = -ENODEV; + goto free_sas_port; + } + + hpsa_sas_port->rphy = rphy; + device->sas_port = hpsa_sas_port; + + rc = hpsa_sas_port_add_rphy(hpsa_sas_port, rphy); + if (rc) + goto free_sas_port; + + return 0; + +free_sas_port: + hpsa_free_sas_port(hpsa_sas_port); + device->sas_port = NULL; + + return rc; +} + +static void hpsa_remove_sas_device(struct hpsa_scsi_dev_t *device) +{ + if (device->sas_port) { + hpsa_free_sas_port(device->sas_port); + device->sas_port = NULL; + } +} + +static int +hpsa_sas_get_linkerrors(struct sas_phy *phy) +{ + return 0; +} + +static int +hpsa_sas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) +{ + return 0; +} + +static int +hpsa_sas_get_bay_identifier(struct sas_rphy *rphy) +{ + return -ENXIO; +} + +static int +hpsa_sas_phy_reset(struct sas_phy *phy, int hard_reset) +{ + return 0; +} + +static int +hpsa_sas_phy_enable(struct sas_phy *phy, int enable) +{ + return 0; +} + +static int +hpsa_sas_phy_setup(struct sas_phy *phy) +{ + return 0; +} + +static void +hpsa_sas_phy_release(struct sas_phy *phy) +{ +} + +static int +hpsa_sas_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates) +{ + return -EINVAL; +} + +/* SMP = Serial Management Protocol */ +static int +hpsa_sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, +struct request *req) +{ + return -EINVAL; +} + +static struct sas_function_template hpsa_sas_transport_functions = { + .get_linkerrors = hpsa_sas_get_linkerrors, + .get_enclosure_identifier = hpsa_sas_get_enclosure_identifier, + .get_bay_identifier = hpsa_sas_get_bay_identifier, + .phy_reset = hpsa_sas_phy_reset, + .phy_enable = hpsa_sas_phy_enable, + .phy_setup = hpsa_sas_phy_setup, + .phy_release = hpsa_sas_phy_release, + .set_phy_speed = hpsa_sas_phy_speed, + .smp_handler = hpsa_sas_smp_handler, +}; + /* * This is it. Register the PCI driver information for the cards we control * the OS will call our registered routines when it finds one of our cards. */ static int __init hpsa_init(void) { - return pci_register_driver(&hpsa_pci_driver); + int rc; + + hpsa_sas_transport_template = + sas_attach_transport(&hpsa_sas_transport_functions); + if (!hpsa_sas_transport_template) + return -ENODEV; + + rc = pci_register_driver(&hpsa_pci_driver); + + if (rc) + sas_release_transport(hpsa_sas_transport_template); + + return rc; } static void __exit hpsa_cleanup(void) { pci_unregister_driver(&hpsa_pci_driver); + sas_release_transport(hpsa_sas_transport_template); } static void __attribute__((unused)) verify_offsets(void) -- cgit v1.2.3 From ec2c3aa94d9207fd2557203f36677da8be75b354 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 4 Nov 2015 15:52:40 -0600 Subject: hpsa: bump the driver version Reviewed-by: Justin Lindley Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Reviewed-by: Gerry Morong Reviewed-by: Hannes Reinecke Reviewed-by: Matthew R. Ochs Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 5f02a603eb4d..57166e68fc92 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -55,8 +55,11 @@ #include "hpsa_cmd.h" #include "hpsa.h" -/* HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.' */ -#define HPSA_DRIVER_VERSION "3.4.10-0" +/* + * HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.' + * with an optional trailing '-' followed by a byte value (0-255). + */ +#define HPSA_DRIVER_VERSION "3.4.14-0" #define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")" #define HPSA "hpsa" -- cgit v1.2.3 From fb53c439d84387621c53808a3957ffd9876e5094 Mon Sep 17 00:00:00 2001 From: Tomas Henzl Date: Fri, 6 Nov 2015 16:24:09 +0100 Subject: hpsa: move lockup_detected attribute to host attr This patch fixes a 'general protection fault' issue by moving the attribute to where it was likely meant. Signed-off-by: Tomas Henzl Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 57166e68fc92..6d4412359d23 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -867,7 +867,6 @@ static struct device_attribute *hpsa_sdev_attrs[] = { &dev_attr_unique_id, &dev_attr_hp_ssd_smart_path_enabled, &dev_attr_path_info, - &dev_attr_lockup_detected, NULL, }; @@ -879,6 +878,7 @@ static struct device_attribute *hpsa_shost_attrs[] = { &dev_attr_resettable, &dev_attr_hp_ssd_smart_path_status, &dev_attr_raid_offload_debug, + &dev_attr_lockup_detected, NULL, }; -- cgit v1.2.3 From 64d513ac31bd02a3c9b69ef04444f36c196f9a9d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 8 Oct 2015 09:28:04 +0100 Subject: scsi: use host wide tags by default This patch changes the !blk-mq path to the same defaults as the blk-mq I/O path by always enabling block tagging, and always using host wide tags. We've had blk-mq available for a few releases so bugs with this mode should have been ironed out, and this ensures we get better coverage of over tagging setup over different configs. Signed-off-by: Christoph Hellwig Acked-by: Jens Axboe Reviewed-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 40669f8dd0df..7506b65d8e6c 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -4983,7 +4983,6 @@ static int hpsa_scan_finished(struct Scsi_Host *sh, static int hpsa_scsi_host_alloc(struct ctlr_info *h) { struct Scsi_Host *sh; - int error; sh = scsi_host_alloc(&hpsa_driver_template, sizeof(h)); if (sh == NULL) { @@ -5004,14 +5003,7 @@ static int hpsa_scsi_host_alloc(struct ctlr_info *h) sh->hostdata[0] = (unsigned long) h; sh->irq = h->intr[h->intr_mode]; sh->unique_id = sh->irq; - error = scsi_init_shared_tag_map(sh, sh->can_queue); - if (error) { - dev_err(&h->pdev->dev, - "%s: scsi_init_shared_tag_map failed for controller %d\n", - __func__, h->ctlr); - scsi_host_put(sh); - return error; - } + h->scsi_host = sh; return 0; } -- cgit v1.2.3