From d725117b2191a88e7bed5d5cb7d5d9439b3b030d Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Mon, 7 Jun 2021 17:29:36 +0800 Subject: [PATCH 1/4] scsi: hisi_sas: Run I_T nexus resets in parallel for clear nexus reset For a clear nexus reset operation, the I_T nexus resets are executed serially for each device. For devices attached through an expander, this may take 2s per device; so, in total, could take a long time. Reduce the total time by running the I_T nexus resets in parallel through async operations. Link: https://lore.kernel.org/r/1623058179-80434-3-git-send-email-john.garry@huawei.com Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen Signed-off-by: chenyi --- drivers/scsi/hisi_sas/hisi_sas.h | 3 +++ drivers/scsi/hisi_sas/hisi_sas_main.c | 23 +++++++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 62f86b9f1ad4..1d4aa9af680c 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -8,6 +8,9 @@ #define _HISI_SAS_H_ #include +#include +#include +#include #include #include #include diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index a23a1c75f632..8521e3d627e0 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -2016,12 +2016,24 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun) return rc; } +static void hisi_sas_async_I_T_nexus_reset(void *data, async_cookie_t cookie) +{ + struct domain_device *device = data; + struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); + int rc; + + rc = hisi_sas_debug_I_T_nexus_reset(device); + if (rc != TMF_RESP_FUNC_COMPLETE) + dev_info(hisi_hba->dev, "I_T_nexus reset fail for dev:%016llx rc=%d\n", + SAS_ADDR(device->sas_addr), rc); +} + static int hisi_sas_clear_nexus_ha(struct sas_ha_struct *sas_ha) { struct hisi_hba *hisi_hba = sas_ha->lldd_ha; - struct device *dev = hisi_hba->dev; HISI_SAS_DECLARE_RST_WORK_ON_STACK(r); - int rc, i; + ASYNC_DOMAIN_EXCLUSIVE(async); + int i; queue_work(hisi_hba->wq, &r.work); wait_for_completion(r.completion); @@ -2036,12 +2048,11 @@ static int hisi_sas_clear_nexus_ha(struct sas_ha_struct *sas_ha) dev_is_expander(device->dev_type)) continue; - rc = hisi_sas_debug_I_T_nexus_reset(device); - if (rc != TMF_RESP_FUNC_COMPLETE) - dev_info(dev, "clear nexus ha: for device[%d] rc=%d\n", - sas_dev->device_id, rc); + async_schedule_domain(hisi_sas_async_I_T_nexus_reset, + device, &async); } + async_synchronize_full_domain(&async); hisi_sas_release_tasks(hisi_hba); return TMF_RESP_FUNC_COMPLETE; -- Gitee From 57865585c9ca30a62a92073012dc6e5356e61a3d Mon Sep 17 00:00:00 2001 From: Yihang Li Date: Thu, 14 Dec 2023 11:45:16 +0800 Subject: [PATCH 2/4] scsi: hisi_sas: Correct the number of global debugfs registers In function debugfs_debugfs_snapshot_global_reg_v3_hw() it uses debugfs_axi_reg.count (which is the number of axi debugfs registers) to acquire the number of global debugfs registers. Use debugfs_global_reg.count to acquire the number of global debugfs registers instead. Fixes: 623a4b6d5c2a ("scsi: hisi_sas: Move debugfs code to v3 hw driver") Signed-off-by: Yihang Li Signed-off-by: Xiang Chen Link: https://lore.kernel.org/r/1702525516-51258-6-git-send-email-chenxiang66@hisilicon.com Signed-off-by: Martin K. Petersen Signed-off-by: chenyi --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index ab86469d9502..8041d70fe2ef 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -3437,7 +3437,7 @@ static void debugfs_snapshot_global_reg_v3_hw(struct hisi_hba *hisi_hba) u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL].data; int i; - for (i = 0; i < debugfs_axi_reg.count; i++, databuf++) + for (i = 0; i < debugfs_global_reg.count; i++, databuf++) *databuf = hisi_sas_read32(hisi_hba, 4 * i); } -- Gitee From 85ae255523b4b2423f933d6eb781e31b1b753823 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Thu, 11 Jan 2024 13:05:32 +0100 Subject: [PATCH 3/4] scsi: core: Kick the requeue list after inserting when flushing When libata calls ata_link_abort() to abort all ata queued commands, it calls blk_abort_request() on the SCSI command representing each QC. This causes scsi_timeout() to be called, which calls scsi_eh_scmd_add() for each SCSI command. scsi_eh_scmd_add() sets the SCSI host to state recovery, and then adds the command to shost->eh_cmd_q. This will wake up the SCSI EH, and eventually the libata EH strategy handler will be called, which calls scsi_eh_flush_done_q() to either flush retry or flush finish each failed command. The commands that are flush retried by scsi_eh_flush_done_q() are done so using scsi_queue_insert(). Before commit 8b566edbdbfb ("scsi: core: Only kick the requeue list if necessary"), __scsi_queue_insert() called blk_mq_requeue_request() with the second argument set to true, indicating that it should always kick/run the requeue list after inserting. After commit 8b566edbdbfb ("scsi: core: Only kick the requeue list if necessary"), __scsi_queue_insert() does not kick/run the requeue list after inserting, if the current SCSI host state is recovery (which is the case in the libata example above). This optimization is probably fine in most cases, as I can only assume that most often someone will eventually kick/run the queues. However, that is not the case for scsi_eh_flush_done_q(), where we can see that the request gets inserted to the requeue list, but the queue is never started after the request has been inserted, leading to the block layer waiting for the completion of command that never gets to run. Since scsi_eh_flush_done_q() is called by SCSI EH context, the SCSI host state is most likely always in recovery when this function is called. Thus, let scsi_eh_flush_done_q() explicitly kick the requeue list after inserting a flush retry command, so that scsi_eh_flush_done_q() keeps the same behavior as before commit 8b566edbdbfb ("scsi: core: Only kick the requeue list if necessary"). Simple reproducer for the libata example above: $ hdparm -Y /dev/sda $ echo 1 > /sys/class/scsi_device/0\:0\:0\:0/device/delete Fixes: 8b566edbdbfb ("scsi: core: Only kick the requeue list if necessary") Reported-by: Kevin Locke Closes: https://lore.kernel.org/linux-scsi/ZZw3Th70wUUvCiCY@kevinlocke.name/ Signed-off-by: Niklas Cassel Link: https://lore.kernel.org/r/20240111120533.3612509-1-cassel@kernel.org Reviewed-by: Bart Van Assche Reviewed-by: Damien Le Moal Signed-off-by: Martin K. Petersen Signed-off-by: chenyi --- drivers/scsi/scsi_error.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index ae2fa170f6ad..2420733b0c1a 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -2087,15 +2087,17 @@ void scsi_eh_flush_done_q(struct list_head *done_q) struct scsi_cmnd *scmd, *next; list_for_each_entry_safe(scmd, next, done_q, eh_entry) { + struct scsi_device *sdev = scmd->device; + list_del_init(&scmd->eh_entry); - if (scsi_device_online(scmd->device) && - !scsi_noretry_cmd(scmd) && + if (scsi_device_online(sdev) && !scsi_noretry_cmd(scmd) && (++scmd->retries <= scmd->allowed)) { SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, "%s: flush retry cmd\n", current->comm)); scsi_queue_insert(scmd, SCSI_MLQUEUE_EH_RETRY); + blk_mq_kick_requeue_list(sdev->request_queue); } else { /* * If just we got sense for the device (called -- Gitee From 462f15dcf681a089a51e5f1fd412da2e9ff1e884 Mon Sep 17 00:00:00 2001 From: Yihang Li Date: Mon, 22 Jan 2024 14:25:46 +0800 Subject: [PATCH 4/4] scsi: hisi_sas: Check whether debugfs is enabled before removing or releasing it hisi_sas debugfs remove should be executed only when debugfs is enabled. Check whether debugfs is enabled and then remove it only if enabled. Signed-off-by: Yihang Li Signed-off-by: Xiang Chen Link: https://lore.kernel.org/r/1705904747-62186-4-git-send-email-chenxiang66@hisilicon.com Signed-off-by: Martin K. Petersen Signed-off-by: chenyi --- drivers/scsi/hisi_sas/hisi_sas_main.c | 3 ++- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 8521e3d627e0..0c5ea402b049 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -2947,7 +2947,8 @@ static __exit void hisi_sas_exit(void) { sas_release_transport(hisi_sas_stt); - debugfs_remove(hisi_sas_debugfs_dir); + if (hisi_sas_debugfs_enable) + debugfs_remove(hisi_sas_debugfs_dir); } module_init(hisi_sas_init); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 8041d70fe2ef..827da3de358a 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -5017,7 +5017,9 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev) hisi_sas_v3_destroy_irqs(pdev, hisi_hba); hisi_sas_free(hisi_hba); - debugfs_exit_v3_hw(hisi_hba); + if (hisi_sas_debugfs_enable) + debugfs_exit_v3_hw(hisi_hba); + scsi_host_put(shost); } -- Gitee