From dfb2e6f46b3074eb85203d8f0888b71ec1c2e37a Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 20 Oct 2017 16:51:08 -0500 Subject: scsi: hpsa: destroy sas transport properties before scsi_host This patch cleans up a lot of warnings when unloading the driver. A current example of the stack trace starts with: [ 142.570715] sysfs group 'power' not found for kobject 'port-5:0' There can be hundreds of these messages during a driver unload. I am resubmitting this patch on behalf of Martin Wilck with his permission. His original patch can be found here: https://www.spinics.net/lists/linux-scsi/msg102085.html This patch did not help until Hannes's commit 9441284fbc39 ("scsi-fixup-kernel-warning-during-rmmod") was applied to the kernel. --------------------------- Original patch description: --------------------------- Unloading the hpsa driver causes warnings [ 1063.793652] WARNING: CPU: 1 PID: 4850 at ../fs/sysfs/group.c:237 device_del+0x54/0x240() [ 1063.793659] sysfs group ffffffff81cf21a0 not found for kobject 'port-2:0' with two different stacks: 1) [ 1063.793774] [] device_del+0x54/0x240 [ 1063.793780] [] transport_remove_classdev+0x4a/0x60 [ 1063.793784] [] attribute_container_device_trigger+0xa6/0xb0 [ 1063.793802] [] sas_port_delete+0x126/0x160 [scsi_transport_sas] [ 1063.793819] [] hpsa_free_sas_port+0x3c/0x70 [hpsa] 2) [ 1063.797103] [] device_del+0x54/0x240 [ 1063.797118] [] sas_port_delete+0x12e/0x160 [scsi_transport_sas] [ 1063.797134] [] hpsa_free_sas_port+0x3c/0x70 [hpsa] This is caused by the fact that host device hostX is deleted before the SAS transport devices hostX/port-a:b. This patch fixes this by reverting the order of device deletions. Tested-by: Don Brace Reviewed-by: Don Brace Signed-off-by: Martin Wilck Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 9abe81021484..aff4a4fee260 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -8684,6 +8684,8 @@ static void hpsa_remove_one(struct pci_dev *pdev) destroy_workqueue(h->rescan_ctlr_wq); destroy_workqueue(h->resubmit_wq); + hpsa_delete_sas_host(h); + /* * Call before disabling interrupts. * scsi_remove_host can trigger I/O operations especially @@ -8718,8 +8720,6 @@ static void hpsa_remove_one(struct pci_dev *pdev) 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 */ } -- cgit From 55ca38b4255bb336c2d35990bdb2b368e19b435a Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 20 Oct 2017 16:51:14 -0500 Subject: scsi: hpsa: cleanup sas_phy structures in sysfs when unloading I am resubmitting this patch on behalf of Martin Wilck with his permission. The original patch can be found here: https://www.spinics.net/lists/linux-scsi/msg102083.html This patch did not help until Hannes's commit 9441284fbc39 ("scsi-fixup-kernel-warning-during-rmmod") was applied to the kernel. -------------------------------------- Original patch description from Martin: -------------------------------------- When the hpsa module is unloaded using rmmod, dangling symlinks remain under /sys/class/sas_phy. Fix this by calling sas_phy_delete() rather than sas_phy_free (which, according to comments, should not be called for PHYs that have been set up successfully, anyway). Tested-by: Don Brace Reviewed-by: Don Brace Signed-off-by: Martin Wilck 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 aff4a4fee260..76461c4cca0c 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -9207,9 +9207,9 @@ 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); + sas_phy_delete(phy); kfree(hpsa_sas_phy); } -- cgit From 421bf80cc2e421ea8efd7bc47f595169d67ae92f Mon Sep 17 00:00:00 2001 From: Scott Teel Date: Fri, 20 Oct 2017 16:51:20 -0500 Subject: scsi: hpsa: clear tmpdevice in scan thread clean up stale information. Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 76461c4cca0c..0330f17c8feb 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -4258,6 +4258,8 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) int phys_dev_index = i - (raid_ctlr_position == 0); bool skip_device = false; + memset(tmpdevice, 0, sizeof(*tmpdevice)); + physical_device = i < nphysicals + (raid_ctlr_position == 0); /* Figure out where the LUN ID info is coming from */ -- cgit From b9b08cade0a6a523c185c5e371f05df63c623c34 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Fri, 20 Oct 2017 16:51:26 -0500 Subject: scsi: hpsa: add controller checkpoint Tell hpsa controller to generate a checkpoint for rare lockup conditions. Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 0330f17c8feb..9c491c507092 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -8009,6 +8009,10 @@ static void controller_lockup_detected(struct ctlr_info *h) spin_unlock_irqrestore(&h->lock, flags); dev_warn(&h->pdev->dev, "Controller lockup detected: 0x%08x after %d\n", lockup_detected, h->heartbeat_sample_interval / HZ); + if (lockup_detected == 0xffff0000) { + dev_warn(&h->pdev->dev, "Telling controller to do a CHKPT\n"); + writel(DOORBELL_GENERATE_CHKPT, h->vaddr + SA5_DOORBELL); + } pci_disable_device(h->pdev); fail_all_outstanding_cmds(h); } -- cgit From 4e1881840933587f42e3ad3788f2c392d19827a6 Mon Sep 17 00:00:00 2001 From: Bader Ali Saleh Date: Fri, 20 Oct 2017 16:51:32 -0500 Subject: scsi: hpsa: update discovery polling Correct a corner case where newly created volumes are not detected automatically on an external RAID controller that has no configured volumes during initial device discovery. The fix is to set the discovery_polling flag when an external RAID controller is detected. This causes a device rescan every 20-30 seconds, so that newly created volumes will be detected automatically. Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 9c491c507092..6056bbdbfcaa 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3472,6 +3472,30 @@ static void hpsa_get_sas_address(struct ctlr_info *h, unsigned char *scsi3addr, dev->sas_address = sa; } +static void hpsa_ext_ctrl_present(struct ctlr_info *h, + struct ReportExtendedLUNdata *physdev) +{ + u32 nphysicals; + int i; + + if (h->discovery_polling) + return; + + nphysicals = (get_unaligned_be32(physdev->LUNListLength) / 24) + 1; + + for (i = 0; i < nphysicals; i++) { + if (physdev->LUN[i].device_type == + BMIC_DEVICE_TYPE_CONTROLLER + && !is_hba_lunid(physdev->LUN[i].lunid)) { + dev_info(&h->pdev->dev, + "External controller present, activate discovery polling and disable rld caching\n"); + hpsa_disable_rld_caching(h); + h->discovery_polling = 1; + break; + } + } +} + /* Get a device id from inquiry page 0x83 */ static bool hpsa_vpd_page_supported(struct ctlr_info *h, unsigned char scsi3addr[], u8 page) @@ -4228,6 +4252,8 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) */ ndevs_to_allocate = nphysicals + nlogicals + MAX_EXT_TARGETS + 1; + hpsa_ext_ctrl_present(h, physdev_list); + /* Allocate the per device structures */ for (i = 0; i < ndevs_to_allocate; i++) { if (i >= HPSA_MAX_DEVICES) { @@ -4298,18 +4324,6 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) figure_bus_target_lun(h, lunaddrbytes, tmpdevice); 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; @@ -8247,7 +8261,6 @@ static void hpsa_rescan_ctlr_worker(struct work_struct *work) if (h->drv_req_rescan || hpsa_offline_devices_ready(h)) { hpsa_perform_rescan(h); } else if (h->discovery_polling) { - hpsa_disable_rld_caching(h); if (hpsa_luns_changed(h)) { dev_info(&h->pdev->dev, "driver discovery polling rescan.\n"); -- cgit From 3026ff9b0339a64d6bdef8858636174d453dce54 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Fri, 20 Oct 2017 16:51:38 -0500 Subject: scsi: hpsa: change timeout for internal cmds There are times when the DEFAULT_TIMEOUT (30 seconds) is not enough. Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 6056bbdbfcaa..4ab53df58f21 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -2929,7 +2929,7 @@ static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr, goto out; } rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); + PCI_DMA_FROMDEVICE, NO_TIMEOUT); if (rc) goto out; ei = c->err_info; @@ -3213,7 +3213,7 @@ static int hpsa_get_raid_map(struct ctlr_info *h, return -1; } rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); + PCI_DMA_FROMDEVICE, NO_TIMEOUT); if (rc) goto out; ei = c->err_info; @@ -3256,7 +3256,7 @@ static int hpsa_bmic_sense_subsystem_information(struct ctlr_info *h, c->Request.CDB[9] = (bmic_device_index >> 8) & 0xff; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); + PCI_DMA_FROMDEVICE, NO_TIMEOUT); if (rc) goto out; ei = c->err_info; @@ -3284,7 +3284,7 @@ static int hpsa_bmic_id_controller(struct ctlr_info *h, goto out; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); + PCI_DMA_FROMDEVICE, NO_TIMEOUT); if (rc) goto out; ei = c->err_info; @@ -3315,7 +3315,7 @@ static int hpsa_bmic_id_physical_device(struct ctlr_info *h, c->Request.CDB[9] = (bmic_device_index >> 8) & 0xff; hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE, - DEFAULT_TIMEOUT); + NO_TIMEOUT); ei = c->err_info; if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) { hpsa_scsi_interpret_error(h, c); @@ -3388,7 +3388,7 @@ static void hpsa_get_enclosure_info(struct ctlr_info *h, c->Request.CDB[5] = 0; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE, - DEFAULT_TIMEOUT); + NO_TIMEOUT); if (rc) goto out; @@ -3628,7 +3628,7 @@ static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical, if (extended_response) c->Request.CDB[1] = extended_response; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); + PCI_DMA_FROMDEVICE, NO_TIMEOUT); if (rc) goto out; ei = c->err_info; @@ -3763,7 +3763,7 @@ static unsigned char hpsa_volume_offline(struct ctlr_info *h, (void) fill_cmd(c, TEST_UNIT_READY, h, NULL, 0, 0, scsi3addr, TYPE_CMD); rc = hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE, - DEFAULT_TIMEOUT); + NO_TIMEOUT); if (rc) { cmd_free(h, c); return HPSA_VPD_LV_STATUS_UNSUPPORTED; @@ -8620,7 +8620,7 @@ static void hpsa_disable_rld_caching(struct ctlr_info *h) goto errout; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); + PCI_DMA_FROMDEVICE, NO_TIMEOUT); if ((rc != 0) || (c->err_info->CommandStatus != 0)) goto errout; @@ -8632,7 +8632,7 @@ static void hpsa_disable_rld_caching(struct ctlr_info *h) goto errout; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_TODEVICE, DEFAULT_TIMEOUT); + PCI_DMA_TODEVICE, NO_TIMEOUT); if ((rc != 0) || (c->err_info->CommandStatus != 0)) goto errout; @@ -8642,7 +8642,7 @@ static void hpsa_disable_rld_caching(struct ctlr_info *h) goto errout; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); + PCI_DMA_FROMDEVICE, NO_TIMEOUT); if ((rc != 0) || (c->err_info->CommandStatus != 0)) goto errout; -- cgit From b2582a65755b342dcc26b1c9398b6a1e6bdfc9a2 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Fri, 20 Oct 2017 16:51:45 -0500 Subject: scsi: hpsa: correct smart path enabled Correct re-enabling ioaccel after: 1) RAID transformations and 2) multi-path fail-overs. Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 189 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 151 insertions(+), 38 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 4ab53df58f21..6a998b09cb1b 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -787,7 +787,12 @@ static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev, } offload_enabled = hdev->offload_enabled; spin_unlock_irqrestore(&h->lock, flags); - return snprintf(buf, 20, "%d\n", offload_enabled); + + if (hdev->devtype == TYPE_DISK || hdev->devtype == TYPE_ZBC) + return snprintf(buf, 20, "%d\n", offload_enabled); + else + return snprintf(buf, 40, "%s\n", + "Not applicable for a controller"); } #define MAX_PATHS 8 @@ -1270,7 +1275,7 @@ static void hpsa_show_dev_msg(const char *level, struct ctlr_info *h, dev->model, label, dev->offload_config ? '+' : '-', - dev->offload_enabled ? '+' : '-', + dev->offload_to_be_enabled ? '+' : '-', dev->expose_device); } @@ -1345,36 +1350,42 @@ lun_assigned: (*nadded)++; hpsa_show_dev_msg(KERN_INFO, h, device, device->expose_device ? "added" : "masked"); - device->offload_to_be_enabled = device->offload_enabled; - device->offload_enabled = 0; return 0; } -/* Update an entry in h->dev[] array. */ +/* + * Called during a scan operation. + * + * Update an entry in h->dev[] array. + */ static void hpsa_scsi_update_entry(struct ctlr_info *h, int entry, struct hpsa_scsi_dev_t *new_entry) { - int offload_enabled; /* assumes h->devlock is held */ BUG_ON(entry < 0 || entry >= HPSA_MAX_DEVICES); /* Raid level changed. */ h->dev[entry]->raid_level = new_entry->raid_level; + /* + * ioacccel_handle may have changed for a dual domain disk + */ + h->dev[entry]->ioaccel_handle = new_entry->ioaccel_handle; + /* Raid offload parameters changed. Careful about the ordering. */ - if (new_entry->offload_config && new_entry->offload_enabled) { + if (new_entry->offload_config && new_entry->offload_to_be_enabled) { /* * if drive is newly offload_enabled, we want to copy the * raid map data first. If previously offload_enabled and * offload_config were set, raid map data had better be - * the same as it was before. if raid map data is changed + * the same as it was before. If raid map data has changed * then it had better be the case that * h->dev[entry]->offload_enabled is currently 0. */ h->dev[entry]->raid_map = new_entry->raid_map; h->dev[entry]->ioaccel_handle = new_entry->ioaccel_handle; } - if (new_entry->hba_ioaccel_enabled) { + if (new_entry->offload_to_be_enabled) { h->dev[entry]->ioaccel_handle = new_entry->ioaccel_handle; wmb(); /* set ioaccel_handle *before* hba_ioaccel_enabled */ } @@ -1385,17 +1396,18 @@ static void hpsa_scsi_update_entry(struct ctlr_info *h, /* * We can turn off ioaccel offload now, but need to delay turning - * it on until we can update h->dev[entry]->phys_disk[], but we + * ioaccel on until we can update h->dev[entry]->phys_disk[], but we * can't do that until all the devices are updated. */ - h->dev[entry]->offload_to_be_enabled = new_entry->offload_enabled; - if (!new_entry->offload_enabled) + h->dev[entry]->offload_to_be_enabled = new_entry->offload_to_be_enabled; + + /* + * turn ioaccel off immediately if told to do so. + */ + if (!new_entry->offload_to_be_enabled) h->dev[entry]->offload_enabled = 0; - offload_enabled = h->dev[entry]->offload_enabled; - h->dev[entry]->offload_enabled = h->dev[entry]->offload_to_be_enabled; hpsa_show_dev_msg(KERN_INFO, h, h->dev[entry], "updated"); - h->dev[entry]->offload_enabled = offload_enabled; } /* Replace an entry from h->dev[] array. */ @@ -1421,9 +1433,8 @@ static void hpsa_scsi_replace_entry(struct ctlr_info *h, h->dev[entry] = new_entry; added[*nadded] = new_entry; (*nadded)++; + hpsa_show_dev_msg(KERN_INFO, h, new_entry, "replaced"); - new_entry->offload_to_be_enabled = new_entry->offload_enabled; - new_entry->offload_enabled = 0; } /* Remove an entry from h->dev[] array. */ @@ -1513,11 +1524,22 @@ static inline int device_updated(struct hpsa_scsi_dev_t *dev1, return 1; if (dev1->offload_config != dev2->offload_config) return 1; - if (dev1->offload_enabled != dev2->offload_enabled) + if (dev1->offload_to_be_enabled != dev2->offload_to_be_enabled) return 1; if (!is_logical_dev_addr_mode(dev1->scsi3addr)) if (dev1->queue_depth != dev2->queue_depth) return 1; + /* + * This can happen for dual domain devices. An active + * path change causes the ioaccel handle to change + * + * for example note the handle differences between p0 and p1 + * Device WWN ,WWN hash,Handle + * D016 p0|0x3 [02]P2E:01:01,0x5000C5005FC4DACA,0x9B5616,0x01030003 + * p1 0x5000C5005FC4DAC9,0x6798C0,0x00040004 + */ + if (dev1->ioaccel_handle != dev2->ioaccel_handle) + return 1; return 0; } @@ -1727,6 +1749,11 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h, * be 0, but we'll turn it off here just in case */ if (!logical_drive->phys_disk[i]) { + dev_warn(&h->pdev->dev, + "%s: [%d:%d:%d:%d] A phys disk component of LV is missing, turning off offload_enabled for LV.\n", + __func__, + h->scsi_host->host_no, logical_drive->bus, + logical_drive->target, logical_drive->lun); logical_drive->offload_enabled = 0; logical_drive->offload_to_be_enabled = 0; logical_drive->queue_depth = 8; @@ -1759,13 +1786,24 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h, /* * If offload is currently enabled, the RAID map and * phys_disk[] assignment *better* not be changing - * and since it isn't changing, we do not need to - * update it. + * because we would be changing ioaccel phsy_disk[] pointers + * on a ioaccel volume processing I/O requests. + * + * If an ioaccel volume status changed, initially because it was + * re-configured and thus underwent a transformation, or + * a drive failed, we would have received a state change + * request and ioaccel should have been turned off. When the + * transformation completes, we get another state change + * request to turn ioaccel back on. In this case, we need + * to update the ioaccel information. + * + * Thus: If it is not currently enabled, but will be after + * the scan completes, make sure the ioaccel pointers + * are up to date. */ - if (dev[i]->offload_enabled) - continue; - hpsa_figure_phys_disk_ptrs(h, dev, ndevices, dev[i]); + if (!dev[i]->offload_enabled && dev[i]->offload_to_be_enabled) + hpsa_figure_phys_disk_ptrs(h, dev, ndevices, dev[i]); } } @@ -1965,8 +2003,13 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, } hpsa_update_log_drive_phys_drive_ptrs(h, h->dev, h->ndevices); - /* Now that h->dev[]->phys_disk[] is coherent, we can enable + /* + * Now that h->dev[]->phys_disk[] is coherent, we can enable * any logical drives that need it enabled. + * + * The raid map should be current by now. + * + * We are updating the device list used for I/O requests. */ for (i = 0; i < h->ndevices; i++) { if (h->dev[i] == NULL) @@ -2441,7 +2484,7 @@ static void process_ioaccel2_completion(struct ctlr_info *h, /* * Any RAID offload error results in retry which will use - * the normal I/O path so the controller can handle whatever's + * the normal I/O path so the controller can handle whatever is * wrong. */ if (is_logical_device(dev) && @@ -3540,6 +3583,13 @@ exit_supported: return true; } +/* + * Called during a scan operation. + * Sets ioaccel status on the new device list, not the existing device list + * + * The device list used during I/O will be updated later in + * adjust_hpsa_scsi_table. + */ static void hpsa_get_ioaccel_status(struct ctlr_info *h, unsigned char *scsi3addr, struct hpsa_scsi_dev_t *this_device) { @@ -3568,12 +3618,12 @@ static void hpsa_get_ioaccel_status(struct ctlr_info *h, this_device->offload_config = !!(ioaccel_status & OFFLOAD_CONFIGURED_BIT); if (this_device->offload_config) { - this_device->offload_enabled = + this_device->offload_to_be_enabled = !!(ioaccel_status & OFFLOAD_ENABLED_BIT); if (hpsa_get_raid_map(h, scsi3addr, this_device)) - this_device->offload_enabled = 0; + this_device->offload_to_be_enabled = 0; } - this_device->offload_to_be_enabled = this_device->offload_enabled; + out: kfree(buf); return; @@ -4307,7 +4357,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) continue; } - /* Get device type, vendor, model, device id */ + /* Get device type, vendor, model, device id, raid_map */ rc = hpsa_update_device_info(h, lunaddrbytes, tmpdevice, &is_OBDR); if (rc == -ENOMEM) { @@ -8067,9 +8117,79 @@ static int detect_controller_lockup(struct ctlr_info *h) return false; } -static void hpsa_ack_ctlr_events(struct ctlr_info *h) +/* + * Set ioaccel status for all ioaccel volumes. + * + * Called from monitor controller worker (hpsa_event_monitor_worker) + * + * A Volume (or Volumes that comprise an Array set may be undergoing a + * transformation, so we will be turning off ioaccel for all volumes that + * make up the Array. + */ +static void hpsa_set_ioaccel_status(struct ctlr_info *h) { + int rc; int i; + u8 ioaccel_status; + unsigned char *buf; + struct hpsa_scsi_dev_t *device; + + if (!h) + return; + + buf = kmalloc(64, GFP_KERNEL); + if (!buf) + return; + + /* + * Run through current device list used during I/O requests. + */ + for (i = 0; i < h->ndevices; i++) { + device = h->dev[i]; + + if (!device) + continue; + if (!device->scsi3addr) + continue; + if (!hpsa_vpd_page_supported(h, device->scsi3addr, + HPSA_VPD_LV_IOACCEL_STATUS)) + continue; + + memset(buf, 0, 64); + + rc = hpsa_scsi_do_inquiry(h, device->scsi3addr, + VPD_PAGE | HPSA_VPD_LV_IOACCEL_STATUS, + buf, 64); + if (rc != 0) + continue; + + ioaccel_status = buf[IOACCEL_STATUS_BYTE]; + device->offload_config = + !!(ioaccel_status & OFFLOAD_CONFIGURED_BIT); + if (device->offload_config) + device->offload_to_be_enabled = + !!(ioaccel_status & OFFLOAD_ENABLED_BIT); + + /* + * Immediately turn off ioaccel for any volume the + * controller tells us to. Some of the reasons could be: + * transformation - change to the LVs of an Array. + * degraded volume - component failure + * + * If ioaccel is to be re-enabled, re-enable later during the + * scan operation so the driver can get a fresh raidmap + * before turning ioaccel back on. + * + */ + if (!device->offload_to_be_enabled) + device->offload_enabled = 0; + } + + kfree(buf); +} + +static void hpsa_ack_ctlr_events(struct ctlr_info *h) +{ char *event_type; if (!(h->fw_support & MISC_FW_EVENT_NOTIFY)) @@ -8087,10 +8207,7 @@ static void hpsa_ack_ctlr_events(struct ctlr_info *h) event_type = "configuration change"; /* Stop sending new RAID offload reqs via the IO accelerator */ scsi_block_requests(h->scsi_host); - for (i = 0; i < h->ndevices; i++) { - h->dev[i]->offload_enabled = 0; - h->dev[i]->offload_to_be_enabled = 0; - } + hpsa_set_ioaccel_status(h); hpsa_drain_accel_commands(h); /* Set 'accelerator path config change' bit */ dev_warn(&h->pdev->dev, @@ -8107,10 +8224,6 @@ static void hpsa_ack_ctlr_events(struct ctlr_info *h) writel(h->events, &(h->cfgtable->clear_event_notify)); writel(DOORBELL_CLEAR_EVENTS, h->vaddr + SA5_DOORBELL); hpsa_wait_for_clear_event_notify_ack(h); -#if 0 - writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); - hpsa_wait_for_mode_change_ack(h); -#endif } return; } -- cgit From 2c5fc3639eb4dd21f91770b16d9df8466f42f0b2 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Fri, 20 Oct 2017 16:51:51 -0500 Subject: scsi: hpsa: update queue depth for externals Preserve external device queue depth during a scan operation. Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 6a998b09cb1b..27a1aca085b3 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1765,8 +1765,12 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h, * way too high for partial stripe writes */ logical_drive->queue_depth = qdepth; - else - logical_drive->queue_depth = h->nr_cmds; + else { + if (logical_drive->external) + logical_drive->queue_depth = EXTERNAL_QD; + else + logical_drive->queue_depth = h->nr_cmds; + } } static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h, -- cgit From 9211a07fc1b25d9d437c5ccd39cb1596eb9adb06 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Fri, 20 Oct 2017 16:51:57 -0500 Subject: scsi: hpsa: reduce warning messages on device removal Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 27a1aca085b3..228d74465fd0 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1865,11 +1865,13 @@ static void hpsa_wait_for_outstanding_commands_for_dev(struct ctlr_info *h, break; if (++waits > 20) break; + msleep(1000); + } + + if (waits > 20) dev_warn(&h->pdev->dev, "%s: removing device with %d outstanding commands!\n", __func__, cmds); - msleep(1000); - } } static void hpsa_remove_device(struct ctlr_info *h, -- cgit From 0ff365f51a4290a63f1044c599df98196223d4bc Mon Sep 17 00:00:00 2001 From: Don Brace Date: Fri, 20 Oct 2017 16:52:04 -0500 Subject: scsi: hpsa: correct logical volume removal Suggested-by: Martin Wilck Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 228d74465fd0..a536ed620e6e 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1882,6 +1882,12 @@ static void hpsa_remove_device(struct ctlr_info *h, if (!h->scsi_host) return; + /* + * Allow for commands to drain + */ + device->removed = 1; + hpsa_wait_for_outstanding_commands_for_dev(h, device); + if (is_logical_device(device)) { /* RAID */ sdev = scsi_device_lookup(h->scsi_host, device->bus, device->target, device->lun); @@ -1899,9 +1905,6 @@ static void hpsa_remove_device(struct ctlr_info *h, } } else { /* HBA */ - device->removed = 1; - hpsa_wait_for_outstanding_commands_for_dev(h, device); - hpsa_remove_sas_device(device); } } -- cgit From 0a7c3bb8951278aae25b3b53eb5f97cca4147cf3 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Fri, 20 Oct 2017 16:52:10 -0500 Subject: scsi: hpsa: add enclosure logical identifier Add support for enclosure logical identifier Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/hpsa.c') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index a536ed620e6e..5428a4cbbded 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -2965,6 +2965,57 @@ static void hpsa_scsi_interpret_error(struct ctlr_info *h, } } +static int hpsa_do_receive_diagnostic(struct ctlr_info *h, u8 *scsi3addr, + u8 page, u8 *buf, size_t bufsize) +{ + int rc = IO_OK; + struct CommandList *c; + struct ErrorInfo *ei; + + c = cmd_alloc(h); + if (fill_cmd(c, RECEIVE_DIAGNOSTIC, h, buf, bufsize, + page, scsi3addr, TYPE_CMD)) { + rc = -1; + 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 u64 hpsa_get_enclosure_logical_identifier(struct ctlr_info *h, + u8 *scsi3addr) +{ + u8 *buf; + u64 sa = 0; + int rc = 0; + + buf = kzalloc(1024, GFP_KERNEL); + if (!buf) + return 0; + + rc = hpsa_do_receive_diagnostic(h, scsi3addr, RECEIVE_DIAGNOSTIC, + buf, 1024); + + if (rc) + goto out; + + sa = get_unaligned_be64(buf+12); + +out: + kfree(buf); + return sa; +} + static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr, u16 page, unsigned char *buf, unsigned char bufsize) @@ -3400,6 +3451,9 @@ static void hpsa_get_enclosure_info(struct ctlr_info *h, bmic_device_index = GET_BMIC_DRIVE_NUMBER(&rle->lunid[0]); + encl_dev->sas_address = + hpsa_get_enclosure_logical_identifier(h, scsi3addr); + if (encl_dev->target == -1 || encl_dev->lun == -1) { rc = IO_OK; goto out; @@ -6571,6 +6625,17 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, c->Request.CDB[0] = HPSA_INQUIRY; c->Request.CDB[4] = size & 0xFF; break; + case RECEIVE_DIAGNOSTIC: + c->Request.CDBLen = 6; + c->Request.type_attr_dir = + TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ); + c->Request.Timeout = 0; + c->Request.CDB[0] = cmd; + c->Request.CDB[1] = 1; + c->Request.CDB[2] = 1; + c->Request.CDB[3] = (size >> 8) & 0xFF; + c->Request.CDB[4] = size & 0xFF; + break; case HPSA_REPORT_LOG: case HPSA_REPORT_PHYS: /* Talking to controller so It's a physical command @@ -9508,7 +9573,7 @@ static int hpsa_add_sas_host(struct ctlr_info *h) struct hpsa_sas_port *hpsa_sas_port; struct hpsa_sas_phy *hpsa_sas_phy; - parent_dev = &h->scsi_host->shost_gendev; + parent_dev = &h->scsi_host->shost_dev; hpsa_sas_node = hpsa_alloc_sas_node(parent_dev); if (!hpsa_sas_node) @@ -9599,7 +9664,7 @@ hpsa_sas_get_linkerrors(struct sas_phy *phy) static int hpsa_sas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) { - *identifier = 0; + *identifier = rphy->identify.sas_address; return 0; } -- cgit From c9edcb2e17bb5532ac09cc627e133c3d94b69e53 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Fri, 20 Oct 2017 16:52:17 -0500 Subject: scsi: hpsa: bump driver version Reviewed-by: Gerry Morong Reviewed-by: Scott Benesh 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 5428a4cbbded..e514489c15c5 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -60,7 +60,7 @@ * 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.20-0" +#define HPSA_DRIVER_VERSION "3.4.20-125" #define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")" #define HPSA "hpsa" -- cgit