From 48d5b9732580bca18fed9ef20da8aa210c646755 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Wed, 10 Jul 2019 21:38:18 +0800 Subject: scsi: ufs: Change names related to error history Remove "uic" term in below error history functions and structures for more general usages, struct ufs_uic_err_reg_hist; void ufshcd_update_uic_reg_hist(struct ufs_uic_err_reg_hist *reg_hist, u32 reg); void ufshcd_print_uic_err_hist(struct ufs_hba *hba, struct ufs_uic)err_reg_hist *err_hist, char *err_name); Signed-off-by: Stanley Chu Reviewed-by: Avri Altman Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 39 ++++++++++++++++++++------------------- drivers/scsi/ufs/ufshcd.h | 20 ++++++++++---------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index e274053109d0..3865ba9886c2 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -390,14 +390,15 @@ static void ufshcd_print_clk_freqs(struct ufs_hba *hba) } } -static void ufshcd_print_uic_err_hist(struct ufs_hba *hba, - struct ufs_uic_err_reg_hist *err_hist, char *err_name) +static void ufshcd_print_err_hist(struct ufs_hba *hba, + struct ufs_err_reg_hist *err_hist, + char *err_name) { int i; bool found = false; - for (i = 0; i < UIC_ERR_REG_HIST_LENGTH; i++) { - int p = (i + err_hist->pos) % UIC_ERR_REG_HIST_LENGTH; + for (i = 0; i < UFS_ERR_REG_HIST_LENGTH; i++) { + int p = (i + err_hist->pos) % UFS_ERR_REG_HIST_LENGTH; if (err_hist->reg[p] == 0) continue; @@ -407,7 +408,7 @@ static void ufshcd_print_uic_err_hist(struct ufs_hba *hba, } if (!found) - dev_err(hba->dev, "No record of %s uic errors\n", err_name); + dev_err(hba->dev, "No record of %s errors\n", err_name); } static void ufshcd_print_host_regs(struct ufs_hba *hba) @@ -423,11 +424,11 @@ static void ufshcd_print_host_regs(struct ufs_hba *hba) ktime_to_us(hba->ufs_stats.last_hibern8_exit_tstamp), hba->ufs_stats.hibern8_exit_cnt); - ufshcd_print_uic_err_hist(hba, &hba->ufs_stats.pa_err, "pa_err"); - ufshcd_print_uic_err_hist(hba, &hba->ufs_stats.dl_err, "dl_err"); - ufshcd_print_uic_err_hist(hba, &hba->ufs_stats.nl_err, "nl_err"); - ufshcd_print_uic_err_hist(hba, &hba->ufs_stats.tl_err, "tl_err"); - ufshcd_print_uic_err_hist(hba, &hba->ufs_stats.dme_err, "dme_err"); + ufshcd_print_err_hist(hba, &hba->ufs_stats.pa_err, "pa_err"); + ufshcd_print_err_hist(hba, &hba->ufs_stats.dl_err, "dl_err"); + ufshcd_print_err_hist(hba, &hba->ufs_stats.nl_err, "nl_err"); + ufshcd_print_err_hist(hba, &hba->ufs_stats.tl_err, "tl_err"); + ufshcd_print_err_hist(hba, &hba->ufs_stats.dme_err, "dme_err"); ufshcd_print_clk_freqs(hba); @@ -5345,12 +5346,12 @@ out: pm_runtime_put_sync(hba->dev); } -static void ufshcd_update_uic_reg_hist(struct ufs_uic_err_reg_hist *reg_hist, - u32 reg) +static void ufshcd_update_reg_hist(struct ufs_err_reg_hist *reg_hist, + u32 reg) { reg_hist->reg[reg_hist->pos] = reg; reg_hist->tstamp[reg_hist->pos] = ktime_get(); - reg_hist->pos = (reg_hist->pos + 1) % UIC_ERR_REG_HIST_LENGTH; + reg_hist->pos = (reg_hist->pos + 1) % UFS_ERR_REG_HIST_LENGTH; } /** @@ -5371,13 +5372,13 @@ static void ufshcd_update_uic_error(struct ufs_hba *hba) * must be checked but this error is handled separately. */ dev_dbg(hba->dev, "%s: UIC Lane error reported\n", __func__); - ufshcd_update_uic_reg_hist(&hba->ufs_stats.pa_err, reg); + ufshcd_update_reg_hist(&hba->ufs_stats.pa_err, reg); } /* PA_INIT_ERROR is fatal and needs UIC reset */ reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_DATA_LINK_LAYER); if (reg) - ufshcd_update_uic_reg_hist(&hba->ufs_stats.dl_err, reg); + ufshcd_update_reg_hist(&hba->ufs_stats.dl_err, reg); if (reg & UIC_DATA_LINK_LAYER_ERROR_PA_INIT) hba->uic_error |= UFSHCD_UIC_DL_PA_INIT_ERROR; @@ -5393,19 +5394,19 @@ static void ufshcd_update_uic_error(struct ufs_hba *hba) /* UIC NL/TL/DME errors needs software retry */ reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_NETWORK_LAYER); if (reg) { - ufshcd_update_uic_reg_hist(&hba->ufs_stats.nl_err, reg); + ufshcd_update_reg_hist(&hba->ufs_stats.nl_err, reg); hba->uic_error |= UFSHCD_UIC_NL_ERROR; } reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_TRANSPORT_LAYER); if (reg) { - ufshcd_update_uic_reg_hist(&hba->ufs_stats.tl_err, reg); + ufshcd_update_reg_hist(&hba->ufs_stats.tl_err, reg); hba->uic_error |= UFSHCD_UIC_TL_ERROR; } reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_DME); if (reg) { - ufshcd_update_uic_reg_hist(&hba->ufs_stats.dme_err, reg); + ufshcd_update_reg_hist(&hba->ufs_stats.dme_err, reg); hba->uic_error |= UFSHCD_UIC_DME_ERROR; } @@ -6681,7 +6682,7 @@ static void ufshcd_tune_unipro_params(struct ufs_hba *hba) static void ufshcd_clear_dbg_ufs_stats(struct ufs_hba *hba) { - int err_reg_hist_size = sizeof(struct ufs_uic_err_reg_hist); + int err_reg_hist_size = sizeof(struct ufs_err_reg_hist); hba->ufs_stats.hibern8_exit_cnt = 0; hba->ufs_stats.last_hibern8_exit_tstamp = ktime_set(0, 0); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 994d73d03207..dcc61f857c38 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -412,17 +412,17 @@ struct ufs_init_prefetch { u32 icc_level; }; -#define UIC_ERR_REG_HIST_LENGTH 8 +#define UFS_ERR_REG_HIST_LENGTH 8 /** - * struct ufs_uic_err_reg_hist - keeps history of uic errors + * struct ufs_err_reg_hist - keeps history of uic errors * @pos: index to indicate cyclic buffer position * @reg: cyclic buffer for registers value * @tstamp: cyclic buffer for time stamp */ -struct ufs_uic_err_reg_hist { +struct ufs_err_reg_hist { int pos; - u32 reg[UIC_ERR_REG_HIST_LENGTH]; - ktime_t tstamp[UIC_ERR_REG_HIST_LENGTH]; + u32 reg[UFS_ERR_REG_HIST_LENGTH]; + ktime_t tstamp[UFS_ERR_REG_HIST_LENGTH]; }; /** @@ -440,11 +440,11 @@ struct ufs_uic_err_reg_hist { struct ufs_stats { u32 hibern8_exit_cnt; ktime_t last_hibern8_exit_tstamp; - struct ufs_uic_err_reg_hist pa_err; - struct ufs_uic_err_reg_hist dl_err; - struct ufs_uic_err_reg_hist nl_err; - struct ufs_uic_err_reg_hist tl_err; - struct ufs_uic_err_reg_hist dme_err; + struct ufs_err_reg_hist pa_err; + struct ufs_err_reg_hist dl_err; + struct ufs_err_reg_hist nl_err; + struct ufs_err_reg_hist tl_err; + struct ufs_err_reg_hist dme_err; }; /** -- cgit v1.2.3-59-g8ed1b From d3c615bf586f2796f24097bfa13386effaa4bf3e Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Wed, 10 Jul 2019 21:38:19 +0800 Subject: scsi: ufs: Add fatal and auto-hibern8 error history Provide more information about fatal and auto-hibern8 errors to improve debugging by extending existing UFS error history framework. [mkp: typos] Signed-off-by: Stanley Chu Reviewed-by: Avri Altman Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 11 ++++++++++- drivers/scsi/ufs/ufshcd.h | 10 +++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 3865ba9886c2..46815e704396 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -429,6 +429,9 @@ static void ufshcd_print_host_regs(struct ufs_hba *hba) ufshcd_print_err_hist(hba, &hba->ufs_stats.nl_err, "nl_err"); ufshcd_print_err_hist(hba, &hba->ufs_stats.tl_err, "tl_err"); ufshcd_print_err_hist(hba, &hba->ufs_stats.dme_err, "dme_err"); + ufshcd_print_err_hist(hba, &hba->ufs_stats.fatal_err, "fatal_err"); + ufshcd_print_err_hist(hba, &hba->ufs_stats.auto_hibern8_err, + "auto_hibern8_err"); ufshcd_print_clk_freqs(hba); @@ -5439,8 +5442,10 @@ static void ufshcd_check_errors(struct ufs_hba *hba) { bool queue_eh_work = false; - if (hba->errors & INT_FATAL_ERRORS) + if (hba->errors & INT_FATAL_ERRORS) { + ufshcd_update_reg_hist(&hba->ufs_stats.fatal_err, hba->errors); queue_eh_work = true; + } if (hba->errors & UIC_ERROR) { hba->uic_error = 0; @@ -5455,6 +5460,8 @@ static void ufshcd_check_errors(struct ufs_hba *hba) __func__, (hba->errors & UIC_HIBERNATE_ENTER) ? "Enter" : "Exit", hba->errors, ufshcd_get_upmcrs(hba)); + ufshcd_update_reg_hist(&hba->ufs_stats.auto_hibern8_err, + hba->errors); queue_eh_work = true; } @@ -6692,6 +6699,8 @@ static void ufshcd_clear_dbg_ufs_stats(struct ufs_hba *hba) memset(&hba->ufs_stats.nl_err, 0, err_reg_hist_size); memset(&hba->ufs_stats.tl_err, 0, err_reg_hist_size); memset(&hba->ufs_stats.dme_err, 0, err_reg_hist_size); + memset(&hba->ufs_stats.fatal_err, 0, err_reg_hist_size); + memset(&hba->ufs_stats.auto_hibern8_err, 0, err_reg_hist_size); hba->req_abort_count = 0; } diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index dcc61f857c38..c6ec5c749ceb 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -414,7 +414,7 @@ struct ufs_init_prefetch { #define UFS_ERR_REG_HIST_LENGTH 8 /** - * struct ufs_err_reg_hist - keeps history of uic errors + * struct ufs_err_reg_hist - keeps history of errors * @pos: index to indicate cyclic buffer position * @reg: cyclic buffer for registers value * @tstamp: cyclic buffer for time stamp @@ -436,15 +436,23 @@ struct ufs_err_reg_hist { * @nl_err: tracks nl-uic errors * @tl_err: tracks tl-uic errors * @dme_err: tracks dme errors + * @fatal_err: tracks fatal errors + * @auto_hibern8_err: tracks auto-hibernate errors */ struct ufs_stats { u32 hibern8_exit_cnt; ktime_t last_hibern8_exit_tstamp; + + /* uic specific errors */ struct ufs_err_reg_hist pa_err; struct ufs_err_reg_hist dl_err; struct ufs_err_reg_hist nl_err; struct ufs_err_reg_hist tl_err; struct ufs_err_reg_hist dme_err; + + /* fatal errors */ + struct ufs_err_reg_hist fatal_err; + struct ufs_err_reg_hist auto_hibern8_err; }; /** -- cgit v1.2.3-59-g8ed1b From c5397f13fc744b15fc9ad5df27172885e2303c39 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Wed, 10 Jul 2019 21:38:20 +0800 Subject: scsi: ufs: Do not reset error history during host reset Currently UFS error history will be reset and lost during host reset flow by ufschd_probe_hba(). Avoid resetting it so error history can be kept as complete as possible to improve debugging. In addition, fix a minor display error in ufshcd_print_err_hist(). [mkp: commit desc clarification] Signed-off-by: Stanley Chu Reviewed-by: Avri Altman Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 46815e704396..f272ec3cad58 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -402,7 +402,7 @@ static void ufshcd_print_err_hist(struct ufs_hba *hba, if (err_hist->reg[p] == 0) continue; - dev_err(hba->dev, "%s[%d] = 0x%x at %lld us\n", err_name, i, + dev_err(hba->dev, "%s[%d] = 0x%x at %lld us\n", err_name, p, err_hist->reg[p], ktime_to_us(err_hist->tstamp[p])); found = true; } @@ -6689,19 +6689,8 @@ static void ufshcd_tune_unipro_params(struct ufs_hba *hba) static void ufshcd_clear_dbg_ufs_stats(struct ufs_hba *hba) { - int err_reg_hist_size = sizeof(struct ufs_err_reg_hist); - hba->ufs_stats.hibern8_exit_cnt = 0; hba->ufs_stats.last_hibern8_exit_tstamp = ktime_set(0, 0); - - memset(&hba->ufs_stats.pa_err, 0, err_reg_hist_size); - memset(&hba->ufs_stats.dl_err, 0, err_reg_hist_size); - memset(&hba->ufs_stats.nl_err, 0, err_reg_hist_size); - memset(&hba->ufs_stats.tl_err, 0, err_reg_hist_size); - memset(&hba->ufs_stats.dme_err, 0, err_reg_hist_size); - memset(&hba->ufs_stats.fatal_err, 0, err_reg_hist_size); - memset(&hba->ufs_stats.auto_hibern8_err, 0, err_reg_hist_size); - hba->req_abort_count = 0; } -- cgit v1.2.3-59-g8ed1b From 8808b4e9dcdc908e1d48b1809416c5f80af9c87e Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Wed, 10 Jul 2019 21:38:21 +0800 Subject: scsi: ufs: Add history of fatal events Currently only "interrupt-based" errors have their own history, however there are some "non-interrupt-based" errors or events which need history to improve debugging or help know the health status of UFS devices. Example of fatal errors: - Link startup error - Suspend error - Resume error Example of abnormal events: - Task or request abort - Device reset (now equals to Logical Unit Reset) - Host reset This patch tries to track above errors and events by existed UFS error history mechanism. Signed-off-by: Stanley Chu Reviewed-by: Avri Altman Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 46 ++++++++++++++++++++++++++++++++++------------ drivers/scsi/ufs/ufshcd.h | 18 ++++++++++++++++-- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index f272ec3cad58..3804a704e565 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -429,9 +429,17 @@ static void ufshcd_print_host_regs(struct ufs_hba *hba) ufshcd_print_err_hist(hba, &hba->ufs_stats.nl_err, "nl_err"); ufshcd_print_err_hist(hba, &hba->ufs_stats.tl_err, "tl_err"); ufshcd_print_err_hist(hba, &hba->ufs_stats.dme_err, "dme_err"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.fatal_err, "fatal_err"); ufshcd_print_err_hist(hba, &hba->ufs_stats.auto_hibern8_err, "auto_hibern8_err"); + ufshcd_print_err_hist(hba, &hba->ufs_stats.fatal_err, "fatal_err"); + ufshcd_print_err_hist(hba, &hba->ufs_stats.link_startup_err, + "link_startup_fail"); + ufshcd_print_err_hist(hba, &hba->ufs_stats.resume_err, "resume_fail"); + ufshcd_print_err_hist(hba, &hba->ufs_stats.suspend_err, + "suspend_fail"); + ufshcd_print_err_hist(hba, &hba->ufs_stats.dev_reset, "dev_reset"); + ufshcd_print_err_hist(hba, &hba->ufs_stats.host_reset, "host_reset"); + ufshcd_print_err_hist(hba, &hba->ufs_stats.task_abort, "task_abort"); ufshcd_print_clk_freqs(hba); @@ -4330,6 +4338,14 @@ static inline int ufshcd_disable_device_tx_lcc(struct ufs_hba *hba) return ufshcd_disable_tx_lcc(hba, true); } +static void ufshcd_update_reg_hist(struct ufs_err_reg_hist *reg_hist, + u32 reg) +{ + reg_hist->reg[reg_hist->pos] = reg; + reg_hist->tstamp[reg_hist->pos] = ktime_get(); + reg_hist->pos = (reg_hist->pos + 1) % UFS_ERR_REG_HIST_LENGTH; +} + /** * ufshcd_link_startup - Initialize unipro link startup * @hba: per adapter instance @@ -4357,6 +4373,8 @@ link_startup: /* check if device is detected by inter-connect layer */ if (!ret && !ufshcd_is_device_present(hba)) { + ufshcd_update_reg_hist(&hba->ufs_stats.link_startup_err, + 0); dev_err(hba->dev, "%s: Device not present\n", __func__); ret = -ENXIO; goto out; @@ -4367,13 +4385,19 @@ link_startup: * but we can't be sure if the link is up until link startup * succeeds. So reset the local Uni-Pro and try again. */ - if (ret && ufshcd_hba_enable(hba)) + if (ret && ufshcd_hba_enable(hba)) { + ufshcd_update_reg_hist(&hba->ufs_stats.link_startup_err, + (u32)ret); goto out; + } } while (ret && retries--); - if (ret) + if (ret) { /* failed to get the link up... retire */ + ufshcd_update_reg_hist(&hba->ufs_stats.link_startup_err, + (u32)ret); goto out; + } if (link_startup_again) { link_startup_again = false; @@ -5349,14 +5373,6 @@ out: pm_runtime_put_sync(hba->dev); } -static void ufshcd_update_reg_hist(struct ufs_err_reg_hist *reg_hist, - u32 reg) -{ - reg_hist->reg[reg_hist->pos] = reg; - reg_hist->tstamp[reg_hist->pos] = ktime_get(); - reg_hist->pos = (reg_hist->pos + 1) % UFS_ERR_REG_HIST_LENGTH; -} - /** * ufshcd_update_uic_error - check and set fatal UIC error flags. * @hba: per-adapter instance @@ -5949,6 +5965,7 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd) out: hba->req_abort_count = 0; + ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, (u32)err); if (!err) { err = SUCCESS; } else { @@ -6042,6 +6059,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) */ scsi_print_command(hba->lrb[tag].cmd); if (!hba->req_abort_count) { + ufshcd_update_reg_hist(&hba->ufs_stats.task_abort, 0); ufshcd_print_host_regs(hba); ufshcd_print_host_state(hba); ufshcd_print_pwr_info(hba); @@ -6177,7 +6195,7 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba) out: if (err) dev_err(hba->dev, "%s: Host init failed %d\n", __func__, err); - + ufshcd_update_reg_hist(&hba->ufs_stats.host_reset, (u32)err); return err; } @@ -7819,6 +7837,8 @@ enable_gating: ufshcd_release(hba); out: hba->pm_op_in_progress = 0; + if (ret) + ufshcd_update_reg_hist(&hba->ufs_stats.suspend_err, (u32)ret); return ret; } @@ -7921,6 +7941,8 @@ disable_irq_and_vops_clks: ufshcd_setup_clocks(hba, false); out: hba->pm_op_in_progress = 0; + if (ret) + ufshcd_update_reg_hist(&hba->ufs_stats.resume_err, (u32)ret); return ret; } diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index c6ec5c749ceb..a43c7135f33d 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -436,8 +436,14 @@ struct ufs_err_reg_hist { * @nl_err: tracks nl-uic errors * @tl_err: tracks tl-uic errors * @dme_err: tracks dme errors - * @fatal_err: tracks fatal errors * @auto_hibern8_err: tracks auto-hibernate errors + * @fatal_err: tracks fatal errors + * @linkup_err: tracks link-startup errors + * @resume_err: tracks resume errors + * @suspend_err: tracks suspend errors + * @dev_reset: tracks device reset events + * @host_reset: tracks host reset events + * @tsk_abort: tracks task abort events */ struct ufs_stats { u32 hibern8_exit_cnt; @@ -451,8 +457,16 @@ struct ufs_stats { struct ufs_err_reg_hist dme_err; /* fatal errors */ - struct ufs_err_reg_hist fatal_err; struct ufs_err_reg_hist auto_hibern8_err; + struct ufs_err_reg_hist fatal_err; + struct ufs_err_reg_hist link_startup_err; + struct ufs_err_reg_hist resume_err; + struct ufs_err_reg_hist suspend_err; + + /* abnormal events */ + struct ufs_err_reg_hist dev_reset; + struct ufs_err_reg_hist host_reset; + struct ufs_err_reg_hist task_abort; }; /** -- cgit v1.2.3-59-g8ed1b From cf949bbe22bee8749078e0b810ee2dc60a983746 Mon Sep 17 00:00:00 2001 From: Avri Altman Date: Wed, 12 Jun 2019 16:34:37 +0300 Subject: scsi: ufs: uapi: Fix SPDX license identifier Added 'WITH Linux-syscall-note' exception which is the officially assigned exception identifier for the kernel syscall exception. This exception makes it possible to include GPL headers into non GPL code without confusing license compliance tools. Fixes: a851b2bd3632 (scsi: uapi: ufs: Make utp_upiu_req visible to user space) Signed-off-by: Avri Altman Reviewed-by: Pedro Sousa Signed-off-by: Martin K. Petersen --- include/uapi/scsi/scsi_bsg_ufs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/uapi/scsi/scsi_bsg_ufs.h b/include/uapi/scsi/scsi_bsg_ufs.h index 17c7abd0803a..9988db6ad244 100644 --- a/include/uapi/scsi/scsi_bsg_ufs.h +++ b/include/uapi/scsi/scsi_bsg_ufs.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * UFS Transport SGIO v4 BSG Message Support * -- cgit v1.2.3-59-g8ed1b From 8930a6c207918d5a5675eedab06a71096b1a3d47 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 30 May 2019 13:28:10 +0200 Subject: scsi: core: add support for request batching This allows a list of requests to be issued, with the LLD only writing the hardware doorbell when necessary, after the last request was prepared. This is more efficient if we have lists of requests to issue, particularly on virtualized hardware, where writing the doorbell is more expensive than on real hardware. The use case for this is plugged IO, where blk-mq flushes a batch of requests all at once. The API is the same as for blk-mq, just with blk-mq concepts tweaked to fit the SCSI subsystem API: the "last" flag in blk_mq_queue_data becomes a flag in scsi_cmnd, while the queue_num in the commit_rqs callback is extracted from the hctx and passed as a parameter. The only complication is that blk-mq uses different plugging heuristics depending on whether commit_rqs is present or not. So we have two different sets of blk_mq_ops and pick one depending on whether the scsi_host template uses commit_rqs or not. Signed-off-by: Paolo Bonzini Reviewed-by: Bart Van Assche Reviewed-by: Ming Lei Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 37 ++++++++++++++++++++++++++++++++++--- include/scsi/scsi_cmnd.h | 1 + include/scsi/scsi_host.h | 16 ++++++++++++++-- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 9381171c2fc0..c72bce2f0cf1 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1666,10 +1666,11 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx, blk_mq_start_request(req); } + cmd->flags &= SCMD_PRESERVED_FLAGS; if (sdev->simple_tags) cmd->flags |= SCMD_TAGGED; - else - cmd->flags &= ~SCMD_TAGGED; + if (bd->last) + cmd->flags |= SCMD_LAST; scsi_init_cmd_errh(cmd); cmd->scsi_done = scsi_mq_done; @@ -1807,10 +1808,37 @@ void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q) } EXPORT_SYMBOL_GPL(__scsi_init_queue); +static const struct blk_mq_ops scsi_mq_ops_no_commit = { + .get_budget = scsi_mq_get_budget, + .put_budget = scsi_mq_put_budget, + .queue_rq = scsi_queue_rq, + .complete = scsi_softirq_done, + .timeout = scsi_timeout, +#ifdef CONFIG_BLK_DEBUG_FS + .show_rq = scsi_show_rq, +#endif + .init_request = scsi_mq_init_request, + .exit_request = scsi_mq_exit_request, + .initialize_rq_fn = scsi_initialize_rq, + .busy = scsi_mq_lld_busy, + .map_queues = scsi_map_queues, +}; + + +static void scsi_commit_rqs(struct blk_mq_hw_ctx *hctx) +{ + struct request_queue *q = hctx->queue; + struct scsi_device *sdev = q->queuedata; + struct Scsi_Host *shost = sdev->host; + + shost->hostt->commit_rqs(shost, hctx->queue_num); +} + static const struct blk_mq_ops scsi_mq_ops = { .get_budget = scsi_mq_get_budget, .put_budget = scsi_mq_put_budget, .queue_rq = scsi_queue_rq, + .commit_rqs = scsi_commit_rqs, .complete = scsi_softirq_done, .timeout = scsi_timeout, #ifdef CONFIG_BLK_DEBUG_FS @@ -1846,7 +1874,10 @@ int scsi_mq_setup_tags(struct Scsi_Host *shost) sizeof(struct scatterlist) * SCSI_INLINE_PROT_SG_CNT; memset(&shost->tag_set, 0, sizeof(shost->tag_set)); - shost->tag_set.ops = &scsi_mq_ops; + if (shost->hostt->commit_rqs) + shost->tag_set.ops = &scsi_mq_ops; + else + shost->tag_set.ops = &scsi_mq_ops_no_commit; shost->tag_set.nr_hw_queues = shost->nr_hw_queues ? : 1; shost->tag_set.queue_depth = shost->can_queue; shost->tag_set.cmd_size = cmd_size; diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 76ed5e4acd38..91bd749a02f7 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -57,6 +57,7 @@ struct scsi_pointer { #define SCMD_TAGGED (1 << 0) #define SCMD_UNCHECKED_ISA_DMA (1 << 1) #define SCMD_INITIALIZED (1 << 2) +#define SCMD_LAST (1 << 3) /* flags preserved across unprep / reprep */ #define SCMD_PRESERVED_FLAGS (SCMD_UNCHECKED_ISA_DMA | SCMD_INITIALIZED) diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index cc139dbd71e5..31e0d6ca1eba 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -80,8 +80,10 @@ struct scsi_host_template { * command block to the LLDD. When the driver finished * processing the command the done callback is invoked. * - * If queuecommand returns 0, then the HBA has accepted the - * command. The done() function must be called on the command + * If queuecommand returns 0, then the driver has accepted the + * command. It must also push it to the HBA if the scsi_cmnd + * flag SCMD_LAST is set, or if the driver does not implement + * commit_rqs. The done() function must be called on the command * when the driver has finished with it. (you may call done on the * command before queuecommand returns, but in this case you * *must* return 0 from queuecommand). @@ -109,6 +111,16 @@ struct scsi_host_template { */ int (* queuecommand)(struct Scsi_Host *, struct scsi_cmnd *); + /* + * The commit_rqs function is used to trigger a hardware + * doorbell after some requests have been queued with + * queuecommand, when an error is encountered before sending + * the request with SCMD_LAST set. + * + * STATUS: OPTIONAL + */ + void (*commit_rqs)(struct Scsi_Host *, u16); + /* * This is an error handling strategy routine. You don't need to * define one of these if you don't want to - there is a default -- cgit v1.2.3-59-g8ed1b From 9e5470fe2d61bd87c27c7722099bafab277f81ec Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 30 May 2019 13:28:11 +0200 Subject: scsi: virtio_scsi: implement request batching Adding the command and kicking the virtqueue so far was done one after another. Make the kick optional, so that we can take into account SCMD_LAST. We also need a commit_rqs callback to kick the device if blk-mq aborts the submission before the last request is reached. Suggested-by: Stefan Hajnoczi Signed-off-by: Paolo Bonzini Reviewed-by: Hannes Reinecke Reviewed-by: Ming Lei Signed-off-by: Martin K. Petersen --- drivers/scsi/virtio_scsi.c | 55 +++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 297e1076e571..cff083049d5c 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -369,14 +369,7 @@ static void virtscsi_event_done(struct virtqueue *vq) virtscsi_vq_done(vscsi, &vscsi->event_vq, virtscsi_complete_event); }; -/** - * virtscsi_add_cmd - add a virtio_scsi_cmd to a virtqueue - * @vq : the struct virtqueue we're talking about - * @cmd : command structure - * @req_size : size of the request buffer - * @resp_size : size of the response buffer - */ -static int virtscsi_add_cmd(struct virtqueue *vq, +static int __virtscsi_add_cmd(struct virtqueue *vq, struct virtio_scsi_cmd *cmd, size_t req_size, size_t resp_size) { @@ -421,17 +414,39 @@ static int virtscsi_add_cmd(struct virtqueue *vq, return virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, GFP_ATOMIC); } -static int virtscsi_kick_cmd(struct virtio_scsi_vq *vq, +static void virtscsi_kick_vq(struct virtio_scsi_vq *vq) +{ + bool needs_kick; + unsigned long flags; + + spin_lock_irqsave(&vq->vq_lock, flags); + needs_kick = virtqueue_kick_prepare(vq->vq); + spin_unlock_irqrestore(&vq->vq_lock, flags); + + if (needs_kick) + virtqueue_notify(vq->vq); +} + +/** + * virtscsi_add_cmd - add a virtio_scsi_cmd to a virtqueue, optionally kick it + * @vq : the struct virtqueue we're talking about + * @cmd : command structure + * @req_size : size of the request buffer + * @resp_size : size of the response buffer + * @kick : whether to kick the virtqueue immediately + */ +static int virtscsi_add_cmd(struct virtio_scsi_vq *vq, struct virtio_scsi_cmd *cmd, - size_t req_size, size_t resp_size) + size_t req_size, size_t resp_size, + bool kick) { unsigned long flags; int err; bool needs_kick = false; spin_lock_irqsave(&vq->vq_lock, flags); - err = virtscsi_add_cmd(vq->vq, cmd, req_size, resp_size); - if (!err) + err = __virtscsi_add_cmd(vq->vq, cmd, req_size, resp_size); + if (!err && kick) needs_kick = virtqueue_kick_prepare(vq->vq); spin_unlock_irqrestore(&vq->vq_lock, flags); @@ -496,6 +511,7 @@ static int virtscsi_queuecommand(struct Scsi_Host *shost, struct virtio_scsi *vscsi = shost_priv(shost); struct virtio_scsi_vq *req_vq = virtscsi_pick_vq_mq(vscsi, sc); struct virtio_scsi_cmd *cmd = scsi_cmd_priv(sc); + bool kick; unsigned long flags; int req_size; int ret; @@ -525,7 +541,8 @@ static int virtscsi_queuecommand(struct Scsi_Host *shost, req_size = sizeof(cmd->req.cmd); } - ret = virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd)); + kick = (sc->flags & SCMD_LAST) != 0; + ret = virtscsi_add_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd), kick); if (ret == -EIO) { cmd->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET; spin_lock_irqsave(&req_vq->vq_lock, flags); @@ -543,8 +560,8 @@ static int virtscsi_tmf(struct virtio_scsi *vscsi, struct virtio_scsi_cmd *cmd) int ret = FAILED; cmd->comp = ∁ - if (virtscsi_kick_cmd(&vscsi->ctrl_vq, cmd, - sizeof cmd->req.tmf, sizeof cmd->resp.tmf) < 0) + if (virtscsi_add_cmd(&vscsi->ctrl_vq, cmd, + sizeof cmd->req.tmf, sizeof cmd->resp.tmf, true) < 0) goto out; wait_for_completion(&comp); @@ -658,6 +675,13 @@ static int virtscsi_map_queues(struct Scsi_Host *shost) return blk_mq_virtio_map_queues(qmap, vscsi->vdev, 2); } +static void virtscsi_commit_rqs(struct Scsi_Host *shost, u16 hwq) +{ + struct virtio_scsi *vscsi = shost_priv(shost); + + virtscsi_kick_vq(&vscsi->req_vqs[hwq]); +} + /* * The host guarantees to respond to each command, although I/O * latencies might be higher than on bare metal. Reset the timer @@ -675,6 +699,7 @@ static struct scsi_host_template virtscsi_host_template = { .this_id = -1, .cmd_size = sizeof(struct virtio_scsi_cmd), .queuecommand = virtscsi_queuecommand, + .commit_rqs = virtscsi_commit_rqs, .change_queue_depth = virtscsi_change_queue_depth, .eh_abort_handler = virtscsi_abort, .eh_device_reset_handler = virtscsi_device_reset, -- cgit v1.2.3-59-g8ed1b From 70a51d8c53176080e82b2aef050f820ccdd4b3f8 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 11 Jul 2019 22:10:37 +0800 Subject: scsi: lpfc: Remove unnecessary null check before kfree A null check before a kfree is redundant, so remove it. This is detected by coccinelle. Signed-off-by: YueHaibing Reviewed-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_bsg.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index b7216d694bff..c7f66239ca70 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -1276,9 +1276,7 @@ lpfc_bsg_hba_set_event(struct bsg_job *job) return 0; /* call job done later */ job_error: - if (dd_data != NULL) - kfree(dd_data); - + kfree(dd_data); job->dd_data = NULL; return rc; } -- cgit v1.2.3-59-g8ed1b From 838c1efc6a0adbf44d16e4714f43443db598cdb5 Mon Sep 17 00:00:00 2001 From: Bean Huo Date: Mon, 15 Jul 2019 11:21:10 +0000 Subject: scsi: ufs: change msleep to usleep_range This patch is to change msleep() to usleep_range() based on Documentation/timers/timers-howto.txt. It suggests using usleep_range() for small msec(1ms - 20ms) since msleep() will often sleep longer than desired value. After changing, booting time will be 5ms-10ms faster than before. I tested this change on two different platforms, one has 5ms faster, another one is about 10ms. I think this is different on different platform. Actually, from UFS host side, 1ms-5ms delay is already sufficient for its initialization of the local UIC layer. Fixes: 7a3e97b0dc4b ([SCSI] ufshcd: UFS Host controller driver) Signed-off-by: Bean Huo Acked-by: Stanley Chu Reviewed-by: Avri Altman Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 3804a704e565..a383d0f54f5d 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -4226,12 +4226,6 @@ static int ufshcd_hba_execute_hce(struct ufs_hba *hba) { int retry; - /* - * msleep of 1 and 5 used in this function might result in msleep(20), - * but it was necessary to send the UFS FPGA to reset mode during - * development and testing of this driver. msleep can be changed to - * mdelay and retry count can be reduced based on the controller. - */ if (!ufshcd_is_hba_active(hba)) /* change controller state to "reset state" */ ufshcd_hba_stop(hba, true); @@ -4254,7 +4248,7 @@ static int ufshcd_hba_execute_hce(struct ufs_hba *hba) * instruction might be read back. * This delay can be changed based on the controller. */ - msleep(1); + usleep_range(1000, 1100); /* wait for the host controller to complete initialization */ retry = 10; @@ -4266,7 +4260,7 @@ static int ufshcd_hba_execute_hce(struct ufs_hba *hba) "Controller enable failed\n"); return -EIO; } - msleep(5); + usleep_range(5000, 5100); } /* enable UIC related interrupts */ -- cgit v1.2.3-59-g8ed1b From 0b3b6fe299c471e44ed8713b7a602882626e693f Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 11 Jul 2019 22:13:17 +0800 Subject: scsi: qla2xxx: Remove unnecessary null check A null check before dma_pool_destroy is redundant, so remove it. This is detected by coccinelle. Signed-off-by: YueHaibing Acked-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2e58cff9d200..3c59157bb3bd 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -4731,8 +4731,7 @@ qla2x00_mem_free(struct qla_hw_data *ha) } } - if (ha->dif_bundl_pool) - dma_pool_destroy(ha->dif_bundl_pool); + dma_pool_destroy(ha->dif_bundl_pool); ha->dif_bundl_pool = NULL; qlt_mem_free(ha); -- cgit v1.2.3-59-g8ed1b From b217598890a26fe49c83f4f3124c343a6d990eb2 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 11 Jul 2019 22:15:39 +0800 Subject: scsi: aic94xx: Remove unnecessary null check kmem_cache_destroy() can handle NULL pointer correctly, so there is no need to check NULL pointer before calling kmem_cache_destroy(). Signed-off-by: YueHaibing Signed-off-by: Martin K. Petersen --- drivers/scsi/aic94xx/aic94xx_init.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 261d8e495fed..f5781e31f57c 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -565,8 +565,7 @@ static void asd_destroy_ha_caches(struct asd_ha_struct *asd_ha) if (asd_ha->hw_prof.scb_ext) asd_free_coherent(asd_ha, asd_ha->hw_prof.scb_ext); - if (asd_ha->hw_prof.ddb_bitmap) - kfree(asd_ha->hw_prof.ddb_bitmap); + kfree(asd_ha->hw_prof.ddb_bitmap); asd_ha->hw_prof.ddb_bitmap = NULL; for (i = 0; i < ASD_MAX_PHYS; i++) { @@ -641,12 +640,10 @@ Err: static void asd_destroy_global_caches(void) { - if (asd_dma_token_cache) - kmem_cache_destroy(asd_dma_token_cache); + kmem_cache_destroy(asd_dma_token_cache); asd_dma_token_cache = NULL; - if (asd_ascb_cache) - kmem_cache_destroy(asd_ascb_cache); + kmem_cache_destroy(asd_ascb_cache); asd_ascb_cache = NULL; } -- cgit v1.2.3-59-g8ed1b From a9651be7e4818d252e2a35f371bde79c556b1560 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 16 Jul 2019 23:39:15 +0300 Subject: scsi: fdomain: use BCTL_RST in fdomain_reset() Commit 1697c6a64c49 ("scsi: fdomain: Add register definitions") somehow missed the use of BCTL_RST in fdomain_reset(), leaving the magic number intact. Fix this issue (with no change in the generated object file). Fixes: 1697c6a64c49 ("scsi: fdomain: Add register definitions") Signed-off-by: Sergei Shtylyov Signed-off-by: Martin K. Petersen --- drivers/scsi/fdomain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index b5e66971b6d9..fcf4cd5ef1ac 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -166,7 +166,7 @@ static int fdomain_test_loopback(int base) static void fdomain_reset(int base) { - outb(1, base + REG_BCTL); + outb(BCTL_RST, base + REG_BCTL); mdelay(20); outb(0, base + REG_BCTL); mdelay(1150); -- cgit v1.2.3-59-g8ed1b From 7a1c0b79dbe3423214e70750a5ee38fb617168ab Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 16 Jul 2019 23:40:47 +0300 Subject: scsi: fdomain: use BSTAT_{MSG|CMD|IO} in fdomain_work() Commit 1697c6a64c49 ("scsi: fdomain: Add register definitions") somehow missed the masking of the 'status' variable with the SCSI phase mask in fdomain_work(), leaving the magic number intact. Fix this issue; while at it, change the order of BSTAT_{MSG|CMD|IO} bits in the MESSAGE IN phase *case* (with no change in the generated object file). Fixes: 1697c6a64c49 ("scsi: fdomain: Add register definitions") Signed-off-by: Sergei Shtylyov Signed-off-by: Martin K. Petersen --- drivers/scsi/fdomain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index fcf4cd5ef1ac..772bdc93930a 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -306,7 +306,7 @@ static void fdomain_work(struct work_struct *work) status = inb(fd->base + REG_BSTAT); if (status & BSTAT_REQ) { - switch (status & 0x0e) { + switch (status & (BSTAT_MSG | BSTAT_CMD | BSTAT_IO)) { case BSTAT_CMD: /* COMMAND OUT */ outb(cmd->cmnd[cmd->SCp.sent_command++], fd->base + REG_SCSI_DATA); @@ -331,7 +331,7 @@ static void fdomain_work(struct work_struct *work) case BSTAT_MSG | BSTAT_CMD: /* MESSAGE OUT */ outb(MESSAGE_REJECT, fd->base + REG_SCSI_DATA); break; - case BSTAT_MSG | BSTAT_IO | BSTAT_CMD: /* MESSAGE IN */ + case BSTAT_MSG | BSTAT_CMD | BSTAT_IO: /* MESSAGE IN */ cmd->SCp.Message = inb(fd->base + REG_SCSI_DATA); if (!cmd->SCp.Message) ++done; -- cgit v1.2.3-59-g8ed1b From 22d5aa3a4570b1419003d19992080c423dbf1734 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 16 Jul 2019 23:41:54 +0300 Subject: scsi: fdomain_isa: use CFG1_IRQ_MASK Commit 1697c6a64c49 ("scsi: fdomain: Add register definitions") somehow missed the uses of CFG1_IRQ_MASK in the Futire Domain ISA driver, leaving the magic numbers intact. Fix this issue (with no change in the generated object file), removing an excess empty line, while at it... Fixes: 1697c6a64c49 ("scsi: fdomain: Add register definitions") Signed-off-by: Sergei Shtylyov Signed-off-by: Martin K. Petersen --- drivers/scsi/fdomain_isa.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/fdomain_isa.c b/drivers/scsi/fdomain_isa.c index 28639adf8219..f2da4fa382e8 100644 --- a/drivers/scsi/fdomain_isa.c +++ b/drivers/scsi/fdomain_isa.c @@ -131,8 +131,7 @@ static int fdomain_isa_match(struct device *dev, unsigned int ndev) if (!request_region(base, FDOMAIN_REGION_SIZE, "fdomain_isa")) return 0; - irq = irqs[(inb(base + REG_CFG1) & 0x0e) >> 1]; - + irq = irqs[(inb(base + REG_CFG1) & CFG1_IRQ_MASK) >> 1]; if (sig) this_id = sig->this_id; @@ -164,7 +163,7 @@ static int fdomain_isa_param_match(struct device *dev, unsigned int ndev) } if (irq_ <= 0) - irq_ = irqs[(inb(io[ndev] + REG_CFG1) & 0x0e) >> 1]; + irq_ = irqs[(inb(io[ndev] + REG_CFG1) & CFG1_IRQ_MASK) >> 1]; sh = fdomain_create(io[ndev], irq_, scsi_id[ndev], dev); if (!sh) { -- cgit v1.2.3-59-g8ed1b From 56cc8fae5f7e9f38cb367754c52491ba1645d1bf Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Thu, 18 Jul 2019 15:45:18 +0800 Subject: scsi: qla2xxx: Replace vmalloc + memset with vzalloc Use vzalloc instead of using vmalloc to allocate memory and then zeroing it with memset. This simplifies the code. Signed-off-by: Chuhong Yuan Acked-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_attr.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 8d560c562e9c..2b92d4659934 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -382,7 +382,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, ha->optrom_region_size = size; ha->optrom_state = QLA_SREADING; - ha->optrom_buffer = vmalloc(ha->optrom_region_size); + ha->optrom_buffer = vzalloc(ha->optrom_region_size); if (ha->optrom_buffer == NULL) { ql_log(ql_log_warn, vha, 0x7062, "Unable to allocate memory for optrom retrieval " @@ -404,7 +404,6 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, "Reading flash region -- 0x%x/0x%x.\n", ha->optrom_region_start, ha->optrom_region_size); - memset(ha->optrom_buffer, 0, ha->optrom_region_size); ha->isp_ops->read_optrom(vha, ha->optrom_buffer, ha->optrom_region_start, ha->optrom_region_size); break; @@ -457,7 +456,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, ha->optrom_region_size = size; ha->optrom_state = QLA_SWRITING; - ha->optrom_buffer = vmalloc(ha->optrom_region_size); + ha->optrom_buffer = vzalloc(ha->optrom_region_size); if (ha->optrom_buffer == NULL) { ql_log(ql_log_warn, vha, 0x7066, "Unable to allocate memory for optrom update " @@ -472,7 +471,6 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, "Staging flash region write -- 0x%x/0x%x.\n", ha->optrom_region_start, ha->optrom_region_size); - memset(ha->optrom_buffer, 0, ha->optrom_region_size); break; case 3: if (ha->optrom_state != QLA_SWRITING) { -- cgit v1.2.3-59-g8ed1b From 1623835507e343fbc30c5806c65cafc149e8fcc7 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 25 Jul 2019 23:07:51 +0300 Subject: scsi: scsi_debugfs: Use for_each_set_bit to simplify code We can use for_each_set_bit() to slightly simplify the code. Signed-off-by: Andy Shevchenko Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debugfs.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/scsi_debugfs.c b/drivers/scsi/scsi_debugfs.c index c5a8756384bc..c19ea7ab54cb 100644 --- a/drivers/scsi/scsi_debugfs.c +++ b/drivers/scsi/scsi_debugfs.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include #include #include @@ -18,9 +19,7 @@ static int scsi_flags_show(struct seq_file *m, const unsigned long flags, bool sep = false; int i; - for (i = 0; i < sizeof(flags) * BITS_PER_BYTE; i++) { - if (!(flags & BIT(i))) - continue; + for_each_set_bit(i, &flags, BITS_PER_LONG) { if (sep) seq_puts(m, "|"); sep = true; -- cgit v1.2.3-59-g8ed1b From 1de540a9263876a068a15ce216bd236e2c3394d6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 26 Jul 2019 09:52:05 +0300 Subject: scsi: mpt3sas: clean up a couple sizeof() uses There is a copy and paste bug here. It uses EVENT_TRIGGERS size instead of SCSI_TRIGGERS size but fortunately both size are 84 bytes so it doesn't affect runtime. These days the preferred style is to just say sizeof(object) instead of sizeof(type) so I have updated the function to the latest style as well. Signed-off-by: Dan Carpenter Acked-by: Sreekanth Reddy Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index d4ecfbbe738c..41c54d4c9451 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -3278,9 +3278,8 @@ diag_trigger_scsi_store(struct device *cdev, ssize_t sz; spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - sz = min(sizeof(struct SL_WH_SCSI_TRIGGERS_T), count); - memset(&ioc->diag_trigger_scsi, 0, - sizeof(struct SL_WH_EVENT_TRIGGERS_T)); + sz = min(sizeof(ioc->diag_trigger_scsi), count); + memset(&ioc->diag_trigger_scsi, 0, sizeof(ioc->diag_trigger_scsi)); memcpy(&ioc->diag_trigger_scsi, buf, sz); if (ioc->diag_trigger_scsi.ValidEntries > NUM_VALID_ENTRIES) ioc->diag_trigger_scsi.ValidEntries = NUM_VALID_ENTRIES; -- cgit v1.2.3-59-g8ed1b From 657bd277c162580674ddb86a90c4aeb62639bff5 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 28 Jul 2019 19:21:19 -0500 Subject: scsi: cxlflash: Mark expected switch fall-throughs Mark switch cases where we are expecting to fall through. This patch fixes the following warnings: drivers/scsi/cxlflash/main.c: In function 'send_afu_cmd': drivers/scsi/cxlflash/main.c:2347:6: warning: this statement may fall through [-Wimplicit-fallthrough=] if (rc) { ^ drivers/scsi/cxlflash/main.c:2357:2: note: here case -EAGAIN: ^~~~ drivers/scsi/cxlflash/main.c: In function 'term_intr': drivers/scsi/cxlflash/main.c:754:6: warning: this statement may fall through [-Wimplicit-fallthrough=] if (index == PRIMARY_HWQ) ^ drivers/scsi/cxlflash/main.c:756:2: note: here case UNMAP_TWO: ^~~~ drivers/scsi/cxlflash/main.c:757:3: warning: this statement may fall through [-Wimplicit-fallthrough=] cfg->ops->unmap_afu_irq(hwq->ctx_cookie, 2, hwq); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/cxlflash/main.c:758:2: note: here case UNMAP_ONE: ^~~~ drivers/scsi/cxlflash/main.c:759:3: warning: this statement may fall through [-Wimplicit-fallthrough=] cfg->ops->unmap_afu_irq(hwq->ctx_cookie, 1, hwq); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/cxlflash/main.c:760:2: note: here case FREE_IRQ: ^~~~ drivers/scsi/cxlflash/main.c: In function 'cxlflash_remove': drivers/scsi/cxlflash/main.c:975:3: warning: this statement may fall through [-Wimplicit-fallthrough=] cxlflash_release_chrdev(cfg); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/cxlflash/main.c:976:2: note: here case INIT_STATE_SCSI: ^~~~ drivers/scsi/cxlflash/main.c:978:3: warning: this statement may fall through [-Wimplicit-fallthrough=] scsi_remove_host(cfg->host); ^~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/cxlflash/main.c:979:2: note: here case INIT_STATE_AFU: ^~~~ drivers/scsi/cxlflash/main.c:980:3: warning: this statement may fall through [-Wimplicit-fallthrough=] term_afu(cfg); ^~~~~~~~~~~~~ drivers/scsi/cxlflash/main.c:981:2: note: here case INIT_STATE_PCI: ^~~~ drivers/scsi/cxlflash/main.c:983:3: warning: this statement may fall through [-Wimplicit-fallthrough=] pci_disable_device(pdev); ^~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/cxlflash/main.c:984:2: note: here case INIT_STATE_NONE: ^~~~ drivers/scsi/cxlflash/main.c: In function 'num_hwqs_store': drivers/scsi/cxlflash/main.c:3018:6: warning: this statement may fall through [-Wimplicit-fallthrough=] if (cfg->state == STATE_NORMAL) ^ drivers/scsi/cxlflash/main.c:3020:2: note: here default: ^~~~~~~ Reported-by: Stephen Rothwell Signed-off-by: Gustavo A. R. Silva Reviewed-by: Kees Cook Acked-by: Matthew R. Ochs Signed-off-by: Martin K. Petersen --- drivers/scsi/cxlflash/main.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index b1f4724efde2..93ef97af22df 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -753,10 +753,13 @@ static void term_intr(struct cxlflash_cfg *cfg, enum undo_level level, /* SISL_MSI_ASYNC_ERROR is setup only for the primary HWQ */ if (index == PRIMARY_HWQ) cfg->ops->unmap_afu_irq(hwq->ctx_cookie, 3, hwq); + /* fall through */ case UNMAP_TWO: cfg->ops->unmap_afu_irq(hwq->ctx_cookie, 2, hwq); + /* fall through */ case UNMAP_ONE: cfg->ops->unmap_afu_irq(hwq->ctx_cookie, 1, hwq); + /* fall through */ case FREE_IRQ: cfg->ops->free_afu_irqs(hwq->ctx_cookie); /* fall through */ @@ -973,14 +976,18 @@ static void cxlflash_remove(struct pci_dev *pdev) switch (cfg->init_state) { case INIT_STATE_CDEV: cxlflash_release_chrdev(cfg); + /* fall through */ case INIT_STATE_SCSI: cxlflash_term_local_luns(cfg); scsi_remove_host(cfg->host); + /* fall through */ case INIT_STATE_AFU: term_afu(cfg); + /* fall through */ case INIT_STATE_PCI: cfg->ops->destroy_afu(cfg->afu_cookie); pci_disable_device(pdev); + /* fall through */ case INIT_STATE_NONE: free_mem(cfg); scsi_host_put(cfg->host); @@ -2353,11 +2360,11 @@ retry: cxlflash_schedule_async_reset(cfg); break; } - /* fall through to retry */ + /* fall through - to retry */ case -EAGAIN: if (++nretry < 2) goto retry; - /* fall through to exit */ + /* fall through - to exit */ default: break; } @@ -3017,6 +3024,7 @@ retry: wait_event(cfg->reset_waitq, cfg->state != STATE_RESET); if (cfg->state == STATE_NORMAL) goto retry; + /* else, fall through */ default: /* Ideally should not happen */ dev_err(dev, "%s: Device is not ready, state=%d\n", -- cgit v1.2.3-59-g8ed1b From 9fba647cfedc15e1ac80d396c116e106da947e55 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 29 Jul 2019 06:29:02 -0500 Subject: scsi: ibmvscsi_tgt: Mark expected switch fall-throughs Mark switch cases where we are expecting to fall through. This patch fixes the following warnings (Building: powerpc allyesconfig): drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c: In function 'ibmvscsis_adapter_info': drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c:1582:6: warning: this statement may fall through [-Wimplicit-fallthrough=] if (connection_broken(vscsi)) ^ drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c:1584:2: note: here default: ^~~~~~~ drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c: In function 'ibmvscsis_ping_response': drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c:2494:16: warning: this statement may fall through [-Wimplicit-fallthrough=] vscsi->flags |= CLIENT_FAILED; drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c:2495:2: note: here case H_DROPPED: ^~~~ drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c:2496:16: warning: this statement may fall through [-Wimplicit-fallthrough=] vscsi->flags |= RESPONSE_Q_DOWN; drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c:2497:2: note: here case H_REMOTE_PARM: ^~~~ Reported-by: Stephen Rothwell Signed-off-by: Gustavo A. R. Silva Reviewed-by: Kees Cook Reviewed-by: Bryant G. Ly Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c index 7f9535392a93..a929fe76102b 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c @@ -1581,6 +1581,7 @@ static long ibmvscsis_adapter_info(struct scsi_info *vscsi, case H_PERMISSION: if (connection_broken(vscsi)) flag_bits = (RESPONSE_Q_DOWN | CLIENT_FAILED); + /* Fall through */ default: dev_err(&vscsi->dev, "adapter_info: h_copy_rdma to client failed, rc %ld\n", rc); @@ -2492,8 +2493,10 @@ static long ibmvscsis_ping_response(struct scsi_info *vscsi) break; case H_CLOSED: vscsi->flags |= CLIENT_FAILED; + /* Fall through */ case H_DROPPED: vscsi->flags |= RESPONSE_Q_DOWN; + /* Fall through */ case H_REMOTE_PARM: dev_err(&vscsi->dev, "ping_response: h_send_crq failed, rc %ld\n", rc); -- cgit v1.2.3-59-g8ed1b From 8f55c307ab577af74efab066ba1e45b0e51e4bae Mon Sep 17 00:00:00 2001 From: Minwoo Im Date: Sun, 28 Jul 2019 03:53:37 +0900 Subject: scsi: mpt3sas: support target smid for [abort|query] task We can request task management IOCTL command(MPI2_FUNCTION_SCSI_TASK_MGMT) to /dev/mpt3ctl. If the given task_type is either abort task or query task, it may need a field named "Initiator Port Transfer Tag to Manage" in the IU. Current code does not support to check target IPTT tag from the tm_request. This patch introduces to check TaskMID given from the userspace as a target tag. We have a rule of relationship between (struct request *req->tag) and smid in mpt3sas_base.c: 3318 u16 3319 mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx, 3320 struct scsi_cmnd *scmd) 3321 { 3322 struct scsiio_tracker *request = scsi_cmd_priv(scmd); 3323 unsigned int tag = scmd->request->tag; 3324 u16 smid; 3325 3326 smid = tag + 1; So if we want to abort a request tagged #X, then we can pass (X + 1) to this IOCTL handler. Otherwise, user space just can pass 0 TaskMID to abort the first outstanding smid which is legacy behaviour. Cc: Sreekanth Reddy Cc: Suganath Prabu Subramani Cc: Sathya Prakash Cc: James E.J. Bottomley Cc: Martin K. Petersen Cc: MPT-FusionLinux.pdl@broadcom.com Signed-off-by: Minwoo Im Acked-by: Sreekanth Reddy Signed-off-by: Minwoo Im Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index 41c54d4c9451..359586027c26 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -596,8 +596,16 @@ _ctl_set_task_mid(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command *karg, if (priv_data->sas_target->handle != handle) continue; st = scsi_cmd_priv(scmd); - tm_request->TaskMID = cpu_to_le16(st->smid); - found = 1; + + /* + * If the given TaskMID from the user space is zero, then the + * first outstanding smid will be picked up. Otherwise, + * targeted smid will be the one. + */ + if (!tm_request->TaskMID || tm_request->TaskMID == st->smid) { + tm_request->TaskMID = cpu_to_le16(st->smid); + found = 1; + } } if (!found) { -- cgit v1.2.3-59-g8ed1b From 5d328de64d89400dcf9911125844d8adc0db697f Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Fri, 26 Jul 2019 09:07:26 -0700 Subject: scsi: qla2xxx: Fix DMA unmap leak With debug kernel we see following wanings indicating memory leak. [28809.523959] WARNING: CPU: 3 PID: 6790 at lib/dma-debug.c:978 dma_debug_device_change+0x166/0x1d0 [28809.523964] pci 0000:0c:00.6: DMA-API: device driver has pending DMA allocations while released from device [count=5] [28809.523964] One of leaked entries details: [device address=0x00000002aefe4000] [size=8208 bytes] [mapped with DMA_BIDIRECTIONAL] [mapped as coherent] Fix this by unmapping DMA memory. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_bsg.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 5441557b424b..11e420f8c493 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -341,6 +341,8 @@ qla2x00_process_els(struct bsg_job *bsg_job) dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); if (!req_sg_cnt) { + dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, + bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); rval = -ENOMEM; goto done_free_fcport; } @@ -348,6 +350,8 @@ qla2x00_process_els(struct bsg_job *bsg_job) rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); if (!rsp_sg_cnt) { + dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); rval = -ENOMEM; goto done_free_fcport; } -- cgit v1.2.3-59-g8ed1b From d376dbda187317d06d3a2d495b43a7983e4a3250 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Fri, 26 Jul 2019 09:07:27 -0700 Subject: scsi: qla2xxx: Fix different size DMA Alloc/Unmap [ 17.177276] qla2xxx 0000:05:00.0: DMA-API: device driver frees DMA memory with different size [device address=0x00000006198b0000] [map size=32784 bytes] [unmap size=8208 bytes] [ 17.177390] RIP: 0010:check_unmap+0x7a2/0x1750 [ 17.177425] Call Trace: [ 17.177438] debug_dma_free_coherent+0x1b5/0x2d5 [ 17.177470] dma_free_attrs+0x7f/0x140 [ 17.177489] qla24xx_sp_unmap+0x1e2/0x610 [qla2xxx] [ 17.177509] qla24xx_async_gnnft_done+0x9c6/0x17d0 [qla2xxx] [ 17.177535] qla2x00_do_work+0x514/0x2200 [qla2xxx] Fixes: b5f3bc39a0e8 ("scsi: qla2xxx: Fix inconsistent DMA mem alloc/free") Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_gs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 9f58e591666d..ebf223cfebbc 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -4152,7 +4152,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp) rspsz, &sp->u.iocb_cmd.u.ctarg.rsp_dma, GFP_KERNEL); - sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = sizeof(struct ct_sns_pkt); + sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = rspsz; if (!sp->u.iocb_cmd.u.ctarg.rsp) { ql_log(ql_log_warn, vha, 0xffff, "Failed to allocate ct_sns request.\n"); -- cgit v1.2.3-59-g8ed1b From 0c6df59061b23c7a951836d23977be34e896d3da Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Fri, 26 Jul 2019 09:07:28 -0700 Subject: scsi: qla2xxx: Fix abort timeout race condition. If an abort times out, the Abort IOCB completion and Abort timer can race against each other. This patch provides unique error code for timer path to allow proper cleanup. [mkp: typo] Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_init.c | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index bad2b12604f1..d3d624d43ec3 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -4628,6 +4628,7 @@ struct secure_flash_update_block_pk { #define QLA_SUSPENDED 0x106 #define QLA_BUSY 0x107 #define QLA_ALREADY_REGISTERED 0x109 +#define QLA_OS_TIMER_EXPIRED 0x10a #define NVRAM_DELAY() udelay(10) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 4059655639d9..68d7496a8aff 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -99,9 +99,22 @@ static void qla24xx_abort_iocb_timeout(void *data) { srb_t *sp = data; struct srb_iocb *abt = &sp->u.iocb_cmd; + struct qla_qpair *qpair = sp->qpair; + u32 handle; + unsigned long flags; + + spin_lock_irqsave(qpair->qp_lock_ptr, flags); + for (handle = 1; handle < qpair->req->num_outstanding_cmds; handle++) { + /* removing the abort */ + if (qpair->req->outstanding_cmds[handle] == sp) { + qpair->req->outstanding_cmds[handle] = NULL; + break; + } + } + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); abt->u.abt.comp_status = CS_TIMEOUT; - sp->done(sp, QLA_FUNCTION_TIMEOUT); + sp->done(sp, QLA_OS_TIMER_EXPIRED); } static void qla24xx_abort_sp_done(void *ptr, int res) @@ -109,7 +122,8 @@ static void qla24xx_abort_sp_done(void *ptr, int res) srb_t *sp = ptr; struct srb_iocb *abt = &sp->u.iocb_cmd; - if (del_timer(&sp->u.iocb_cmd.timer)) { + if ((res == QLA_OS_TIMER_EXPIRED) || + del_timer(&sp->u.iocb_cmd.timer)) { if (sp->flags & SRB_WAKEUP_ON_COMP) complete(&abt->u.abt.comp); else -- cgit v1.2.3-59-g8ed1b From 178235f43ea142cf0f07dba67657494fcec21254 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Fri, 26 Jul 2019 09:07:29 -0700 Subject: scsi: qla2xxx: Use Correct index for Q-Pair array For target mode, the default number of Q-Pairs allowed to use is 2. If the number of Q-Pairs allocated is lower than the default Q-Pairs, then lower value should be the set as default. [mkp: typo] Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 1c1f63be6eed..d733e405c625 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -6671,6 +6671,8 @@ qlt_enable_vha(struct scsi_qla_host *vha) if (vha->qlini_mode == QLA2XXX_INI_MODE_ENABLED) return; + if (ha->tgt.num_act_qpairs > ha->max_qpairs) + ha->tgt.num_act_qpairs = ha->max_qpairs; spin_lock_irqsave(&ha->hardware_lock, flags); tgt->tgt_stopped = 0; qlt_set_mode(vha); -- cgit v1.2.3-59-g8ed1b From 5e5402c147083786db2238302e25c44b7a7dc5e9 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Fri, 26 Jul 2019 09:07:30 -0700 Subject: scsi: qla2xxx: Skip FW dump on LOOP initialization error Firmware dump captured during LOOP Init error does not yield any significant information. This patch removes call to trigger firmware dump collection during Loop Initialization. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_isr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 78aec50abe0f..e8ce57cb897e 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -776,7 +776,6 @@ skip_rio: case MBA_LOOP_INIT_ERR: ql_log(ql_log_warn, vha, 0x5090, "LOOP INIT ERROR (%x).\n", mb[1]); - ha->isp_ops->fw_dump(vha, 1); set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); break; -- cgit v1.2.3-59-g8ed1b From 7f4374e67b3046c9628cf0ab93a117704a38e95d Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Fri, 26 Jul 2019 09:07:31 -0700 Subject: scsi: qla2xxx: Reject EH_{abort|device_reset|target_request} Reject eh_{abort|device_reset|target_reset} when rport is being torn down or chip is down. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 3c59157bb3bd..6128da465439 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1296,6 +1296,9 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) if (!qpair) return SUCCESS; + if (sp->fcport && sp->fcport->deleted) + return SUCCESS; + spin_lock_irqsave(qpair->qp_lock_ptr, flags); if (sp->type != SRB_SCSI_CMD || GET_CMD_SP(sp) != cmd) { /* there's a chance an interrupt could clear @@ -1420,6 +1423,9 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, if (err != 0) return err; + if (fcport->deleted) + return SUCCESS; + ql_log(ql_log_info, vha, 0x8009, "%s RESET ISSUED nexus=%ld:%d:%llu cmd=%p.\n", name, vha->host_no, cmd->device->id, cmd->device->lun, cmd); @@ -1534,6 +1540,9 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) return ret; ret = FAILED; + if (qla2x00_chip_is_down(vha)) + return ret; + ql_log(ql_log_info, vha, 0x8012, "BUS RESET ISSUED nexus=%ld:%d:%llu.\n", vha->host_no, id, lun); -- cgit v1.2.3-59-g8ed1b From 8b5292bcfcacf15182a77a973a98d310e76fd58b Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Fri, 26 Jul 2019 09:07:32 -0700 Subject: scsi: qla2xxx: Fix Relogin to prevent modifying scan_state flag Relogin fails to move forward due to scan_state flag indicating device is not there. Before relogin process, Session delete process accidently modified the scan_state flag. [mkp: typos plus corrected Fixes: sha as reported by sfr] Fixes: 2dee5521028c ("scsi: qla2xxx: Fix login state machine freeze") Cc: stable@vger.kernel.org Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 25 ++++++++++++++++++++----- drivers/scsi/qla2xxx/qla_os.c | 1 + drivers/scsi/qla2xxx/qla_target.c | 1 - 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 68d7496a8aff..02bbc5bdaa43 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -303,8 +303,13 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, struct srb_iocb *lio; int rval = QLA_FUNCTION_FAILED; - if (!vha->flags.online) - goto done; + if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT) || + fcport->loop_id == FC_NO_LOOP_ID) { + ql_log(ql_log_warn, vha, 0xffff, + "%s: %8phC - not sending command.\n", + __func__, fcport->port_name); + return rval; + } sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); if (!sp) @@ -1276,8 +1281,13 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt) struct port_database_24xx *pd; struct qla_hw_data *ha = vha->hw; - if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT)) + if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT) || + fcport->loop_id == FC_NO_LOOP_ID) { + ql_log(ql_log_warn, vha, 0xffff, + "%s: %8phC - not sending command.\n", + __func__, fcport->port_name); return rval; + } fcport->disc_state = DSC_GPDB; @@ -1967,8 +1977,11 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea) return; } - if (fcport->disc_state == DSC_DELETE_PEND) + if ((fcport->disc_state == DSC_DELETE_PEND) || + (fcport->disc_state == DSC_DELETED)) { + set_bit(RELOGIN_NEEDED, &vha->dpc_flags); return; + } if (ea->sp->gen2 != fcport->login_gen) { /* target side must have changed it. */ @@ -6712,8 +6725,10 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) } /* Clear all async request states across all VPs. */ - list_for_each_entry(fcport, &vha->vp_fcports, list) + list_for_each_entry(fcport, &vha->vp_fcports, list) { fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT); + fcport->scan_state = 0; + } spin_lock_irqsave(&ha->vport_slock, flags); list_for_each_entry(vp, &ha->vp_list, list) { atomic_inc(&vp->vref_count); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 6128da465439..769a2ffea79f 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -5085,6 +5085,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) if (fcport) { fcport->id_changed = 1; fcport->scan_state = QLA_FCPORT_FOUND; + fcport->chip_reset = vha->hw->base_qpair->chip_reset; memcpy(fcport->node_name, e->u.new_sess.node_name, WWN_SIZE); if (pla) { diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index d733e405c625..d0061ae1488e 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -1209,7 +1209,6 @@ static void qla24xx_chk_fcp_state(struct fc_port *sess) sess->logout_on_delete = 0; sess->logo_ack_needed = 0; sess->fw_login_state = DSC_LS_PORT_UNAVAIL; - sess->scan_state = 0; } } -- cgit v1.2.3-59-g8ed1b From 3a4b6cc7332130ac5cbf3b505d8cddf0aa2ea745 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Fri, 26 Jul 2019 09:07:33 -0700 Subject: scsi: qla2xxx: Fix premature timer expiration For any qla2xxx async command, the SRB buffer is used to send it. In setting up the SRB buffer, the timer for this command is started before all memory allocation has finished. Under low memory pressure, memory alloc can go to sleep and not wake up before the timer expires. Once timer has expired, the timer thread will access uninitialize fields resulting into NULL pointer crash. This patch fixes this crash by moving the start of timer after everything is setup. backtrace shows following PID: 3720 TASK: ffff996928401040 CPU: 0 COMMAND: "qla2xxx_1_dpc" 0 [ffff99652751b698] __schedule at ffffffff965676c7 1 [ffff99652751b728] schedule at ffffffff96567bc9 2 [ffff99652751b738] schedule_timeout at ffffffff965655e8 3 [ffff99652751b7e0] io_schedule_timeout at ffffffff9656726d 4 [ffff99652751b810] congestion_wait at ffffffff95fd8d12 5 [ffff99652751b870] isolate_migratepages_range at ffffffff95fddaf3 6 [ffff99652751b930] compact_zone at ffffffff95fdde96 7 [ffff99652751b980] compact_zone_order at ffffffff95fde0bc 8 [ffff99652751ba20] try_to_compact_pages at ffffffff95fde481 9 [ffff99652751ba80] __alloc_pages_direct_compact at ffffffff9655cc31 10 [ffff99652751bae0] __alloc_pages_slowpath at ffffffff9655d101 11 [ffff99652751bbd0] __alloc_pages_nodemask at ffffffff95fc0e95 12 [ffff99652751bc80] dma_generic_alloc_coherent at ffffffff95e3217f 13 [ffff99652751bcc8] x86_swiotlb_alloc_coherent at ffffffff95e6b7a1 14 [ffff99652751bcf8] qla2x00_rft_id at ffffffffc055b5e0 [qla2xxx] 15 [ffff99652751bd50] qla2x00_loop_resync at ffffffffc0533e71 [qla2xxx] 16 [ffff99652751be68] qla2x00_do_dpc at ffffffffc05210ca [qla2xxx] PID: 0 TASK: ffffffff96a18480 CPU: 0 COMMAND: "swapper/0" 0 [ffff99652fc03ae0] machine_kexec at ffffffff95e63674 1 [ffff99652fc03b40] __crash_kexec at ffffffff95f1ce12 2 [ffff99652fc03c10] crash_kexec at ffffffff95f1cf00 3 [ffff99652fc03c28] oops_end at ffffffff9656c758 4 [ffff99652fc03c50] no_context at ffffffff9655aa7e 5 [ffff99652fc03ca0] __bad_area_nosemaphore at ffffffff9655ab15 6 [ffff99652fc03cf0] bad_area_nosemaphore at ffffffff9655ac86 7 [ffff99652fc03d00] __do_page_fault at ffffffff9656f6b0 8 [ffff99652fc03d70] do_page_fault at ffffffff9656f915 9 [ffff99652fc03da0] page_fault at ffffffff9656b758 [exception RIP: unknown or invalid address] RIP: 0000000000000000 RSP: ffff99652fc03e50 RFLAGS: 00010202 RAX: 0000000000000000 RBX: ffff99652b79a600 RCX: ffff99652b79a760 RDX: ffff99652b79a600 RSI: ffffffffc0525ad0 RDI: ffff99652b79a600 RBP: ffff99652fc03e60 R8: ffffffff96a18a18 R9: ffffffff96ee3c00 R10: 0000000000000002 R11: ffff99652fc03de8 R12: ffff99652b79a760 R13: 0000000000000100 R14: ffffffffc0525ad0 R15: ffff99652b79a600 ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 10 [ffff99652fc03e50] qla2x00_sp_timeout at ffffffffc0525af8 [qla2xxx] 11 [ffff99652fc03e68] call_timer_fn at ffffffff95ea7f58 12 [ffff99652fc03ea0] run_timer_softirq at ffffffff95eaa3bd 13 [ffff99652fc03f18] __do_softirq at ffffffff95ea0f05 14 [ffff99652fc03f88] call_softirq at ffffffff9657832c 15 [ffff99652fc03fa0] do_softirq at ffffffff95e2e675 16 [ffff99652fc03fc0] irq_exit at ffffffff95ea1285 17 [ffff99652fc03fd8] smp_apic_timer_interrupt at ffffffff965796c8 18 [ffff99652fc03ff0] apic_timer_interrupt at ffffffff96575df2 Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_iocb.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index d3d624d43ec3..b91ef7b75e8d 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -537,6 +537,7 @@ typedef struct srb { wait_queue_head_t nvme_ls_waitq; struct fc_port *fcport; struct scsi_qla_host *vha; + unsigned int start_timer:1; uint32_t handle; uint16_t flags; uint16_t type; diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 9312b19ed708..1886de92034c 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -2540,7 +2540,7 @@ void qla2x00_init_timer(srb_t *sp, unsigned long tmo) sp->free = qla2x00_sp_free; if (IS_QLAFX00(sp->vha->hw) && sp->type == SRB_FXIOCB_DCMD) init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp); - add_timer(&sp->u.iocb_cmd.timer); + sp->start_timer = 1; } static void @@ -3668,6 +3668,9 @@ qla2x00_start_sp(srb_t *sp) break; } + if (sp->start_timer) + add_timer(&sp->u.iocb_cmd.timer); + wmb(); qla2x00_start_iocbs(vha, qp->req); done: -- cgit v1.2.3-59-g8ed1b From f0cecc1eec0c24e790a4daac71858f1f14e6f7b5 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Fri, 26 Jul 2019 09:07:34 -0700 Subject: scsi: qla2xxx: Retry fabric Scan on IOCB queue full when fabric scan thread encounters IOCB Q Full, schedule a delayed work to retry fabric scan. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_gs.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index ebf223cfebbc..749109c8f20b 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -4053,9 +4053,6 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp, rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) { - spin_lock_irqsave(&vha->work_lock, flags); - vha->scan.scan_flags &= ~SF_SCANNING; - spin_unlock_irqrestore(&vha->work_lock, flags); goto done_free_sp; } @@ -4079,6 +4076,17 @@ done_free_sp: sp->free(sp); + spin_lock_irqsave(&vha->work_lock, flags); + vha->scan.scan_flags &= ~SF_SCANNING; + if (vha->scan.scan_flags == 0) { + ql_dbg(ql_dbg_disc, vha, 0xffff, + "%s: schedule\n", __func__); + vha->scan.scan_flags |= SF_QUEUED; + schedule_delayed_work(&vha->scan.scan_work, 5); + } + spin_unlock_irqrestore(&vha->work_lock, flags); + + return rval; } /* GNNFT */ @@ -4208,9 +4216,6 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp) rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) { - spin_lock_irqsave(&vha->work_lock, flags); - vha->scan.scan_flags &= ~SF_SCANNING; - spin_unlock_irqrestore(&vha->work_lock, flags); goto done_free_sp; } @@ -4234,6 +4239,17 @@ done_free_sp: sp->free(sp); + spin_lock_irqsave(&vha->work_lock, flags); + vha->scan.scan_flags &= ~SF_SCANNING; + if (vha->scan.scan_flags == 0) { + ql_dbg(ql_dbg_disc, vha, 0xffff, + "%s: schedule\n", __func__); + vha->scan.scan_flags |= SF_QUEUED; + schedule_delayed_work(&vha->scan.scan_work, 5); + } + spin_unlock_irqrestore(&vha->work_lock, flags); + + return rval; } -- cgit v1.2.3-59-g8ed1b From 26a77799195f4ff105f877042012c7fb355b3da1 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 26 Jul 2019 09:07:35 -0700 Subject: scsi: qla2xxx: Correct error handling during initialization failures Current code misses or fails to account for proper recovery during early initialization failures: - Properly unwind allocations during probe() failures. - Protect against non-initialization memory allocations during unwinding. - Propagate error status during HW initialization. - Release SCSI host reference when memory allocations fail. Signed-off-by: Andrew Vasquez Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 4 ++++ drivers/scsi/qla2xxx/qla_os.c | 12 +++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 02bbc5bdaa43..1a8b4a587e0f 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2293,6 +2293,10 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) if (qla_ini_mode_enabled(vha) || qla_dual_mode_enabled(vha)) rval = qla2x00_init_rings(vha); + /* No point in continuing if firmware initialization failed. */ + if (rval != QLA_SUCCESS) + return rval; + ha->flags.chip_reset_done = 1; if (rval == QLA_SUCCESS && IS_QLA84XX(ha)) { diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 769a2ffea79f..73655c81ab77 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1809,8 +1809,13 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) int que; struct qla_hw_data *ha = vha->hw; + /* Continue only if initialization complete. */ + if (!ha->base_qpair) + return; __qla2x00_abort_all_cmds(ha->base_qpair, res); + if (!ha->queue_pair_map) + return; for (que = 0; que < ha->max_qpairs; que++) { if (!ha->queue_pair_map[que]) continue; @@ -3163,6 +3168,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ql_log(ql_log_fatal, base_vha, 0x003d, "Failed to allocate memory for queue pointers..." "aborting.\n"); + ret = -ENODEV; goto probe_failed; } @@ -4717,7 +4723,7 @@ qla2x00_mem_free(struct qla_hw_data *ha) mempool_destroy(ha->ctx_mempool); ha->ctx_mempool = NULL; - if (ql2xenabledif) { + if (ql2xenabledif && ha->dif_bundl_pool) { struct dsd_dma *dsd, *nxt; list_for_each_entry_safe(dsd, nxt, &ha->pool.unusable.head, @@ -4812,7 +4818,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, if (!vha->gnl.l) { ql_log(ql_log_fatal, vha, 0xd04a, "Alloc failed for name list.\n"); - scsi_remove_host(vha->host); + scsi_host_put(vha->host); return NULL; } @@ -4824,7 +4830,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, "Alloc failed for scan database.\n"); dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l, vha->gnl.ldma); - scsi_remove_host(vha->host); + scsi_host_put(vha->host); return NULL; } INIT_DELAYED_WORK(&vha->scan.scan_work, qla_scan_work_fn); -- cgit v1.2.3-59-g8ed1b From 9e744591ef1b8df27c25c68dac858dada8688f77 Mon Sep 17 00:00:00 2001 From: Arun Easi Date: Fri, 26 Jul 2019 09:07:36 -0700 Subject: scsi: qla2xxx: Fix NVMe port discovery after a short device port loss The following sequence of event leads to NVME port disappearing: - device port shut - nvme_fc_unregister_remoteport - device port online - remote port delete completes - relogin is scheduled - "post gidpn" message appears due to rscn generation # mismatch In short, if a device comes back online sooner than an unregister completion, a mismatch in rscn generation number occurs, which is not handled correctly during device relogin. Fix this by starting with a redo of GNL. When ql2xextended_error_logging is enabled, the re-plugged device's discovery stops with the following messages printed: --8<-- qla2xxx [0000:41:00.0]-480d:3: Relogin scheduled. qla2xxx [0000:41:00.0]-4800:3: DPC handler sleeping. qla2xxx [0000:41:00.0]-2902:3: qla24xx_handle_relogin_event 21:00:00:24:ff:17:9e:91 DS 0 LS 7 P 0 del 2 cnfl (null) rscn 1|2 login 1|2 fl 1 qla2xxx [0000:41:00.0]-28e9:3: qla24xx_handle_relogin_event 1666 21:00:00:24:ff:17:9e:91 post gidpn qla2xxx [0000:41:00.0]-480e:3: Relogin end. --8<-- Signed-off-by: Arun Easi Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 1a8b4a587e0f..194a15b2f5f7 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1687,9 +1687,9 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha, } if (fcport->last_rscn_gen != fcport->rscn_gen) { - ql_dbg(ql_dbg_disc, vha, 0x20e9, "%s %d %8phC post gidpn\n", + ql_dbg(ql_dbg_disc, vha, 0x20e9, "%s %d %8phC post gnl\n", __func__, __LINE__, fcport->port_name); - + qla24xx_post_gnl_work(vha, fcport); return; } -- cgit v1.2.3-59-g8ed1b From a36f1443e6fc738c1bcfc4be80d6f1609163c614 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 26 Jul 2019 09:07:37 -0700 Subject: scsi: qla2xxx: Use common update-firmware-options routine for ISP27xx+ Leverage the generic routine, qla24xx_update_fw_options(), for the configuration of firmware options for ISP27xx/ISP28xx. Signed-off-by: Andrew Vasquez Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 73655c81ab77..17a3f91ba5a3 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2491,7 +2491,7 @@ static struct isp_operations qla27xx_isp_ops = { .config_rings = qla24xx_config_rings, .reset_adapter = qla24xx_reset_adapter, .nvram_config = qla81xx_nvram_config, - .update_fw_options = qla81xx_update_fw_options, + .update_fw_options = qla24xx_update_fw_options, .load_risc = qla81xx_load_risc, .pci_info_str = qla24xx_pci_info_str, .fw_version_str = qla24xx_fw_version_str, -- cgit v1.2.3-59-g8ed1b From f00b3428a801758243693e046b34226e92bc56b3 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Fri, 26 Jul 2019 09:07:38 -0700 Subject: scsi: qla2xxx: Fix hang in fcport delete path A hang was observed in the fcport delete path when the device was responding slow and an issue-lip path (results in session termination) was taken. Fix this by issuing logo requests unconditionally. PID: 19491 TASK: ffff8e23e67bb150 CPU: 0 COMMAND: "kworker/0:0" #0 [ffff8e2370297bf8] __schedule at ffffffffb4f7dbb0 #1 [ffff8e2370297c88] schedule at ffffffffb4f7e199 #2 [ffff8e2370297c98] schedule_timeout at ffffffffb4f7ba68 #3 [ffff8e2370297d40] msleep at ffffffffb48ad9ff #4 [ffff8e2370297d58] qlt_free_session_done at ffffffffc0c32052 [qla2xxx] #5 [ffff8e2370297e20] process_one_work at ffffffffb48bcfdf #6 [ffff8e2370297e68] worker_thread at ffffffffb48bdca6 #7 [ffff8e2370297ec8] kthread at ffffffffb48c4f81 Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 194a15b2f5f7..d82d1a2b3543 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -378,9 +378,6 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport) struct srb_iocb *lio; int rval = QLA_FUNCTION_FAILED; - if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT)) - return rval; - fcport->flags |= FCF_ASYNC_SENT; sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); if (!sp) -- cgit v1.2.3-59-g8ed1b From 03cc44bf682af289d6536eb911e928b415bd0e1f Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Fri, 26 Jul 2019 09:07:39 -0700 Subject: scsi: qla2xxx: Allow NVMe IO to resume with short cable pull Current driver report dev_loss_tmo to 0 for NVMe devices with short cable pull. This causes NVMe controller to be freed along with NVMe namespace. The side affect is IO would stop. By not setting dev_loss_tmo to 0, NVMe namespace would stay until cable is plugged back in. This allows IO to resume afterward. [mkp: commit desc] Signed-off-by: Arun Easi Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_nvme.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 963094b3c300..af7919a5acdc 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -653,7 +653,9 @@ void qla_nvme_unregister_remote_port(struct fc_port *fcport) "%s: unregister remoteport on %p %8phN\n", __func__, fcport, fcport->port_name); - nvme_fc_set_remoteport_devloss(fcport->nvme_remote_port, 0); + if (test_bit(PFLG_DRIVER_REMOVING, &fcport->vha->pci_flags)) + nvme_fc_set_remoteport_devloss(fcport->nvme_remote_port, 0); + init_completion(&fcport->nvme_del_done); ret = nvme_fc_unregister_remoteport(fcport->nvme_remote_port); if (ret) -- cgit v1.2.3-59-g8ed1b From 4d0b32b853f52760bf70288f2751d2ca86581352 Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Fri, 26 Jul 2019 09:07:40 -0700 Subject: scsi: qla2xxx: Update driver version to 10.01.00.18-k Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index cd6bdf71e533..0833546a1b43 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.01.00.16-k" +#define QLA2XXX_VERSION "10.01.00.18-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 1 -- cgit v1.2.3-59-g8ed1b From 88d5c343949ed4dc7547f307bbbb1aff3e9fa1d4 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 26 Jul 2019 21:55:40 +0800 Subject: scsi: megaraid_sas: Make a bunch of functions static Fix sparse warnings: drivers/scsi/megaraid/megaraid_sas_fusion.c:3369:1: warning: symbol 'complete_cmd_fusion' was not declared. Should it be static? drivers/scsi/megaraid/megaraid_sas_fusion.c:3535:6: warning: symbol 'megasas_sync_irqs' was not declared. Should it be static? drivers/scsi/megaraid/megaraid_sas_fusion.c:3554:1: warning: symbol 'megasas_complete_cmd_dpc_fusion' was not declared. Should it be static? drivers/scsi/megaraid/megaraid_sas_fusion.c:3573:13: warning: symbol 'megasas_isr_fusion' was not declared. Should it be static? drivers/scsi/megaraid/megaraid_sas_fusion.c:3604:1: warning: symbol 'build_mpt_mfi_pass_thru' was not declared. Should it be static? drivers/scsi/megaraid/megaraid_sas_fusion.c:3661:40: warning: symbol 'build_mpt_cmd' was not declared. Should it be static? drivers/scsi/megaraid/megaraid_sas_fusion.c:3688:1: warning: symbol 'megasas_issue_dcmd_fusion' was not declared. Should it be static? drivers/scsi/megaraid/megaraid_sas_fusion.c:3881:5: warning: symbol 'megasas_wait_for_outstanding_fusion' was not declared. Should it be static? drivers/scsi/megaraid/megaraid_sas_fusion.c:4005:6: warning: symbol 'megasas_refire_mgmt_cmd' was not declared. Should it be static? drivers/scsi/megaraid/megaraid_sas_fusion.c:4525:25: warning: symbol 'megasas_get_peer_instance' was not declared. Should it be static? drivers/scsi/megaraid/megaraid_sas_fusion.c:4825:7: warning: symbol 'megasas_fusion_crash_dump' was not declared. Should it be static? Reported-by: Hulk Robot Signed-off-by: YueHaibing Acked-by: Sumit Saxena Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_fusion.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index a32b3f0fcd15..fa4e1b607e04 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -3510,7 +3510,7 @@ megasas_complete_r1_command(struct megasas_instance *instance, * @instance: Adapter soft state * Completes all commands that is in reply descriptor queue */ -int +static int complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex, struct megasas_irq_context *irq_context) { @@ -3701,7 +3701,7 @@ static void megasas_enable_irq_poll(struct megasas_instance *instance) * megasas_sync_irqs - Synchronizes all IRQs owned by adapter * @instance: Adapter soft state */ -void megasas_sync_irqs(unsigned long instance_addr) +static void megasas_sync_irqs(unsigned long instance_addr) { u32 count, i; struct megasas_instance *instance = @@ -3759,7 +3759,7 @@ int megasas_irqpoll(struct irq_poll *irqpoll, int budget) * * Tasklet to complete cmds */ -void +static void megasas_complete_cmd_dpc_fusion(unsigned long instance_addr) { struct megasas_instance *instance = @@ -3779,7 +3779,7 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr) /** * megasas_isr_fusion - isr entry point */ -irqreturn_t megasas_isr_fusion(int irq, void *devp) +static irqreturn_t megasas_isr_fusion(int irq, void *devp) { struct megasas_irq_context *irq_context = devp; struct megasas_instance *instance = irq_context->instance; @@ -3815,7 +3815,7 @@ irqreturn_t megasas_isr_fusion(int irq, void *devp) * mfi_cmd: megasas_cmd pointer * */ -void +static void build_mpt_mfi_pass_thru(struct megasas_instance *instance, struct megasas_cmd *mfi_cmd) { @@ -3873,7 +3873,7 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance, * @cmd: mfi cmd to build * */ -union MEGASAS_REQUEST_DESCRIPTOR_UNION * +static union MEGASAS_REQUEST_DESCRIPTOR_UNION * build_mpt_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) { union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc = NULL; @@ -3899,7 +3899,7 @@ build_mpt_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) * @cmd: mfi cmd pointer * */ -void +static void megasas_issue_dcmd_fusion(struct megasas_instance *instance, struct megasas_cmd *cmd) { @@ -4095,8 +4095,9 @@ static inline void megasas_trigger_snap_dump(struct megasas_instance *instance) } /* This function waits for outstanding commands on fusion to complete */ -int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance, - int reason, int *convert) +static int +megasas_wait_for_outstanding_fusion(struct megasas_instance *instance, + int reason, int *convert) { int i, outstanding, retval = 0, hb_seconds_missed = 0; u32 fw_state, abs_state; @@ -4220,7 +4221,7 @@ void megasas_reset_reply_desc(struct megasas_instance *instance) * megasas_refire_mgmt_cmd : Re-fire management commands * @instance: Controller's soft instance */ -void megasas_refire_mgmt_cmd(struct megasas_instance *instance) +static void megasas_refire_mgmt_cmd(struct megasas_instance *instance) { int j; struct megasas_cmd_fusion *cmd_fusion; @@ -4746,7 +4747,8 @@ out: } /*SRIOV get other instance in cluster if any*/ -struct megasas_instance *megasas_get_peer_instance(struct megasas_instance *instance) +static struct +megasas_instance *megasas_get_peer_instance(struct megasas_instance *instance) { int i; @@ -5052,7 +5054,7 @@ out: } /* Fusion Crash dump collection */ -void megasas_fusion_crash_dump(struct megasas_instance *instance) +static void megasas_fusion_crash_dump(struct megasas_instance *instance) { u32 status_reg; u8 partial_copy = 0; -- cgit v1.2.3-59-g8ed1b From e5460f084b84f06756e558fbfd2313202fb1dbd0 Mon Sep 17 00:00:00 2001 From: Qian Cai Date: Fri, 26 Jul 2019 10:25:43 -0400 Subject: scsi: megaraid_sas: Fix a compilation warning The commit de516379e85f ("scsi: megaraid_sas: changes to function prototypes") introduced a comilation warning due to it changed the function prototype of read_fw_status_reg() to take an instance pointer instead, but forgot to remove an unused variable. drivers/scsi/megaraid/megaraid_sas_fusion.c: In function 'megasas_fusion_update_can_queue': drivers/scsi/megaraid/megaraid_sas_fusion.c:326:39: warning: variable 'reg_set' set but not used [-Wunused-but-set-variable] struct megasas_register_set __iomem *reg_set; ^~~~~~~ Fixes: de516379e85f ("scsi: megaraid_sas: changes to function prototypes") Signed-off-by: Qian Cai Acked-by: Sumit Saxena Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_fusion.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index fa4e1b607e04..fadab7a91573 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -323,9 +323,6 @@ megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_c { u16 cur_max_fw_cmds = 0; u16 ldio_threshold = 0; - struct megasas_register_set __iomem *reg_set; - - reg_set = instance->reg_set; /* ventura FW does not fill outbound_scratch_pad_2 with queue depth */ if (instance->adapter_type < VENTURA_SERIES) -- cgit v1.2.3-59-g8ed1b From 4c73598732f7954867d95e315e5465b6ce7767a0 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 28 Jul 2019 19:26:08 -0500 Subject: scsi: ibmvfc: Mark expected switch fall-throughs Mark switch cases where we are expecting to fall through. This patch fixes the following warnings: drivers/scsi/ibmvscsi/ibmvfc.c: In function 'ibmvfc_npiv_login_done': drivers/scsi/ibmvscsi/ibmvfc.c:4022:3: warning: this statement may fall through [-Wimplicit-fallthrough=] ibmvfc_retry_host_init(vhost); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/ibmvscsi/ibmvfc.c:4023:2: note: here case IBMVFC_MAD_DRIVER_FAILED: ^~~~ drivers/scsi/ibmvscsi/ibmvfc.c: In function 'ibmvfc_bsg_request': drivers/scsi/ibmvscsi/ibmvfc.c:1830:11: warning: this statement may fall through [-Wimplicit-fallthrough=] port_id = (bsg_request->rqst_data.h_els.port_id[0] << 16) | ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (bsg_request->rqst_data.h_els.port_id[1] << 8) | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bsg_request->rqst_data.h_els.port_id[2]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/ibmvscsi/ibmvfc.c:1833:2: note: here case FC_BSG_RPT_ELS: ^~~~ drivers/scsi/ibmvscsi/ibmvfc.c:1838:11: warning: this statement may fall through [-Wimplicit-fallthrough=] port_id = (bsg_request->rqst_data.h_ct.port_id[0] << 16) | ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (bsg_request->rqst_data.h_ct.port_id[1] << 8) | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bsg_request->rqst_data.h_ct.port_id[2]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/ibmvscsi/ibmvfc.c:1841:2: note: here case FC_BSG_RPT_CT: ^~~~ Reported-by: Stephen Rothwell Signed-off-by: Gustavo A. R. Silva Reviewed-by: Kees Cook Acked-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi/ibmvfc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index acd16e0d52cf..fe38d92c9c9f 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -1830,6 +1830,7 @@ static int ibmvfc_bsg_request(struct bsg_job *job) port_id = (bsg_request->rqst_data.h_els.port_id[0] << 16) | (bsg_request->rqst_data.h_els.port_id[1] << 8) | bsg_request->rqst_data.h_els.port_id[2]; + /* fall through */ case FC_BSG_RPT_ELS: fc_flags = IBMVFC_FC_ELS; break; @@ -1838,6 +1839,7 @@ static int ibmvfc_bsg_request(struct bsg_job *job) port_id = (bsg_request->rqst_data.h_ct.port_id[0] << 16) | (bsg_request->rqst_data.h_ct.port_id[1] << 8) | bsg_request->rqst_data.h_ct.port_id[2]; + /* fall through */ case FC_BSG_RPT_CT: fc_flags = IBMVFC_FC_CT_IU; break; @@ -4020,6 +4022,7 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt) return; case IBMVFC_MAD_CRQ_ERROR: ibmvfc_retry_host_init(vhost); + /* fall through */ case IBMVFC_MAD_DRIVER_FAILED: ibmvfc_free_event(evt); return; -- cgit v1.2.3-59-g8ed1b From 6d44c692c12c33bab92d3e0f524f66c3e97b7bdd Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 29 Jul 2019 06:03:45 -0500 Subject: scsi: qlogicpti: Mark expected switch fall-throughs Mark switch cases where we are expecting to fall through. This patch fixes the following warnings (Building: sparc defconfig): drivers/scsi/qlogicpti.c: In function 'qlogicpti_mbox_command': drivers/scsi/qlogicpti.c:202:10: warning: this statement may fall through [-Wimplicit-fallthrough=] case 6: sbus_writew(param[5], qpti->qregs + MBOX5); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/qlogicpti.c:203:2: note: here case 5: sbus_writew(param[4], qpti->qregs + MBOX4); ^~~~ drivers/scsi/qlogicpti.c:203:10: warning: this statement may fall through [-Wimplicit-fallthrough=] case 5: sbus_writew(param[4], qpti->qregs + MBOX4); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/qlogicpti.c:204:2: note: here case 4: sbus_writew(param[3], qpti->qregs + MBOX3); ^~~~ drivers/scsi/qlogicpti.c:204:10: warning: this statement may fall through [-Wimplicit-fallthrough=] case 4: sbus_writew(param[3], qpti->qregs + MBOX3); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/qlogicpti.c:205:2: note: here case 3: sbus_writew(param[2], qpti->qregs + MBOX2); ^~~~ drivers/scsi/qlogicpti.c:205:10: warning: this statement may fall through [-Wimplicit-fallthrough=] case 3: sbus_writew(param[2], qpti->qregs + MBOX2); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/qlogicpti.c:206:2: note: here case 2: sbus_writew(param[1], qpti->qregs + MBOX1); ^~~~ drivers/scsi/qlogicpti.c:206:10: warning: this statement may fall through [-Wimplicit-fallthrough=] case 2: sbus_writew(param[1], qpti->qregs + MBOX1); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/qlogicpti.c:207:2: note: here case 1: sbus_writew(param[0], qpti->qregs + MBOX0); ^~~~ drivers/scsi/qlogicpti.c:256:19: warning: this statement may fall through [-Wimplicit-fallthrough=] case 6: param[5] = sbus_readw(qpti->qregs + MBOX5); ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/qlogicpti.c:257:2: note: here case 5: param[4] = sbus_readw(qpti->qregs + MBOX4); ^~~~ drivers/scsi/qlogicpti.c:257:19: warning: this statement may fall through [-Wimplicit-fallthrough=] case 5: param[4] = sbus_readw(qpti->qregs + MBOX4); ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/qlogicpti.c:258:2: note: here case 4: param[3] = sbus_readw(qpti->qregs + MBOX3); ^~~~ drivers/scsi/qlogicpti.c:258:19: warning: this statement may fall through [-Wimplicit-fallthrough=] case 4: param[3] = sbus_readw(qpti->qregs + MBOX3); ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/qlogicpti.c:259:2: note: here case 3: param[2] = sbus_readw(qpti->qregs + MBOX2); ^~~~ drivers/scsi/qlogicpti.c:259:19: warning: this statement may fall through [-Wimplicit-fallthrough=] case 3: param[2] = sbus_readw(qpti->qregs + MBOX2); ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/qlogicpti.c:260:2: note: here case 2: param[1] = sbus_readw(qpti->qregs + MBOX1); ^~~~ drivers/scsi/qlogicpti.c:260:19: warning: this statement may fall through [-Wimplicit-fallthrough=] case 2: param[1] = sbus_readw(qpti->qregs + MBOX1); ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/qlogicpti.c:261:2: note: here case 1: param[0] = sbus_readw(qpti->qregs + MBOX0); ^~~~ Reported-by: Stephen Rothwell Signed-off-by: Gustavo A. R. Silva Reviewed-by: Kees Cook Signed-off-by: Martin K. Petersen --- drivers/scsi/qlogicpti.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 9335849f6bea..d539beef3ce8 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -200,10 +200,15 @@ static int qlogicpti_mbox_command(struct qlogicpti *qpti, u_short param[], int f /* Write mailbox command registers. */ switch (mbox_param[param[0]] >> 4) { case 6: sbus_writew(param[5], qpti->qregs + MBOX5); + /* Fall through */ case 5: sbus_writew(param[4], qpti->qregs + MBOX4); + /* Fall through */ case 4: sbus_writew(param[3], qpti->qregs + MBOX3); + /* Fall through */ case 3: sbus_writew(param[2], qpti->qregs + MBOX2); + /* Fall through */ case 2: sbus_writew(param[1], qpti->qregs + MBOX1); + /* Fall through */ case 1: sbus_writew(param[0], qpti->qregs + MBOX0); } @@ -254,10 +259,15 @@ static int qlogicpti_mbox_command(struct qlogicpti *qpti, u_short param[], int f /* Read back output parameters. */ switch (mbox_param[param[0]] & 0xf) { case 6: param[5] = sbus_readw(qpti->qregs + MBOX5); + /* Fall through */ case 5: param[4] = sbus_readw(qpti->qregs + MBOX4); + /* Fall through */ case 4: param[3] = sbus_readw(qpti->qregs + MBOX3); + /* Fall through */ case 3: param[2] = sbus_readw(qpti->qregs + MBOX2); + /* Fall through */ case 2: param[1] = sbus_readw(qpti->qregs + MBOX1); + /* Fall through */ case 1: param[0] = sbus_readw(qpti->qregs + MBOX0); } -- cgit v1.2.3-59-g8ed1b From c78a66584d0318e2a01a3f10857c9b517d23bf7a Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 29 Jul 2019 09:30:07 -0500 Subject: scsi: sun3_scsi: Mark expected switch fall-throughs Mark switch cases where we are expecting to fall through. This patch fixes the following warnings: drivers/scsi/sun3_scsi.c: warning: this statement may fall through [-Wimplicit-fallthrough=]: => 399:9, 403:9 Reported-by: Geert Uytterhoeven Signed-off-by: Gustavo A. R. Silva Tested-by: Geert Uytterhoeven Signed-off-by: Martin K. Petersen --- drivers/scsi/sun3_scsi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index 3d80ab67a626..955e4c938d49 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -397,10 +397,12 @@ static int sun3scsi_dma_finish(int write_flag) case CSR_LEFT_3: *vaddr = (dregs->bpack_lo & 0xff00) >> 8; vaddr--; + /* Fall through */ case CSR_LEFT_2: *vaddr = (dregs->bpack_hi & 0x00ff); vaddr--; + /* Fall through */ case CSR_LEFT_1: *vaddr = (dregs->bpack_hi & 0xff00) >> 8; -- cgit v1.2.3-59-g8ed1b From c72a9692923f67a0ba862093848d1834259e01c3 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 29 Jul 2019 16:03:13 -0500 Subject: scsi: wd33c93: Mark expected switch fall-through Mark switch cases where we are expecting to fall through. This patch fixes the following warning (Building: m68k): drivers/scsi/wd33c93.c: In function round_4 : drivers/scsi/wd33c93.c:1856:11: warning: this statement may fall through [-Wimplicit-fallthrough=] case 2: ++x; ^~~ drivers/scsi/wd33c93.c:1857:3: note: here case 3: ++x; ^~~~ Signed-off-by: Gustavo A. R. Silva Reviewed-by: Kees Cook Signed-off-by: Martin K. Petersen --- drivers/scsi/wd33c93.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index fb7b289fa09f..f81046f0e68a 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -1854,6 +1854,7 @@ round_4(unsigned int x) case 1: --x; break; case 2: ++x; + /* fall through */ case 3: ++x; } return x; -- cgit v1.2.3-59-g8ed1b From 4b828fe156a662a4b6135019bf077040340f299b Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 30 Jul 2019 08:55:17 +0300 Subject: scsi: ufs: revamp string descriptor reading Define new a type: uc_string_id for easier string handling and less casting. Reduce number or string copies in price of a dynamic allocation. Signed-off-by: Tomas Winkler Tested-by: Avri Altman Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-sysfs.c | 18 ++--- drivers/scsi/ufs/ufs.h | 2 +- drivers/scsi/ufs/ufshcd.c | 162 ++++++++++++++++++++++++++----------------- drivers/scsi/ufs/ufshcd.h | 7 +- 4 files changed, 112 insertions(+), 77 deletions(-) diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index f478685122ff..969a36b15897 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -571,9 +571,10 @@ static ssize_t _name##_show(struct device *dev, \ int ret; \ int desc_len = QUERY_DESC_MAX_SIZE; \ u8 *desc_buf; \ + \ desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_ATOMIC); \ - if (!desc_buf) \ - return -ENOMEM; \ + if (!desc_buf) \ + return -ENOMEM; \ ret = ufshcd_query_descriptor_retry(hba, \ UPIU_QUERY_OPCODE_READ_DESC, QUERY_DESC_IDN_DEVICE, \ 0, 0, desc_buf, &desc_len); \ @@ -582,14 +583,13 @@ static ssize_t _name##_show(struct device *dev, \ goto out; \ } \ index = desc_buf[DEVICE_DESC_PARAM##_pname]; \ - memset(desc_buf, 0, QUERY_DESC_MAX_SIZE); \ - if (ufshcd_read_string_desc(hba, index, desc_buf, \ - QUERY_DESC_MAX_SIZE, true)) { \ - ret = -EINVAL; \ + kfree(desc_buf); \ + desc_buf = NULL; \ + ret = ufshcd_read_string_desc(hba, index, &desc_buf, \ + SD_ASCII_STD); \ + if (ret < 0) \ goto out; \ - } \ - ret = snprintf(buf, PAGE_SIZE, "%s\n", \ - desc_buf + QUERY_DESC_HDR_SIZE); \ + ret = snprintf(buf, PAGE_SIZE, "%s\n", desc_buf); \ out: \ kfree(desc_buf); \ return ret; \ diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 99a9c4d16f6b..3327981ef894 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -541,7 +541,7 @@ struct ufs_dev_info { */ struct ufs_dev_desc { u16 wmanufacturerid; - char model[MAX_MODEL_LEN + 1]; + u8 *model; }; /** diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index a383d0f54f5d..507fd51e8039 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -299,16 +299,6 @@ static void ufshcd_scsi_block_requests(struct ufs_hba *hba) scsi_block_requests(hba->host); } -/* replace non-printable or non-ASCII characters with spaces */ -static inline void ufshcd_remove_non_printable(char *val) -{ - if (!val) - return; - - if (*val < 0x20 || *val > 0x7e) - *val = ' '; -} - static void ufshcd_add_cmd_upiu_trace(struct ufs_hba *hba, unsigned int tag, const char *str) { @@ -3211,7 +3201,7 @@ out: static inline int ufshcd_read_desc(struct ufs_hba *hba, enum desc_idn desc_id, int desc_index, - u8 *buf, + void *buf, u32 size) { return ufshcd_read_desc_param(hba, desc_id, desc_index, 0, buf, size); @@ -3229,49 +3219,78 @@ static int ufshcd_read_device_desc(struct ufs_hba *hba, u8 *buf, u32 size) return ufshcd_read_desc(hba, QUERY_DESC_IDN_DEVICE, 0, buf, size); } +/** + * struct uc_string_id - unicode string + * + * @len: size of this descriptor inclusive + * @type: descriptor type + * @uc: unicode string character + */ +struct uc_string_id { + u8 len; + u8 type; + wchar_t uc[0]; +} __packed; + +/* replace non-printable or non-ASCII characters with spaces */ +static inline char ufshcd_remove_non_printable(u8 ch) +{ + return (ch >= 0x20 && ch <= 0x7e) ? ch : ' '; +} + /** * ufshcd_read_string_desc - read string descriptor * @hba: pointer to adapter instance * @desc_index: descriptor index - * @buf: pointer to buffer where descriptor would be read - * @size: size of buf + * @buf: pointer to buffer where descriptor would be read, + * the caller should free the memory. * @ascii: if true convert from unicode to ascii characters + * null terminated string. * - * Return 0 in case of success, non-zero otherwise + * Return: + * * string size on success. + * * -ENOMEM: on allocation failure + * * -EINVAL: on a wrong parameter */ -int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, - u8 *buf, u32 size, bool ascii) +int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index, + u8 **buf, bool ascii) { - int err = 0; + struct uc_string_id *uc_str; + u8 *str; + int ret; - err = ufshcd_read_desc(hba, - QUERY_DESC_IDN_STRING, desc_index, buf, size); + if (!buf) + return -EINVAL; - if (err) { - dev_err(hba->dev, "%s: reading String Desc failed after %d retries. err = %d\n", - __func__, QUERY_REQ_RETRIES, err); + uc_str = kzalloc(QUERY_DESC_MAX_SIZE, GFP_KERNEL); + if (!uc_str) + return -ENOMEM; + + ret = ufshcd_read_desc(hba, QUERY_DESC_IDN_STRING, + desc_index, uc_str, + QUERY_DESC_MAX_SIZE); + if (ret < 0) { + dev_err(hba->dev, "Reading String Desc failed after %d retries. err = %d\n", + QUERY_REQ_RETRIES, ret); + str = NULL; + goto out; + } + + if (uc_str->len <= QUERY_DESC_HDR_SIZE) { + dev_dbg(hba->dev, "String Desc is of zero length\n"); + str = NULL; + ret = 0; goto out; } if (ascii) { - int desc_len; - int ascii_len; + ssize_t ascii_len; int i; - char *buff_ascii; - - desc_len = buf[0]; /* remove header and divide by 2 to move from UTF16 to UTF8 */ - ascii_len = (desc_len - QUERY_DESC_HDR_SIZE) / 2 + 1; - if (size < ascii_len + QUERY_DESC_HDR_SIZE) { - dev_err(hba->dev, "%s: buffer allocated size is too small\n", - __func__); - err = -ENOMEM; - goto out; - } - - buff_ascii = kmalloc(ascii_len, GFP_KERNEL); - if (!buff_ascii) { - err = -ENOMEM; + ascii_len = (uc_str->len - QUERY_DESC_HDR_SIZE) / 2 + 1; + str = kzalloc(ascii_len, GFP_KERNEL); + if (!str) { + ret = -ENOMEM; goto out; } @@ -3279,22 +3298,29 @@ int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, * the descriptor contains string in UTF16 format * we need to convert to utf-8 so it can be displayed */ - utf16s_to_utf8s((wchar_t *)&buf[QUERY_DESC_HDR_SIZE], - desc_len - QUERY_DESC_HDR_SIZE, - UTF16_BIG_ENDIAN, buff_ascii, ascii_len); + ret = utf16s_to_utf8s(uc_str->uc, + uc_str->len - QUERY_DESC_HDR_SIZE, + UTF16_BIG_ENDIAN, str, ascii_len); /* replace non-printable or non-ASCII characters with spaces */ - for (i = 0; i < ascii_len; i++) - ufshcd_remove_non_printable(&buff_ascii[i]); + for (i = 0; i < ret; i++) + str[i] = ufshcd_remove_non_printable(str[i]); - memset(buf + QUERY_DESC_HDR_SIZE, 0, - size - QUERY_DESC_HDR_SIZE); - memcpy(buf + QUERY_DESC_HDR_SIZE, buff_ascii, ascii_len); - buf[QUERY_DESC_LENGTH_OFFSET] = ascii_len + QUERY_DESC_HDR_SIZE; - kfree(buff_ascii); + str[ret++] = '\0'; + + } else { + str = kzalloc(uc_str->len, GFP_KERNEL); + if (!str) { + ret = -ENOMEM; + goto out; + } + memcpy(str, uc_str, uc_str->len); + ret = uc_str->len; } out: - return err; + *buf = str; + kfree(uc_str); + return ret; } /** @@ -6473,6 +6499,9 @@ static int ufs_get_device_desc(struct ufs_hba *hba, u8 model_index; u8 *desc_buf; + if (!dev_desc) + return -EINVAL; + buff_len = max_t(size_t, hba->desc_size.dev_desc, QUERY_DESC_MAX_SIZE + 1); desc_buf = kmalloc(buff_len, GFP_KERNEL); @@ -6496,31 +6525,31 @@ static int ufs_get_device_desc(struct ufs_hba *hba, desc_buf[DEVICE_DESC_PARAM_MANF_ID + 1]; model_index = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME]; - - /* Zero-pad entire buffer for string termination. */ - memset(desc_buf, 0, buff_len); - - err = ufshcd_read_string_desc(hba, model_index, desc_buf, - QUERY_DESC_MAX_SIZE, true/*ASCII*/); - if (err) { + err = ufshcd_read_string_desc(hba, model_index, + &dev_desc->model, SD_ASCII_STD); + if (err < 0) { dev_err(hba->dev, "%s: Failed reading Product Name. err = %d\n", __func__, err); goto out; } - desc_buf[QUERY_DESC_MAX_SIZE] = '\0'; - strlcpy(dev_desc->model, (desc_buf + QUERY_DESC_HDR_SIZE), - min_t(u8, desc_buf[QUERY_DESC_LENGTH_OFFSET], - MAX_MODEL_LEN)); - - /* Null terminate the model string */ - dev_desc->model[MAX_MODEL_LEN] = '\0'; + /* + * ufshcd_read_string_desc returns size of the string + * reset the error value + */ + err = 0; out: kfree(desc_buf); return err; } +static void ufs_put_device_desc(struct ufs_dev_desc *dev_desc) +{ + kfree(dev_desc->model); + dev_desc->model = NULL; +} + static void ufs_fixup_device_setup(struct ufs_hba *hba, struct ufs_dev_desc *dev_desc) { @@ -6529,8 +6558,9 @@ static void ufs_fixup_device_setup(struct ufs_hba *hba, for (f = ufs_fixups; f->quirk; f++) { if ((f->card.wmanufacturerid == dev_desc->wmanufacturerid || f->card.wmanufacturerid == UFS_ANY_VENDOR) && - (STR_PRFX_EQUAL(f->card.model, dev_desc->model) || - !strcmp(f->card.model, UFS_ANY_MODEL))) + ((dev_desc->model && + STR_PRFX_EQUAL(f->card.model, dev_desc->model)) || + !strcmp(f->card.model, UFS_ANY_MODEL))) hba->dev_quirks |= f->quirk; } } @@ -6872,6 +6902,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) } ufs_fixup_device_setup(hba, &card); + ufs_put_device_desc(&card); + ufshcd_tune_unipro_params(hba); /* UFS device is also active now */ diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index a43c7135f33d..9f61550abc7f 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -913,8 +913,11 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, enum attr_idn idn, u8 index, u8 selector, u32 *attr_val); int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, enum flag_idn idn, bool *flag_res); -int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, - u8 *buf, u32 size, bool ascii); + +#define SD_ASCII_STD true +#define SD_RAW false +int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index, + u8 **buf, bool ascii); int ufshcd_hold(struct ufs_hba *hba, bool async); void ufshcd_release(struct ufs_hba *hba); -- cgit v1.2.3-59-g8ed1b From 09addb1d169ed2e67a0314e6275b42e7b8605d79 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 1 Aug 2019 15:38:12 -0700 Subject: scsi: core: Make scsi_internal_device_unblock_nowait() reject invalid new_state The only 'new_state' values passed by upstream kernel code to scsi_internal_device_unblock_nowait() are SDEV_RUNNING and SDEV_TRANSPORT_OFFLINE. These are the only values that should be passed to this function. Hence check the value of the 'new_state' argument to avoid that scsi_internal_device_unblock_nowait() would be used to trigger an illegal SCSI device state transition. In this context 'illegal' means not allowed by scsi_device_set_state(). Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Johannes Thumshirn Cc: Ming Lei Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index c72bce2f0cf1..7a4ac7a8e907 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2707,6 +2707,14 @@ void scsi_start_queue(struct scsi_device *sdev) int scsi_internal_device_unblock_nowait(struct scsi_device *sdev, enum scsi_device_state new_state) { + switch (new_state) { + case SDEV_RUNNING: + case SDEV_TRANSPORT_OFFLINE: + break; + default: + return -EINVAL; + } + /* * Try to transition the scsi device to SDEV_RUNNING or one of the * offlined states and goose the device queue if successful. -- cgit v1.2.3-59-g8ed1b From 94ef80a5f0d72376a0dd2cfed0bd123123b405e2 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 1 Aug 2019 15:38:13 -0700 Subject: scsi: core: Complain if scsi_target_block() fails If scsi_target_block() fails that can break the code that calls this function. Hence complain loudly if scsi_target_block() fails. Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Johannes Thumshirn Cc: Ming Lei Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 7a4ac7a8e907..d47d637e6be2 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2772,7 +2772,12 @@ static int scsi_internal_device_unblock(struct scsi_device *sdev, static void device_block(struct scsi_device *sdev, void *data) { - scsi_internal_device_block(sdev); + int ret; + + ret = scsi_internal_device_block(sdev); + + WARN_ONCE(ret, "scsi_internal_device_block(%s) failed: ret = %d\n", + dev_name(&sdev->sdev_gendev), ret); } static int -- cgit v1.2.3-59-g8ed1b From dccc96abfb21dc19d69e707c38c8ba439bba7160 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 1 Aug 2019 15:38:14 -0700 Subject: scsi: core: Reduce memory required for SCSI logging The data structure used for log messages is so large that it can cause a boot failure. Since allocations from that data structure can fail anyway, use kmalloc() / kfree() instead of that data structure. See also https://bugzilla.kernel.org/show_bug.cgi?id=204119. See also commit ded85c193a39 ("scsi: Implement per-cpu logging buffer") # v4.0. Reported-by: Jan Palus Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Johannes Thumshirn Cc: Ming Lei Cc: Jan Palus Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_logging.c | 48 +++------------------------------------------ include/scsi/scsi_dbg.h | 2 -- 2 files changed, 3 insertions(+), 47 deletions(-) diff --git a/drivers/scsi/scsi_logging.c b/drivers/scsi/scsi_logging.c index 39b8cc4574b4..c6ed0b12e807 100644 --- a/drivers/scsi/scsi_logging.c +++ b/drivers/scsi/scsi_logging.c @@ -15,57 +15,15 @@ #include #include -#define SCSI_LOG_SPOOLSIZE 4096 - -#if (SCSI_LOG_SPOOLSIZE / SCSI_LOG_BUFSIZE) > BITS_PER_LONG -#warning SCSI logging bitmask too large -#endif - -struct scsi_log_buf { - char buffer[SCSI_LOG_SPOOLSIZE]; - unsigned long map; -}; - -static DEFINE_PER_CPU(struct scsi_log_buf, scsi_format_log); - static char *scsi_log_reserve_buffer(size_t *len) { - struct scsi_log_buf *buf; - unsigned long map_bits = sizeof(buf->buffer) / SCSI_LOG_BUFSIZE; - unsigned long idx = 0; - - preempt_disable(); - buf = this_cpu_ptr(&scsi_format_log); - idx = find_first_zero_bit(&buf->map, map_bits); - if (likely(idx < map_bits)) { - while (test_and_set_bit(idx, &buf->map)) { - idx = find_next_zero_bit(&buf->map, map_bits, idx); - if (idx >= map_bits) - break; - } - } - if (WARN_ON(idx >= map_bits)) { - preempt_enable(); - return NULL; - } - *len = SCSI_LOG_BUFSIZE; - return buf->buffer + idx * SCSI_LOG_BUFSIZE; + *len = 128; + return kmalloc(*len, GFP_ATOMIC); } static void scsi_log_release_buffer(char *bufptr) { - struct scsi_log_buf *buf; - unsigned long idx; - int ret; - - buf = this_cpu_ptr(&scsi_format_log); - if (bufptr >= buf->buffer && - bufptr < buf->buffer + SCSI_LOG_SPOOLSIZE) { - idx = (bufptr - buf->buffer) / SCSI_LOG_BUFSIZE; - ret = test_and_clear_bit(idx, &buf->map); - WARN_ON(!ret); - } - preempt_enable(); + kfree(bufptr); } static inline const char *scmd_name(const struct scsi_cmnd *scmd) diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h index e03bd9d41fa8..7b196d234626 100644 --- a/include/scsi/scsi_dbg.h +++ b/include/scsi/scsi_dbg.h @@ -6,8 +6,6 @@ struct scsi_cmnd; struct scsi_device; struct scsi_sense_hdr; -#define SCSI_LOG_BUFSIZE 128 - extern void scsi_print_command(struct scsi_cmnd *); extern size_t __scsi_format_command(char *, size_t, const unsigned char *, size_t); -- cgit v1.2.3-59-g8ed1b From cb8b3359eb9c606421a42f3968c12211d6462906 Mon Sep 17 00:00:00 2001 From: Anil Varughese Date: Fri, 2 Aug 2019 12:21:12 +0100 Subject: scsi: ufs: Configure clock in .hce_enable_notify() in Cadence UFS Configure CDNS_UFS_REG_HCLKDIV in .hce_enable_notify() instead of .setup_clock() because if UFSHCD resets the controller ip because of phy or device related errors then CDNS_UFS_REG_HCLKDIV is reset to default value and .setup_clock() is not called later in the sequence whereas .hce_enable_notify will be called everytime controller is reenabled. Signed-off-by: Anil Varughese Reviewed-by: Vignesh Raghavendra Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/cdns-pltfrm.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c index 86dbb723f3ac..993519080a84 100644 --- a/drivers/scsi/ufs/cdns-pltfrm.c +++ b/drivers/scsi/ufs/cdns-pltfrm.c @@ -62,17 +62,16 @@ static int cdns_ufs_set_hclkdiv(struct ufs_hba *hba) } /** - * Sets clocks used by the controller + * Called before and after HCE enable bit is set. * @hba: host controller instance - * @on: if true, enable clocks, otherwise disable * @status: notify stage (pre, post change) * * Return zero for success and non-zero for failure */ -static int cdns_ufs_setup_clocks(struct ufs_hba *hba, bool on, - enum ufs_notify_change_status status) +static int cdns_ufs_hce_enable_notify(struct ufs_hba *hba, + enum ufs_notify_change_status status) { - if ((!on) || (status == PRE_CHANGE)) + if (status != PRE_CHANGE) return 0; return cdns_ufs_set_hclkdiv(hba); @@ -114,13 +113,13 @@ static int cdns_ufs_m31_16nm_phy_initialization(struct ufs_hba *hba) static const struct ufs_hba_variant_ops cdns_ufs_pltfm_hba_vops = { .name = "cdns-ufs-pltfm", - .setup_clocks = cdns_ufs_setup_clocks, + .hce_enable_notify = cdns_ufs_hce_enable_notify, }; static const struct ufs_hba_variant_ops cdns_ufs_m31_16nm_pltfm_hba_vops = { .name = "cdns-ufs-pltfm", .init = cdns_ufs_init, - .setup_clocks = cdns_ufs_setup_clocks, + .hce_enable_notify = cdns_ufs_hce_enable_notify, .phy_initialization = cdns_ufs_m31_16nm_phy_initialization, }; -- cgit v1.2.3-59-g8ed1b From 7d8948627a7cd84c45069276e5fcddf6ab074baa Mon Sep 17 00:00:00 2001 From: Li Zhong Date: Mon, 5 Aug 2019 08:43:36 +0800 Subject: scsi: target: tcmu: clean the nl_cmd of the udev when nl send fails If the userspace process crashes while we send the nl msg, it is possible that the cmd in curr_nl_cmd of tcmu_dev never gets reset to 0, and and returns busy for other commands after the userspace process is restartd. More details below: /backstores/user:file/file> set attribute dev_size=2048 Cannot set attribute dev_size: [Errno 3] No such process /backstores/user:file/file> set attribute dev_size=2048 Cannot set attribute dev_size: [Errno 16] Device or resource busy with following kernel messages: [173605.747169] Unable to reconfigure device [173616.686674] tcmu daemon: command reply support 1. [173623.866978] netlink cmd 3 already executing on file [173623.866984] Unable to reconfigure device Also, it is not safe to leave the nl_cmd in the list, and not get deleted. This patch removes the nl_cmd from the list, and clear its data if it is not sent successfully. Signed-off-by: Li Zhong Acked-by: Mike Christie Signed-off-by: Martin K. Petersen --- drivers/target/target_core_user.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 04eda111920e..68045cbca595 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -1708,6 +1708,24 @@ static int tcmu_init_genl_cmd_reply(struct tcmu_dev *udev, int cmd) return 0; } +static void tcmu_destroy_genl_cmd_reply(struct tcmu_dev *udev) +{ + struct tcmu_nl_cmd *nl_cmd = &udev->curr_nl_cmd; + + if (!tcmu_kern_cmd_reply_supported) + return; + + if (udev->nl_reply_supported <= 0) + return; + + mutex_lock(&tcmu_nl_cmd_mutex); + + list_del(&nl_cmd->nl_list); + memset(nl_cmd, 0, sizeof(*nl_cmd)); + + mutex_unlock(&tcmu_nl_cmd_mutex); +} + static int tcmu_wait_genl_cmd_reply(struct tcmu_dev *udev) { struct tcmu_nl_cmd *nl_cmd = &udev->curr_nl_cmd; @@ -1788,6 +1806,8 @@ static int tcmu_netlink_event_send(struct tcmu_dev *udev, if (ret == 0 || (ret == -ESRCH && cmd == TCMU_CMD_ADDED_DEVICE)) return tcmu_wait_genl_cmd_reply(udev); + else + tcmu_destroy_genl_cmd_reply(udev); return ret; } -- cgit v1.2.3-59-g8ed1b From 69a76d08f2e41fa7f27bd6c4c0dce92cce01744a Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sat, 3 Aug 2019 21:34:43 +0200 Subject: scsi: ncr53c8xx: Mark expected switch fall-through Signed-off-by: Helge Deller Signed-off-by: Martin K. Petersen --- drivers/scsi/ncr53c8xx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index e6a95498ac0d..e0b427fdf818 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -3910,11 +3910,14 @@ static void __init ncr_prepare_setting(struct ncb *np) np->scsi_mode = SMODE_HVD; break; } + /* fall through */ case 3: /* SYMBIOS controllers report HVD through GPIO3 */ if (INB(nc_gpreg) & 0x08) break; + /* fall through */ case 2: /* Set HVD unconditionally */ np->scsi_mode = SMODE_HVD; + /* fall through */ case 1: /* Trust previous settings for HVD */ if (np->sv_stest2 & 0x20) np->scsi_mode = SMODE_HVD; @@ -6714,6 +6717,7 @@ void ncr_int_sir (struct ncb *np) OUTL_DSP (scr_to_cpu(tp->lp[0]->jump_ccb[0])); return; } + /* fall through */ case SIR_RESEL_BAD_TARGET: /* Will send a TARGET RESET message */ case SIR_RESEL_BAD_LUN: /* Will send a TARGET RESET message */ case SIR_RESEL_BAD_I_T_L_Q: /* Will send an ABORT TAG message */ -- cgit v1.2.3-59-g8ed1b From 93352abc81a90314bf032038200ce96989a32c62 Mon Sep 17 00:00:00 2001 From: John Garry Date: Mon, 5 Aug 2019 21:47:58 +0800 Subject: scsi: hisi_sas: Make max IPTT count equal for all hw revisions There is a small optimisation to be had by making the max IPTT the same for all hw revisions, that being we can drop the check for read and write pointer being the same in the get free slot function. Change v1 hw to have max IPTT of 4096 - same as v2 and v3 hw - and drop hisi_sas_hw.max_command_entries. Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 6 ++++-- drivers/scsi/hisi_sas/hisi_sas_main.c | 30 +++++++++++++----------------- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 3 --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 1 - drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 7 ++----- 5 files changed, 19 insertions(+), 28 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 42a02cc47a60..1fa3e53e857d 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -31,7 +31,10 @@ #define HISI_SAS_MAX_DEVICES HISI_SAS_MAX_ITCT_ENTRIES #define HISI_SAS_RESET_BIT 0 #define HISI_SAS_REJECT_CMD_BIT 1 -#define HISI_SAS_RESERVED_IPTT_CNT 96 +#define HISI_SAS_MAX_COMMANDS (HISI_SAS_QUEUE_SLOTS) +#define HISI_SAS_RESERVED_IPTT 96 +#define HISI_SAS_UNRESERVED_IPTT \ + (HISI_SAS_MAX_COMMANDS - HISI_SAS_RESERVED_IPTT) #define HISI_SAS_STATUS_BUF_SZ (sizeof(struct hisi_sas_status_buffer)) #define HISI_SAS_COMMAND_TABLE_SZ (sizeof(union hisi_sas_command_table)) @@ -292,7 +295,6 @@ struct hisi_sas_hw { int delay_ms, int timeout_ms); void (*snapshot_prepare)(struct hisi_hba *hisi_hba); void (*snapshot_restore)(struct hisi_hba *hisi_hba); - int max_command_entries; int complete_hdr_size; struct scsi_host_template *sht; diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index cb746cfc2fa8..94c7c2b48b17 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -180,8 +180,8 @@ static void hisi_sas_slot_index_free(struct hisi_hba *hisi_hba, int slot_idx) { unsigned long flags; - if (hisi_hba->hw->slot_index_alloc || (slot_idx >= - hisi_hba->hw->max_command_entries - HISI_SAS_RESERVED_IPTT_CNT)) { + if (hisi_hba->hw->slot_index_alloc || + slot_idx >= HISI_SAS_UNRESERVED_IPTT) { spin_lock_irqsave(&hisi_hba->lock, flags); hisi_sas_slot_index_clear(hisi_hba, slot_idx); spin_unlock_irqrestore(&hisi_hba->lock, flags); @@ -211,8 +211,7 @@ static int hisi_sas_slot_index_alloc(struct hisi_hba *hisi_hba, if (index >= hisi_hba->slot_index_count) { index = find_next_zero_bit(bitmap, hisi_hba->slot_index_count, - hisi_hba->hw->max_command_entries - - HISI_SAS_RESERVED_IPTT_CNT); + HISI_SAS_UNRESERVED_IPTT); if (index >= hisi_hba->slot_index_count) { spin_unlock_irqrestore(&hisi_hba->lock, flags); return -SAS_QUEUE_FULL; @@ -2291,7 +2290,7 @@ static struct sas_domain_function_template hisi_sas_transport_ops = { void hisi_sas_init_mem(struct hisi_hba *hisi_hba) { - int i, s, j, max_command_entries = hisi_hba->hw->max_command_entries; + int i, s, j, max_command_entries = HISI_SAS_MAX_COMMANDS; struct hisi_sas_breakpoint *sata_breakpoint = hisi_hba->sata_breakpoint; for (i = 0; i < hisi_hba->queue_count; i++) { @@ -2328,7 +2327,7 @@ EXPORT_SYMBOL_GPL(hisi_sas_init_mem); int hisi_sas_alloc(struct hisi_hba *hisi_hba) { struct device *dev = hisi_hba->dev; - int i, j, s, max_command_entries = hisi_hba->hw->max_command_entries; + int i, j, s, max_command_entries = HISI_SAS_MAX_COMMANDS; int max_command_entries_ru, sz_slot_buf_ru; int blk_cnt, slots_per_blk; @@ -2458,8 +2457,7 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba) hisi_sas_init_mem(hisi_hba); hisi_sas_slot_index_init(hisi_hba); - hisi_hba->last_slot_index = hisi_hba->hw->max_command_entries - - HISI_SAS_RESERVED_IPTT_CNT; + hisi_hba->last_slot_index = HISI_SAS_UNRESERVED_IPTT; hisi_hba->wq = create_singlethread_workqueue(dev_name(dev)); if (!hisi_hba->wq) { @@ -2672,13 +2670,11 @@ int hisi_sas_probe(struct platform_device *pdev, shost->max_channel = 1; shost->max_cmd_len = 16; if (hisi_hba->hw->slot_index_alloc) { - shost->can_queue = hisi_hba->hw->max_command_entries; - shost->cmd_per_lun = hisi_hba->hw->max_command_entries; + shost->can_queue = HISI_SAS_MAX_COMMANDS; + shost->cmd_per_lun = HISI_SAS_MAX_COMMANDS; } else { - shost->can_queue = hisi_hba->hw->max_command_entries - - HISI_SAS_RESERVED_IPTT_CNT; - shost->cmd_per_lun = hisi_hba->hw->max_command_entries - - HISI_SAS_RESERVED_IPTT_CNT; + shost->can_queue = HISI_SAS_UNRESERVED_IPTT; + shost->cmd_per_lun = HISI_SAS_UNRESERVED_IPTT; } sha->sas_ha_name = DRV_NAME; @@ -2794,7 +2790,7 @@ static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba) { - int max_command_entries = hisi_hba->hw->max_command_entries; + int max_command_entries = HISI_SAS_MAX_COMMANDS; void *databuf = hisi_hba->debugfs_iost; struct hisi_sas_iost *iost; int i; @@ -3008,7 +3004,7 @@ static int hisi_sas_debugfs_iost_show(struct seq_file *s, void *p) { struct hisi_hba *hisi_hba = s->private; struct hisi_sas_iost *debugfs_iost = hisi_hba->debugfs_iost; - int i, ret, max_command_entries = hisi_hba->hw->max_command_entries; + int i, ret, max_command_entries = HISI_SAS_MAX_COMMANDS; __le64 *iost = &debugfs_iost->qw0; for (i = 0; i < max_command_entries; i++, debugfs_iost++) { @@ -3177,7 +3173,7 @@ EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler); void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) { - int max_command_entries = hisi_hba->hw->max_command_entries; + int max_command_entries = HISI_SAS_MAX_COMMANDS; struct device *dev = hisi_hba->dev; int p, i, c, d; size_t sz; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 3912216e8a4f..afdbaccbbc5e 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -401,8 +401,6 @@ enum { TRANS_RX_SMP_RESP_TIMEOUT_ERR, /* 0x31a */ }; -#define HISI_SAS_COMMAND_ENTRIES_V1_HW 8192 - #define HISI_SAS_PHY_MAX_INT_NR (HISI_SAS_PHY_INT_NR * HISI_SAS_MAX_PHYS) #define HISI_SAS_CQ_MAX_INT_NR (HISI_SAS_MAX_QUEUES) #define HISI_SAS_FATAL_INT_NR (2) @@ -1830,7 +1828,6 @@ static const struct hisi_sas_hw hisi_sas_v1_hw = { .phy_set_linkrate = phy_set_linkrate_v1_hw, .phy_get_max_linkrate = phy_get_max_linkrate_v1_hw, .get_wideport_bitmap = get_wideport_bitmap_v1_hw, - .max_command_entries = HISI_SAS_COMMAND_ENTRIES_V1_HW, .complete_hdr_size = sizeof(struct hisi_sas_complete_v1_hdr), .sht = &sht_v1_hw, }; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index e9b15d45f98f..fc98bd9e5588 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -3616,7 +3616,6 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = { .get_events = phy_get_events_v2_hw, .phy_set_linkrate = phy_set_linkrate_v2_hw, .phy_get_max_linkrate = phy_get_max_linkrate_v2_hw, - .max_command_entries = HISI_SAS_COMMAND_ENTRIES_V2_HW, .complete_hdr_size = sizeof(struct hisi_sas_complete_v2_hdr), .soft_reset = soft_reset_v2_hw, .get_phys_state = get_phys_state_v2_hw, diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 5f0f6df11adf..0171cdb4da81 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2935,7 +2935,6 @@ static struct scsi_host_template sht_v3_hw = { static const struct hisi_sas_hw hisi_sas_v3_hw = { .hw_init = hisi_sas_v3_init, .setup_itct = setup_itct_v3_hw, - .max_command_entries = HISI_SAS_COMMAND_ENTRIES_V3_HW, .get_wideport_bitmap = get_wideport_bitmap_v3_hw, .complete_hdr_size = sizeof(struct hisi_sas_complete_v3_hdr), .clear_itct = clear_itct_v3_hw, @@ -3076,10 +3075,8 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) shost->max_lun = ~0; shost->max_channel = 1; shost->max_cmd_len = 16; - shost->can_queue = hisi_hba->hw->max_command_entries - - HISI_SAS_RESERVED_IPTT_CNT; - shost->cmd_per_lun = hisi_hba->hw->max_command_entries - - HISI_SAS_RESERVED_IPTT_CNT; + shost->can_queue = HISI_SAS_UNRESERVED_IPTT; + shost->cmd_per_lun = HISI_SAS_UNRESERVED_IPTT; sha->sas_ha_name = DRV_NAME; sha->dev = dev; -- cgit v1.2.3-59-g8ed1b From 897cc769bcc09204cb80ce5db7a8d9c404bdb6ec Mon Sep 17 00:00:00 2001 From: John Garry Date: Mon, 5 Aug 2019 21:47:59 +0800 Subject: scsi: hisi_sas: Drop hisi_sas_hw.get_free_slot In commit 1273d65f29045 ("scsi: hisi_sas: change queue depth from 512 to 4096"), the depth of each queue is the same as the max IPTT in the system. As such, as long as we have an IPTT allocated, we will have enough space on any delivery queue. All .get_free_slot functions were checking for space on the queue by reading the DQ read pointer. Drop this, and also raise the code into common code, as there is nothing hw specific remaining. Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 1 - drivers/scsi/hisi_sas/hisi_sas_main.c | 27 +++++++-------------------- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 32 -------------------------------- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 26 -------------------------- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 33 --------------------------------- 5 files changed, 7 insertions(+), 112 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 1fa3e53e857d..c1b56b482a23 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -260,7 +260,6 @@ struct hisi_sas_hw { struct domain_device *device); struct hisi_sas_device *(*alloc_dev)(struct domain_device *device); void (*sl_notify_ssp)(struct hisi_hba *hisi_hba, int phy_no); - int (*get_free_slot)(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq); void (*start_delivery)(struct hisi_sas_dq *dq); void (*prep_ssp)(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot); diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 94c7c2b48b17..54bbab7151c7 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -519,13 +519,8 @@ static int hisi_sas_task_prep(struct sas_task *task, slot = &hisi_hba->slot_info[slot_idx]; spin_lock_irqsave(&dq->lock, flags); - wr_q_index = hisi_hba->hw->get_free_slot(hisi_hba, dq); - if (wr_q_index < 0) { - spin_unlock_irqrestore(&dq->lock, flags); - rc = -EAGAIN; - goto err_out_tag; - } - + wr_q_index = dq->wr_point; + dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS; list_add_tail(&slot->delivery, &dq->list); spin_unlock_irqrestore(&dq->lock, flags); spin_lock_irqsave(&sas_dev->lock, flags); @@ -579,8 +574,6 @@ static int hisi_sas_task_prep(struct sas_task *task, return 0; -err_out_tag: - hisi_sas_slot_index_free(hisi_hba, slot_idx); err_out_dif_dma_unmap: if (!sas_protocol_ata(task->task_proto)) hisi_sas_dif_dma_unmap(hisi_hba, task, n_elem_dif); @@ -1963,7 +1956,7 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id, struct asd_sas_port *sas_port = device->port; struct hisi_sas_cmd_hdr *cmd_hdr_base; int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx; - unsigned long flags, flags_dq = 0; + unsigned long flags; int wr_q_index; if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) @@ -1982,15 +1975,11 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id, slot_idx = rc; slot = &hisi_hba->slot_info[slot_idx]; - spin_lock_irqsave(&dq->lock, flags_dq); - wr_q_index = hisi_hba->hw->get_free_slot(hisi_hba, dq); - if (wr_q_index < 0) { - spin_unlock_irqrestore(&dq->lock, flags_dq); - rc = -EAGAIN; - goto err_out_tag; - } + spin_lock_irqsave(&dq->lock, flags); + wr_q_index = dq->wr_point; + dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS; list_add_tail(&slot->delivery, &dq->list); - spin_unlock_irqrestore(&dq->lock, flags_dq); + spin_unlock_irqrestore(&dq->lock, flags); spin_lock_irqsave(&sas_dev->lock, flags); list_add_tail(&slot->entry, &sas_dev->list); spin_unlock_irqrestore(&sas_dev->lock, flags); @@ -2027,8 +2016,6 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id, return 0; -err_out_tag: - hisi_sas_slot_index_free(hisi_hba, slot_idx); err_out: dev_err(dev, "internal abort task prep: failed[%d]!\n", rc); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index afdbaccbbc5e..b13cbc64d2a9 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -416,13 +416,6 @@ static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off) return readl(regs); } -static u32 hisi_sas_read32_relaxed(struct hisi_hba *hisi_hba, u32 off) -{ - void __iomem *regs = hisi_hba->regs + off; - - return readl_relaxed(regs); -} - static void hisi_sas_write32(struct hisi_hba *hisi_hba, u32 off, u32 val) { @@ -864,30 +857,6 @@ static int get_wideport_bitmap_v1_hw(struct hisi_hba *hisi_hba, int port_id) return bitmap; } -/* - * The callpath to this function and upto writing the write - * queue pointer should be safe from interruption. - */ -static int -get_free_slot_v1_hw(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq) -{ - struct device *dev = hisi_hba->dev; - int queue = dq->id; - u32 r, w; - - w = dq->wr_point; - r = hisi_sas_read32_relaxed(hisi_hba, - DLVRY_Q_0_RD_PTR + (queue * 0x14)); - if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) { - dev_warn(dev, "could not find free slot\n"); - return -EAGAIN; - } - - dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS; - - return w; -} - /* DQ lock must be taken here */ static void start_delivery_v1_hw(struct hisi_sas_dq *dq) { @@ -1818,7 +1787,6 @@ static const struct hisi_sas_hw hisi_sas_v1_hw = { .clear_itct = clear_itct_v1_hw, .prep_smp = prep_smp_v1_hw, .prep_ssp = prep_ssp_v1_hw, - .get_free_slot = get_free_slot_v1_hw, .start_delivery = start_delivery_v1_hw, .slot_complete = slot_complete_v1_hw, .phys_init = phys_init_v1_hw, diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index fc98bd9e5588..de33e31cd88a 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -1637,31 +1637,6 @@ static int get_wideport_bitmap_v2_hw(struct hisi_hba *hisi_hba, int port_id) return bitmap; } -/* - * The callpath to this function and upto writing the write - * queue pointer should be safe from interruption. - */ -static int -get_free_slot_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq) -{ - struct device *dev = hisi_hba->dev; - int queue = dq->id; - u32 r, w; - - w = dq->wr_point; - r = hisi_sas_read32_relaxed(hisi_hba, - DLVRY_Q_0_RD_PTR + (queue * 0x14)); - if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) { - dev_warn(dev, "full queue=%d r=%d w=%d\n", - queue, r, w); - return -EAGAIN; - } - - dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS; - - return w; -} - /* DQ lock must be taken here */ static void start_delivery_v2_hw(struct hisi_sas_dq *dq) { @@ -3606,7 +3581,6 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = { .prep_ssp = prep_ssp_v2_hw, .prep_stp = prep_ata_v2_hw, .prep_abort = prep_abort_v2_hw, - .get_free_slot = get_free_slot_v2_hw, .start_delivery = start_delivery_v2_hw, .slot_complete = slot_complete_v2_hw, .phys_init = phys_init_v2_hw, diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 0171cdb4da81..b99abc788487 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -499,13 +499,6 @@ static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off) return readl(regs); } -static u32 hisi_sas_read32_relaxed(struct hisi_hba *hisi_hba, u32 off) -{ - void __iomem *regs = hisi_hba->regs + off; - - return readl_relaxed(regs); -} - static void hisi_sas_write32(struct hisi_hba *hisi_hba, u32 off, u32 val) { void __iomem *regs = hisi_hba->regs + off; @@ -1006,31 +999,6 @@ static int get_wideport_bitmap_v3_hw(struct hisi_hba *hisi_hba, int port_id) return bitmap; } -/** - * The callpath to this function and upto writing the write - * queue pointer should be safe from interruption. - */ -static int -get_free_slot_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq) -{ - struct device *dev = hisi_hba->dev; - int queue = dq->id; - u32 r, w; - - w = dq->wr_point; - r = hisi_sas_read32_relaxed(hisi_hba, - DLVRY_Q_0_RD_PTR + (queue * 0x14)); - if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) { - dev_warn(dev, "full queue=%d r=%d w=%d\n", - queue, r, w); - return -EAGAIN; - } - - dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS; - - return w; -} - static void start_delivery_v3_hw(struct hisi_sas_dq *dq) { struct hisi_hba *hisi_hba = dq->hisi_hba; @@ -2943,7 +2911,6 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = { .prep_smp = prep_smp_v3_hw, .prep_stp = prep_ata_v3_hw, .prep_abort = prep_abort_v3_hw, - .get_free_slot = get_free_slot_v3_hw, .start_delivery = start_delivery_v3_hw, .slot_complete = slot_complete_v3_hw, .phys_init = phys_init_v3_hw, -- cgit v1.2.3-59-g8ed1b From bee0cf25c030776a8ecfc3c951d3b73259dc6839 Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Mon, 5 Aug 2019 21:48:00 +0800 Subject: scsi: hisi_sas: Fix pointer usage error in show debugfs IOST/ITCT Fix how the pointer is set in hisi_sas_debugfs_iost_show() and hisi_sas_debugfs_itct_show(). Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 54bbab7151c7..325ec4306794 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -2992,9 +2992,10 @@ static int hisi_sas_debugfs_iost_show(struct seq_file *s, void *p) struct hisi_hba *hisi_hba = s->private; struct hisi_sas_iost *debugfs_iost = hisi_hba->debugfs_iost; int i, ret, max_command_entries = HISI_SAS_MAX_COMMANDS; - __le64 *iost = &debugfs_iost->qw0; for (i = 0; i < max_command_entries; i++, debugfs_iost++) { + __le64 *iost = &debugfs_iost->qw0; + ret = hisi_sas_show_row_64(s, i, sizeof(*debugfs_iost), iost); if (ret) @@ -3022,9 +3023,10 @@ static int hisi_sas_debugfs_itct_show(struct seq_file *s, void *p) int i, ret; struct hisi_hba *hisi_hba = s->private; struct hisi_sas_itct *debugfs_itct = hisi_hba->debugfs_itct; - __le64 *itct = &debugfs_itct->qw0; for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, debugfs_itct++) { + __le64 *itct = &debugfs_itct->qw0; + ret = hisi_sas_show_row_64(s, i, sizeof(*debugfs_itct), itct); if (ret) -- cgit v1.2.3-59-g8ed1b From bbe0a7b348b336625292092c74fc7817aeb8d30b Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Mon, 5 Aug 2019 21:48:01 +0800 Subject: scsi: hisi_sas: Snapshot HW cache of IOST and ITCT at debugfs The value of IOST/ITCT is updated to cache first, and then synchronize to DDR periodically. So the value in IOST/ITCT cache is the latest data and it's important for debugging. So, the HW cache of IOST and ITCT should be snapshot at debugfs. Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 17 +++++ drivers/scsi/hisi_sas/hisi_sas_main.c | 114 ++++++++++++++++++++++++++++++++- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 32 +++++++++ 3 files changed, 161 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index c1b56b482a23..5a2fbbbed53e 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -36,6 +36,9 @@ #define HISI_SAS_UNRESERVED_IPTT \ (HISI_SAS_MAX_COMMANDS - HISI_SAS_RESERVED_IPTT) +#define HISI_SAS_IOST_ITCT_CACHE_NUM 64 +#define HISI_SAS_IOST_ITCT_CACHE_DW_SZ 10 + #define HISI_SAS_STATUS_BUF_SZ (sizeof(struct hisi_sas_status_buffer)) #define HISI_SAS_COMMAND_TABLE_SZ (sizeof(union hisi_sas_command_table)) @@ -252,6 +255,15 @@ struct hisi_sas_debugfs_reg { }; }; +struct hisi_sas_iost_itct_cache { + u32 data[HISI_SAS_IOST_ITCT_CACHE_DW_SZ]; +}; + +enum hisi_sas_debugfs_cache_type { + HISI_SAS_ITCT_CACHE, + HISI_SAS_IOST_CACHE, +}; + struct hisi_sas_hw { int (*hw_init)(struct hisi_hba *hisi_hba); void (*setup_itct)(struct hisi_hba *hisi_hba, @@ -294,6 +306,9 @@ struct hisi_sas_hw { int delay_ms, int timeout_ms); void (*snapshot_prepare)(struct hisi_hba *hisi_hba); void (*snapshot_restore)(struct hisi_hba *hisi_hba); + void (*read_iost_itct_cache)(struct hisi_hba *hisi_hba, + enum hisi_sas_debugfs_cache_type type, + u32 *cache); int complete_hdr_size; struct scsi_host_template *sht; @@ -379,6 +394,8 @@ struct hisi_hba { struct hisi_sas_cmd_hdr *debugfs_cmd_hdr[HISI_SAS_MAX_QUEUES]; struct hisi_sas_iost *debugfs_iost; struct hisi_sas_itct *debugfs_itct; + u64 *debugfs_iost_cache; + u64 *debugfs_itct_cache; struct dentry *debugfs_dir; struct dentry *debugfs_dump_dentry; diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 325ec4306794..240b6faaf25f 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -2763,10 +2763,14 @@ static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba) static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) { + void *cachebuf = hisi_hba->debugfs_itct_cache; void *databuf = hisi_hba->debugfs_itct; struct hisi_sas_itct *itct; int i; + hisi_hba->hw->read_iost_itct_cache(hisi_hba, HISI_SAS_ITCT_CACHE, + cachebuf); + itct = hisi_hba->itct; for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) { @@ -2778,10 +2782,14 @@ static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba) { int max_command_entries = HISI_SAS_MAX_COMMANDS; + void *cachebuf = hisi_hba->debugfs_iost_cache; void *databuf = hisi_hba->debugfs_iost; struct hisi_sas_iost *iost; int i; + hisi_hba->hw->read_iost_itct_cache(hisi_hba, HISI_SAS_IOST_CACHE, + cachebuf); + iost = hisi_hba->iost; for (i = 0; i < max_command_entries; i++, iost++) { @@ -3018,6 +3026,46 @@ static const struct file_operations hisi_sas_debugfs_iost_fops = { .owner = THIS_MODULE, }; +static int hisi_sas_debugfs_iost_cache_show(struct seq_file *s, void *p) +{ + struct hisi_hba *hisi_hba = s->private; + struct hisi_sas_iost_itct_cache *iost_cache = + (struct hisi_sas_iost_itct_cache *)hisi_hba->debugfs_iost_cache; + u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; + int i, tab_idx; + __le64 *iost; + + for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, iost_cache++) { + /* + * Data struct of IOST cache: + * Data[1]: BIT0~15: Table index + * Bit16: Valid mask + * Data[2]~[9]: IOST table + */ + tab_idx = (iost_cache->data[1] & 0xffff); + iost = (__le64 *)iost_cache; + + hisi_sas_show_row_64(s, tab_idx, cache_size, iost); + } + + return 0; +} + +static int hisi_sas_debugfs_iost_cache_open(struct inode *inode, + struct file *filp) +{ + return single_open(filp, hisi_sas_debugfs_iost_cache_show, + inode->i_private); +} + +static const struct file_operations hisi_sas_debugfs_iost_cache_fops = { + .open = hisi_sas_debugfs_iost_cache_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + static int hisi_sas_debugfs_itct_show(struct seq_file *s, void *p) { int i, ret; @@ -3049,6 +3097,46 @@ static const struct file_operations hisi_sas_debugfs_itct_fops = { .owner = THIS_MODULE, }; +static int hisi_sas_debugfs_itct_cache_show(struct seq_file *s, void *p) +{ + struct hisi_hba *hisi_hba = s->private; + struct hisi_sas_iost_itct_cache *itct_cache = + (struct hisi_sas_iost_itct_cache *)hisi_hba->debugfs_itct_cache; + u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; + int i, tab_idx; + __le64 *itct; + + for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, itct_cache++) { + /* + * Data struct of ITCT cache: + * Data[1]: BIT0~15: Table index + * Bit16: Valid mask + * Data[2]~[9]: ITCT table + */ + tab_idx = itct_cache->data[1] & 0xffff; + itct = (__le64 *)itct_cache; + + hisi_sas_show_row_64(s, tab_idx, cache_size, itct); + } + + return 0; +} + +static int hisi_sas_debugfs_itct_cache_open(struct inode *inode, + struct file *filp) +{ + return single_open(filp, hisi_sas_debugfs_itct_cache_show, + inode->i_private); +} + +static const struct file_operations hisi_sas_debugfs_itct_cache_fops = { + .open = hisi_sas_debugfs_itct_cache_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) { struct dentry *dump_dentry; @@ -3095,9 +3183,15 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) debugfs_create_file("iost", 0400, dump_dentry, hisi_hba, &hisi_sas_debugfs_iost_fops); + debugfs_create_file("iost_cache", 0400, dump_dentry, hisi_hba, + &hisi_sas_debugfs_iost_cache_fops); + debugfs_create_file("itct", 0400, dump_dentry, hisi_hba, &hisi_sas_debugfs_itct_fops); + debugfs_create_file("itct_cache", 0400, dump_dentry, hisi_hba, + &hisi_sas_debugfs_itct_cache_fops); + return; } @@ -3212,14 +3306,26 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) goto fail_iost_dq; } - /* Alloc buffer for iost */ sz = max_command_entries * sizeof(struct hisi_sas_iost); hisi_hba->debugfs_iost = devm_kmalloc(dev, sz, GFP_KERNEL); if (!hisi_hba->debugfs_iost) goto fail_iost_dq; - /* Alloc buffer for itct */ + sz = HISI_SAS_IOST_ITCT_CACHE_NUM * + sizeof(struct hisi_sas_iost_itct_cache); + + hisi_hba->debugfs_iost_cache = devm_kmalloc(dev, sz, GFP_KERNEL); + if (!hisi_hba->debugfs_iost_cache) + goto fail_iost_cache; + + sz = HISI_SAS_IOST_ITCT_CACHE_NUM * + sizeof(struct hisi_sas_iost_itct_cache); + + hisi_hba->debugfs_itct_cache = devm_kmalloc(dev, sz, GFP_KERNEL); + if (!hisi_hba->debugfs_itct_cache) + goto fail_itct_cache; + /* New memory allocation must be locate before itct */ sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct); @@ -3229,6 +3335,10 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) return; fail_itct: + devm_kfree(dev, hisi_hba->debugfs_iost_cache); +fail_itct_cache: + devm_kfree(dev, hisi_hba->debugfs_iost_cache); +fail_iost_cache: devm_kfree(dev, hisi_hba->debugfs_iost); fail_iost_dq: for (i = 0; i < d; i++) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index b99abc788487..c8ca6ead639b 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -71,6 +71,7 @@ #define HGC_DQE_ECC_MB_ADDR_OFF 16 #define HGC_DQE_ECC_MB_ADDR_MSK (0xfff << HGC_DQE_ECC_MB_ADDR_OFF) #define CHNL_INT_STATUS 0x148 +#define TAB_DFX 0x14c #define HGC_ITCT_ECC_ADDR 0x150 #define HGC_ITCT_ECC_1B_ADDR_OFF 0 #define HGC_ITCT_ECC_1B_ADDR_MSK (0x3ff << \ @@ -83,6 +84,7 @@ #define AXI_ERR_INFO_MSK (0xff << AXI_ERR_INFO_OFF) #define FIFO_ERR_INFO_OFF 8 #define FIFO_ERR_INFO_MSK (0xff << FIFO_ERR_INFO_OFF) +#define TAB_RD_TYPE 0x15c #define INT_COAL_EN 0x19c #define OQ_INT_COAL_TIME 0x1a0 #define OQ_INT_COAL_CNT 0x1a4 @@ -2877,6 +2879,35 @@ static void debugfs_snapshot_restore_v3_hw(struct hisi_hba *hisi_hba) clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); } +static void read_iost_itct_cache_v3_hw(struct hisi_hba *hisi_hba, + enum hisi_sas_debugfs_cache_type type, + u32 *cache) +{ + u32 cache_dw_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * + HISI_SAS_IOST_ITCT_CACHE_NUM; + u32 *buf = cache; + u32 i, val; + + hisi_sas_write32(hisi_hba, TAB_RD_TYPE, type); + + for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_DW_SZ; i++) { + val = hisi_sas_read32(hisi_hba, TAB_DFX); + if (val == 0xffffffff) + break; + } + + if (val != 0xffffffff) { + pr_err("Issue occur when reading IOST/ITCT cache!\n"); + return; + } + + memset(buf, 0, cache_dw_size * 4); + buf[0] = val; + + for (i = 1; i < cache_dw_size; i++) + buf[i] = hisi_sas_read32(hisi_hba, TAB_DFX); +} + static struct scsi_host_template sht_v3_hw = { .name = DRV_NAME, .module = THIS_MODULE, @@ -2929,6 +2960,7 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = { .debugfs_reg_port = &debugfs_port_reg, .snapshot_prepare = debugfs_snapshot_prepare_v3_hw, .snapshot_restore = debugfs_snapshot_restore_v3_hw, + .read_iost_itct_cache = read_iost_itct_cache_v3_hw, }; static struct Scsi_Host * -- cgit v1.2.3-59-g8ed1b From b0b3e4290e288bb633c4ff6331b2c0b9530aa9b8 Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Mon, 5 Aug 2019 21:48:02 +0800 Subject: scsi: hisi_sas: Snapshot AXI and RAS register at debugfs The AXI and RAS register values should also should be snapshot at debugfs. Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 12 ++- drivers/scsi/hisi_sas/hisi_sas_main.c | 132 +++++++++++++++++++++++++++++---- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 36 ++++++++- 3 files changed, 162 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 5a2fbbbed53e..fd998d07ffcd 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -259,6 +259,13 @@ struct hisi_sas_iost_itct_cache { u32 data[HISI_SAS_IOST_ITCT_CACHE_DW_SZ]; }; +enum hisi_sas_debugfs_reg_array_member { + DEBUGFS_GLOBAL = 0, + DEBUGFS_AXI, + DEBUGFS_RAS, + DEBUGFS_REGS_NUM +}; + enum hisi_sas_debugfs_cache_type { HISI_SAS_ITCT_CACHE, HISI_SAS_IOST_CACHE, @@ -312,7 +319,7 @@ struct hisi_sas_hw { int complete_hdr_size; struct scsi_host_template *sht; - const struct hisi_sas_debugfs_reg *debugfs_reg_global; + const struct hisi_sas_debugfs_reg *debugfs_reg_array[DEBUGFS_REGS_NUM]; const struct hisi_sas_debugfs_reg *debugfs_reg_port; }; @@ -388,7 +395,8 @@ struct hisi_hba { unsigned int *reply_map; /* debugfs memories */ - u32 *debugfs_global_reg; + /* Put Global AXI and RAS Register into register array */ + u32 *debugfs_regs[DEBUGFS_REGS_NUM]; u32 *debugfs_port_reg[HISI_SAS_MAX_PHYS]; void *debugfs_complete_hdr[HISI_SAS_MAX_QUEUES]; struct hisi_sas_cmd_hdr *debugfs_cmd_hdr[HISI_SAS_MAX_QUEUES]; diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 240b6faaf25f..04b3b0040059 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -2752,15 +2752,42 @@ static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba) static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba) { - u32 *databuf = (u32 *)hisi_hba->debugfs_global_reg; + u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_GLOBAL]; + const struct hisi_sas_hw *hw = hisi_hba->hw; const struct hisi_sas_debugfs_reg *global = - hisi_hba->hw->debugfs_reg_global; + hw->debugfs_reg_array[DEBUGFS_GLOBAL]; int i; for (i = 0; i < global->count; i++, databuf++) *databuf = global->read_global_reg(hisi_hba, 4 * i); } +static void hisi_sas_debugfs_snapshot_axi_reg(struct hisi_hba *hisi_hba) +{ + u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_AXI]; + const struct hisi_sas_hw *hw = hisi_hba->hw; + const struct hisi_sas_debugfs_reg *axi = + hw->debugfs_reg_array[DEBUGFS_AXI]; + int i; + + for (i = 0; i < axi->count; i++, databuf++) + *databuf = axi->read_global_reg(hisi_hba, + 4 * i + axi->base_off); +} + +static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba) +{ + u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_RAS]; + const struct hisi_sas_hw *hw = hisi_hba->hw; + const struct hisi_sas_debugfs_reg *ras = + hw->debugfs_reg_array[DEBUGFS_RAS]; + int i; + + for (i = 0; i < ras->count; i++, databuf++) + *databuf = ras->read_global_reg(hisi_hba, + 4 * i + ras->base_off); +} + static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) { void *cachebuf = hisi_hba->debugfs_itct_cache; @@ -2836,9 +2863,9 @@ static int hisi_sas_debugfs_global_show(struct seq_file *s, void *p) { struct hisi_hba *hisi_hba = s->private; const struct hisi_sas_hw *hw = hisi_hba->hw; - const struct hisi_sas_debugfs_reg *reg_global = hw->debugfs_reg_global; + const void *reg_global = hw->debugfs_reg_array[DEBUGFS_GLOBAL]; - hisi_sas_debugfs_print_reg(hisi_hba->debugfs_global_reg, + hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_GLOBAL], reg_global, s); return 0; @@ -2858,6 +2885,58 @@ static const struct file_operations hisi_sas_debugfs_global_fops = { .owner = THIS_MODULE, }; +static int hisi_sas_debugfs_axi_show(struct seq_file *s, void *p) +{ + struct hisi_hba *hisi_hba = s->private; + const struct hisi_sas_hw *hw = hisi_hba->hw; + const void *reg_axi = hw->debugfs_reg_array[DEBUGFS_AXI]; + + hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_AXI], + reg_axi, s); + + return 0; +} + +static int hisi_sas_debugfs_axi_open(struct inode *inode, struct file *filp) +{ + return single_open(filp, hisi_sas_debugfs_axi_show, + inode->i_private); +} + +static const struct file_operations hisi_sas_debugfs_axi_fops = { + .open = hisi_sas_debugfs_axi_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int hisi_sas_debugfs_ras_show(struct seq_file *s, void *p) +{ + struct hisi_hba *hisi_hba = s->private; + const struct hisi_sas_hw *hw = hisi_hba->hw; + const void *reg_ras = hw->debugfs_reg_array[DEBUGFS_RAS]; + + hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_RAS], + reg_ras, s); + + return 0; +} + +static int hisi_sas_debugfs_ras_open(struct inode *inode, struct file *filp) +{ + return single_open(filp, hisi_sas_debugfs_ras_show, + inode->i_private); +} + +static const struct file_operations hisi_sas_debugfs_ras_fops = { + .open = hisi_sas_debugfs_ras_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + static int hisi_sas_debugfs_port_show(struct seq_file *s, void *p) { struct hisi_sas_phy *phy = s->private; @@ -3192,6 +3271,12 @@ static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) debugfs_create_file("itct_cache", 0400, dump_dentry, hisi_hba, &hisi_sas_debugfs_itct_cache_fops); + debugfs_create_file("axi", 0400, dump_dentry, hisi_hba, + &hisi_sas_debugfs_axi_fops); + + debugfs_create_file("ras", 0400, dump_dentry, hisi_hba, + &hisi_sas_debugfs_ras_fops); + return; } @@ -3201,6 +3286,8 @@ static void hisi_sas_debugfs_snapshot_regs(struct hisi_hba *hisi_hba) hisi_sas_debugfs_snapshot_global_reg(hisi_hba); hisi_sas_debugfs_snapshot_port_reg(hisi_hba); + hisi_sas_debugfs_snapshot_axi_reg(hisi_hba); + hisi_sas_debugfs_snapshot_ras_reg(hisi_hba); hisi_sas_debugfs_snapshot_cq_reg(hisi_hba); hisi_sas_debugfs_snapshot_dq_reg(hisi_hba); hisi_sas_debugfs_snapshot_itct_reg(hisi_hba); @@ -3257,6 +3344,7 @@ EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler); void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) { int max_command_entries = HISI_SAS_MAX_COMMANDS; + const struct hisi_sas_hw *hw = hisi_hba->hw; struct device *dev = hisi_hba->dev; int p, i, c, d; size_t sz; @@ -3268,16 +3356,14 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) hisi_hba, &hisi_sas_debugfs_trigger_dump_fops); - /* Alloc buffer for global */ - sz = hisi_hba->hw->debugfs_reg_global->count * 4; - hisi_hba->debugfs_global_reg = - devm_kmalloc(dev, sz, GFP_KERNEL); + sz = hw->debugfs_reg_array[DEBUGFS_GLOBAL]->count * 4; + hisi_hba->debugfs_regs[DEBUGFS_GLOBAL] = + devm_kmalloc(dev, sz, GFP_KERNEL); - if (!hisi_hba->debugfs_global_reg) + if (!hisi_hba->debugfs_regs[DEBUGFS_GLOBAL]) goto fail_global; - /* Alloc buffer for port */ - sz = hisi_hba->hw->debugfs_reg_port->count * 4; + sz = hw->debugfs_reg_port->count * 4; for (p = 0; p < hisi_hba->n_phy; p++) { hisi_hba->debugfs_port_reg[p] = devm_kmalloc(dev, sz, GFP_KERNEL); @@ -3286,8 +3372,21 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) goto fail_port; } - /* Alloc buffer for cq */ - sz = hisi_hba->hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS; + sz = hw->debugfs_reg_array[DEBUGFS_AXI]->count * 4; + hisi_hba->debugfs_regs[DEBUGFS_AXI] = + devm_kmalloc(dev, sz, GFP_KERNEL); + + if (!hisi_hba->debugfs_regs[DEBUGFS_AXI]) + goto fail_axi; + + sz = hw->debugfs_reg_array[DEBUGFS_RAS]->count * 4; + hisi_hba->debugfs_regs[DEBUGFS_RAS] = + devm_kmalloc(dev, sz, GFP_KERNEL); + + if (!hisi_hba->debugfs_regs[DEBUGFS_RAS]) + goto fail_ras; + + sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS; for (c = 0; c < hisi_hba->queue_count; c++) { hisi_hba->debugfs_complete_hdr[c] = devm_kmalloc(dev, sz, GFP_KERNEL); @@ -3296,7 +3395,6 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) goto fail_cq; } - /* Alloc buffer for dq */ sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS; for (d = 0; d < hisi_hba->queue_count; d++) { hisi_hba->debugfs_cmd_hdr[d] = @@ -3346,10 +3444,14 @@ fail_iost_dq: fail_cq: for (i = 0; i < c; i++) devm_kfree(dev, hisi_hba->debugfs_complete_hdr[i]); + devm_kfree(dev, hisi_hba->debugfs_regs[DEBUGFS_RAS]); +fail_ras: + devm_kfree(dev, hisi_hba->debugfs_regs[DEBUGFS_AXI]); +fail_axi: fail_port: for (i = 0; i < p; i++) devm_kfree(dev, hisi_hba->debugfs_port_reg[i]); - devm_kfree(dev, hisi_hba->debugfs_global_reg); + devm_kfree(dev, hisi_hba->debugfs_regs[DEBUGFS_GLOBAL]); fail_global: debugfs_remove_recursive(hisi_hba->debugfs_dir); dev_dbg(dev, "failed to init debugfs!\n"); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index c8ca6ead639b..072a39d5c4ad 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2857,6 +2857,38 @@ static const struct hisi_sas_debugfs_reg debugfs_global_reg = { .read_global_reg = hisi_sas_read32, }; +static const struct hisi_sas_debugfs_reg_lu debugfs_axi_reg_lu[] = { + HISI_SAS_DEBUGFS_REG(AM_CFG_MAX_TRANS), + HISI_SAS_DEBUGFS_REG(AM_CFG_SINGLE_PORT_MAX_TRANS), + HISI_SAS_DEBUGFS_REG(AXI_CFG), + HISI_SAS_DEBUGFS_REG(AM_ROB_ECC_ERR_ADDR), + {} +}; + +static const struct hisi_sas_debugfs_reg debugfs_axi_reg = { + .lu = debugfs_axi_reg_lu, + .count = 0x61, + .base_off = AXI_MASTER_CFG_BASE, + .read_global_reg = hisi_sas_read32, +}; + +static const struct hisi_sas_debugfs_reg_lu debugfs_ras_reg_lu[] = { + HISI_SAS_DEBUGFS_REG(SAS_RAS_INTR1), + HISI_SAS_DEBUGFS_REG(SAS_RAS_INTR0_MASK), + HISI_SAS_DEBUGFS_REG(SAS_RAS_INTR1_MASK), + HISI_SAS_DEBUGFS_REG(CFG_SAS_RAS_INTR_MASK), + HISI_SAS_DEBUGFS_REG(SAS_RAS_INTR2), + HISI_SAS_DEBUGFS_REG(SAS_RAS_INTR2_MASK), + {} +}; + +static const struct hisi_sas_debugfs_reg debugfs_ras_reg = { + .lu = debugfs_ras_reg_lu, + .count = 0x10, + .base_off = RAS_BASE, + .read_global_reg = hisi_sas_read32, +}; + static void debugfs_snapshot_prepare_v3_hw(struct hisi_hba *hisi_hba) { struct device *dev = hisi_hba->dev; @@ -2956,7 +2988,9 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = { .get_events = phy_get_events_v3_hw, .write_gpio = write_gpio_v3_hw, .wait_cmds_complete_timeout = wait_cmds_complete_timeout_v3_hw, - .debugfs_reg_global = &debugfs_global_reg, + .debugfs_reg_array[DEBUGFS_GLOBAL] = &debugfs_global_reg, + .debugfs_reg_array[DEBUGFS_AXI] = &debugfs_axi_reg, + .debugfs_reg_array[DEBUGFS_RAS] = &debugfs_ras_reg, .debugfs_reg_port = &debugfs_port_reg, .snapshot_prepare = debugfs_snapshot_prepare_v3_hw, .snapshot_restore = debugfs_snapshot_restore_v3_hw, -- cgit v1.2.3-59-g8ed1b From 445ee2de112a18419aeae72fdae4221cd90f2948 Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Mon, 5 Aug 2019 21:48:03 +0800 Subject: scsi: hisi_sas: Fix out of bound at debug_I_T_nexus_reset() Fix a possible out-of-bounds access in hisi_sas_debug_I_T_nexus_reset(). Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 04b3b0040059..02ad91c01a44 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1762,13 +1762,14 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) struct hisi_sas_device *sas_dev = device->lldd_dev; struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); struct sas_ha_struct *sas_ha = &hisi_hba->sha; - struct asd_sas_phy *sas_phy = sas_ha->sas_phy[local_phy->number]; - struct hisi_sas_phy *phy = container_of(sas_phy, - struct hisi_sas_phy, sas_phy); DECLARE_COMPLETION_ONSTACK(phyreset); int rc, reset_type; if (scsi_is_sas_phy_local(local_phy)) { + struct asd_sas_phy *sas_phy = + sas_ha->sas_phy[local_phy->number]; + struct hisi_sas_phy *phy = + container_of(sas_phy, struct hisi_sas_phy, sas_phy); phy->in_reset = 1; phy->reset_completion = &phyreset; } @@ -1780,6 +1781,10 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) sas_put_local_phy(local_phy); if (scsi_is_sas_phy_local(local_phy)) { + struct asd_sas_phy *sas_phy = + sas_ha->sas_phy[local_phy->number]; + struct hisi_sas_phy *phy = + container_of(sas_phy, struct hisi_sas_phy, sas_phy); int ret = wait_for_completion_timeout(&phyreset, 2 * HZ); unsigned long flags; -- cgit v1.2.3-59-g8ed1b From d380f55503ed28461422546900baedc3b512b4b7 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Mon, 5 Aug 2019 21:48:04 +0800 Subject: scsi: hisi_sas: Don't bother clearing status buffer IU in task prep For struct hisi_sas_status_buffer, it contains struct hisi_sas_err_record and iu[1024]. The struct iu[1024] will be filled fully by the response of disks, so it is not need to initialize them to 0, but for the struct hisi_sas_err_record, SAS controller only fill some fields of hisi_sas_err_record according to hw designer, so it should be initialised to 0. After the change, cpu utilization percentage of memset() is changed from 1.7% to 0.12%. Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 02ad91c01a44..7efa8dfa0cc1 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -545,7 +545,8 @@ static int hisi_sas_task_prep(struct sas_task *task, memset(slot->cmd_hdr, 0, sizeof(struct hisi_sas_cmd_hdr)); memset(hisi_sas_cmd_hdr_addr_mem(slot), 0, HISI_SAS_COMMAND_TABLE_SZ); - memset(hisi_sas_status_buf_addr_mem(slot), 0, HISI_SAS_STATUS_BUF_SZ); + memset(hisi_sas_status_buf_addr_mem(slot), 0, + sizeof(struct hisi_sas_err_record)); switch (task->task_proto) { case SAS_PROTOCOL_SMP: @@ -2005,7 +2006,8 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id, memset(slot->cmd_hdr, 0, sizeof(struct hisi_sas_cmd_hdr)); memset(hisi_sas_cmd_hdr_addr_mem(slot), 0, HISI_SAS_COMMAND_TABLE_SZ); - memset(hisi_sas_status_buf_addr_mem(slot), 0, HISI_SAS_STATUS_BUF_SZ); + memset(hisi_sas_status_buf_addr_mem(slot), 0, + sizeof(struct hisi_sas_err_record)); hisi_sas_task_prep_abort(hisi_hba, slot, device_id, abort_flag, task_tag); -- cgit v1.2.3-59-g8ed1b From 599aefc81effaaf78c02d44461f7157f22ee3b1d Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Mon, 5 Aug 2019 21:48:05 +0800 Subject: scsi: hisi_sas: Make slot buf minimum allocation of PAGE_SIZE For a system with PAGE_SIZE of 16K or 64K, the size every time we want to alloc may be small like 4K, but for function dmam_alloc_coherent(), the least size it allocates is PAGE_SIZE, so it will waste much memory for the situation. To solve the issue, limit the minimum allocation size of slot buf to PAGE_SIZE. Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 7efa8dfa0cc1..39ae69e42d26 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -2389,7 +2389,7 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba) else sz_slot_buf_ru = sizeof(struct hisi_sas_slot_buf_table); sz_slot_buf_ru = roundup(sz_slot_buf_ru, 64); - s = lcm(max_command_entries_ru, sz_slot_buf_ru); + s = max(lcm(max_command_entries_ru, sz_slot_buf_ru), PAGE_SIZE); blk_cnt = (max_command_entries_ru * sz_slot_buf_ru) / s; slots_per_blk = s / sz_slot_buf_ru; -- cgit v1.2.3-59-g8ed1b From 1c003146c64bb3ae86f1a08d73a7e4551d7cd04a Mon Sep 17 00:00:00 2001 From: John Garry Date: Mon, 5 Aug 2019 21:48:06 +0800 Subject: scsi: hisi_sas: Drop kmap_atomic() in SMP command completion The call to kmap_atomic() in the SMP command completion code is unnecessary, since kmap() is only really concerned with highmem, which is not relevant on arm64. The controller only finds itself in arm64 systems. Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 4 +--- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 +--- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index b13cbc64d2a9..015bf00a20e6 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1275,11 +1275,10 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba, } case SAS_PROTOCOL_SMP: { - void *to; struct scatterlist *sg_resp = &task->smp_task.smp_resp; + void *to = page_address(sg_page(sg_resp)); ts->stat = SAM_STAT_GOOD; - to = kmap_atomic(sg_page(sg_resp)); dma_unmap_sg(dev, &task->smp_task.smp_resp, 1, DMA_FROM_DEVICE); @@ -1289,7 +1288,6 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba, hisi_sas_status_buf_addr_mem(slot) + sizeof(struct hisi_sas_err_record), sg_dma_len(sg_resp)); - kunmap_atomic(to); break; } case SAS_PROTOCOL_SATA: diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index de33e31cd88a..c3cf3b77c655 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2419,10 +2419,9 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) case SAS_PROTOCOL_SMP: { struct scatterlist *sg_resp = &task->smp_task.smp_resp; - void *to; + void *to = page_address(sg_page(sg_resp)); ts->stat = SAM_STAT_GOOD; - to = kmap_atomic(sg_page(sg_resp)); dma_unmap_sg(dev, &task->smp_task.smp_resp, 1, DMA_FROM_DEVICE); @@ -2432,7 +2431,6 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) hisi_sas_status_buf_addr_mem(slot) + sizeof(struct hisi_sas_err_record), sg_dma_len(sg_resp)); - kunmap_atomic(to); break; } case SAS_PROTOCOL_SATA: diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 072a39d5c4ad..fcb2ef5f24b9 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2211,10 +2211,9 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) } case SAS_PROTOCOL_SMP: { struct scatterlist *sg_resp = &task->smp_task.smp_resp; - void *to; + void *to = page_address(sg_page(sg_resp)); ts->stat = SAM_STAT_GOOD; - to = kmap_atomic(sg_page(sg_resp)); dma_unmap_sg(dev, &task->smp_task.smp_resp, 1, DMA_FROM_DEVICE); @@ -2224,7 +2223,6 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) hisi_sas_status_buf_addr_mem(slot) + sizeof(struct hisi_sas_err_record), sg_dma_len(sg_resp)); - kunmap_atomic(to); break; } case SAS_PROTOCOL_SATA: -- cgit v1.2.3-59-g8ed1b From 5f6c32d7ce576e9275ab2e9b21192f5cd5f24273 Mon Sep 17 00:00:00 2001 From: John Garry Date: Mon, 5 Aug 2019 21:48:07 +0800 Subject: scsi: hisi_sas: Drop SMP resp frame DMA mapping The SMP frame response is written to the command table and not the SMP response pointer from libsas, so don't bother DMA mapping (and unmapping) the SMP response from libsas. Suggested-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 28 +++++++--------------------- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 4 +--- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 +--- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 +--- 4 files changed, 10 insertions(+), 30 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 39ae69e42d26..a2255701b50b 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -300,7 +300,7 @@ static void hisi_sas_task_prep_abort(struct hisi_hba *hisi_hba, static void hisi_sas_dma_unmap(struct hisi_hba *hisi_hba, struct sas_task *task, int n_elem, - int n_elem_req, int n_elem_resp) + int n_elem_req) { struct device *dev = hisi_hba->dev; @@ -314,16 +314,13 @@ static void hisi_sas_dma_unmap(struct hisi_hba *hisi_hba, if (n_elem_req) dma_unmap_sg(dev, &task->smp_task.smp_req, 1, DMA_TO_DEVICE); - if (n_elem_resp) - dma_unmap_sg(dev, &task->smp_task.smp_resp, - 1, DMA_FROM_DEVICE); } } } static int hisi_sas_dma_map(struct hisi_hba *hisi_hba, struct sas_task *task, int *n_elem, - int *n_elem_req, int *n_elem_resp) + int *n_elem_req) { struct device *dev = hisi_hba->dev; int rc; @@ -331,7 +328,7 @@ static int hisi_sas_dma_map(struct hisi_hba *hisi_hba, if (sas_protocol_ata(task->task_proto)) { *n_elem = task->num_scatter; } else { - unsigned int req_len, resp_len; + unsigned int req_len; if (task->num_scatter) { *n_elem = dma_map_sg(dev, task->scatter, @@ -352,17 +349,6 @@ static int hisi_sas_dma_map(struct hisi_hba *hisi_hba, rc = -EINVAL; goto err_out_dma_unmap; } - *n_elem_resp = dma_map_sg(dev, &task->smp_task.smp_resp, - 1, DMA_FROM_DEVICE); - if (!*n_elem_resp) { - rc = -ENOMEM; - goto err_out_dma_unmap; - } - resp_len = sg_dma_len(&task->smp_task.smp_resp); - if (resp_len & 0x3) { - rc = -EINVAL; - goto err_out_dma_unmap; - } } } @@ -377,7 +363,7 @@ static int hisi_sas_dma_map(struct hisi_hba *hisi_hba, err_out_dma_unmap: /* It would be better to call dma_unmap_sg() here, but it's messy */ hisi_sas_dma_unmap(hisi_hba, task, *n_elem, - *n_elem_req, *n_elem_resp); + *n_elem_req); prep_out: return rc; } @@ -449,7 +435,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct asd_sas_port *sas_port = device->port; struct device *dev = hisi_hba->dev; int dlvry_queue_slot, dlvry_queue, rc, slot_idx; - int n_elem = 0, n_elem_dif = 0, n_elem_req = 0, n_elem_resp = 0; + int n_elem = 0, n_elem_dif = 0, n_elem_req = 0; struct hisi_sas_dq *dq; unsigned long flags; int wr_q_index; @@ -485,7 +471,7 @@ static int hisi_sas_task_prep(struct sas_task *task, } rc = hisi_sas_dma_map(hisi_hba, task, &n_elem, - &n_elem_req, &n_elem_resp); + &n_elem_req); if (rc < 0) goto prep_out; @@ -580,7 +566,7 @@ err_out_dif_dma_unmap: hisi_sas_dif_dma_unmap(hisi_hba, task, n_elem_dif); err_out_dma_unmap: hisi_sas_dma_unmap(hisi_hba, task, n_elem, - n_elem_req, n_elem_resp); + n_elem_req); prep_out: dev_err(dev, "task prep: failed[%d]!\n", rc); return rc; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 015bf00a20e6..16974421cb31 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1280,14 +1280,12 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba, ts->stat = SAM_STAT_GOOD; - dma_unmap_sg(dev, &task->smp_task.smp_resp, 1, - DMA_FROM_DEVICE); dma_unmap_sg(dev, &task->smp_task.smp_req, 1, DMA_TO_DEVICE); memcpy(to + sg_resp->offset, hisi_sas_status_buf_addr_mem(slot) + sizeof(struct hisi_sas_err_record), - sg_dma_len(sg_resp)); + sg_resp->length); break; } case SAS_PROTOCOL_SATA: diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index c3cf3b77c655..9955b4fbdd0d 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2423,14 +2423,12 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) ts->stat = SAM_STAT_GOOD; - dma_unmap_sg(dev, &task->smp_task.smp_resp, 1, - DMA_FROM_DEVICE); dma_unmap_sg(dev, &task->smp_task.smp_req, 1, DMA_TO_DEVICE); memcpy(to + sg_resp->offset, hisi_sas_status_buf_addr_mem(slot) + sizeof(struct hisi_sas_err_record), - sg_dma_len(sg_resp)); + sg_resp->length); break; } case SAS_PROTOCOL_SATA: diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index fcb2ef5f24b9..95a298d4e211 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2215,14 +2215,12 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) ts->stat = SAM_STAT_GOOD; - dma_unmap_sg(dev, &task->smp_task.smp_resp, 1, - DMA_FROM_DEVICE); dma_unmap_sg(dev, &task->smp_task.smp_req, 1, DMA_TO_DEVICE); memcpy(to + sg_resp->offset, hisi_sas_status_buf_addr_mem(slot) + sizeof(struct hisi_sas_err_record), - sg_dma_len(sg_resp)); + sg_resp->length); break; } case SAS_PROTOCOL_SATA: -- cgit v1.2.3-59-g8ed1b From e16963f378faf82d307cad2796953f198497c614 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Mon, 5 Aug 2019 21:48:08 +0800 Subject: scsi: hisi_sas: Drop free_irq() when devm_request_irq() failed It will free irq automatically if devm_request_irq() failed, so drop free_irq() if devm_request_irq() failed. Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 34 +++++++--------------------------- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 21 ++++----------------- 2 files changed, 11 insertions(+), 44 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 9955b4fbdd0d..a3f8c51b3500 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -3304,8 +3304,8 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) { struct platform_device *pdev = hisi_hba->platform_dev; struct device *dev = &pdev->dev; - int irq, rc, irq_map[128]; - int i, phy_no, fatal_no, queue_no, k; + int irq, rc = 0, irq_map[128]; + int i, phy_no, fatal_no, queue_no; for (i = 0; i < 128; i++) irq_map[i] = platform_get_irq(pdev, i); @@ -3318,7 +3318,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) dev_err(dev, "irq init: could not request phy interrupt %d, rc=%d\n", irq, rc); rc = -ENOENT; - goto free_phy_int_irqs; + goto err_out; } } @@ -3332,7 +3332,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) dev_err(dev, "irq init: could not request sata interrupt %d, rc=%d\n", irq, rc); rc = -ENOENT; - goto free_sata_int_irqs; + goto err_out; } } @@ -3344,7 +3344,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) dev_err(dev, "irq init: could not request fatal interrupt %d, rc=%d\n", irq, rc); rc = -ENOENT; - goto free_fatal_int_irqs; + goto err_out; } } @@ -3359,34 +3359,14 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) dev_err(dev, "irq init: could not request cq interrupt %d, rc=%d\n", irq, rc); rc = -ENOENT; - goto free_cq_int_irqs; + goto err_out; } tasklet_init(t, cq_tasklet_v2_hw, (unsigned long)cq); } hisi_hba->cq_nvecs = hisi_hba->queue_count; - return 0; - -free_cq_int_irqs: - for (k = 0; k < queue_no; k++) { - struct hisi_sas_cq *cq = &hisi_hba->cq[k]; - - free_irq(irq_map[k + 96], cq); - tasklet_kill(&cq->tasklet); - } -free_fatal_int_irqs: - for (k = 0; k < fatal_no; k++) - free_irq(irq_map[k + 81], hisi_hba); -free_sata_int_irqs: - for (k = 0; k < phy_no; k++) { - struct hisi_sas_phy *phy = &hisi_hba->phy[k]; - - free_irq(irq_map[k + 72], phy); - } -free_phy_int_irqs: - for (k = 0; k < i; k++) - free_irq(irq_map[k + 1], hisi_hba); +err_out: return rc; } diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 95a298d4e211..3cc53e5b92f2 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2351,8 +2351,7 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) { struct device *dev = hisi_hba->dev; struct pci_dev *pdev = hisi_hba->pci_dev; - int vectors, rc; - int i, k; + int vectors, rc, i; int max_msi = HISI_SAS_MSI_COUNT_V3_HW, min_msi; if (auto_affine_msi_experimental) { @@ -2400,7 +2399,7 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) if (rc) { dev_err(dev, "could not request chnl interrupt, rc=%d\n", rc); rc = -ENOENT; - goto free_phy_irq; + goto free_irq_vectors; } rc = devm_request_irq(dev, pci_irq_vector(pdev, 11), @@ -2409,7 +2408,7 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) if (rc) { dev_err(dev, "could not request fatal interrupt, rc=%d\n", rc); rc = -ENOENT; - goto free_chnl_interrupt; + goto free_irq_vectors; } /* Init tasklets for cq only */ @@ -2426,7 +2425,7 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) dev_err(dev, "could not request cq%d interrupt, rc=%d\n", i, rc); rc = -ENOENT; - goto free_cq_irqs; + goto free_irq_vectors; } tasklet_init(t, cq_tasklet_v3_hw, (unsigned long)cq); @@ -2434,18 +2433,6 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) return 0; -free_cq_irqs: - for (k = 0; k < i; k++) { - struct hisi_sas_cq *cq = &hisi_hba->cq[k]; - int nr = hisi_sas_intr_conv ? 16 : 16 + k; - - free_irq(pci_irq_vector(pdev, nr), cq); - } - free_irq(pci_irq_vector(pdev, 11), hisi_hba); -free_chnl_interrupt: - free_irq(pci_irq_vector(pdev, 2), hisi_hba); -free_phy_irq: - free_irq(pci_irq_vector(pdev, 1), hisi_hba); free_irq_vectors: pci_free_irq_vectors(pdev); return rc; -- cgit v1.2.3-59-g8ed1b From 7bf18e849d80e1beb118fd6d3bd5ccfcb1267d09 Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Mon, 5 Aug 2019 21:48:09 +0800 Subject: scsi: hisi_sas: Modify return type of debugfs functions For functions which always return 0, which is never checked, make to return void. Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 51 +++++++++++++---------------------- 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index a2255701b50b..be15280343d1 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -2956,8 +2956,8 @@ static const struct file_operations hisi_sas_debugfs_port_fops = { .owner = THIS_MODULE, }; -static int hisi_sas_show_row_64(struct seq_file *s, int index, - int sz, __le64 *ptr) +static void hisi_sas_show_row_64(struct seq_file *s, int index, + int sz, __le64 *ptr) { int i; @@ -2970,12 +2970,10 @@ static int hisi_sas_show_row_64(struct seq_file *s, int index, } seq_puts(s, "\n"); - - return 0; } -static int hisi_sas_show_row_32(struct seq_file *s, int index, - int sz, __le32 *ptr) +static void hisi_sas_show_row_32(struct seq_file *s, int index, + int sz, __le32 *ptr) { int i; @@ -2987,11 +2985,9 @@ static int hisi_sas_show_row_32(struct seq_file *s, int index, seq_puts(s, "\n\t"); } seq_puts(s, "\n"); - - return 0; } -static int hisi_sas_cq_show_slot(struct seq_file *s, int slot, void *cq_ptr) +static void hisi_sas_cq_show_slot(struct seq_file *s, int slot, void *cq_ptr) { struct hisi_sas_cq *cq = cq_ptr; struct hisi_hba *hisi_hba = cq->hisi_hba; @@ -2999,20 +2995,18 @@ static int hisi_sas_cq_show_slot(struct seq_file *s, int slot, void *cq_ptr) __le32 *complete_hdr = complete_queue + (hisi_hba->hw->complete_hdr_size * slot); - return hisi_sas_show_row_32(s, slot, - hisi_hba->hw->complete_hdr_size, - complete_hdr); + hisi_sas_show_row_32(s, slot, + hisi_hba->hw->complete_hdr_size, + complete_hdr); } static int hisi_sas_debugfs_cq_show(struct seq_file *s, void *p) { struct hisi_sas_cq *cq = s->private; - int slot, ret; + int slot; for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) { - ret = hisi_sas_cq_show_slot(s, slot, cq); - if (ret) - return ret; + hisi_sas_cq_show_slot(s, slot, cq); } return 0; } @@ -3030,7 +3024,7 @@ static const struct file_operations hisi_sas_debugfs_cq_fops = { .owner = THIS_MODULE, }; -static int hisi_sas_dq_show_slot(struct seq_file *s, int slot, void *dq_ptr) +static void hisi_sas_dq_show_slot(struct seq_file *s, int slot, void *dq_ptr) { struct hisi_sas_dq *dq = dq_ptr; struct hisi_hba *hisi_hba = dq->hisi_hba; @@ -3038,18 +3032,15 @@ static int hisi_sas_dq_show_slot(struct seq_file *s, int slot, void *dq_ptr) __le32 *cmd_hdr = cmd_queue + sizeof(struct hisi_sas_cmd_hdr) * slot; - return hisi_sas_show_row_32(s, slot, sizeof(struct hisi_sas_cmd_hdr), - cmd_hdr); + hisi_sas_show_row_32(s, slot, sizeof(struct hisi_sas_cmd_hdr), cmd_hdr); } static int hisi_sas_debugfs_dq_show(struct seq_file *s, void *p) { - int slot, ret; + int slot; for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) { - ret = hisi_sas_dq_show_slot(s, slot, s->private); - if (ret) - return ret; + hisi_sas_dq_show_slot(s, slot, s->private); } return 0; } @@ -3071,15 +3062,12 @@ static int hisi_sas_debugfs_iost_show(struct seq_file *s, void *p) { struct hisi_hba *hisi_hba = s->private; struct hisi_sas_iost *debugfs_iost = hisi_hba->debugfs_iost; - int i, ret, max_command_entries = HISI_SAS_MAX_COMMANDS; + int i, max_command_entries = HISI_SAS_MAX_COMMANDS; for (i = 0; i < max_command_entries; i++, debugfs_iost++) { __le64 *iost = &debugfs_iost->qw0; - ret = hisi_sas_show_row_64(s, i, sizeof(*debugfs_iost), - iost); - if (ret) - return ret; + hisi_sas_show_row_64(s, i, sizeof(*debugfs_iost), iost); } return 0; @@ -3140,17 +3128,14 @@ static const struct file_operations hisi_sas_debugfs_iost_cache_fops = { static int hisi_sas_debugfs_itct_show(struct seq_file *s, void *p) { - int i, ret; + int i; struct hisi_hba *hisi_hba = s->private; struct hisi_sas_itct *debugfs_itct = hisi_hba->debugfs_itct; for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, debugfs_itct++) { __le64 *itct = &debugfs_itct->qw0; - ret = hisi_sas_show_row_64(s, i, sizeof(*debugfs_itct), - itct); - if (ret) - return ret; + hisi_sas_show_row_64(s, i, sizeof(*debugfs_itct), itct); } return 0; -- cgit v1.2.3-59-g8ed1b From a07b48766c5232b98154f68010512a9269f2841e Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Mon, 5 Aug 2019 21:48:10 +0800 Subject: scsi: hisi_sas: Remove some unnecessary code Remove some unnecessary code, including: - Explicit zeroing of memory allocated for dmam_alloc_coherent() - Some duplicated code - Some redundant masking Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 5 ++--- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 5 +---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index be15280343d1..e1c52811f4c7 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -2358,7 +2358,7 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba) s = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct); hisi_hba->itct = dmam_alloc_coherent(dev, s, &hisi_hba->itct_dma, - GFP_KERNEL | __GFP_ZERO); + GFP_KERNEL); if (!hisi_hba->itct) goto err_out; @@ -2385,7 +2385,7 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba) void *buf; buf = dmam_alloc_coherent(dev, s, &buf_dma, - GFP_KERNEL | __GFP_ZERO); + GFP_KERNEL); if (!buf) goto err_out; @@ -2434,7 +2434,6 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba) GFP_KERNEL); if (!hisi_hba->sata_breakpoint) goto err_out; - hisi_sas_init_mem(hisi_hba); hisi_sas_slot_index_init(hisi_hba); hisi_hba->last_slot_index = HISI_SAS_UNRESERVED_IPTT; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 3cc53e5b92f2..db8c7e4b1954 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -1914,7 +1914,7 @@ static void fatal_ecc_int_v3_hw(struct hisi_hba *hisi_hba) u32 irq_value, irq_msk; irq_msk = hisi_sas_read32(hisi_hba, SAS_ECC_INTR_MSK); - hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, irq_msk | 0xffffffff); + hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, 0xffffffff); irq_value = hisi_sas_read32(hisi_hba, SAS_ECC_INTR); if (irq_value) @@ -3008,8 +3008,6 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev) else hisi_hba->prot_mask = prot_mask; - timer_setup(&hisi_hba->timer, NULL, 0); - if (hisi_sas_get_fw_info(hisi_hba) < 0) goto err_out; @@ -3099,7 +3097,6 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) sha->lldd_module = THIS_MODULE; sha->sas_addr = &hisi_hba->sas_addr[0]; sha->num_phys = hisi_hba->n_phy; - sha->core.shost = hisi_hba->shost; for (i = 0; i < hisi_hba->n_phy; i++) { sha->sas_phy[i] = &hisi_hba->phy[i].sas_phy; -- cgit v1.2.3-59-g8ed1b From e7513f666bc73c357805df498df34179c8b4fc9b Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Mon, 5 Aug 2019 21:48:11 +0800 Subject: scsi: hisi_sas: replace "%p" with "%pK" The format specifier "%p" can leak kernel address, and use "%pK" instead. Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 2 +- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 6 +++--- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index e1c52811f4c7..acb87b4f9622 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -2102,7 +2102,7 @@ _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, } exit: - dev_dbg(dev, "internal task abort: task to dev %016llx task=%p resp: 0x%x sts 0x%x\n", + dev_dbg(dev, "internal task abort: task to dev %016llx task=%pK resp: 0x%x sts 0x%x\n", SAS_ADDR(device->sas_addr), task, task->task_status.resp, /* 0 is complete, -1 is undelivered */ task->task_status.stat); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index a3f8c51b3500..fba4fcad4735 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2393,7 +2393,7 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) slot_err_v2_hw(hisi_hba, task, slot, 2); if (ts->stat != SAS_DATA_UNDERRUN) - dev_info(dev, "erroneous completion iptt=%d task=%p dev id=%d CQ hdr: 0x%x 0x%x 0x%x 0x%x Error info: 0x%x 0x%x 0x%x 0x%x\n", + dev_info(dev, "erroneous completion iptt=%d task=%pK dev id=%d CQ hdr: 0x%x 0x%x 0x%x 0x%x Error info: 0x%x 0x%x 0x%x 0x%x\n", slot->idx, task, sas_dev->device_id, complete_hdr->dw0, complete_hdr->dw1, complete_hdr->act, complete_hdr->dw3, @@ -2455,7 +2455,7 @@ out: spin_lock_irqsave(&task->task_state_lock, flags); if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { spin_unlock_irqrestore(&task->task_state_lock, flags); - dev_info(dev, "slot complete: task(%p) aborted\n", task); + dev_info(dev, "slot complete: task(%pK) aborted\n", task); return SAS_ABORTED_TASK; } task->task_state_flags |= SAS_TASK_STATE_DONE; @@ -2466,7 +2466,7 @@ out: spin_lock_irqsave(&device->done_lock, flags); if (test_bit(SAS_HA_FROZEN, &ha->state)) { spin_unlock_irqrestore(&device->done_lock, flags); - dev_info(dev, "slot complete: task(%p) ignored\n", + dev_info(dev, "slot complete: task(%pK) ignored\n", task); return sts; } diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index db8c7e4b1954..2adb5c93bd81 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2190,7 +2190,7 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) slot_err_v3_hw(hisi_hba, task, slot); if (ts->stat != SAS_DATA_UNDERRUN) - dev_info(dev, "erroneous completion iptt=%d task=%p dev id=%d CQ hdr: 0x%x 0x%x 0x%x 0x%x Error info: 0x%x 0x%x 0x%x 0x%x\n", + dev_info(dev, "erroneous completion iptt=%d task=%pK dev id=%d CQ hdr: 0x%x 0x%x 0x%x 0x%x Error info: 0x%x 0x%x 0x%x 0x%x\n", slot->idx, task, sas_dev->device_id, dw0, dw1, complete_hdr->act, dw3, error_info[0], error_info[1], @@ -2245,7 +2245,7 @@ out: spin_lock_irqsave(&task->task_state_lock, flags); if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { spin_unlock_irqrestore(&task->task_state_lock, flags); - dev_info(dev, "slot complete: task(%p) aborted\n", task); + dev_info(dev, "slot complete: task(%pK) aborted\n", task); return SAS_ABORTED_TASK; } task->task_state_flags |= SAS_TASK_STATE_DONE; @@ -2256,7 +2256,7 @@ out: spin_lock_irqsave(&device->done_lock, flags); if (test_bit(SAS_HA_FROZEN, &ha->state)) { spin_unlock_irqrestore(&device->done_lock, flags); - dev_info(dev, "slot complete: task(%p) ignored\n ", + dev_info(dev, "slot complete: task(%pK) ignored\n ", task); return sts; } -- cgit v1.2.3-59-g8ed1b From a5ac1f5d9a4285adf4e88ffde7ca8ae823d72441 Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Mon, 5 Aug 2019 21:48:12 +0800 Subject: scsi: hisi_sas: Consolidate internal abort calls in LU reset operation In hisi_sas_lu_reset(), we call internal abort for SAS and SATA device codepaths -> consolidate into a single call. Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index acb87b4f9622..d60eaaa4c5e8 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1829,18 +1829,18 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun) struct device *dev = hisi_hba->dev; int rc = TMF_RESP_FUNC_FAILED; + /* Clear internal IO and then lu reset */ + rc = hisi_sas_internal_task_abort(hisi_hba, device, + HISI_SAS_INT_ABT_DEV, 0); + if (rc < 0) { + dev_err(dev, "lu_reset: internal abort failed\n"); + goto out; + } + hisi_sas_dereg_device(hisi_hba, device); + if (dev_is_sata(device)) { struct sas_phy *phy; - /* Clear internal IO and then hardreset */ - rc = hisi_sas_internal_task_abort(hisi_hba, device, - HISI_SAS_INT_ABT_DEV, 0); - if (rc < 0) { - dev_err(dev, "lu_reset: internal abort failed\n"); - goto out; - } - hisi_sas_dereg_device(hisi_hba, device); - phy = sas_get_local_phy(device); rc = sas_phy_reset(phy, 1); @@ -1851,14 +1851,6 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun) } else { struct hisi_sas_tmf_task tmf_task = { .tmf = TMF_LU_RESET }; - rc = hisi_sas_internal_task_abort(hisi_hba, device, - HISI_SAS_INT_ABT_DEV, 0); - if (rc < 0) { - dev_err(dev, "lu_reset: internal abort failed\n"); - goto out; - } - hisi_sas_dereg_device(hisi_hba, device); - rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task); if (rc == TMF_RESP_FUNC_COMPLETE) hisi_sas_release_task(hisi_hba, device); -- cgit v1.2.3-59-g8ed1b From afcd609e8e7907ccfa04fef0a3adb7d60a298ed6 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 31 Jul 2019 23:22:14 +0100 Subject: scsi: pm80xx: remove redundant assignments to variable rc There are several occasions where variable rc is being initialized with a value that is never read and error is being re-assigned a little later on. Clean up the code by removing rc entirely and just returning the return value from the call to pm8001_issue_ssp_tmf Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Acked-by: Jack Wang Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_sas.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index 9453705f643a..7e48154e11c3 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -1308,28 +1308,22 @@ out: int pm8001_abort_task_set(struct domain_device *dev, u8 *lun) { - int rc = TMF_RESP_FUNC_FAILED; struct pm8001_tmf_task tmf_task; tmf_task.tmf = TMF_ABORT_TASK_SET; - rc = pm8001_issue_ssp_tmf(dev, lun, &tmf_task); - return rc; + return pm8001_issue_ssp_tmf(dev, lun, &tmf_task); } int pm8001_clear_aca(struct domain_device *dev, u8 *lun) { - int rc = TMF_RESP_FUNC_FAILED; struct pm8001_tmf_task tmf_task; tmf_task.tmf = TMF_CLEAR_ACA; - rc = pm8001_issue_ssp_tmf(dev, lun, &tmf_task); - - return rc; + return pm8001_issue_ssp_tmf(dev, lun, &tmf_task); } int pm8001_clear_task_set(struct domain_device *dev, u8 *lun) { - int rc = TMF_RESP_FUNC_FAILED; struct pm8001_tmf_task tmf_task; struct pm8001_device *pm8001_dev = dev->lldd_dev; struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); @@ -1338,7 +1332,6 @@ int pm8001_clear_task_set(struct domain_device *dev, u8 *lun) pm8001_printk("I_T_L_Q clear task set[%x]\n", pm8001_dev->device_id)); tmf_task.tmf = TMF_CLEAR_TASK_SET; - rc = pm8001_issue_ssp_tmf(dev, lun, &tmf_task); - return rc; + return pm8001_issue_ssp_tmf(dev, lun, &tmf_task); } -- cgit v1.2.3-59-g8ed1b From f23ca2cb2781102b560dbd96fe093b146fd8ec1a Mon Sep 17 00:00:00 2001 From: Suganath Prabu Date: Sat, 3 Aug 2019 09:59:46 -0400 Subject: scsi: mpt3sas: Add support for PCIe Lane margin PCIe Lane margin tool box request requires IEEE sgl's and hence driver fills the SGL field with IEEE sgl's while issuing the PCIe Lane margin ioctl request to the HBA firmware. Signed-off-by: Suganath Prabu Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index 359586027c26..b6483b7dd3f7 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -929,13 +929,14 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, Mpi2ToolboxCleanRequest_t *toolbox_request = (Mpi2ToolboxCleanRequest_t *)mpi_request; - if (toolbox_request->Tool == MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL) { + if ((toolbox_request->Tool == MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL) + || (toolbox_request->Tool == + MPI26_TOOLBOX_BACKEND_PCIE_LANE_MARGIN)) ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); - } else { + else ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); - } ioc->put_smid_default(ioc, smid); break; } -- cgit v1.2.3-59-g8ed1b From e224e03b0c6a2381ed1ea5325c846582d87d6fae Mon Sep 17 00:00:00 2001 From: Suganath Prabu Date: Sat, 3 Aug 2019 09:59:47 -0400 Subject: scsi: mpt3sas: memset request frame before reusing Driver gets a request frame from the free pool of DMA-able request frames and fill in the required information and pass the address of the frame to IOC/FW to pull the complete request frame. In certain places the driver used the request frame allocated from the free pool without completely clearing the previous data stored in it. The request contents were cleared only for the size of the new request to be issued and that left out some stale data in the unused part of the request. Though the IOC/FW is not expected to access the request beyond the specified size, it is good practice to clear complete request message frame. So reinitialize the complete request message frame with 0s before using it. Signed-off-by: Suganath Prabu Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 2 ++ drivers/scsi/mpt3sas/mpt3sas_ctl.c | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 684662888792..277f7bca76e1 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -5035,6 +5035,7 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc) _base_release_memory_pools(ioc); goto retry_allocation; } + memset(ioc->request, 0, sz); if (retry_sz) ioc_err(ioc, "request pool: dma_alloc_coherent succeed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), total(%d kb)\n", @@ -5866,6 +5867,7 @@ mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc, ioc->base_cmds.status = MPT3_CMD_PENDING; request = mpt3sas_base_get_msg_frame(ioc, smid); ioc->base_cmds.smid = smid; + memset(request, 0, ioc->request_sz); memcpy(request, mpi_request, sizeof(Mpi2SepReply_t)); init_completion(&ioc->base_cmds.done); ioc->put_smid_default(ioc, smid); diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index b6483b7dd3f7..ab78bcf9fbc6 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -715,6 +715,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, ioc->ctl_cmds.status = MPT3_CMD_PENDING; memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); request = mpt3sas_base_get_msg_frame(ioc, smid); + memset(request, 0, ioc->request_sz); memcpy(request, mpi_request, karg.data_sge_offset*4); ioc->ctl_cmds.smid = smid; data_out_sz = karg.data_out_size; -- cgit v1.2.3-59-g8ed1b From ffedeae1fa545a1d07e6827180c3923bf67af59f Mon Sep 17 00:00:00 2001 From: Suganath Prabu Date: Sat, 3 Aug 2019 09:59:48 -0400 Subject: scsi: mpt3sas: Gracefully handle online firmware update Issue: During online Firmware upgrade operations it is possible that MaxDevHandles filled in IOCFacts may change with new FW. With this we may observe kernel panics when driver try to access the pd_handles or blocking_handles buffers at offset greater than the old firmware's MaxDevHandle value. Fix: _base_check_ioc_facts_changes() looks for increase/decrease in IOCFacts attributes during online firmware upgrade and increases the pd_handles, blocking_handles, etc buffer sizes to new firmware's MaxDevHandle value if this new firmware's MaxDevHandle value is greater than the old firmware's MaxDevHandle value. Signed-off-by: Suganath Prabu Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 93 +++++++++++++++++++++++++++++++++++++ drivers/scsi/mpt3sas/mpt3sas_base.h | 2 + 2 files changed, 95 insertions(+) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 277f7bca76e1..f72933cc6622 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -7118,6 +7118,13 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) if (r) goto out_free_resources; + /* + * Copy current copy of IOCFacts in prev_fw_facts + * and it will be used during online firmware upgrade. + */ + memcpy(&ioc->prev_fw_facts, &ioc->facts, + sizeof(struct mpt3sas_facts)); + ioc->non_operational_loop = 0; ioc->got_task_abort_from_ioctl = 0; return 0; @@ -7279,6 +7286,85 @@ mpt3sas_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc) wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 10 * HZ); } +/** + * _base_check_ioc_facts_changes - Look for increase/decrease of IOCFacts + * attributes during online firmware upgrade and update the corresponding + * IOC variables accordingly. + * + * @ioc: Pointer to MPT_ADAPTER structure + */ +static int +_base_check_ioc_facts_changes(struct MPT3SAS_ADAPTER *ioc) +{ + u16 pd_handles_sz; + void *pd_handles = NULL, *blocking_handles = NULL; + void *pend_os_device_add = NULL, *device_remove_in_progress = NULL; + struct mpt3sas_facts *old_facts = &ioc->prev_fw_facts; + + if (ioc->facts.MaxDevHandle > old_facts->MaxDevHandle) { + pd_handles_sz = (ioc->facts.MaxDevHandle / 8); + if (ioc->facts.MaxDevHandle % 8) + pd_handles_sz++; + + pd_handles = krealloc(ioc->pd_handles, pd_handles_sz, + GFP_KERNEL); + if (!pd_handles) { + ioc_info(ioc, + "Unable to allocate the memory for pd_handles of sz: %d\n", + pd_handles_sz); + return -ENOMEM; + } + memset(pd_handles + ioc->pd_handles_sz, 0, + (pd_handles_sz - ioc->pd_handles_sz)); + ioc->pd_handles = pd_handles; + + blocking_handles = krealloc(ioc->blocking_handles, + pd_handles_sz, GFP_KERNEL); + if (!blocking_handles) { + ioc_info(ioc, + "Unable to allocate the memory for " + "blocking_handles of sz: %d\n", + pd_handles_sz); + return -ENOMEM; + } + memset(blocking_handles + ioc->pd_handles_sz, 0, + (pd_handles_sz - ioc->pd_handles_sz)); + ioc->blocking_handles = blocking_handles; + ioc->pd_handles_sz = pd_handles_sz; + + pend_os_device_add = krealloc(ioc->pend_os_device_add, + pd_handles_sz, GFP_KERNEL); + if (!pend_os_device_add) { + ioc_info(ioc, + "Unable to allocate the memory for pend_os_device_add of sz: %d\n", + pd_handles_sz); + return -ENOMEM; + } + memset(pend_os_device_add + ioc->pend_os_device_add_sz, 0, + (pd_handles_sz - ioc->pend_os_device_add_sz)); + ioc->pend_os_device_add = pend_os_device_add; + ioc->pend_os_device_add_sz = pd_handles_sz; + + device_remove_in_progress = krealloc( + ioc->device_remove_in_progress, pd_handles_sz, GFP_KERNEL); + if (!device_remove_in_progress) { + ioc_info(ioc, + "Unable to allocate the memory for " + "device_remove_in_progress of sz: %d\n " + , pd_handles_sz); + return -ENOMEM; + } + memset(device_remove_in_progress + + ioc->device_remove_in_progress_sz, 0, + (pd_handles_sz - ioc->device_remove_in_progress_sz)); + ioc->device_remove_in_progress = device_remove_in_progress; + ioc->device_remove_in_progress_sz = pd_handles_sz; + } + + memcpy(&ioc->prev_fw_facts, &ioc->facts, sizeof(struct mpt3sas_facts)); + return 0; +} + /** * mpt3sas_base_hard_reset_handler - reset controller * @ioc: Pointer to MPT_ADAPTER structure @@ -7342,6 +7428,13 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, if (r) goto out; + r = _base_check_ioc_facts_changes(ioc); + if (r) { + ioc_info(ioc, + "Some of the parameters got changed in this new firmware" + " image and it requires system reboot\n"); + goto out; + } if (ioc->rdpq_array_enable && !ioc->rdpq_array_capable) panic("%s: Issue occurred with flashing controller firmware." "Please reboot the system and ensure that the correct" diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 6afbdb044310..5cd6148ad9bd 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1066,6 +1066,7 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc); * @event_log: event log pointer * @event_masks: events that are masked * @facts: static facts data + * @prev_fw_facts: previous fw facts data * @pfacts: static port facts data * @manu_pg0: static manufacturing page 0 * @manu_pg10: static manufacturing page 10 @@ -1276,6 +1277,7 @@ struct MPT3SAS_ADAPTER { /* static config pages */ struct mpt3sas_facts facts; + struct mpt3sas_facts prev_fw_facts; struct mpt3sas_port_facts *pfacts; Mpi2ManufacturingPage0_t manu_pg0; struct Mpi2ManufacturingPage10_t manu_pg10; -- cgit v1.2.3-59-g8ed1b From 635ee6c73034ea4488a8e26bb0d0291d83146863 Mon Sep 17 00:00:00 2001 From: Suganath Prabu Date: Sat, 3 Aug 2019 09:59:49 -0400 Subject: scsi: mpt3sas: Update MPI headers to 2.6.8 spec Updated MPI to 2.6.8 specification and header files to 2.00.54. Signed-off-by: Suganath Prabu Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpi/mpi2.h | 5 +++-- drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h | 10 +++++++-- drivers/scsi/mpt3sas/mpi/mpi2_image.h | 39 +++++++++++++++++++---------------- drivers/scsi/mpt3sas/mpi/mpi2_pci.h | 13 ++++++------ drivers/scsi/mpt3sas/mpi/mpi2_tool.h | 13 ++++++------ 5 files changed, 46 insertions(+), 34 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpi/mpi2.h b/drivers/scsi/mpt3sas/mpi/mpi2.h index 7efd17a3c25b..18b1e31b5eb8 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2.h @@ -9,7 +9,7 @@ * scatter/gather formats. * Creation Date: June 21, 2006 * - * mpi2.h Version: 02.00.53 + * mpi2.h Version: 02.00.54 * * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 * prefix are for use only on MPI v2.5 products, and must not be used @@ -121,6 +121,7 @@ * 08-15-18 02.00.52 Bumped MPI2_HEADER_VERSION_UNIT. * 08-28-18 02.00.53 Bumped MPI2_HEADER_VERSION_UNIT. * Added MPI2_IOCSTATUS_FAILURE + * 12-17-18 02.00.54 Bumped MPI2_HEADER_VERSION_UNIT * -------------------------------------------------------------------------- */ @@ -161,7 +162,7 @@ /* Unit and Dev versioning for this MPI header set */ -#define MPI2_HEADER_VERSION_UNIT (0x35) +#define MPI2_HEADER_VERSION_UNIT (0x36) #define MPI2_HEADER_VERSION_DEV (0x00) #define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) #define MPI2_HEADER_VERSION_UNIT_SHIFT (8) diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h index 167d79d145ca..3a6871aecada 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h @@ -7,7 +7,7 @@ * Title: MPI Configuration messages and pages * Creation Date: November 10, 2006 * - * mpi2_cnfg.h Version: 02.00.46 + * mpi2_cnfg.h Version: 02.00.47 * * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 * prefix are for use only on MPI v2.5 products, and must not be used @@ -244,6 +244,11 @@ * Added DMDReport Delay Time defines to * PCIeIOUnitPage1 * -------------------------------------------------------------------------- + * 08-02-18 02.00.44 Added Slotx2, Slotx4 to ManPage 7. + * 08-15-18 02.00.45 Added ProductSpecific field at end of IOC Page 1 + * 08-28-18 02.00.46 Added NVMs Write Cache flag to IOUnitPage1 + * Added DMDReport Delay Time defines to PCIeIOUnitPage1 + * 12-17-18 02.00.47 Swap locations of Slotx2 and Slotx4 in ManPage 7. */ #ifndef MPI2_CNFG_H @@ -810,7 +815,8 @@ typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO { U8 Location; /*0x14 */ U8 ReceptacleID; /*0x15 */ U16 Slot; /*0x16 */ - U32 Reserved2; /*0x18 */ + U16 Slotx2; /*0x18 */ + U16 Slotx4; /*0x1A */ } MPI2_MANPAGE7_CONNECTOR_INFO, *PTR_MPI2_MANPAGE7_CONNECTOR_INFO, Mpi2ManPage7ConnectorInfo_t, diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_image.h b/drivers/scsi/mpt3sas/mpi/mpi2_image.h index 4959585f029d..a3f677853098 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_image.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_image.h @@ -5,7 +5,7 @@ * Name: mpi2_image.h * Description: Contains definitions for firmware and other component images * Creation Date: 04/02/2018 - * Version: 02.06.03 + * Version: 02.06.04 * * * Version History @@ -17,6 +17,8 @@ * 08-14-18 02.06.01 Corrected define for MPI26_IMAGE_HEADER_SIGNATURE0_MPI26 * 08-28-18 02.06.02 Added MPI2_EXT_IMAGE_TYPE_RDE * 09-07-18 02.06.03 Added MPI26_EVENT_PCIE_TOPO_PI_16_LANES + * 12-17-18 02.06.04 Addd MPI2_EXT_IMAGE_TYPE_PBLP + * Shorten some defines to be compatible with DOS */ #ifndef MPI2_IMAGE_H #define MPI2_IMAGE_H @@ -200,17 +202,17 @@ typedef struct _MPI26_COMPONENT_IMAGE_HEADER { #define MPI26_IMAGE_HEADER_SIGNATURE0_MPI26 (0xEB000042) /**** Definitions for Signature1 field ****/ -#define MPI26_IMAGE_HEADER_SIGNATURE1_APPLICATION (0x20505041) -#define MPI26_IMAGE_HEADER_SIGNATURE1_CBB (0x20424243) -#define MPI26_IMAGE_HEADER_SIGNATURE1_MFG (0x2047464D) -#define MPI26_IMAGE_HEADER_SIGNATURE1_BIOS (0x534F4942) -#define MPI26_IMAGE_HEADER_SIGNATURE1_HIIM (0x4D494948) -#define MPI26_IMAGE_HEADER_SIGNATURE1_HIIA (0x41494948) -#define MPI26_IMAGE_HEADER_SIGNATURE1_CPLD (0x444C5043) -#define MPI26_IMAGE_HEADER_SIGNATURE1_SPD (0x20445053) -#define MPI26_IMAGE_HEADER_SIGNATURE1_NVDATA (0x5444564E) -#define MPI26_IMAGE_HEADER_SIGNATURE1_GAS_GAUGE (0x20534147) -#define MPI26_IMAGE_HEADER_SIGNATURE1_PBLP (0x50424C50) +#define MPI26_IMAGE_HEADER_SIG1_APPLICATION (0x20505041) +#define MPI26_IMAGE_HEADER_SIG1_CBB (0x20424243) +#define MPI26_IMAGE_HEADER_SIG1_MFG (0x2047464D) +#define MPI26_IMAGE_HEADER_SIG1_BIOS (0x534F4942) +#define MPI26_IMAGE_HEADER_SIG1_HIIM (0x4D494948) +#define MPI26_IMAGE_HEADER_SIG1_HIIA (0x41494948) +#define MPI26_IMAGE_HEADER_SIG1_CPLD (0x444C5043) +#define MPI26_IMAGE_HEADER_SIG1_SPD (0x20445053) +#define MPI26_IMAGE_HEADER_SIG1_NVDATA (0x5444564E) +#define MPI26_IMAGE_HEADER_SIG1_GAS_GAUGE (0x20534147) +#define MPI26_IMAGE_HEADER_SIG1_PBLP (0x504C4250) /**** Definitions for Signature2 field ****/ #define MPI26_IMAGE_HEADER_SIGNATURE2_VALUE (0x50584546) @@ -278,6 +280,7 @@ typedef struct _MPI2_EXT_IMAGE_HEADER { #define MPI2_EXT_IMAGE_TYPE_MEGARAID (0x08) #define MPI2_EXT_IMAGE_TYPE_ENCRYPTED_HASH (0x09) #define MPI2_EXT_IMAGE_TYPE_RDE (0x0A) +#define MPI2_EXT_IMAGE_TYPE_PBLP (0x0B) #define MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC (0x80) #define MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC (0xFF) @@ -472,12 +475,12 @@ Mpi25EncryptedHashEntry_t, *pMpi25EncryptedHashEntry_t; #define MPI25_HASH_ALGORITHM_UNUSED (0x00) #define MPI25_HASH_ALGORITHM_SHA256 (0x01) -#define MPI26_HASH_ALGORITHM_VERSION_MASK (0xE0) -#define MPI26_HASH_ALGORITHM_VERSION_NONE (0x00) -#define MPI26_HASH_ALGORITHM_VERSION_SHA1 (0x20) -#define MPI26_HASH_ALGORITHM_VERSION_SHA2 (0x40) -#define MPI26_HASH_ALGORITHM_VERSION_SHA3 (0x60) -#define MPI26_HASH_ALGORITHM_SIZE_MASK (0x1F) +#define MPI26_HASH_ALGORITHM_VER_MASK (0xE0) +#define MPI26_HASH_ALGORITHM_VER_NONE (0x00) +#define MPI26_HASH_ALGORITHM_VER_SHA1 (0x20) +#define MPI26_HASH_ALGORITHM_VER_SHA2 (0x40) +#define MPI26_HASH_ALGORITHM_VER_SHA3 (0x60) +#define MPI26_HASH_ALGORITHM_SIZE_MASK (0x1F) #define MPI26_HASH_ALGORITHM_SIZE_256 (0x01) #define MPI26_HASH_ALGORITHM_SIZE_512 (0x02) diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_pci.h b/drivers/scsi/mpt3sas/mpi/mpi2_pci.h index 63a09509d7d1..bb7b79cfa558 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_pci.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_pci.h @@ -6,7 +6,7 @@ * Title: MPI PCIe Attached Devices structures and definitions. * Creation Date: October 9, 2012 * - * mpi2_pci.h Version: 02.00.03 + * mpi2_pci.h Version: 02.00.04 * * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 * prefix are for use only on MPI v2.5 products, and must not be used @@ -24,6 +24,8 @@ * 07-01-16 02.00.02 Added MPI26_NVME_FLAGS_FORCE_ADMIN_ERR_RESP to * NVME Encapsulated Request. * 07-22-18 02.00.03 Updted flags field for NVME Encapsulated req + * 12-17-18 02.00.04 Added MPI26_PCIE_DEVINFO_SCSI + * Shortten some defines to be compatible with DOS * -------------------------------------------------------------------------- */ @@ -41,7 +43,7 @@ #define MPI26_PCIE_DEVINFO_NO_DEVICE (0x00000000) #define MPI26_PCIE_DEVINFO_PCI_SWITCH (0x00000001) #define MPI26_PCIE_DEVINFO_NVME (0x00000003) - +#define MPI26_PCIE_DEVINFO_SCSI (0x00000004) /**************************************************************************** * NVMe Encapsulated message @@ -75,10 +77,9 @@ typedef struct _MPI26_NVME_ENCAPSULATED_REQUEST { #define MPI26_NVME_FLAGS_SUBMISSIONQ_IO (0x0000) #define MPI26_NVME_FLAGS_SUBMISSIONQ_ADMIN (0x0010) /*Error Response Address Space */ -#define MPI26_NVME_FLAGS_MASK_ERROR_RSP_ADDR (0x000C) -#define MPI26_NVME_FLAGS_MASK_ERROR_RSP_ADDR_MASK (0x000C) -#define MPI26_NVME_FLAGS_SYSTEM_RSP_ADDR (0x0000) -#define MPI26_NVME_FLAGS_IOCCTL_RSP_ADDR (0x0008) +#define MPI26_NVME_FLAGS_ERR_RSP_ADDR_MASK (0x000C) +#define MPI26_NVME_FLAGS_ERR_RSP_ADDR_SYSTEM (0x0000) +#define MPI26_NVME_FLAGS_ERR_RSP_ADDR_IOCTL (0x0008) /* Data Direction*/ #define MPI26_NVME_FLAGS_DATADIRECTION_MASK (0x0003) #define MPI26_NVME_FLAGS_NODATATRANSFER (0x0000) diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_tool.h b/drivers/scsi/mpt3sas/mpi/mpi2_tool.h index 3f966b6796b3..17ef7f63b938 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_tool.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_tool.h @@ -7,7 +7,7 @@ * Title: MPI diagnostic tool structures and definitions * Creation Date: March 26, 2007 * - * mpi2_tool.h Version: 02.00.15 + * mpi2_tool.h Version: 02.00.16 * * Version History * --------------- @@ -40,6 +40,7 @@ * Tool Request Message. * 07-22-18 02.00.15 Added defines for new TOOLBOX_PCIE_LANE_MARGINING tool. * Added option for DeviceInfo field in ISTWI tool. + * 12-17-18 02.00.16 Shorten some defines to be compatible with DOS. * -------------------------------------------------------------------------- */ @@ -230,11 +231,11 @@ typedef struct _MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST { #define MPI2_TOOL_ISTWI_FLAG_PAGE_ADDR_MASK (0x07) /*MPI26 TOOLBOX Request MsgFlags defines */ -#define MPI26_TOOLBOX_REQ_MSGFLAGS_ADDRESSING_MASK (0x01) +#define MPI26_TOOL_ISTWI_MSGFLG_ADDR_MASK (0x01) /*Request uses Man Page 43 device index addressing */ -#define MPI26_TOOLBOX_REQ_MSGFLAGS_ADDRESSING_DEVINDEX (0x00) +#define MPI26_TOOL_ISTWI_MSGFLG_ADDR_INDEX (0x00) /*Request uses Man Page 43 device info struct addressing */ -#define MPI26_TOOLBOX_REQ_MSGFLAGS_ADDRESSING_DEVINFO (0x01) +#define MPI26_TOOL_ISTWI_MSGFLG_ADDR_INFO (0x01) /*Toolbox ISTWI Read Write Tool reply message */ typedef struct _MPI2_TOOLBOX_ISTWI_REPLY { @@ -403,7 +404,7 @@ Mpi2ToolboxTextDisplayRequest_t, */ /*Toolbox Backend Lane Margining Tool request message */ -typedef struct _MPI26_TOOLBOX_LANE_MARGINING_REQUEST { +typedef struct _MPI26_TOOLBOX_LANE_MARGIN_REQUEST { U8 Tool; /*0x00 */ U8 Reserved1; /*0x01 */ U8 ChainOffset; /*0x02 */ @@ -434,7 +435,7 @@ typedef struct _MPI26_TOOLBOX_LANE_MARGINING_REQUEST { /*Toolbox Backend Lane Margining Tool reply message */ -typedef struct _MPI26_TOOLBOX_LANE_MARGINING_REPLY { +typedef struct _MPI26_TOOLBOX_LANE_MARGIN_REPLY { U8 Tool; /*0x00 */ U8 Reserved1; /*0x01 */ U8 MsgLength; /*0x02 */ -- cgit v1.2.3-59-g8ed1b From 5bb309dbbbf2157786004201eb70dafd283b54b5 Mon Sep 17 00:00:00 2001 From: Suganath Prabu Date: Sat, 3 Aug 2019 09:59:50 -0400 Subject: scsi: mpt3sas: Enumerate SES of a managed PCIe switch SES device of managed PCIe switch will be enumerated same as NVMe drives. The device info type for this SES device is MPI26_PCIE_DEVINFO_SCSI (0x4), whereas the device info type for NVMe drives is MPI26_PCIE_DEVINFO_NVME (0x3). Based on this device info type driver determines whether the device is NVMe drive or a SES device of a managed PCIe switch. This SES device doesn't have the PCIe device page 2 information like NVMe drives, so driver won't read PCIe device page 2 information for SES device. This SES device uses only IEEE SGL's, So driver build's IEEE SGL's whenever it receives any SCSI commands for this SES device. Signed-off-by: Suganath Prabu Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 5 ++ drivers/scsi/mpt3sas/mpt3sas_base.h | 16 +++++++ drivers/scsi/mpt3sas/mpt3sas_ctl.c | 7 +-- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 92 +++++++++++++++++++++++------------- 4 files changed, 83 insertions(+), 37 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index f72933cc6622..44d19cb6b069 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -2260,6 +2260,11 @@ base_is_prp_possible(struct MPT3SAS_ADAPTER *ioc, bool build_prp = true; data_length = scsi_bufflen(scmd); + if (pcie_device && + (mpt3sas_scsih_is_pcie_scsi_device(pcie_device->device_info))) { + build_prp = false; + return build_prp; + } /* If Datalenth is <= 16K and number of SGE’s entries are <= 2 * we built IEEE SGL diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 5cd6148ad9bd..f6a1ae1cf4c0 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1735,4 +1735,20 @@ mpt3sas_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, /* NCQ Prio Handling Check */ bool scsih_ncq_prio_supp(struct scsi_device *sdev); +/** + * _scsih_is_pcie_scsi_device - determines if device is an pcie scsi device + * @device_info: bitfield providing information about the device. + * Context: none + * + * Returns 1 if scsi device. + */ +static inline int +mpt3sas_scsih_is_pcie_scsi_device(u32 device_info) +{ + if ((device_info & + MPI26_PCIE_DEVINFO_MASK_DEVICE_TYPE) == MPI26_PCIE_DEVINFO_SCSI) + return 1; + else + return 0; +} #endif /* MPT3SAS_BASE_H_INCLUDED */ diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index ab78bcf9fbc6..5592919a952d 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -662,7 +662,6 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, size_t data_in_sz = 0; long ret; u16 device_handle = MPT3SAS_INVALID_DEVICE_HANDLE; - u8 tr_method = MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE; issue_reset = 0; @@ -1057,12 +1056,14 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, mpt3sas_halt_firmware(ioc); pcie_device = mpt3sas_get_pdev_by_handle(ioc, le16_to_cpu(mpi_request->FunctionDependent1)); - if (pcie_device && (!ioc->tm_custom_handling)) + if (pcie_device && (!ioc->tm_custom_handling) && + (!(mpt3sas_scsih_is_pcie_scsi_device( + pcie_device->device_info)))) mpt3sas_scsih_issue_locked_tm(ioc, le16_to_cpu(mpi_request->FunctionDependent1), 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 0, pcie_device->reset_timeout, - tr_method); + MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE); else mpt3sas_scsih_issue_locked_tm(ioc, le16_to_cpu(mpi_request->FunctionDependent1), diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 717ba0845a2a..c8b83894833f 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -1433,17 +1433,20 @@ _scsih_is_end_device(u32 device_info) } /** - * _scsih_is_nvme_device - determines if device is an nvme device + * _scsih_is_nvme_pciescsi_device - determines if + * device is an pcie nvme/scsi device * @device_info: bitfield providing information about the device. * Context: none * - * Return: 1 if nvme device. + * Returns 1 if device is pcie device type nvme/scsi. */ static int -_scsih_is_nvme_device(u32 device_info) +_scsih_is_nvme_pciescsi_device(u32 device_info) { - if ((device_info & MPI26_PCIE_DEVINFO_MASK_DEVICE_TYPE) - == MPI26_PCIE_DEVINFO_NVME) + if (((device_info & MPI26_PCIE_DEVINFO_MASK_DEVICE_TYPE) + == MPI26_PCIE_DEVINFO_NVME) || + ((device_info & MPI26_PCIE_DEVINFO_MASK_DEVICE_TYPE) + == MPI26_PCIE_DEVINFO_SCSI)) return 1; else return 0; @@ -2872,7 +2875,8 @@ scsih_abort(struct scsi_cmnd *scmd) handle = sas_device_priv_data->sas_target->handle; pcie_device = mpt3sas_get_pdev_by_handle(ioc, handle); - if (pcie_device && (!ioc->tm_custom_handling)) + if (pcie_device && (!ioc->tm_custom_handling) && + (!(mpt3sas_scsih_is_pcie_scsi_device(pcie_device->device_info)))) timeout = ioc->nvme_abort_timeout; r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, @@ -2943,11 +2947,13 @@ scsih_dev_reset(struct scsi_cmnd *scmd) pcie_device = mpt3sas_get_pdev_by_handle(ioc, handle); - if (pcie_device && (!ioc->tm_custom_handling)) { + if (pcie_device && (!ioc->tm_custom_handling) && + (!(mpt3sas_scsih_is_pcie_scsi_device(pcie_device->device_info)))) { tr_timeout = pcie_device->reset_timeout; tr_method = MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE; } else tr_method = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; + r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->lun, MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 0, tr_timeout, tr_method); @@ -3020,7 +3026,8 @@ scsih_target_reset(struct scsi_cmnd *scmd) pcie_device = mpt3sas_get_pdev_by_handle(ioc, handle); - if (pcie_device && (!ioc->tm_custom_handling)) { + if (pcie_device && (!ioc->tm_custom_handling) && + (!(mpt3sas_scsih_is_pcie_scsi_device(pcie_device->device_info)))) { tr_timeout = pcie_device->reset_timeout; tr_method = MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE; } else @@ -3598,7 +3605,9 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) sas_address = pcie_device->wwid; } spin_unlock_irqrestore(&ioc->pcie_device_lock, flags); - if (pcie_device && (!ioc->tm_custom_handling)) + if (pcie_device && (!ioc->tm_custom_handling) && + (!(mpt3sas_scsih_is_pcie_scsi_device( + pcie_device->device_info)))) tr_method = MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE; else @@ -6694,7 +6703,7 @@ _scsih_pcie_check_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) /* check if this is end device */ device_info = le32_to_cpu(pcie_device_pg0.DeviceInfo); - if (!(_scsih_is_nvme_device(device_info))) + if (!(_scsih_is_nvme_pciescsi_device(device_info))) return; wwid = le64_to_cpu(pcie_device_pg0.WWID); @@ -6803,7 +6812,8 @@ _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) pcie_device_pg0.AccessStatus)) return 0; - if (!(_scsih_is_nvme_device(le32_to_cpu(pcie_device_pg0.DeviceInfo)))) + if (!(_scsih_is_nvme_pciescsi_device(le32_to_cpu + (pcie_device_pg0.DeviceInfo)))) return 0; pcie_device = mpt3sas_get_pdev_by_wwid(ioc, wwid); @@ -6813,6 +6823,31 @@ _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) return 0; } + /* PCIe Device Page 2 contains read-only information about a + * specific NVMe device; therefore, this page is only + * valid for NVMe devices and skip for pcie devices of type scsi. + */ + if (!(mpt3sas_scsih_is_pcie_scsi_device( + le32_to_cpu(pcie_device_pg0.DeviceInfo)))) { + if (mpt3sas_config_get_pcie_device_pg2(ioc, &mpi_reply, + &pcie_device_pg2, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, + handle)) { + ioc_err(ioc, + "failure at %s:%d/%s()!\n", __FILE__, + __LINE__, __func__); + return 0; + } + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + ioc_err(ioc, + "failure at %s:%d/%s()!\n", __FILE__, + __LINE__, __func__); + return 0; + } + } + pcie_device = kzalloc(sizeof(struct _pcie_device), GFP_KERNEL); if (!pcie_device) { ioc_err(ioc, "failure at %s:%d/%s()!\n", @@ -6855,27 +6890,16 @@ _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) le64_to_cpu(enclosure_dev->pg0.EnclosureLogicalID); } /* TODO -- Add device name once FW supports it */ - if (mpt3sas_config_get_pcie_device_pg2(ioc, &mpi_reply, - &pcie_device_pg2, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)) { - ioc_err(ioc, "failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - kfree(pcie_device); - return 0; - } - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - ioc_err(ioc, "failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - kfree(pcie_device); - return 0; - } - pcie_device->nvme_mdts = - le32_to_cpu(pcie_device_pg2.MaximumDataTransferSize); - if (pcie_device_pg2.ControllerResetTO) - pcie_device->reset_timeout = - pcie_device_pg2.ControllerResetTO; - else + if (!(mpt3sas_scsih_is_pcie_scsi_device( + le32_to_cpu(pcie_device_pg0.DeviceInfo)))) { + pcie_device->nvme_mdts = + le32_to_cpu(pcie_device_pg2.MaximumDataTransferSize); + if (pcie_device_pg2.ControllerResetTO) + pcie_device->reset_timeout = + pcie_device_pg2.ControllerResetTO; + else + pcie_device->reset_timeout = 30; + } else pcie_device->reset_timeout = 30; if (ioc->wait_for_discovery_to_complete) @@ -8594,7 +8618,7 @@ _scsih_search_responding_pcie_devices(struct MPT3SAS_ADAPTER *ioc) } handle = le16_to_cpu(pcie_device_pg0.DevHandle); device_info = le32_to_cpu(pcie_device_pg0.DeviceInfo); - if (!(_scsih_is_nvme_device(device_info))) + if (!(_scsih_is_nvme_pciescsi_device(device_info))) continue; _scsih_mark_responding_pcie_device(ioc, &pcie_device_pg0); } @@ -9175,7 +9199,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) break; } handle = le16_to_cpu(pcie_device_pg0.DevHandle); - if (!(_scsih_is_nvme_device( + if (!(_scsih_is_nvme_pciescsi_device( le32_to_cpu(pcie_device_pg0.DeviceInfo)))) continue; pcie_device = mpt3sas_get_pdev_by_wwid(ioc, -- cgit v1.2.3-59-g8ed1b From 3c090ce3f0fba1efb44eb9317ebf8e8150197a21 Mon Sep 17 00:00:00 2001 From: Suganath Prabu Date: Sat, 3 Aug 2019 09:59:51 -0400 Subject: scsi: mpt3sas: Allow ioctls to blocked access status NVMe If driver sees the NVMe drive with "DEVICE_BLOCKED" AccessStatus in its PCIe Device Page0, then driver removes the drive from its internal list and does not allow any IOCTL commands to be sent to the drive and will return the IOCTLs with "-ENODEV" status. The driver will now allow NVMe Encapsulated IOCTL issued to the NVMe device with an access status of DEVICE_BLOCKED. This change allows the user to flash new drive firmware online and revive the drive. Add NVMe device only the driver's internal list even though the device is in the blocked state so that the device will be visible to Apps. This way Apps can send NVMe Encapsulated IOCTLs to this drive and bring the drive online. This NVMe drive with DEVICE_BLOCKED access status won't added to the SML, it will be added only in the driver's internal list. [mkp: clarified desc] Signed-off-by: Suganath Prabu Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 2 ++ drivers/scsi/mpt3sas/mpt3sas_scsih.c | 27 +++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index f6a1ae1cf4c0..c13554e82f3d 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -583,6 +583,7 @@ static inline void sas_device_put(struct _sas_device *s) * @enclosure_level: The level of device's enclosure from the controller * @connector_name: ASCII value of the Connector's name * @serial_number: pointer of serial number string allocated runtime + * @access_status: Device's Access Status * @refcount: reference count for deletion */ struct _pcie_device { @@ -604,6 +605,7 @@ struct _pcie_device { u8 connector_name[4]; u8 *serial_number; u8 reset_timeout; + u8 access_status; struct kref refcount; }; /** diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index c8b83894833f..91e9a91f8df2 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -1152,6 +1152,11 @@ _scsih_pcie_device_add(struct MPT3SAS_ADAPTER *ioc, list_add_tail(&pcie_device->list, &ioc->pcie_device_list); spin_unlock_irqrestore(&ioc->pcie_device_lock, flags); + if (pcie_device->access_status == + MPI26_PCIEDEV0_ASTATUS_DEVICE_BLOCKED) { + clear_bit(pcie_device->handle, ioc->pend_os_device_add); + return; + } if (scsi_add_device(ioc->shost, PCIE_CHANNEL, pcie_device->id, 0)) { _scsih_pcie_device_remove(ioc, pcie_device); } else if (!pcie_device->starget) { @@ -1196,7 +1201,9 @@ _scsih_pcie_device_init_add(struct MPT3SAS_ADAPTER *ioc, spin_lock_irqsave(&ioc->pcie_device_lock, flags); pcie_device_get(pcie_device); list_add_tail(&pcie_device->list, &ioc->pcie_device_init_list); - _scsih_determine_boot_device(ioc, pcie_device, PCIE_CHANNEL); + if (pcie_device->access_status != + MPI26_PCIEDEV0_ASTATUS_DEVICE_BLOCKED) + _scsih_determine_boot_device(ioc, pcie_device, PCIE_CHANNEL); spin_unlock_irqrestore(&ioc->pcie_device_lock, flags); } /** @@ -6548,6 +6555,11 @@ _scsih_check_pcie_access_status(struct MPT3SAS_ADAPTER *ioc, u64 wwid, break; case MPI26_PCIEDEV0_ASTATUS_DEVICE_BLOCKED: desc = "PCIe device blocked"; + ioc_info(ioc, + "Device with Access Status (%s): wwid(0x%016llx), " + "handle(0x%04x)\n ll only be added to the internal list", + desc, (u64)wwid, handle); + rc = 0; break; case MPI26_PCIEDEV0_ASTATUS_MEMORY_SPACE_ACCESS_FAILED: desc = "PCIe device mem space access failed"; @@ -6652,7 +6664,8 @@ _scsih_pcie_device_remove_from_sml(struct MPT3SAS_ADAPTER *ioc, pcie_device->enclosure_level, pcie_device->connector_name); - if (pcie_device->starget) + if (pcie_device->starget && (pcie_device->access_status != + MPI26_PCIEDEV0_ASTATUS_DEVICE_BLOCKED)) scsi_remove_target(&pcie_device->starget->dev); dewtprintk(ioc, ioc_info(ioc, "%s: exit: handle(0x%04x), wwid(0x%016llx)\n", @@ -6718,6 +6731,7 @@ _scsih_pcie_check_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) if (unlikely(pcie_device->handle != handle)) { starget = pcie_device->starget; sas_target_priv_data = starget->hostdata; + pcie_device->access_status = pcie_device_pg0.AccessStatus; starget_printk(KERN_INFO, starget, "handle changed from(0x%04x) to (0x%04x)!!!\n", pcie_device->handle, handle); @@ -6859,6 +6873,7 @@ _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) pcie_device->id = ioc->pcie_target_id++; pcie_device->channel = PCIE_CHANNEL; pcie_device->handle = handle; + pcie_device->access_status = pcie_device_pg0.AccessStatus; pcie_device->device_info = le32_to_cpu(pcie_device_pg0.DeviceInfo); pcie_device->wwid = wwid; pcie_device->port_num = pcie_device_pg0.PortNum; @@ -8531,6 +8546,8 @@ _scsih_mark_responding_pcie_device(struct MPT3SAS_ADAPTER *ioc, if ((pcie_device->wwid == le64_to_cpu(pcie_device_pg0->WWID)) && (pcie_device->slot == le16_to_cpu( pcie_device_pg0->Slot))) { + pcie_device->access_status = + pcie_device_pg0->AccessStatus; pcie_device->responding = 1; starget = pcie_device->starget; if (starget && starget->hostdata) { @@ -10063,6 +10080,12 @@ _scsih_probe_pcie(struct MPT3SAS_ADAPTER *ioc) pcie_device_put(pcie_device); continue; } + if (pcie_device->access_status == + MPI26_PCIEDEV0_ASTATUS_DEVICE_BLOCKED) { + pcie_device_make_active(ioc, pcie_device); + pcie_device_put(pcie_device); + continue; + } rc = scsi_add_device(ioc->shost, PCIE_CHANNEL, pcie_device->id, 0); if (rc) { -- cgit v1.2.3-59-g8ed1b From ba630ea068d7cb593ae3bb7085846c5a137d10a6 Mon Sep 17 00:00:00 2001 From: Suganath Prabu Date: Sat, 3 Aug 2019 09:59:52 -0400 Subject: scsi: mpt3sas: Support MEMORY MOVE Tool box command Host uses the Memory Move Tool to copy data from any source/destination combination of system memory and IOC memory. Memory Move Tool box request contains two SGE fields, First SGE field must contains the source buffer details described by an MPI Simple SGE. The second SGE field must contains the destination buffer details described by an MPI Simple SGE. Source -> Destination 1. IOC -> IOC (Both the SGE's will be filled by application) 2. HOST -> HOST (Both the SGE's will be filled by the host, application should give sgl_offset to first SGE offset) 3. IOC -> HOST (Application will fill the first SGE and set the sgl_offset to second SGE and hence driver fills the second SGE) 4. HOST -> IOC (Application will fill IOC buffer information in the first SGE and set the sgl_offset to second SGE. Then driver will fill the second SGE with Host buffer information and just before posting the command to the firmware, driver will swap these two SGEs so that first SGE contains the HOST buffer information and second SGE contains the IOC information. Driver has to take care only of the 4th case, other three cases are by default supported by the current driver design. Signed-off-by: Suganath Prabu Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index 5592919a952d..d766ae71a61d 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -934,9 +934,32 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, MPI26_TOOLBOX_BACKEND_PCIE_LANE_MARGIN)) ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); - else + else if (toolbox_request->Tool == + MPI2_TOOLBOX_MEMORY_MOVE_TOOL) { + Mpi2ToolboxMemMoveRequest_t *mem_move_request = + (Mpi2ToolboxMemMoveRequest_t *)request; + Mpi2SGESimple64_t tmp, *src = NULL, *dst = NULL; + + ioc->build_sg_mpi(ioc, psge, data_out_dma, + data_out_sz, data_in_dma, data_in_sz); + if (data_out_sz && !data_in_sz) { + dst = + (Mpi2SGESimple64_t *)&mem_move_request->SGL; + src = (void *)dst + ioc->sge_size; + + memcpy(&tmp, src, ioc->sge_size); + memcpy(src, dst, ioc->sge_size); + memcpy(dst, &tmp, ioc->sge_size); + } + if (ioc->logging_level & MPT_DEBUG_TM) { + ioc_info(ioc, + "Mpi2ToolboxMemMoveRequest_t request msg\n"); + _debug_dump_mf(mem_move_request, + ioc->request_sz/4); + } + } else ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz, - data_in_dma, data_in_sz); + data_in_dma, data_in_sz); ioc->put_smid_default(ioc, smid); break; } -- cgit v1.2.3-59-g8ed1b From 3ac8e47bbf2dfada890396b2994fe2765afd8cef Mon Sep 17 00:00:00 2001 From: Suganath Prabu Date: Sat, 3 Aug 2019 09:59:53 -0400 Subject: scsi: mpt3sas: Add sysfs to know supported features Currently with sysfs parameter "drv_support_bitmap" driver exposes whether driver supports toolbox memory move command or not. And application should issue the toolbox memory move command only if driver tell that memory move tool box command is supported through this sysfs parameter. In future we can utilize this sysfs parameter if any new feature is added and need to notify the same to applications. Signed-off-by: Suganath Prabu Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 4 ++++ drivers/scsi/mpt3sas/mpt3sas_ctl.c | 19 +++++++++++++++++++ drivers/scsi/mpt3sas/mpt3sas_scsih.c | 4 ++++ 3 files changed, 27 insertions(+) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index c13554e82f3d..f970a842ab23 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1047,6 +1047,7 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc); * @schedule_dead_ioc_flush_running_cmds: callback to flush pending commands * @thresh_hold: Max number of reply descriptors processed * before updating Host Index + * @drv_support_bitmap: driver's supported feature bit map * @scsi_io_cb_idx: shost generated commands * @tm_cb_idx: task management commands * @scsih_cb_idx: scsih internal commands @@ -1230,6 +1231,7 @@ struct MPT3SAS_ADAPTER { bool msix_load_balance; u16 thresh_hold; u8 high_iops_queues; + u32 drv_support_bitmap; /* internal commands, callback index */ u8 scsi_io_cb_idx; @@ -1454,6 +1456,8 @@ struct MPT3SAS_ADAPTER { GET_MSIX_INDEX get_msix_index_for_smlio; }; +#define MPT_DRV_SUPPORT_BITMAP_MEMMOVE 0x00000001 + typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply); diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index d766ae71a61d..da29005d72bd 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -3382,6 +3382,24 @@ static DEVICE_ATTR_RW(diag_trigger_mpi); /*****************************************/ +/** + * drv_support_bitmap_show - driver supported feature bitmap + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * A sysfs 'read-only' shost attribute. + */ +static ssize_t +drv_support_bitmap_show(struct device *cdev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); + + return snprintf(buf, PAGE_SIZE, "0x%08x\n", ioc->drv_support_bitmap); +} +static DEVICE_ATTR_RO(drv_support_bitmap); + struct device_attribute *mpt3sas_host_attrs[] = { &dev_attr_version_fw, &dev_attr_version_bios, @@ -3407,6 +3425,7 @@ struct device_attribute *mpt3sas_host_attrs[] = { &dev_attr_diag_trigger_event, &dev_attr_diag_trigger_scsi, &dev_attr_diag_trigger_mpi, + &dev_attr_drv_support_bitmap, &dev_attr_BRM_status, NULL, }; diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 91e9a91f8df2..e6d952722313 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -10500,6 +10500,10 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx; ioc->logging_level = logging_level; ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds; + /* + * Enable MEMORY MOVE support flag. + */ + ioc->drv_support_bitmap |= MPT_DRV_SUPPORT_BITMAP_MEMMOVE; /* misc semaphores and spin locks */ mutex_init(&ioc->reset_in_progress_mutex); /* initializing pci_access_mutex lock */ -- cgit v1.2.3-59-g8ed1b From 9c067c053f94d36006cd0a29cf02b0b6be54c6ca Mon Sep 17 00:00:00 2001 From: Suganath Prabu Date: Sat, 3 Aug 2019 09:59:54 -0400 Subject: scsi: mpt3sas: Handle fault during HBA initialization During HBA initialization time, if handshake operation fails due to some firmware fault then currently driver is terminating the HBA initialization. It is possible that HBA may come up properly if diag reset is issued. So improvement is made in driver in such a way that before terminating the HBA initialization, driver checks the IOC state and if IOC state is in fault state then issue diag reset for once. If diag reset is successful then continue with HBA initialization else terminate the HBA initialization. Signed-off-by: Suganath Prabu Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 75 ++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 44d19cb6b069..848f2115d9fd 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -3181,6 +3181,37 @@ mpt3sas_base_unmap_resources(struct MPT3SAS_ADAPTER *ioc) } } +static int +_base_diag_reset(struct MPT3SAS_ADAPTER *ioc); + +/** + * _base_check_for_fault_and_issue_reset - check if IOC is in fault state + * and if it is in fault state then issue diag reset. + * @ioc: per adapter object + * + * Returns: 0 for success, non-zero for failure. + */ +static int +_base_check_for_fault_and_issue_reset(struct MPT3SAS_ADAPTER *ioc) +{ + u32 ioc_state; + int rc = -EFAULT; + + dinitprintk(ioc, pr_info("%s\n", __func__)); + if (ioc->pci_error_recovery) + return 0; + ioc_state = mpt3sas_base_get_iocstate(ioc, 0); + dhsprintk(ioc, pr_info("%s: ioc_state(0x%08x)\n", __func__, ioc_state)); + + if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { + mpt3sas_base_fault_info(ioc, ioc_state & + MPI2_DOORBELL_DATA_MASK); + rc = _base_diag_reset(ioc); + } + + return rc; +} + /** * mpt3sas_base_map_resources - map in controller resources (io/irq/memap) * @ioc: per adapter object @@ -3193,7 +3224,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) struct pci_dev *pdev = ioc->pdev; u32 memap_sz; u32 pio_sz; - int i, r = 0; + int i, r = 0, rc; u64 pio_chip = 0; phys_addr_t chip_phys = 0; struct adapter_reply_queue *reply_q; @@ -3254,8 +3285,11 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) _base_mask_interrupts(ioc); r = _base_get_ioc_facts(ioc); - if (r) - goto out_fail; + if (r) { + rc = _base_check_for_fault_and_issue_reset(ioc); + if (rc || (_base_get_ioc_facts(ioc))) + goto out_fail; + } if (!ioc->rdpq_array_enable_assigned) { ioc->rdpq_array_enable = ioc->rdpq_array_capable; @@ -5414,8 +5448,6 @@ _base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout) * * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell. */ -static int -_base_diag_reset(struct MPT3SAS_ADAPTER *ioc); static int _base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout) @@ -6691,7 +6723,7 @@ _base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, enum reset_type type) static int _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc) { - int r, i, index; + int r, i, index, rc; unsigned long flags; u32 reply_address; u16 smid; @@ -6794,8 +6826,19 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc) skip_init_reply_post_free_queue: r = _base_send_ioc_init(ioc); - if (r) - return r; + if (r) { + /* + * No need to check IOC state for fault state & issue + * diag reset during host reset. This check is need + * only during driver load time. + */ + if (!ioc->is_driver_loading) + return r; + + rc = _base_check_for_fault_and_issue_reset(ioc); + if (rc || (_base_send_ioc_init(ioc))) + return r; + } /* initialize reply free host index */ ioc->reply_free_host_index = ioc->reply_free_queue_depth - 1; @@ -6887,7 +6930,7 @@ mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc) int mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) { - int r, i; + int r, i, rc; int cpu_id, last_cpu_id = 0; dinitprintk(ioc, ioc_info(ioc, "%s\n", __func__)); @@ -6931,8 +6974,11 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) pci_set_drvdata(ioc->pdev, ioc->shost); r = _base_get_ioc_facts(ioc); - if (r) - goto out_free_resources; + if (r) { + rc = _base_check_for_fault_and_issue_reset(ioc); + if (rc || (_base_get_ioc_facts(ioc))) + goto out_free_resources; + } switch (ioc->hba_mpi_version_belonged) { case MPI2_VERSION: @@ -7000,8 +7046,11 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) { r = _base_get_port_facts(ioc, i); - if (r) - goto out_free_resources; + if (r) { + rc = _base_check_for_fault_and_issue_reset(ioc); + if (rc || (_base_get_port_facts(ioc, i))) + goto out_free_resources; + } } r = _base_allocate_memory_pools(ioc); -- cgit v1.2.3-59-g8ed1b From 1edc677019c23eda6d2e9b6c3c88ef3972e41bd1 Mon Sep 17 00:00:00 2001 From: Suganath Prabu Date: Sat, 3 Aug 2019 09:59:55 -0400 Subject: scsi: mpt3sas: Reduce the performance drop This patch is to reduce the performance drop depth observed on SATA HDD when ATA PT command is outstanding. Driver returns IO commands with status "SAM_STAT_BUSY" whenever ATA PT command is outstanding. With this, IO commands will be retried until this outstanding ATA PT to complete and hence we will observe drop in performance. As the driver is completing the subsequent IOs commands with SAM_STAT_BUSY status, these IOs has to go though the block layer. Hence it adds latency to the IOs and large performance drop is observed. So to reduce this performance dropp, added improvement in driver to return the subsequent IOs with SCSI_MLQUEUE_DEVICE_BUSY status instead of completing the IOs with SAM_STAT_BUSY status when ATA PT command is outstanding. Sending command back with SCSI_MLQUEUE_DEVICE_BUSY does not go through complete block layer stack (as scsi_done won't be called) SML will immediately retry the command and this method will avoid latency of block layer stack and the performance impact will be reduced. On Local setup, ran 512k sequential read IO operation on HGST SATA drive with existing driver & with this improvement drivers and here is the result, 1. With existing driver: IOs are running at bandwidth of ~230 rMB/s and whenever any ATA PT command is outstanding (e.g issued from systemd-udevd daemon) then this bandwidth drops to ~150 rMB/s. 2. With this improvement driver: IOs are running at bandwidth of ~230 rMB/s and whenever any ATA PT command is outstanding then this bandwidth drops to just ~190 rMB/s. Signed-off-by: Suganath Prabu Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index e6d952722313..67e9a91af1cf 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -4670,11 +4670,8 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) * since we're lockless at this point */ do { - if (test_bit(0, &sas_device_priv_data->ata_command_pending)) { - scmd->result = SAM_STAT_BUSY; - scmd->scsi_done(scmd); - return 0; - } + if (test_bit(0, &sas_device_priv_data->ata_command_pending)) + return SCSI_MLQUEUE_DEVICE_BUSY; } while (_scsih_set_satl_pending(scmd, true)); if (scmd->sc_data_direction == DMA_FROM_DEVICE) -- cgit v1.2.3-59-g8ed1b From 54d74e6b9d98bc7520e41fea3b3de07a24a766ca Mon Sep 17 00:00:00 2001 From: Suganath Prabu Date: Sat, 3 Aug 2019 09:59:56 -0400 Subject: scsi: mpt3sas: Run SAS DEVICE STATUS CHANGE EVENT from ISR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In some cases, like while performing extensive expander reset or phy reset, user may observe that drives are not visible in OS. Driver's firmware-worker thread is blocked for more than 120 seconds resulting in a call trace. 1. Received target add event for Device A and hence driver has registered this device to SML by calling sas_rphy_add(). SML has half added this device and returned the control to the driver by quitting from sas_rphy_add() API, and started some background scanning on this device A. 2. While background scanning is going on device A, driver has received SAS DEVICE STATUS CHANGE EVENT with RC code "Internal device reset" event and hence driver has set tm_busy flag for this Device A from FW worker thread context. When tm_busy flag is set then driver return scsi commands with device busy status asking the kernel to retry the command after some time. So background scanning for device A will be waiting for this tm_busy to be cleared. 3. Meanwhile driver has received a target add event for Device B and hence driver called sas_rphy_add() API to register this device with SML. But since background scanning for Device A is still pending and SML is not quitting from sas_rphy_add(), the driver’s firmware worker thread got blocked. 4. Now driver has received SAS DEVICE STATUS CHANGE EVENT with RC code "Internal device reset complete" event. But as driver’s firmware worker thread got blocked in Step3, it can’t process this event and it was not clearing the tm_busy flag and deadlock occurred (where SML was waiting for tm_busy flag to be cleared and our FW worker thread is waiting for SML to quit from sas_device_rphy_add() API). Same deadlock will be observed even if device B is getting removed in step3. So to limit these types of deadlocks driver will process the SAS DEVICE STATUS CHANGE EVENT events from ISR context instead of processing this event from worker thread context. This improvement avoids above deadlock. Signed-off-by: Suganath Prabu Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 67e9a91af1cf..9904775493d0 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -6469,24 +6469,17 @@ _scsih_sas_device_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc, /** * _scsih_sas_device_status_change_event - handle device status change * @ioc: per adapter object - * @fw_event: The fw_event_work object + * @event_data: The fw event * Context: user. */ static void _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) + Mpi2EventDataSasDeviceStatusChange_t *event_data) { struct MPT3SAS_TARGET *target_priv_data; struct _sas_device *sas_device; u64 sas_address; unsigned long flags; - Mpi2EventDataSasDeviceStatusChange_t *event_data = - (Mpi2EventDataSasDeviceStatusChange_t *) - fw_event->event_data; - - if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) - _scsih_sas_device_status_change_event_debug(ioc, - event_data); /* In MPI Revision K (0xC), the internal device reset complete was * implemented, so avoid setting tm_busy flag for older firmware. @@ -6518,6 +6511,12 @@ _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc, else target_priv_data->tm_busy = 0; + if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) + ioc_info(ioc, + "%s tm_busy flag for handle(0x%04x)\n", + (target_priv_data->tm_busy == 1) ? "Enable" : "Disable", + target_priv_data->handle); + out: if (sas_device) sas_device_put(sas_device); @@ -9346,7 +9345,10 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) _scsih_sas_topology_change_event(ioc, fw_event); break; case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: - _scsih_sas_device_status_change_event(ioc, fw_event); + if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) + _scsih_sas_device_status_change_event_debug(ioc, + (Mpi2EventDataSasDeviceStatusChange_t *) + fw_event->event_data); break; case MPI2_EVENT_SAS_DISCOVERY: _scsih_sas_discovery_event(ioc, fw_event); @@ -9519,6 +9521,10 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, break; } case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: + _scsih_sas_device_status_change_event(ioc, + (Mpi2EventDataSasDeviceStatusChange_t *) + mpi_reply->EventData); + break; case MPI2_EVENT_IR_OPERATION_STATUS: case MPI2_EVENT_SAS_DISCOVERY: case MPI2_EVENT_SAS_DEVICE_DISCOVERY_ERROR: -- cgit v1.2.3-59-g8ed1b From 6e0b7ca281d764b5ae3d2cb97cf2dfe185e7b91e Mon Sep 17 00:00:00 2001 From: Suganath Prabu Date: Sat, 3 Aug 2019 09:59:57 -0400 Subject: scsi: mpt3sas: Update driver version to 31.100.00.00 Updated driver version from 29.100.00.00 to 31.100.00.00 which is equivalent to Phase 12 OOB. Signed-off-by: Suganath Prabu Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index f970a842ab23..745e0e13b7ab 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -76,8 +76,8 @@ #define MPT3SAS_DRIVER_NAME "mpt3sas" #define MPT3SAS_AUTHOR "Avago Technologies " #define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver" -#define MPT3SAS_DRIVER_VERSION "29.100.00.00" -#define MPT3SAS_MAJOR_VERSION 29 +#define MPT3SAS_DRIVER_VERSION "31.100.00.00" +#define MPT3SAS_MAJOR_VERSION 31 #define MPT3SAS_MINOR_VERSION 100 #define MPT3SAS_BUILD_VERSION 0 #define MPT3SAS_RELEASE_VERSION 00 -- cgit v1.2.3-59-g8ed1b From d2d2b5a5741d317bed1fa38211f1f3b142d8cf7a Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:22 -0700 Subject: scsi: qla2xxx: Make qla2x00_abort_srb() again decrease the sp reference count Since qla2x00_abort_srb() starts with increasing the reference count of @sp, decrease that same reference count before returning. Cc: Himanshu Madhani Fixes: 219d27d7147e ("scsi: qla2xxx: Fix race conditions in the code for aborting SCSI commands") # v5.2. Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 17a3f91ba5a3..b667f13b62df 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1755,6 +1755,8 @@ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, spin_lock_irqsave(qp->qp_lock_ptr, *flags); sp->comp = NULL; } + + atomic_dec(&sp->ref_count); } static void -- cgit v1.2.3-59-g8ed1b From 8dd9593cc07ad7d999bef81b06789ef873a94881 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:23 -0700 Subject: scsi: qla2xxx: Really fix qla2xxx_eh_abort() I'm not sure how this happened but the patch that was intended to fix abort handling was incomplete. This patch fixes that patch as follows: - If aborting the SCSI command failed, wait until the SCSI command completes. - Return SUCCESS instead of FAILED if an abort attempt races with SCSI command completion. - Since qla2xxx_eh_abort() increments the sp reference count by calling sp_get(), decrement the sp reference count before returning. Cc: Himanshu Madhani Fixes: 219d27d7147e ("scsi: qla2xxx: Fix race conditions in the code for aborting SCSI commands") Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index b667f13b62df..db1f1aac79f2 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1269,6 +1269,7 @@ static int qla2xxx_eh_abort(struct scsi_cmnd *cmd) { scsi_qla_host_t *vha = shost_priv(cmd->device->host); + DECLARE_COMPLETION_ONSTACK(comp); srb_t *sp; int ret; unsigned int id; @@ -1307,6 +1308,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) return SUCCESS; } + /* Get a reference to the sp and drop the lock. */ if (sp_get(sp)){ /* ref_count is already 0 */ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); @@ -1334,6 +1336,23 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) sp->done(sp, DID_ABORT << 16); ret = SUCCESS; break; + case QLA_FUNCTION_PARAMETER_ERROR: { + /* Wait for the command completion. */ + uint32_t ratov = ha->r_a_tov/10; + uint32_t ratov_j = msecs_to_jiffies(4 * ratov * 1000); + + WARN_ON_ONCE(sp->comp); + sp->comp = ∁ + if (!wait_for_completion_timeout(&comp, ratov_j)) { + ql_dbg(ql_dbg_taskm, vha, 0xffff, + "%s: Abort wait timer (4 * R_A_TOV[%d]) expired\n", + __func__, ha->r_a_tov); + ret = FAILED; + } else { + ret = SUCCESS; + } + break; + } default: /* * Either abort failed or abort and completion raced. Let @@ -1343,6 +1362,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) break; } + sp->comp = NULL; + atomic_dec(&sp->ref_count); ql_log(ql_log_info, vha, 0x801c, "Abort command issued nexus=%ld:%d:%llu -- %x.\n", vha->host_no, id, lun, ret); -- cgit v1.2.3-59-g8ed1b From c1c7178c26202db0856cb9189ccca043b95d13bc Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:24 -0700 Subject: scsi: qla2xxx: Improve Linux kernel coding style conformance Insert a space where required, surround complex expressions in macros with parentheses, use the UL suffix instead of the (unsigned long) cast, do not use line continuations when not necessary and do not explicitly initialize static variables to zero. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 10 +++++----- drivers/scsi/qla2xxx/qla_init.c | 2 +- drivers/scsi/qla2xxx/qla_iocb.c | 1 + drivers/scsi/qla2xxx/qla_nvme.c | 1 - drivers/scsi/qla2xxx/qla_nx.c | 10 +++++----- drivers/scsi/qla2xxx/qla_nx.h | 14 +++++++------- drivers/scsi/qla2xxx/qla_os.c | 6 +++--- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index b91ef7b75e8d..a94b0d440f0f 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -117,9 +117,9 @@ #define RD_REG_BYTE_RELAXED(addr) readb_relaxed(addr) #define RD_REG_WORD_RELAXED(addr) readw_relaxed(addr) #define RD_REG_DWORD_RELAXED(addr) readl_relaxed(addr) -#define WRT_REG_BYTE(addr, data) writeb(data,addr) -#define WRT_REG_WORD(addr, data) writew(data,addr) -#define WRT_REG_DWORD(addr, data) writel(data,addr) +#define WRT_REG_BYTE(addr, data) writeb(data, addr) +#define WRT_REG_WORD(addr, data) writew(data, addr) +#define WRT_REG_DWORD(addr, data) writel(data, addr) /* * ISP83XX specific remote register addresses @@ -207,7 +207,7 @@ * 133Mhz slot. */ #define RD_REG_WORD_PIO(addr) (inw((unsigned long)addr)) -#define WRT_REG_WORD_PIO(addr, data) (outw(data,(unsigned long)addr)) +#define WRT_REG_WORD_PIO(addr, data) (outw(data, (unsigned long)addr)) /* * Fibre Channel device definitions. @@ -3851,7 +3851,7 @@ struct qla_hw_data { /* NVRAM configuration data */ #define MAX_NVRAM_SIZE 4096 -#define VPD_OFFSET MAX_NVRAM_SIZE / 2 +#define VPD_OFFSET (MAX_NVRAM_SIZE / 2) uint16_t nvram_size; uint16_t nvram_base; void *nvram; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index d82d1a2b3543..3585eb7b87b5 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -5397,7 +5397,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport) "%s %8phN. rport %p is %s mode\n", __func__, fcport->port_name, rport, (fcport->port_type == FCT_TARGET) ? "tgt" : - ((fcport->port_type & FCT_NVME) ? "nvme" :"ini")); + ((fcport->port_type & FCT_NVME) ? "nvme" : "ini")); fc_remote_port_rolechg(rport, rport_ids.roles); } diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 1886de92034c..b514ab4d243e 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -1364,6 +1364,7 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, cur_dsd++; return 0; } + /** * qla24xx_build_scsi_crc_2_iocbs() - Build IOCB command utilizing Command * Type 6 IOCB types. diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index af7919a5acdc..16028ee8c7a7 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -267,7 +267,6 @@ static void qla_nvme_ls_abort(struct nvme_fc_local_port *lport, schedule_work(&priv->abort_work); } - static int qla_nvme_ls_req(struct nvme_fc_local_port *lport, struct nvme_fc_remote_port *rport, struct nvmefc_ls_req *fd) { diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index c760ae354174..c1c832271ccb 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -1985,7 +1985,7 @@ qla82xx_check_rcvpeg_state(struct qla_hw_data *ha) } /* ISR related functions */ -static struct qla82xx_legacy_intr_set legacy_intr[] = \ +static struct qla82xx_legacy_intr_set legacy_intr[] = QLA82XX_LEGACY_INTR_CONFIG; /* @@ -3286,7 +3286,7 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha) case QLA8XXX_DEV_NEED_QUIESCENT: qla82xx_need_qsnt_handler(vha); /* Reset timeout value after quiescence handler */ - dev_init_timeout = jiffies + (ha->fcoe_dev_init_timeout\ + dev_init_timeout = jiffies + (ha->fcoe_dev_init_timeout * HZ); break; case QLA8XXX_DEV_QUIESCENT: @@ -3301,7 +3301,7 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha) qla82xx_idc_lock(ha); /* Reset timeout value after quiescence handler */ - dev_init_timeout = jiffies + (ha->fcoe_dev_init_timeout\ + dev_init_timeout = jiffies + (ha->fcoe_dev_init_timeout * HZ); break; case QLA8XXX_DEV_FAILED: @@ -4232,7 +4232,7 @@ qla82xx_md_collect(scsi_qla_host_t *vha) goto md_failed; } - entry_hdr = (qla82xx_md_entry_hdr_t *) \ + entry_hdr = (qla82xx_md_entry_hdr_t *) (((uint8_t *)ha->md_tmplt_hdr) + tmplt_hdr->first_entry_offset); /* Walk through the entry headers */ @@ -4339,7 +4339,7 @@ qla82xx_md_collect(scsi_qla_host_t *vha) data_collected = (uint8_t *)data_ptr - (uint8_t *)ha->md_dump; skip_nxt_entry: - entry_hdr = (qla82xx_md_entry_hdr_t *) \ + entry_hdr = (qla82xx_md_entry_hdr_t *) (((uint8_t *)entry_hdr) + entry_hdr->entry_size); } diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h index 3c7beef92c35..230abee10598 100644 --- a/drivers/scsi/qla2xxx/qla_nx.h +++ b/drivers/scsi/qla2xxx/qla_nx.h @@ -486,13 +486,13 @@ #define QLA82XX_ADDR_QDR_NET (0x0000000300000000ULL) #define QLA82XX_P3_ADDR_QDR_NET_MAX (0x0000000303ffffffULL) -#define QLA82XX_PCI_CRBSPACE (unsigned long)0x06000000 -#define QLA82XX_PCI_DIRECT_CRB (unsigned long)0x04400000 -#define QLA82XX_PCI_CAMQM (unsigned long)0x04800000 -#define QLA82XX_PCI_CAMQM_MAX (unsigned long)0x04ffffff -#define QLA82XX_PCI_DDR_NET (unsigned long)0x00000000 -#define QLA82XX_PCI_QDR_NET (unsigned long)0x04000000 -#define QLA82XX_PCI_QDR_NET_MAX (unsigned long)0x043fffff +#define QLA82XX_PCI_CRBSPACE 0x06000000UL +#define QLA82XX_PCI_DIRECT_CRB 0x04400000UL +#define QLA82XX_PCI_CAMQM 0x04800000UL +#define QLA82XX_PCI_CAMQM_MAX 0x04ffffffUL +#define QLA82XX_PCI_DDR_NET 0x00000000UL +#define QLA82XX_PCI_QDR_NET 0x04000000UL +#define QLA82XX_PCI_QDR_NET_MAX 0x043fffffUL /* * Register offsets for MN diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index db1f1aac79f2..8f972e1b5215 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -69,7 +69,7 @@ MODULE_PARM_DESC(ql2xplogiabsentdevice, "a Fabric scan. This is needed for several broken switches. " "Default is 0 - no PLOGI. 1 - perform PLOGI."); -int ql2xloginretrycount = 0; +int ql2xloginretrycount; module_param(ql2xloginretrycount, int, S_IRUGO); MODULE_PARM_DESC(ql2xloginretrycount, "Specify an alternate value for the NVRAM login retry count."); @@ -234,7 +234,7 @@ MODULE_PARM_DESC(ql2xmdenable, "0 - MiniDump disabled. " "1 (Default) - MiniDump enabled."); -int ql2xexlogins = 0; +int ql2xexlogins; module_param(ql2xexlogins, uint, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(ql2xexlogins, "Number of extended Logins. " @@ -250,7 +250,7 @@ module_param(ql2xiniexchg, uint, 0644); MODULE_PARM_DESC(ql2xiniexchg, "Number of initiator exchanges."); -int ql2xfwholdabts = 0; +int ql2xfwholdabts; module_param(ql2xfwholdabts, int, S_IRUGO); MODULE_PARM_DESC(ql2xfwholdabts, "Allow FW to hold status IOCB until ABTS rsp received. " -- cgit v1.2.3-59-g8ed1b From 0184793df2e860534380a66aa76b8807e71188c2 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:25 -0700 Subject: scsi: qla2xxx: Use tabs instead of spaces for indentation This patch only modifies whitespace. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_gs.c | 78 +++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 749109c8f20b..7dc9eeb0c401 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3467,54 +3467,54 @@ done: void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea) { - fc_port_t *fcport = ea->fcport; + fc_port_t *fcport = ea->fcport; - qla24xx_post_gnl_work(vha, fcport); + qla24xx_post_gnl_work(vha, fcport); } void qla24xx_async_gffid_sp_done(void *s, int res) { - struct srb *sp = s; - struct scsi_qla_host *vha = sp->vha; - fc_port_t *fcport = sp->fcport; - struct ct_sns_rsp *ct_rsp; - struct event_arg ea; - - ql_dbg(ql_dbg_disc, vha, 0x2133, - "Async done-%s res %x ID %x. %8phC\n", - sp->name, res, fcport->d_id.b24, fcport->port_name); - - fcport->flags &= ~FCF_ASYNC_SENT; - ct_rsp = &fcport->ct_desc.ct_sns->p.rsp; - /* - * FC-GS-7, 5.2.3.12 FC-4 Features - format - * The format of the FC-4 Features object, as defined by the FC-4, - * Shall be an array of 4-bit values, one for each type code value - */ - if (!res) { - if (ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET] & 0xf) { - /* w1 b00:03 */ - fcport->fc4_type = - ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET]; - fcport->fc4_type &= 0xf; - } + struct srb *sp = s; + struct scsi_qla_host *vha = sp->vha; + fc_port_t *fcport = sp->fcport; + struct ct_sns_rsp *ct_rsp; + struct event_arg ea; + + ql_dbg(ql_dbg_disc, vha, 0x2133, + "Async done-%s res %x ID %x. %8phC\n", + sp->name, res, fcport->d_id.b24, fcport->port_name); - if (ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET] & 0xf) { - /* w5 [00:03]/28h */ - fcport->fc4f_nvme = - ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET]; - fcport->fc4f_nvme &= 0xf; + fcport->flags &= ~FCF_ASYNC_SENT; + ct_rsp = &fcport->ct_desc.ct_sns->p.rsp; + /* + * FC-GS-7, 5.2.3.12 FC-4 Features - format + * The format of the FC-4 Features object, as defined by the FC-4, + * Shall be an array of 4-bit values, one for each type code value + */ + if (!res) { + if (ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET] & 0xf) { + /* w1 b00:03 */ + fcport->fc4_type = + ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET]; + fcport->fc4_type &= 0xf; } - } - memset(&ea, 0, sizeof(ea)); - ea.sp = sp; - ea.fcport = sp->fcport; - ea.rc = res; - ea.event = FCME_GFFID_DONE; + if (ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET] & 0xf) { + /* w5 [00:03]/28h */ + fcport->fc4f_nvme = + ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET]; + fcport->fc4f_nvme &= 0xf; + } + } - qla2x00_fcport_event_handler(vha, &ea); - sp->free(sp); + memset(&ea, 0, sizeof(ea)); + ea.sp = sp; + ea.fcport = sp->fcport; + ea.rc = res; + ea.event = FCME_GFFID_DONE; + + qla2x00_fcport_event_handler(vha, &ea); + sp->free(sp); } /* Get FC4 Feature with Nport ID. */ -- cgit v1.2.3-59-g8ed1b From ba0cef2532717354d90ea81dc47837d61c98defc Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:26 -0700 Subject: scsi: qla2xxx: Include the header file from qla_dsd.h Since the put_unaligned_*() macros are used in this header file, include the header file that defines these macros. Cc: Himanshu Madhani Fixes: 15b7a68c1d03 ("scsi: qla2xxx: Introduce the dsd32 and dsd64 data structures") # v5.2-rc1. Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_dsd.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_dsd.h b/drivers/scsi/qla2xxx/qla_dsd.h index 7479924ba422..20788054b91b 100644 --- a/drivers/scsi/qla2xxx/qla_dsd.h +++ b/drivers/scsi/qla2xxx/qla_dsd.h @@ -1,6 +1,8 @@ #ifndef _QLA_DSD_H_ #define _QLA_DSD_H_ +#include + /* 32-bit data segment descriptor (8 bytes) */ struct dsd32 { __le32 address; -- cgit v1.2.3-59-g8ed1b From 3f5ee085d37d5e7ddb95e265853a395d289fb4d2 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:27 -0700 Subject: scsi: qla2xxx: Remove an include directive from qla_mr.c There is no bsg code in the qla_mr.c source file. Hence do not include the header file from qla_mr.c. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_mr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index 942ee13b96a4..cd892edec4dc 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3-59-g8ed1b From 36645232d9fccc3cea0e91499d1048f27db60f6f Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:28 -0700 Subject: scsi: qla2xxx: Remove a superfluous forward declaration Since qlt_make_local_sess() is defined before it is called, remove the forward declaration of that function. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index d0061ae1488e..4c5f9c02c379 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -4106,8 +4106,6 @@ static inline int qlt_get_fcp_task_attr(struct scsi_qla_host *vha, return fcp_task_attr; } -static struct fc_port *qlt_make_local_sess(struct scsi_qla_host *, - uint8_t *); /* * Process context for I/O path into tcm_qla2xxx code */ -- cgit v1.2.3-59-g8ed1b From c254b52b58b50a8599fefefd8793a64249b15044 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:29 -0700 Subject: scsi: qla2xxx: Declare the fourth ql_dump_buffer() argument const This patch makes it clear to humans and also to the compiler that ql_dump_buffer() does not modify the memory the @buf argument points at. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_dbg.c | 3 ++- drivers/scsi/qla2xxx/qla_gbl.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 9e80646722e2..30afc59c1870 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -2743,7 +2743,8 @@ ql_dump_regs(uint level, scsi_qla_host_t *vha, uint id) void -ql_dump_buffer(uint level, scsi_qla_host_t *vha, uint id, void *buf, uint size) +ql_dump_buffer(uint level, scsi_qla_host_t *vha, uint id, const void *buf, + uint size) { uint cnt; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index f9669fdf7798..6f6801722a09 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -630,7 +630,7 @@ extern ulong qla27xx_fwdt_template_size(void *); extern void qla2xxx_dump_post_process(scsi_qla_host_t *, int); extern void ql_dump_regs(uint, scsi_qla_host_t *, uint); -extern void ql_dump_buffer(uint, scsi_qla_host_t *, uint, void *, uint); +extern void ql_dump_buffer(uint, scsi_qla_host_t *, uint, const void *, uint); /* * Global Function Prototypes in qla_gs.c source file. */ -- cgit v1.2.3-59-g8ed1b From 909c1d1492b634b13a5d960e6803f0d2751509a0 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:30 -0700 Subject: scsi: qla2xxx: Change the return type of qla2x00_update_ms_fdmi_iocb() into void The value returned by this function is not used. Hence change the return type of this function into 'void' and remove the return statement. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_gs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 7dc9eeb0c401..5ec3c2b96f3f 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -1479,7 +1479,7 @@ qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size, return ct_pkt; } -static inline ms_iocb_entry_t * +static void qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size) { struct qla_hw_data *ha = vha->hw; @@ -1493,8 +1493,6 @@ qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size) ms_pkt->req_bytecount = cpu_to_le32(req_size); ms_pkt->req_dsd.length = ms_pkt->req_bytecount; } - - return ms_pkt; } /** -- cgit v1.2.3-59-g8ed1b From 6d58ef05fd33f0f48923d8ed0a8a002c268313e2 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:31 -0700 Subject: scsi: qla2xxx: Reduce the scope of three local variables in qla2xxx_queuecommand() This patch makes it clear that the tag, hwq and qpair variables are only used in the mq path. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 8f972e1b5215..a5acd5e2dfb1 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -845,9 +845,6 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); srb_t *sp; int rval; - struct qla_qpair *qpair = NULL; - uint32_t tag; - uint16_t hwq; if (unlikely(test_bit(UNLOADING, &base_vha->dpc_flags)) || WARN_ON_ONCE(!rport)) { @@ -856,6 +853,10 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) } if (ha->mqenable) { + uint32_t tag; + uint16_t hwq; + struct qla_qpair *qpair = NULL; + tag = blk_mq_unique_tag(cmd->request); hwq = blk_mq_unique_tag_to_hwq(tag); qpair = ha->queue_pair_map[hwq]; -- cgit v1.2.3-59-g8ed1b From bb6efb1ea639ac01184d057afc5c5f94496e348d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:32 -0700 Subject: scsi: qla2xxx: Declare qla_tgt_cmd.cdb const Make it clear that the CDB is not modified after processing of a SCSI command has started. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index b8d244f1e189..29d98757acff 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -912,7 +912,7 @@ struct qla_tgt_cmd { uint8_t scsi_status, sense_key, asc, ascq; struct crc_context *ctx; - uint8_t *cdb; + const uint8_t *cdb; uint64_t lba; uint16_t a_guard, e_guard, a_app_tag, e_app_tag; uint32_t a_ref_tag, e_ref_tag; -- cgit v1.2.3-59-g8ed1b From 9e75b5e2c8384080842015d26c9272fd55c0d798 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:33 -0700 Subject: scsi: qla2xxx: Change data_dsd into an array This patch does not change any functionality but fixes a Coverity complaint about using a scalar as an array. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 4 ++-- drivers/scsi/qla2xxx/qla_iocb.c | 4 ++-- drivers/scsi/qla2xxx/qla_target.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index a94b0d440f0f..1c6811bd5625 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -1852,7 +1852,7 @@ struct crc_context { uint16_t reserved_2; uint16_t reserved_3; uint32_t reserved_4; - struct dsd64 data_dsd; + struct dsd64 data_dsd[1]; uint32_t reserved_5[2]; uint32_t reserved_6; } nobundling; @@ -1862,7 +1862,7 @@ struct crc_context { uint16_t reserved_1; __le16 dseg_count; /* Data segment count */ uint32_t reserved_2; - struct dsd64 data_dsd; + struct dsd64 data_dsd[1]; struct dsd64 dif_dsd; } bundling; } u; diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index b514ab4d243e..6b120254f414 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -1516,7 +1516,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, } if (!bundling) { - cur_dsd = &crc_ctx_pkt->u.nobundling.data_dsd; + cur_dsd = &crc_ctx_pkt->u.nobundling.data_dsd[0]; } else { /* * Configure Bundling if we need to fetch interlaving @@ -1526,7 +1526,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, crc_ctx_pkt->u.bundling.dif_byte_count = cpu_to_le32(dif_bytes); crc_ctx_pkt->u.bundling.dseg_count = cpu_to_le16(tot_dsds - tot_prot_dsds); - cur_dsd = &crc_ctx_pkt->u.bundling.data_dsd; + cur_dsd = &crc_ctx_pkt->u.bundling.data_dsd[0]; } /* Finish the common fields of CRC pkt */ diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 4c5f9c02c379..b8241d7b1f8a 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -3163,7 +3163,7 @@ qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm) pkt->crc_context_len = CRC_CONTEXT_LEN_FW; if (!bundling) { - cur_dsd = &crc_ctx_pkt->u.nobundling.data_dsd; + cur_dsd = &crc_ctx_pkt->u.nobundling.data_dsd[0]; } else { /* * Configure Bundling if we need to fetch interlaving @@ -3173,7 +3173,7 @@ qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm) crc_ctx_pkt->u.bundling.dif_byte_count = cpu_to_le32(dif_bytes); crc_ctx_pkt->u.bundling.dseg_count = cpu_to_le16(prm->tot_dsds - prm->prot_seg_cnt); - cur_dsd = &crc_ctx_pkt->u.bundling.data_dsd; + cur_dsd = &crc_ctx_pkt->u.bundling.data_dsd[0]; } /* Finish the common fields of CRC pkt */ -- cgit v1.2.3-59-g8ed1b From 57bf595a6f24370424f625aac123cd12dbff5ffe Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:34 -0700 Subject: scsi: qla2xxx: Verify locking assumptions at runtime Make sure that locking assumptions are verified at runtime if kernel debugging is enabled. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index b8241d7b1f8a..ded5f13372af 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -789,6 +789,8 @@ qlt_plogi_ack_find_add(struct scsi_qla_host *vha, port_id_t *id, { struct qlt_plogi_ack_t *pla; + lockdep_assert_held(&vha->hw->hardware_lock); + list_for_each_entry(pla, &vha->plogi_ack_list, list) { if (pla->id.b24 == id->b24) { ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x210d, @@ -4713,6 +4715,8 @@ static int qlt_handle_login(struct scsi_qla_host *vha, struct qlt_plogi_ack_t *pla; unsigned long flags; + lockdep_assert_held(&vha->hw->hardware_lock); + wwn = wwn_to_u64(iocb->u.isp24.port_name); port_id.b.domain = iocb->u.isp24.port_id[2]; @@ -4886,6 +4890,8 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, int res = 0; unsigned long flags; + lockdep_assert_held(&ha->hardware_lock); + wwn = wwn_to_u64(iocb->u.isp24.port_name); port_id.b.domain = iocb->u.isp24.port_id[2]; @@ -5162,6 +5168,8 @@ static void qlt_handle_imm_notify(struct scsi_qla_host *vha, int send_notify_ack = 1; uint16_t status; + lockdep_assert_held(&ha->hardware_lock); + status = le16_to_cpu(iocb->u.isp2x.status); switch (status) { case IMM_NTFY_LIP_RESET: -- cgit v1.2.3-59-g8ed1b From 9c17c3b1e0490e436d17b63e8751b2fba030c0f7 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:35 -0700 Subject: scsi: qla2xxx: Reduce the number of casts in GID list code This patch makes the code that parses the GID list easier to read without changing the behavior of the code. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_dfs.c | 9 +++------ drivers/scsi/qla2xxx/qla_init.c | 18 ++++++++---------- drivers/scsi/qla2xxx/qla_target.c | 9 +++------ 3 files changed, 14 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c index a432caebefec..0a6fb359f4d5 100644 --- a/drivers/scsi/qla2xxx/qla_dfs.c +++ b/drivers/scsi/qla2xxx/qla_dfs.c @@ -57,10 +57,9 @@ qla2x00_dfs_tgt_port_database_show(struct seq_file *s, void *unused) { scsi_qla_host_t *vha = s->private; struct qla_hw_data *ha = vha->hw; - struct gid_list_info *gid_list; + struct gid_list_info *gid_list, *gid; dma_addr_t gid_list_dma; fc_port_t fc_port; - char *id_iter; int rc, i; uint16_t entries, loop_id; struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; @@ -82,13 +81,11 @@ qla2x00_dfs_tgt_port_database_show(struct seq_file *s, void *unused) if (rc != QLA_SUCCESS) goto out_free_id_list; - id_iter = (char *)gid_list; + gid = gid_list; seq_puts(s, "Port Name Port ID Loop ID\n"); for (i = 0; i < entries; i++) { - struct gid_list_info *gid = - (struct gid_list_info *)id_iter; loop_id = le16_to_cpu(gid->loop_id); memset(&fc_port, 0, sizeof(fc_port_t)); @@ -99,7 +96,7 @@ qla2x00_dfs_tgt_port_database_show(struct seq_file *s, void *unused) fc_port.port_name, fc_port.d_id.b.domain, fc_port.d_id.b.area, fc_port.d_id.b.al_pa, fc_port.loop_id); - id_iter += ha->gid_list_info_size; + gid = (void *)gid + ha->gid_list_info_size; } out_free_id_list: dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha), diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 3585eb7b87b5..c24d7667d3c9 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -5086,7 +5086,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) uint16_t index; uint16_t entries; - char *id_iter; + struct gid_list_info *gid; uint16_t loop_id; uint8_t domain, area, al_pa; struct qla_hw_data *ha = vha->hw; @@ -5161,18 +5161,16 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) new_fcport->flags &= ~FCF_FABRIC_DEVICE; /* Add devices to port list. */ - id_iter = (char *)ha->gid_list; + gid = ha->gid_list; for (index = 0; index < entries; index++) { - domain = ((struct gid_list_info *)id_iter)->domain; - area = ((struct gid_list_info *)id_iter)->area; - al_pa = ((struct gid_list_info *)id_iter)->al_pa; + domain = gid->domain; + area = gid->area; + al_pa = gid->al_pa; if (IS_QLA2100(ha) || IS_QLA2200(ha)) - loop_id = (uint16_t) - ((struct gid_list_info *)id_iter)->loop_id_2100; + loop_id = gid->loop_id_2100; else - loop_id = le16_to_cpu( - ((struct gid_list_info *)id_iter)->loop_id); - id_iter += ha->gid_list_info_size; + loop_id = le16_to_cpu(gid->loop_id); + gid = (void *)gid + ha->gid_list_info_size; /* Bypass reserved domain fields. */ if ((domain & 0xf0) == 0xf0) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index ded5f13372af..3a25536c2492 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -1290,8 +1290,7 @@ static int qla24xx_get_loop_id(struct scsi_qla_host *vha, const uint8_t *s_id, { struct qla_hw_data *ha = vha->hw; dma_addr_t gid_list_dma; - struct gid_list_info *gid_list; - char *id_iter; + struct gid_list_info *gid_list, *gid; int res, rc, i; uint16_t entries; @@ -1314,11 +1313,9 @@ static int qla24xx_get_loop_id(struct scsi_qla_host *vha, const uint8_t *s_id, goto out_free_id_list; } - id_iter = (char *)gid_list; + gid = gid_list; res = -ENOENT; for (i = 0; i < entries; i++) { - struct gid_list_info *gid = (struct gid_list_info *)id_iter; - if ((gid->al_pa == s_id[2]) && (gid->area == s_id[1]) && (gid->domain == s_id[0])) { @@ -1326,7 +1323,7 @@ static int qla24xx_get_loop_id(struct scsi_qla_host *vha, const uint8_t *s_id, res = 0; break; } - id_iter += ha->gid_list_info_size; + gid = (void *)gid + ha->gid_list_info_size; } out_free_id_list: -- cgit v1.2.3-59-g8ed1b From 09434912ed4c0b6948fee8b0bb1b058211ef4cac Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:36 -0700 Subject: scsi: qla2xxx: Simplify qlt_lport_dump() Simplify the implementation of this function by using the %phC format specifier instead of using explicit for-loops. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 3a25536c2492..221912da67c6 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -6497,22 +6497,10 @@ void qlt_remove_target_resources(struct qla_hw_data *ha) static void qlt_lport_dump(struct scsi_qla_host *vha, u64 wwpn, unsigned char *b) { - int i; - - pr_debug("qla2xxx HW vha->node_name: "); - for (i = 0; i < WWN_SIZE; i++) - pr_debug("%02x ", vha->node_name[i]); - pr_debug("\n"); - pr_debug("qla2xxx HW vha->port_name: "); - for (i = 0; i < WWN_SIZE; i++) - pr_debug("%02x ", vha->port_name[i]); - pr_debug("\n"); - - pr_debug("qla2xxx passed configfs WWPN: "); + pr_debug("qla2xxx HW vha->node_name: %8phC\n", vha->node_name); + pr_debug("qla2xxx HW vha->port_name: %8phC\n", vha->port_name); put_unaligned_be64(wwpn, b); - for (i = 0; i < WWN_SIZE; i++) - pr_debug("%02x ", b[i]); - pr_debug("\n"); + pr_debug("qla2xxx passed configfs WWPN: %8phC\n", b); } /** -- cgit v1.2.3-59-g8ed1b From 53be100b36aeca6bbc611edd07ce65fdba8b18ac Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:37 -0700 Subject: scsi: qla2xxx: Remove a superfluous pointer check Checking a pointer after it has been dereferenced is not useful. This was detected by Coverity. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_nvme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 16028ee8c7a7..bba25c38a118 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -222,7 +222,7 @@ static void qla_nvme_abort_work(struct work_struct *work) "%s called for sp=%p, hndl=%x on fcport=%p deleted=%d\n", __func__, sp, sp->handle, fcport, fcport->deleted); - if (!ha->flags.fw_started && (fcport && fcport->deleted)) + if (!ha->flags.fw_started && fcport->deleted) goto out; if (ha->flags.host_shutting_down) { -- cgit v1.2.3-59-g8ed1b From 8b21900b09a55ccee1aaddaabee729484f641997 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:38 -0700 Subject: scsi: qla2xxx: Remove two superfluous tests Since qlt_remove_target() only calls qlt_release() if vha->vha_tgt.qla_tgt != NULL, checking that pointer inside qlt_release() is not necessary. This patch fixes the following Coverity complaint: CID 188348 (#1 of 1): Dereference after null check (FORWARD_NULL) var_deref_model: Passing null pointer &vha->vha_tgt.qla_tgt->tgt_list_entry to list_del, which dereferences it. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 221912da67c6..12a3e77e0d02 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -1580,11 +1580,10 @@ static void qlt_release(struct qla_tgt *tgt) struct qla_qpair_hint *h; struct qla_hw_data *ha = vha->hw; - if ((vha->vha_tgt.qla_tgt != NULL) && !tgt->tgt_stop && - !tgt->tgt_stopped) + if (!tgt->tgt_stop && !tgt->tgt_stopped) qlt_stop_phase1(tgt); - if ((vha->vha_tgt.qla_tgt != NULL) && !tgt->tgt_stopped) + if (!tgt->tgt_stopped) qlt_stop_phase2(tgt); for (i = 0; i < vha->hw->max_qpairs + 1; i++) { -- cgit v1.2.3-59-g8ed1b From f1333c48a4ad472683fedae075d2dab6aa8c0273 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:39 -0700 Subject: scsi: qla2xxx: Simplify qla24xx_abort_sp_done() Instead of explicitly checking whether a timeout has occurred, ignore the del_timer() return value. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index c24d7667d3c9..cab5f2f90714 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -122,13 +122,11 @@ static void qla24xx_abort_sp_done(void *ptr, int res) srb_t *sp = ptr; struct srb_iocb *abt = &sp->u.iocb_cmd; - if ((res == QLA_OS_TIMER_EXPIRED) || - del_timer(&sp->u.iocb_cmd.timer)) { - if (sp->flags & SRB_WAKEUP_ON_COMP) - complete(&abt->u.abt.comp); - else - sp->free(sp); - } + del_timer(&sp->u.iocb_cmd.timer); + if (sp->flags & SRB_WAKEUP_ON_COMP) + complete(&abt->u.abt.comp); + else + sp->free(sp); } static int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait) -- cgit v1.2.3-59-g8ed1b From ac452b8e79320c9e90c78edf32ba2d42431e4daf Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:40 -0700 Subject: scsi: qla2xxx: Fix session lookup in qlt_abort_work() Pass the correct session ID to find_sess_by_s_id() instead of passing an uninitialized variable. Cc: Himanshu Madhani Fixes: 2d70c103fd2a ("[SCSI] qla2xxx: Add LLD target-mode infrastructure for >= 24xx series") # v3.5. Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 12a3e77e0d02..ea22e62257cb 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -6198,7 +6198,6 @@ static void qlt_abort_work(struct qla_tgt *tgt, struct qla_hw_data *ha = vha->hw; struct fc_port *sess = NULL; unsigned long flags = 0, flags2 = 0; - uint32_t be_s_id; uint8_t s_id[3]; int rc; @@ -6211,8 +6210,7 @@ static void qlt_abort_work(struct qla_tgt *tgt, s_id[1] = prm->abts.fcp_hdr_le.s_id[1]; s_id[2] = prm->abts.fcp_hdr_le.s_id[0]; - sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, - (unsigned char *)&be_s_id); + sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id); if (!sess) { spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2); -- cgit v1.2.3-59-g8ed1b From b3e9772d9ec5aed081ed06b1431a52945dc37ccf Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:41 -0700 Subject: scsi: qla2xxx: Report the firmware status code if a mailbox command fails It is helpful when debugging this driver to have the firmware status code available if a mailbox command fails. Hence report that firmware status code. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_mbx.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 133f5f6270ff..783a84606047 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -394,8 +394,12 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) goto premature_exit; } - if (ha->mailbox_out[0] != MBS_COMMAND_COMPLETE) + if (ha->mailbox_out[0] != MBS_COMMAND_COMPLETE) { + ql_dbg(ql_dbg_mbx, vha, 0x11ff, + "mb_out[0] = %#x <> %#x\n", ha->mailbox_out[0], + MBS_COMMAND_COMPLETE); rval = QLA_FUNCTION_FAILED; + } /* Load return mailbox registers. */ iptr2 = mcp->mb; -- cgit v1.2.3-59-g8ed1b From 1df627b4f7fa5b28ac10b39869c769373376d8f5 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:42 -0700 Subject: scsi: qla2xxx: Do not corrupt vha->plogi_ack_list Delete the PLOGIN ACK data structure from the vha->plogi_ack_list before freeing that data structure to avoid that that list gets corrupted. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 8 ++++++-- drivers/scsi/qla2xxx/qla_target.c | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index a5acd5e2dfb1..37e24987c852 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -5083,8 +5083,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) "%s %8phC mem alloc fail.\n", __func__, e->u.new_sess.port_name); - if (pla) + if (pla) { + list_del(&pla->list); kmem_cache_free(qla_tgt_plogi_cachep, pla); + } return; } @@ -5195,8 +5197,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) if (free_fcport) { qla2x00_free_fcport(fcport); - if (pla) + if (pla) { + list_del(&pla->list); kmem_cache_free(qla_tgt_plogi_cachep, pla); + } } } diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index ea22e62257cb..9cd5e2fba8ca 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -4796,8 +4796,10 @@ static int qlt_handle_login(struct scsi_qla_host *vha, __func__, sess->port_name, sec); } - if (!conflict_sess) + if (!conflict_sess) { + list_del(&pla->list); kmem_cache_free(qla_tgt_plogi_cachep, pla); + } qlt_send_term_imm_notif(vha, iocb, 1); goto out; -- cgit v1.2.3-59-g8ed1b From cc74049f35e84b6727c70589750c84e6166963ae Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:43 -0700 Subject: scsi: qla2xxx: Use strlcpy() instead of strncpy() This patch fixes several gcc complaints about string truncation. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_mr.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index cd892edec4dc..b6be7e7f2a43 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -1880,22 +1880,22 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) phost_info = &preg_hsi->hsi; memset(preg_hsi, 0, sizeof(struct register_host_info)); phost_info->os_type = OS_TYPE_LINUX; - strncpy(phost_info->sysname, - p_sysid->sysname, SYSNAME_LENGTH); - strncpy(phost_info->nodename, - p_sysid->nodename, NODENAME_LENGTH); + strlcpy(phost_info->sysname, p_sysid->sysname, + sizeof(phost_info->sysname)); + strlcpy(phost_info->nodename, p_sysid->nodename, + sizeof(phost_info->nodename)); if (!strcmp(phost_info->nodename, "(none)")) ha->mr.host_info_resend = true; - strncpy(phost_info->release, - p_sysid->release, RELEASE_LENGTH); - strncpy(phost_info->version, - p_sysid->version, VERSION_LENGTH); - strncpy(phost_info->machine, - p_sysid->machine, MACHINE_LENGTH); - strncpy(phost_info->domainname, - p_sysid->domainname, DOMNAME_LENGTH); - strncpy(phost_info->hostdriver, - QLA2XXX_VERSION, VERSION_LENGTH); + strlcpy(phost_info->release, p_sysid->release, + sizeof(phost_info->release)); + strlcpy(phost_info->version, p_sysid->version, + sizeof(phost_info->version)); + strlcpy(phost_info->machine, p_sysid->machine, + sizeof(phost_info->machine)); + strlcpy(phost_info->domainname, p_sysid->domainname, + sizeof(phost_info->domainname)); + strlcpy(phost_info->hostdriver, QLA2XXX_VERSION, + sizeof(phost_info->hostdriver)); preg_hsi->utc = (uint64_t)ktime_get_real_seconds(); ql_dbg(ql_dbg_init, vha, 0x0149, "ISP%04X: Host registration with firmware\n", -- cgit v1.2.3-59-g8ed1b From 58e060e11b0b18298208e5d0d1bd9bd98b4238a7 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:44 -0700 Subject: scsi: qla2xxx: Complain if a mailbox command times out This patch fixes the following Coverity complaint: Unchecked return value (CHECKED_RETURN) check_return: Calling wait_for_completion_timeout without checking return value (as is done elsewhere 14 out of 17 times). Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_mr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index b6be7e7f2a43..9e3f2f462a2e 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -148,7 +148,8 @@ qlafx00_mailbox_command(scsi_qla_host_t *vha, struct mbx_cmd_32 *mcp) QLAFX00_SET_HST_INTR(ha, ha->mbx_intr_code); spin_unlock_irqrestore(&ha->hardware_lock, flags); - wait_for_completion_timeout(&ha->mbx_intr_comp, mcp->tov * HZ); + WARN_ON_ONCE(wait_for_completion_timeout(&ha->mbx_intr_comp, + mcp->tov * HZ) != 0); } else { ql_dbg(ql_dbg_mbx, vha, 0x112c, "Cmd=%x Polling Mode.\n", command); -- cgit v1.2.3-59-g8ed1b From 6f153bcf12f4637673a24ee5393438251b82794c Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:45 -0700 Subject: scsi: qla2xxx: Complain if parsing the version string fails This patch fixes a Coverity complaint about not checking the sscanf() return value. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_tmpl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c index de696a07532e..7ed481dd8ee6 100644 --- a/drivers/scsi/qla2xxx/qla_tmpl.c +++ b/drivers/scsi/qla2xxx/qla_tmpl.c @@ -860,8 +860,9 @@ qla27xx_driver_info(struct qla27xx_fwdt_template *tmp) { uint8_t v[] = { 0, 0, 0, 0, 0, 0 }; - sscanf(qla2x00_version_str, "%hhu.%hhu.%hhu.%hhu.%hhu.%hhu", - v+0, v+1, v+2, v+3, v+4, v+5); + WARN_ON_ONCE(sscanf(qla2x00_version_str, + "%hhu.%hhu.%hhu.%hhu.%hhu.%hhu", + v+0, v+1, v+2, v+3, v+4, v+5) != 6); tmp->driver_info[0] = v[3] << 24 | v[2] << 16 | v[1] << 8 | v[0]; tmp->driver_info[1] = v[5] << 8 | v[4]; -- cgit v1.2.3-59-g8ed1b From 258f0752ef363caafb0bce311369d50c87aa0b25 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:46 -0700 Subject: scsi: qla2xxx: Remove dead code Since sess == NULL before 'goto out_term2' is executed, the code under 'if (sess)' cannot be reached. Hence remove that code. This was detected by Coverity. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 9cd5e2fba8ca..ba53329e8bf9 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -6249,9 +6249,6 @@ static void qlt_abort_work(struct qla_tgt *tgt, out_term2: spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2); - if (sess) - ha->tgt.tgt_ops->put_sess(sess); - out_term: spin_lock_irqsave(&ha->hardware_lock, flags); qlt_24xx_send_abts_resp(ha->base_qpair, &prm->abts, -- cgit v1.2.3-59-g8ed1b From 282d10565ee9b574c40b1233a7a666034e76aa4c Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:47 -0700 Subject: scsi: qla2xxx: Simplify a debug statement Read the FC port state once instead of twice. This patch fixes the following Coverity complaint: Unchecked return value (CHECKED_RETURN) check_return: Calling atomic_read without checking return value (as is done elsewhere 80 out of 92 times). Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_isr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index e8ce57cb897e..55eb51539cb0 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -2726,7 +2726,7 @@ check_scsi_status: "Port to be marked lost on fcport=%02x%02x%02x, current " "port state= %s comp_status %x.\n", fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa, - port_state_str[atomic_read(&fcport->state)], + port_state_str[FCS_ONLINE], comp_status); qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1); -- cgit v1.2.3-59-g8ed1b From c29282c65d1cf54daeea63be46243d7f69d72f4d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:48 -0700 Subject: scsi: qla2xxx: Fix qla24xx_process_bidir_cmd() Set the r??_data_len variables before using these instead of after. This patch fixes the following Coverity complaint: const: At condition req_data_len != rsp_data_len, the value of req_data_len must be equal to 0. const: At condition req_data_len != rsp_data_len, the value of rsp_data_len must be equal to 0. dead_error_condition: The condition req_data_len != rsp_data_len cannot be true. Cc: Himanshu Madhani Fixes: a9b6f722f62d ("[SCSI] qla2xxx: Implementation of bidirectional.") # v3.7. Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_bsg.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 11e420f8c493..240b07b0098a 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -1782,8 +1782,8 @@ qla24xx_process_bidir_cmd(struct bsg_job *bsg_job) uint16_t nextlid = 0; uint32_t tot_dsds; srb_t *sp = NULL; - uint32_t req_data_len = 0; - uint32_t rsp_data_len = 0; + uint32_t req_data_len; + uint32_t rsp_data_len; /* Check the type of the adapter */ if (!IS_BIDI_CAPABLE(ha)) { @@ -1888,6 +1888,9 @@ qla24xx_process_bidir_cmd(struct bsg_job *bsg_job) goto done_unmap_sg; } + req_data_len = bsg_job->request_payload.payload_len; + rsp_data_len = bsg_job->reply_payload.payload_len; + if (req_data_len != rsp_data_len) { rval = EXT_STATUS_BUSY; ql_log(ql_log_warn, vha, 0x70aa, @@ -1895,10 +1898,6 @@ qla24xx_process_bidir_cmd(struct bsg_job *bsg_job) goto done_unmap_sg; } - req_data_len = bsg_job->request_payload.payload_len; - rsp_data_len = bsg_job->reply_payload.payload_len; - - /* Alloc SRB structure */ sp = qla2x00_get_sp(vha, &(vha->bidir_fcport), GFP_KERNEL); if (!sp) { -- cgit v1.2.3-59-g8ed1b From 3a392b4f384a08919c93e5f751e9fffa1ad723e3 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:49 -0700 Subject: scsi: qla2xxx: Remove unreachable code from qla83xx_idc_lock() This was detected by Coverity. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 37e24987c852..2ba06a84c501 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -5720,7 +5720,6 @@ exit: void qla83xx_idc_lock(scsi_qla_host_t *base_vha, uint16_t requester_id) { - uint16_t options = (requester_id << 15) | BIT_6; uint32_t data; uint32_t lock_owner; struct qla_hw_data *ha = base_vha->hw; @@ -5753,22 +5752,6 @@ retry_lock: } return; - - /* XXX: IDC-lock implementation using access-control mbx */ -retry_lock2: - if (qla83xx_access_control(base_vha, options, 0, 0, NULL)) { - ql_dbg(ql_dbg_p3p, base_vha, 0xb072, - "Failed to acquire IDC lock. retrying...\n"); - /* Retry/Perform IDC-Lock recovery */ - if (qla83xx_idc_lock_recovery(base_vha) == QLA_SUCCESS) { - qla83xx_wait_logic(); - goto retry_lock2; - } else - ql_log(ql_log_warn, base_vha, 0xb076, - "IDC Lock recovery FAILED.\n"); - } - - return; } void -- cgit v1.2.3-59-g8ed1b From f91ff36a5731ca41f9009a00bf9f9b8e6c623dae Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:50 -0700 Subject: scsi: qla2xxx: Suppress a Coveritiy complaint about integer overflow This patch fixes the following Coverity complaint: Unintentional integer overflow (OVERFLOW_BEFORE_WIDEN) overflow_before_widen: Potentially overflowing expression dma_eng_num * 65536U with type unsigned int (32 bits, unsigned) is evaluated using 32-bit arithmetic, and then used in a context that expects an expression of type uint64_t (64 bits, unsigned). Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_nx2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_nx2.c b/drivers/scsi/qla2xxx/qla_nx2.c index 369ac04d0454..c056f466f1f4 100644 --- a/drivers/scsi/qla2xxx/qla_nx2.c +++ b/drivers/scsi/qla2xxx/qla_nx2.c @@ -2810,7 +2810,7 @@ error: #define ISP8044_PEX_DMA_ENGINE_INDEX 8 #define ISP8044_PEX_DMA_BASE_ADDRESS 0x77320000 -#define ISP8044_PEX_DMA_NUM_OFFSET 0x10000 +#define ISP8044_PEX_DMA_NUM_OFFSET 0x10000UL #define ISP8044_PEX_DMA_CMD_ADDR_LOW 0x0 #define ISP8044_PEX_DMA_CMD_ADDR_HIGH 0x04 #define ISP8044_PEX_DMA_CMD_STS_AND_CNTRL 0x08 -- cgit v1.2.3-59-g8ed1b From c4707fccb36412d3a5e58e426071ea2b220aab83 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:51 -0700 Subject: scsi: qla2xxx: Suppress multiple Coverity complaint about out-of-bounds accesses This patch does not change any functionality. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_gs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 5ec3c2b96f3f..33e0cf210332 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -1555,7 +1555,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha) /* Attributes */ ct_req->req.rhba.attrs.count = cpu_to_be32(FDMI_HBA_ATTR_COUNT); - entries = ct_req->req.rhba.hba_identifier; + entries = &ct_req->req; /* Nodename. */ eiter = entries + size; @@ -1764,7 +1764,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha) /* Attributes */ ct_req->req.rpa.attrs.count = cpu_to_be32(FDMI_PORT_ATTR_COUNT); - entries = ct_req->req.rpa.port_name; + entries = &ct_req->req; /* FC4 types. */ eiter = entries + size; @@ -1977,7 +1977,7 @@ qla2x00_fdmiv2_rhba(scsi_qla_host_t *vha) /* Attributes */ ct_req->req.rhba2.attrs.count = cpu_to_be32(FDMIV2_HBA_ATTR_COUNT); - entries = ct_req->req.rhba2.hba_identifier; + entries = &ct_req->req; /* Nodename. */ eiter = entries + size; @@ -2336,7 +2336,7 @@ qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha) /* Attributes */ ct_req->req.rpa2.attrs.count = cpu_to_be32(FDMIV2_PORT_ATTR_COUNT); - entries = ct_req->req.rpa2.port_name; + entries = &ct_req->req; /* FC4 types. */ eiter = entries + size; -- cgit v1.2.3-59-g8ed1b From e6803efae5acd109fad9f2f07dab674563441a53 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:52 -0700 Subject: scsi: qla2xxx: Always check the qla2x00_wait_for_hba_online() return value This patch fixes several Coverity complaints about not always checking the qla2x00_wait_for_hba_online() return value. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_attr.c | 3 ++- drivers/scsi/qla2xxx/qla_target.c | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 2b92d4659934..e3de20918efb 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -724,7 +724,8 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, break; } else { /* Make sure FC side is not in reset */ - qla2x00_wait_for_hba_online(vha); + WARN_ON_ONCE(qla2x00_wait_for_hba_online(vha) != + QLA_SUCCESS); /* Issue MPI reset */ scsi_block_requests(vha->host); diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index ba53329e8bf9..d20e0c21710e 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -6673,7 +6673,8 @@ qlt_enable_vha(struct scsi_qla_host *vha) } else { set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); qla2xxx_wake_dpc(base_vha); - qla2x00_wait_for_hba_online(base_vha); + WARN_ON_ONCE(qla2x00_wait_for_hba_online(base_vha) != + QLA_SUCCESS); } mutex_unlock(&ha->optrom_mutex); } @@ -6704,7 +6705,9 @@ static void qlt_disable_vha(struct scsi_qla_host *vha) set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); qla2xxx_wake_dpc(vha); - qla2x00_wait_for_hba_online(vha); + if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) + ql_dbg(ql_dbg_tgt, vha, 0xe081, + "qla2x00_wait_for_hba_online() failed\n"); } /* -- cgit v1.2.3-59-g8ed1b From bc97c9484baefe5092120b2b81c3993296ad14ad Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:53 -0700 Subject: scsi: qla2xxx: Declare fourth qla2x00_set_model_info() argument const Make it clear to humans and also to the compiler that the string passed as fourth argument is not modified. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_gbl.h | 4 ++-- drivers/scsi/qla2xxx/qla_init.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 6f6801722a09..fc54e7c86463 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -822,8 +822,8 @@ extern int qla82xx_device_state_handler(scsi_qla_host_t *); extern void qla8xxx_dev_failed_handler(scsi_qla_host_t *); extern void qla82xx_clear_qsnt_ready(scsi_qla_host_t *); -extern void qla2x00_set_model_info(scsi_qla_host_t *, uint8_t *, - size_t, char *); +extern void qla2x00_set_model_info(scsi_qla_host_t *, uint8_t *, size_t, + const char *); extern int qla82xx_mbx_intr_enable(scsi_qla_host_t *); extern int qla82xx_mbx_intr_disable(scsi_qla_host_t *); extern void qla82xx_start_iocbs(scsi_qla_host_t *); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index cab5f2f90714..1fd9a086748e 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -4426,7 +4426,7 @@ qla2x00_configure_hba(scsi_qla_host_t *vha) inline void qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, - char *def) + const char *def) { char *st, *en; uint16_t index; -- cgit v1.2.3-59-g8ed1b From fcef08932db7770cc176555ac2f08574b1e43af6 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:54 -0700 Subject: scsi: qla2xxx: Complain if waiting for pending commands times out Such a timeout is a severe issue. Hence complain if waiting for pending commands times out. This patch fixes a small bug: it modifies qla82xx_chip_reset_cleanup() such that the "Done waiting" message is reported if qla82xx_chip_reset_cleanup() succeeded instead of if that function failed. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 3 ++- drivers/scsi/qla2xxx/qla_nx.c | 4 +++- drivers/scsi/qla2xxx/qla_os.c | 7 +++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 1fd9a086748e..2d9a379fd8fb 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -6634,7 +6634,8 @@ qla2x00_quiesce_io(scsi_qla_host_t *vha) LOOP_DOWN_TIME); } /* Wait for pending cmds to complete */ - qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST); + WARN_ON_ONCE(qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST) + != QLA_SUCCESS); } void diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index c1c832271ccb..a91d426add75 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -3710,10 +3710,12 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha) /* Wait for pending cmds (physical and virtual) to complete */ if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, - WAIT_HOST)) { + WAIT_HOST) == QLA_SUCCESS) { ql_dbg(ql_dbg_init, vha, 0x00b3, "Done wait for " "pending commands.\n"); + } else { + WARN_ON_ONCE(true); } } } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2ba06a84c501..e91681cbd75d 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1059,8 +1059,8 @@ qc24_fail_command: * cmd = Scsi Command to wait on. * * Return: - * Not Found : 0 - * Found : 1 + * Completed in time : QLA_SUCCESS + * Did not complete in time : QLA_FUNCTION_FAILED */ static int qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd) @@ -1372,6 +1372,9 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) return ret; } +/* + * Returns: QLA_SUCCESS or QLA_FUNCTION_FAILED. + */ int qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, uint64_t l, enum nexus_wait_type type) -- cgit v1.2.3-59-g8ed1b From dc6d6d34e1f674b39d91454fca2b826e190e0351 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:55 -0700 Subject: scsi: qla2xxx: Check the PCI info string output buffer size Pass the output buffer size to the code that generates a PCI info string and check the output buffer size while generating a PCI info string. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_attr.c | 3 ++- drivers/scsi/qla2xxx/qla_def.h | 2 +- drivers/scsi/qla2xxx/qla_gbl.h | 2 +- drivers/scsi/qla2xxx/qla_mr.c | 8 +++--- drivers/scsi/qla2xxx/qla_os.c | 59 +++++++++++++++++------------------------ 5 files changed, 32 insertions(+), 42 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index e3de20918efb..e9c449ef515c 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1125,7 +1125,8 @@ qla2x00_pci_info_show(struct device *dev, struct device_attribute *attr, char pci_info[30]; return scnprintf(buf, PAGE_SIZE, "%s\n", - vha->hw->isp_ops->pci_info_str(vha, pci_info)); + vha->hw->isp_ops->pci_info_str(vha, pci_info, + sizeof(pci_info))); } static ssize_t diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 1c6811bd5625..8c8279ef3e32 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -3112,7 +3112,7 @@ struct isp_operations { void (*update_fw_options) (struct scsi_qla_host *); int (*load_risc) (struct scsi_qla_host *, uint32_t *); - char * (*pci_info_str) (struct scsi_qla_host *, char *); + char * (*pci_info_str)(struct scsi_qla_host *, char *, size_t); char * (*fw_version_str)(struct scsi_qla_host *, char *, size_t); irq_handler_t intr_handler; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index fc54e7c86463..2d9664086f15 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -732,7 +732,7 @@ extern int qlafx00_initialize_adapter(struct scsi_qla_host *); extern int qlafx00_soft_reset(scsi_qla_host_t *); extern int qlafx00_chip_diag(scsi_qla_host_t *); extern void qlafx00_config_rings(struct scsi_qla_host *); -extern char *qlafx00_pci_info_str(struct scsi_qla_host *, char *); +extern char *qlafx00_pci_info_str(struct scsi_qla_host *, char *, size_t); extern char *qlafx00_fw_version_str(struct scsi_qla_host *, char *, size_t); extern irqreturn_t qlafx00_intr_handler(int, void *); extern void qlafx00_enable_intrs(struct qla_hw_data *); diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index 9e3f2f462a2e..759fcfecc310 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -688,14 +688,12 @@ qlafx00_config_rings(struct scsi_qla_host *vha) } char * -qlafx00_pci_info_str(struct scsi_qla_host *vha, char *str) +qlafx00_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len) { struct qla_hw_data *ha = vha->hw; - if (pci_is_pcie(ha->pdev)) { - strcpy(str, "PCIe iSA"); - return str; - } + if (pci_is_pcie(ha->pdev)) + strlcpy(str, "PCIe iSA", str_len); return str; } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index e91681cbd75d..a247dce0cb95 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -536,80 +536,70 @@ static void qla2x00_free_queues(struct qla_hw_data *ha) } static char * -qla2x00_pci_info_str(struct scsi_qla_host *vha, char *str) +qla2x00_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len) { struct qla_hw_data *ha = vha->hw; - static char *pci_bus_modes[] = { + static const char *const pci_bus_modes[] = { "33", "66", "100", "133", }; uint16_t pci_bus; - strcpy(str, "PCI"); pci_bus = (ha->pci_attr & (BIT_9 | BIT_10)) >> 9; if (pci_bus) { - strcat(str, "-X ("); - strcat(str, pci_bus_modes[pci_bus]); + snprintf(str, str_len, "PCI-X (%s MHz)", + pci_bus_modes[pci_bus]); } else { pci_bus = (ha->pci_attr & BIT_8) >> 8; - strcat(str, " ("); - strcat(str, pci_bus_modes[pci_bus]); + snprintf(str, str_len, "PCI (%s MHz)", pci_bus_modes[pci_bus]); } - strcat(str, " MHz)"); - return (str); + return str; } static char * -qla24xx_pci_info_str(struct scsi_qla_host *vha, char *str) +qla24xx_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len) { - static char *pci_bus_modes[] = { "33", "66", "100", "133", }; + static const char *const pci_bus_modes[] = { + "33", "66", "100", "133", + }; struct qla_hw_data *ha = vha->hw; uint32_t pci_bus; if (pci_is_pcie(ha->pdev)) { - char lwstr[6]; uint32_t lstat, lspeed, lwidth; + const char *speed_str; pcie_capability_read_dword(ha->pdev, PCI_EXP_LNKCAP, &lstat); lspeed = lstat & PCI_EXP_LNKCAP_SLS; lwidth = (lstat & PCI_EXP_LNKCAP_MLW) >> 4; - strcpy(str, "PCIe ("); switch (lspeed) { case 1: - strcat(str, "2.5GT/s "); + speed_str = "2.5GT/s"; break; case 2: - strcat(str, "5.0GT/s "); + speed_str = "5.0GT/s"; break; case 3: - strcat(str, "8.0GT/s "); + speed_str = "8.0GT/s"; break; default: - strcat(str, " "); + speed_str = ""; break; } - snprintf(lwstr, sizeof(lwstr), "x%d)", lwidth); - strcat(str, lwstr); + snprintf(str, str_len, "PCIe (%s x%d)", speed_str, lwidth); return str; } - strcpy(str, "PCI"); pci_bus = (ha->pci_attr & CSRX_PCIX_BUS_MODE_MASK) >> 8; - if (pci_bus == 0 || pci_bus == 8) { - strcat(str, " ("); - strcat(str, pci_bus_modes[pci_bus >> 3]); - } else { - strcat(str, "-X "); - if (pci_bus & BIT_2) - strcat(str, "Mode 2"); - else - strcat(str, "Mode 1"); - strcat(str, " ("); - strcat(str, pci_bus_modes[pci_bus & ~BIT_2]); - } - strcat(str, " MHz)"); + if (pci_bus == 0 || pci_bus == 8) + snprintf(str, str_len, "PCI (%s MHz)", + pci_bus_modes[pci_bus >> 3]); + else + snprintf(str, str_len, "PCI-X Mode %d (%s MHz)", + pci_bus & 4 ? 2 : 1, + pci_bus_modes[pci_bus & 3]); return str; } @@ -3460,7 +3450,8 @@ skip_dpc: "QLogic %s - %s.\n", ha->model_number, ha->model_desc); ql_log(ql_log_info, base_vha, 0x00fc, "ISP%04X: %s @ %s hdma%c host#=%ld fw=%s.\n", - pdev->device, ha->isp_ops->pci_info_str(base_vha, pci_info), + pdev->device, ha->isp_ops->pci_info_str(base_vha, pci_info, + sizeof(pci_info)), pci_name(pdev), ha->flags.enable_64bit_addressing ? '+' : '-', base_vha->host_no, ha->isp_ops->fw_version_str(base_vha, fw_str, sizeof(fw_str))); -- cgit v1.2.3-59-g8ed1b From 527e9b704c3d46da1cd4061a5ce939456eac8566 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:56 -0700 Subject: scsi: qla2xxx: Use memcpy() and strlcpy() instead of strcpy() and strncpy() This patch makes the string manipulation code easier to verify. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 18 ++++++++++-------- drivers/scsi/qla2xxx/qla_mr.c | 6 ++++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 2d9a379fd8fb..5258d2486e25 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -4438,7 +4438,7 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, if (len > sizeof(zero)) len = sizeof(zero); if (memcmp(model, &zero, len) != 0) { - strncpy(ha->model_number, model, len); + memcpy(ha->model_number, model, len); st = en = ha->model_number; en += len - 1; while (en > st) { @@ -4451,21 +4451,23 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, if (use_tbl && ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && index < QLA_MODEL_NAMES) - strncpy(ha->model_desc, + strlcpy(ha->model_desc, qla2x00_model_name[index * 2 + 1], - sizeof(ha->model_desc) - 1); + sizeof(ha->model_desc)); } else { index = (ha->pdev->subsystem_device & 0xff); if (use_tbl && ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && index < QLA_MODEL_NAMES) { - strcpy(ha->model_number, - qla2x00_model_name[index * 2]); - strncpy(ha->model_desc, + strlcpy(ha->model_number, + qla2x00_model_name[index * 2], + sizeof(ha->model_number)); + strlcpy(ha->model_desc, qla2x00_model_name[index * 2 + 1], - sizeof(ha->model_desc) - 1); + sizeof(ha->model_desc)); } else { - strcpy(ha->model_number, def); + strlcpy(ha->model_number, def, + sizeof(ha->model_number)); } } if (IS_FWI2_CAPABLE(ha)) diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index 759fcfecc310..78b3679e1b9c 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -1939,8 +1939,10 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) if (fx_type == FXDISC_GET_CONFIG_INFO) { struct config_info_data *pinfo = (struct config_info_data *) fdisc->u.fxiocb.rsp_addr; - strcpy(vha->hw->model_number, pinfo->model_num); - strcpy(vha->hw->model_desc, pinfo->model_description); + strlcpy(vha->hw->model_number, pinfo->model_num, + ARRAY_SIZE(vha->hw->model_number)); + strlcpy(vha->hw->model_desc, pinfo->model_description, + ARRAY_SIZE(vha->hw->model_desc)); memcpy(&vha->hw->mr.symbolic_name, pinfo->symbolic_name, sizeof(vha->hw->mr.symbolic_name)); memcpy(&vha->hw->mr.serial_num, pinfo->serial_num, -- cgit v1.2.3-59-g8ed1b From fb3250974a484882caf10605ebff9ecb23773475 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:57 -0700 Subject: scsi: qla2xxx: Complain if a soft reset fails Failure of a soft reset is a severe failure. Hence report such failures. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_tmpl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c index 7ed481dd8ee6..294d77c02cdf 100644 --- a/drivers/scsi/qla2xxx/qla_tmpl.c +++ b/drivers/scsi/qla2xxx/qla_tmpl.c @@ -429,7 +429,7 @@ qla27xx_fwdt_entry_t266(struct scsi_qla_host *vha, ql_dbg(ql_dbg_misc, vha, 0xd20a, "%s: reset risc [%lx]\n", __func__, *len); if (buf) - qla24xx_soft_reset(vha->hw); + WARN_ON_ONCE(qla24xx_soft_reset(vha->hw) != QLA_SUCCESS); return qla27xx_next_entry(ent); } -- cgit v1.2.3-59-g8ed1b From df95f39ae76474d922d9be9c0260dc263c451b09 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:58 -0700 Subject: scsi: qla2xxx: Introduce the be_id_t and le_id_t data types for FC src/dst IDs Introduce the be_id_t and le_id_t data types for Fibre Channel source and destination ID formats supported by the firmware instead of using an uint8_t[3] array. Introduce functions for converting from and to the port_id_t data types. This patch does not change the behavior of the qla2xxx driver but improves source code readability and also allows the compiler to verify the endianness of Fibre Channel IDs. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 71 +++++++++++++++++++-- drivers/scsi/qla2xxx/qla_gs.c | 62 +++++------------- drivers/scsi/qla2xxx/qla_nvme.h | 2 +- drivers/scsi/qla2xxx/qla_target.c | 126 +++++++++++++------------------------ drivers/scsi/qla2xxx/qla_target.h | 33 ++++------ drivers/scsi/qla2xxx/tcm_qla2xxx.c | 23 ++----- 6 files changed, 144 insertions(+), 173 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 8c8279ef3e32..779bf3fcab0f 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -34,6 +34,20 @@ #include #include +/* Big endian Fibre Channel S_ID (source ID) or D_ID (destination ID). */ +typedef struct { + uint8_t domain; + uint8_t area; + uint8_t al_pa; +} be_id_t; + +/* Little endian Fibre Channel S_ID (source ID) or D_ID (destination ID). */ +typedef struct { + uint8_t al_pa; + uint8_t area; + uint8_t domain; +} le_id_t; + #include "qla_bsg.h" #include "qla_dsd.h" #include "qla_nx.h" @@ -343,6 +357,51 @@ typedef union { } port_id_t; #define INVALID_PORT_ID 0xFFFFFF +static inline le_id_t be_id_to_le(be_id_t id) +{ + le_id_t res; + + res.domain = id.domain; + res.area = id.area; + res.al_pa = id.al_pa; + + return res; +} + +static inline be_id_t le_id_to_be(le_id_t id) +{ + be_id_t res; + + res.domain = id.domain; + res.area = id.area; + res.al_pa = id.al_pa; + + return res; +} + +static inline port_id_t be_to_port_id(be_id_t id) +{ + port_id_t res; + + res.b.domain = id.domain; + res.b.area = id.area; + res.b.al_pa = id.al_pa; + res.b.rsvd_1 = 0; + + return res; +} + +static inline be_id_t port_id_to_be_id(port_id_t port_id) +{ + be_id_t res; + + res.domain = port_id.b.domain; + res.area = port_id.b.area; + res.al_pa = port_id.b.al_pa; + + return res; +} + struct els_logo_payload { uint8_t opcode; uint8_t rsvd[3]; @@ -2746,7 +2805,7 @@ struct ct_sns_req { /* GA_NXT, GPN_ID, GNN_ID, GFT_ID, GFPN_ID */ struct { uint8_t reserved; - uint8_t port_id[3]; + be_id_t port_id; } port_id; struct { @@ -2765,13 +2824,13 @@ struct ct_sns_req { struct { uint8_t reserved; - uint8_t port_id[3]; + be_id_t port_id; uint8_t fc4_types[32]; } rft_id; struct { uint8_t reserved; - uint8_t port_id[3]; + be_id_t port_id; uint16_t reserved2; uint8_t fc4_feature; uint8_t fc4_type; @@ -2779,7 +2838,7 @@ struct ct_sns_req { struct { uint8_t reserved; - uint8_t port_id[3]; + be_id_t port_id; uint8_t node_name[8]; } rnn_id; @@ -2866,7 +2925,7 @@ struct ct_rsp_hdr { struct ct_sns_gid_pt_data { uint8_t control_byte; - uint8_t port_id[3]; + be_id_t port_id; }; /* It's the same for both GPN_FT and GNN_FT */ @@ -2896,7 +2955,7 @@ struct ct_sns_rsp { union { struct { uint8_t port_type; - uint8_t port_id[3]; + be_id_t port_id; uint8_t port_name[8]; uint8_t sym_port_name_len; uint8_t sym_port_name[255]; diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 33e0cf210332..18117b5f32bc 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -226,9 +226,7 @@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport) ct_rsp = &ha->ct_sns->p.rsp; /* Prepare CT arguments -- port_id */ - ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain; - ct_req->req.port_id.port_id[1] = fcport->d_id.b.area; - ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa; + ct_req->req.port_id.port_id = port_id_to_be_id(fcport->d_id); /* Execute MS IOCB */ rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, @@ -242,9 +240,7 @@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport) rval = QLA_FUNCTION_FAILED; } else { /* Populate fc_port_t entry. */ - fcport->d_id.b.domain = ct_rsp->rsp.ga_nxt.port_id[0]; - fcport->d_id.b.area = ct_rsp->rsp.ga_nxt.port_id[1]; - fcport->d_id.b.al_pa = ct_rsp->rsp.ga_nxt.port_id[2]; + fcport->d_id = be_to_port_id(ct_rsp->rsp.ga_nxt.port_id); memcpy(fcport->node_name, ct_rsp->rsp.ga_nxt.node_name, WWN_SIZE); @@ -337,9 +333,7 @@ qla2x00_gid_pt(scsi_qla_host_t *vha, sw_info_t *list) /* Set port IDs in switch info list. */ for (i = 0; i < ha->max_fibre_devices; i++) { gid_data = &ct_rsp->rsp.gid_pt.entries[i]; - list[i].d_id.b.domain = gid_data->port_id[0]; - list[i].d_id.b.area = gid_data->port_id[1]; - list[i].d_id.b.al_pa = gid_data->port_id[2]; + list[i].d_id = be_to_port_id(gid_data->port_id); memset(list[i].fabric_port_name, 0, WWN_SIZE); list[i].fp_speed = PORT_SPEED_UNKNOWN; @@ -403,9 +397,7 @@ qla2x00_gpn_id(scsi_qla_host_t *vha, sw_info_t *list) ct_rsp = &ha->ct_sns->p.rsp; /* Prepare CT arguments -- port_id */ - ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain; - ct_req->req.port_id.port_id[1] = list[i].d_id.b.area; - ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa; + ct_req->req.port_id.port_id = port_id_to_be_id(list[i].d_id); /* Execute MS IOCB */ rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, @@ -472,9 +464,7 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list) ct_rsp = &ha->ct_sns->p.rsp; /* Prepare CT arguments -- port_id */ - ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain; - ct_req->req.port_id.port_id[1] = list[i].d_id.b.area; - ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa; + ct_req->req.port_id.port_id = port_id_to_be_id(list[i].d_id); /* Execute MS IOCB */ rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, @@ -639,9 +629,7 @@ static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id) ct_req = qla2x00_prep_ct_req(ct_sns, RFT_ID_CMD, RFT_ID_RSP_SIZE); /* Prepare CT arguments -- port_id, FC-4 types */ - ct_req->req.rft_id.port_id[0] = vha->d_id.b.domain; - ct_req->req.rft_id.port_id[1] = vha->d_id.b.area; - ct_req->req.rft_id.port_id[2] = vha->d_id.b.al_pa; + ct_req->req.rft_id.port_id = port_id_to_be_id(vha->d_id); ct_req->req.rft_id.fc4_types[2] = 0x01; /* FCP-3 */ if (vha->flags.nvme_enabled) @@ -737,9 +725,7 @@ static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id, ct_req = qla2x00_prep_ct_req(ct_sns, RFF_ID_CMD, RFF_ID_RSP_SIZE); /* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */ - ct_req->req.rff_id.port_id[0] = d_id->b.domain; - ct_req->req.rff_id.port_id[1] = d_id->b.area; - ct_req->req.rff_id.port_id[2] = d_id->b.al_pa; + ct_req->req.rff_id.port_id = port_id_to_be_id(*d_id); ct_req->req.rff_id.fc4_feature = fc4feature; ct_req->req.rff_id.fc4_type = fc4type; /* SCSI - FCP */ @@ -830,9 +816,7 @@ static int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t *d_id, ct_req = qla2x00_prep_ct_req(ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE); /* Prepare CT arguments -- port_id, node_name */ - ct_req->req.rnn_id.port_id[0] = vha->d_id.b.domain; - ct_req->req.rnn_id.port_id[1] = vha->d_id.b.area; - ct_req->req.rnn_id.port_id[2] = vha->d_id.b.al_pa; + ct_req->req.rnn_id.port_id = port_id_to_be_id(vha->d_id); memcpy(ct_req->req.rnn_id.node_name, vha->node_name, WWN_SIZE); sp->u.iocb_cmd.u.ctarg.req_size = RNN_ID_REQ_SIZE; @@ -2728,9 +2712,7 @@ qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list) ct_rsp = &ha->ct_sns->p.rsp; /* Prepare CT arguments -- port_id */ - ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain; - ct_req->req.port_id.port_id[1] = list[i].d_id.b.area; - ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa; + ct_req->req.port_id.port_id = port_id_to_be_id(list[i].d_id); /* Execute MS IOCB */ rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, @@ -2934,9 +2916,7 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list) ct_rsp = &ha->ct_sns->p.rsp; /* Prepare CT arguments -- port_id */ - ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain; - ct_req->req.port_id.port_id[1] = list[i].d_id.b.area; - ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa; + ct_req->req.port_id.port_id = port_id_to_be_id(list[i].d_id); /* Execute MS IOCB */ rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, @@ -3293,20 +3273,18 @@ static void qla2x00_async_gpnid_sp_done(void *s, int res) if (res) ql_dbg(ql_dbg_disc, vha, 0x2066, "Async done-%s fail res %x rscn gen %d ID %3phC. %8phC\n", - sp->name, res, sp->gen1, ct_req->req.port_id.port_id, + sp->name, res, sp->gen1, &ct_req->req.port_id.port_id, ct_rsp->rsp.gpn_id.port_name); else ql_dbg(ql_dbg_disc, vha, 0x2066, "Async done-%s good rscn gen %d ID %3phC. %8phC\n", - sp->name, sp->gen1, ct_req->req.port_id.port_id, + sp->name, sp->gen1, &ct_req->req.port_id.port_id, ct_rsp->rsp.gpn_id.port_name); memset(&ea, 0, sizeof(ea)); memcpy(ea.port_name, ct_rsp->rsp.gpn_id.port_name, WWN_SIZE); ea.sp = sp; - ea.id.b.domain = ct_req->req.port_id.port_id[0]; - ea.id.b.area = ct_req->req.port_id.port_id[1]; - ea.id.b.al_pa = ct_req->req.port_id.port_id[2]; + ea.id = be_to_port_id(ct_req->req.port_id.port_id); ea.rc = res; ea.event = FCME_GPNID_DONE; @@ -3417,9 +3395,7 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id) ct_req = qla2x00_prep_ct_req(ct_sns, GPN_ID_CMD, GPN_ID_RSP_SIZE); /* GPN_ID req */ - ct_req->req.port_id.port_id[0] = id->b.domain; - ct_req->req.port_id.port_id[1] = id->b.area; - ct_req->req.port_id.port_id[2] = id->b.al_pa; + ct_req->req.port_id.port_id = port_id_to_be_id(*id); sp->u.iocb_cmd.u.ctarg.req_size = GPN_ID_REQ_SIZE; sp->u.iocb_cmd.u.ctarg.rsp_size = GPN_ID_RSP_SIZE; @@ -3430,7 +3406,7 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id) ql_dbg(ql_dbg_disc, vha, 0x2067, "Async-%s hdl=%x ID %3phC.\n", sp->name, - sp->handle, ct_req->req.port_id.port_id); + sp->handle, &ct_req->req.port_id.port_id); rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) @@ -4332,9 +4308,7 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport) GNN_ID_RSP_SIZE); /* GNN_ID req */ - ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain; - ct_req->req.port_id.port_id[1] = fcport->d_id.b.area; - ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa; + ct_req->req.port_id.port_id = port_id_to_be_id(fcport->d_id); /* req & rsp use the same buffer */ @@ -4464,9 +4438,7 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport) GFPN_ID_RSP_SIZE); /* GFPN_ID req */ - ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain; - ct_req->req.port_id.port_id[1] = fcport->d_id.b.area; - ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa; + ct_req->req.port_id.port_id = port_id_to_be_id(fcport->d_id); /* req & rsp use the same buffer */ diff --git a/drivers/scsi/qla2xxx/qla_nvme.h b/drivers/scsi/qla2xxx/qla_nvme.h index 67bb4a2a3742..68a8d09a36ef 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.h +++ b/drivers/scsi/qla2xxx/qla_nvme.h @@ -119,7 +119,7 @@ struct pt_ls4_rx_unsol { uint32_t exchange_address; uint8_t d_id[3]; uint8_t r_ctl; - uint8_t s_id[3]; + be_id_t s_id; uint8_t cs_ctl; uint8_t f_ctl[3]; uint8_t type; diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index d20e0c21710e..3dd897d3e400 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -188,18 +188,19 @@ static inline int qlt_issue_marker(struct scsi_qla_host *vha, int vha_locked) static inline struct scsi_qla_host *qlt_find_host_by_d_id(struct scsi_qla_host *vha, - uint8_t *d_id) + be_id_t d_id) { struct scsi_qla_host *host; uint32_t key = 0; - if ((vha->d_id.b.area == d_id[1]) && (vha->d_id.b.domain == d_id[0]) && - (vha->d_id.b.al_pa == d_id[2])) + if (vha->d_id.b.area == d_id.area && + vha->d_id.b.domain == d_id.domain && + vha->d_id.b.al_pa == d_id.al_pa) return vha; - key = (uint32_t)d_id[0] << 16; - key |= (uint32_t)d_id[1] << 8; - key |= (uint32_t)d_id[2]; + key = d_id.domain << 16; + key |= d_id.area << 8; + key |= d_id.al_pa; host = btree_lookup32(&vha->hw->tgt.host_map, key); if (!host) @@ -357,9 +358,9 @@ static bool qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha, ql_dbg(ql_dbg_tgt, vha, 0xe03e, "qla_target(%d): Received ATIO_TYPE7 " "with unknown d_id %x:%x:%x\n", vha->vp_idx, - atio->u.isp24.fcp_hdr.d_id[0], - atio->u.isp24.fcp_hdr.d_id[1], - atio->u.isp24.fcp_hdr.d_id[2]); + atio->u.isp24.fcp_hdr.d_id.domain, + atio->u.isp24.fcp_hdr.d_id.area, + atio->u.isp24.fcp_hdr.d_id.al_pa); qlt_queue_unknown_atio(vha, atio, ha_locked); @@ -1285,7 +1286,7 @@ static void qlt_clear_tgt_db(struct qla_tgt *tgt) /* At this point tgt could be already dead */ } -static int qla24xx_get_loop_id(struct scsi_qla_host *vha, const uint8_t *s_id, +static int qla24xx_get_loop_id(struct scsi_qla_host *vha, be_id_t s_id, uint16_t *loop_id) { struct qla_hw_data *ha = vha->hw; @@ -1316,9 +1317,9 @@ static int qla24xx_get_loop_id(struct scsi_qla_host *vha, const uint8_t *s_id, gid = gid_list; res = -ENOENT; for (i = 0; i < entries; i++) { - if ((gid->al_pa == s_id[2]) && - (gid->area == s_id[1]) && - (gid->domain == s_id[0])) { + if (gid->al_pa == s_id.al_pa && + gid->area == s_id.area && + gid->domain == s_id.domain) { *loop_id = le16_to_cpu(gid->loop_id); res = 0; break; @@ -1769,12 +1770,8 @@ static int qlt_build_abts_resp_iocb(struct qla_tgt_mgmt_cmd *mcmd) resp->fcp_hdr_le.f_ctl[1] = *p++; resp->fcp_hdr_le.f_ctl[2] = *p; - resp->fcp_hdr_le.d_id[0] = abts->fcp_hdr_le.s_id[0]; - resp->fcp_hdr_le.d_id[1] = abts->fcp_hdr_le.s_id[1]; - resp->fcp_hdr_le.d_id[2] = abts->fcp_hdr_le.s_id[2]; - resp->fcp_hdr_le.s_id[0] = abts->fcp_hdr_le.d_id[0]; - resp->fcp_hdr_le.s_id[1] = abts->fcp_hdr_le.d_id[1]; - resp->fcp_hdr_le.s_id[2] = abts->fcp_hdr_le.d_id[2]; + resp->fcp_hdr_le.d_id = abts->fcp_hdr_le.s_id; + resp->fcp_hdr_le.s_id = abts->fcp_hdr_le.d_id; resp->exchange_addr_to_abort = abts->exchange_addr_to_abort; if (mcmd->fc_tm_rsp == FCP_TMF_CMPL) { @@ -1845,19 +1842,11 @@ static void qlt_24xx_send_abts_resp(struct qla_qpair *qpair, resp->fcp_hdr_le.f_ctl[1] = *p++; resp->fcp_hdr_le.f_ctl[2] = *p; if (ids_reversed) { - resp->fcp_hdr_le.d_id[0] = abts->fcp_hdr_le.d_id[0]; - resp->fcp_hdr_le.d_id[1] = abts->fcp_hdr_le.d_id[1]; - resp->fcp_hdr_le.d_id[2] = abts->fcp_hdr_le.d_id[2]; - resp->fcp_hdr_le.s_id[0] = abts->fcp_hdr_le.s_id[0]; - resp->fcp_hdr_le.s_id[1] = abts->fcp_hdr_le.s_id[1]; - resp->fcp_hdr_le.s_id[2] = abts->fcp_hdr_le.s_id[2]; + resp->fcp_hdr_le.d_id = abts->fcp_hdr_le.d_id; + resp->fcp_hdr_le.s_id = abts->fcp_hdr_le.s_id; } else { - resp->fcp_hdr_le.d_id[0] = abts->fcp_hdr_le.s_id[0]; - resp->fcp_hdr_le.d_id[1] = abts->fcp_hdr_le.s_id[1]; - resp->fcp_hdr_le.d_id[2] = abts->fcp_hdr_le.s_id[2]; - resp->fcp_hdr_le.s_id[0] = abts->fcp_hdr_le.d_id[0]; - resp->fcp_hdr_le.s_id[1] = abts->fcp_hdr_le.d_id[1]; - resp->fcp_hdr_le.s_id[2] = abts->fcp_hdr_le.d_id[2]; + resp->fcp_hdr_le.d_id = abts->fcp_hdr_le.s_id; + resp->fcp_hdr_le.s_id = abts->fcp_hdr_le.d_id; } resp->exchange_addr_to_abort = abts->exchange_addr_to_abort; if (status == FCP_TMF_CMPL) { @@ -1924,18 +1913,14 @@ static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha, tmp = (CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_TERMINATE); if (mcmd) { - ctio->initiator_id[0] = entry->fcp_hdr_le.s_id[0]; - ctio->initiator_id[1] = entry->fcp_hdr_le.s_id[1]; - ctio->initiator_id[2] = entry->fcp_hdr_le.s_id[2]; + ctio->initiator_id = entry->fcp_hdr_le.s_id; if (mcmd->flags & QLA24XX_MGMT_ABORT_IO_ATTR_VALID) tmp |= (mcmd->abort_io_attr << 9); else if (qpair->retry_term_cnt & 1) tmp |= (0x4 << 9); } else { - ctio->initiator_id[0] = entry->fcp_hdr_le.d_id[0]; - ctio->initiator_id[1] = entry->fcp_hdr_le.d_id[1]; - ctio->initiator_id[2] = entry->fcp_hdr_le.d_id[2]; + ctio->initiator_id = entry->fcp_hdr_le.d_id; if (qpair->retry_term_cnt & 1) tmp |= (0x4 << 9); @@ -1969,8 +1954,7 @@ static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha, * XXX does not go through the list of other port (which may have cmds * for the same lun) */ -static void abort_cmds_for_lun(struct scsi_qla_host *vha, - u64 lun, uint8_t *s_id) +static void abort_cmds_for_lun(struct scsi_qla_host *vha, u64 lun, be_id_t s_id) { struct qla_tgt_sess_op *op; struct qla_tgt_cmd *cmd; @@ -2146,7 +2130,7 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha, struct qla_hw_data *ha = vha->hw; struct fc_port *sess; uint32_t tag = abts->exchange_addr_to_abort; - uint8_t s_id[3]; + be_id_t s_id; int rc; unsigned long flags; @@ -2170,13 +2154,11 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf011, "qla_target(%d): task abort (s_id=%x:%x:%x, " - "tag=%d, param=%x)\n", vha->vp_idx, abts->fcp_hdr_le.s_id[2], - abts->fcp_hdr_le.s_id[1], abts->fcp_hdr_le.s_id[0], tag, + "tag=%d, param=%x)\n", vha->vp_idx, abts->fcp_hdr_le.s_id.domain, + abts->fcp_hdr_le.s_id.area, abts->fcp_hdr_le.s_id.al_pa, tag, le32_to_cpu(abts->fcp_hdr_le.parameter)); - s_id[0] = abts->fcp_hdr_le.s_id[2]; - s_id[1] = abts->fcp_hdr_le.s_id[1]; - s_id[2] = abts->fcp_hdr_le.s_id[0]; + s_id = le_id_to_be(abts->fcp_hdr_le.s_id); spin_lock_irqsave(&ha->tgt.sess_lock, flags); sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id); @@ -2240,9 +2222,7 @@ static void qlt_24xx_send_task_mgmt_ctio(struct qla_qpair *qpair, ctio->nport_handle = mcmd->sess->loop_id; ctio->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); ctio->vp_index = ha->vp_idx; - ctio->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; - ctio->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; - ctio->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; + ctio->initiator_id = be_id_to_le(atio->u.isp24.fcp_hdr.s_id); ctio->exchange_addr = atio->u.isp24.exchange_addr; temp = (atio->u.isp24.attr << 9)| CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS; @@ -2299,9 +2279,7 @@ void qlt_send_resp_ctio(struct qla_qpair *qpair, struct qla_tgt_cmd *cmd, ctio->nport_handle = cmd->sess->loop_id; ctio->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); ctio->vp_index = vha->vp_idx; - ctio->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; - ctio->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; - ctio->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; + ctio->initiator_id = be_id_to_le(atio->u.isp24.fcp_hdr.s_id); ctio->exchange_addr = atio->u.isp24.exchange_addr; temp = (atio->u.isp24.attr << 9) | CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS; @@ -2602,9 +2580,7 @@ static int qlt_24xx_build_ctio_pkt(struct qla_qpair *qpair, pkt->handle |= CTIO_COMPLETION_HANDLE_MARK; pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id); pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); - pkt->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; - pkt->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; - pkt->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; + pkt->initiator_id = be_id_to_le(atio->u.isp24.fcp_hdr.s_id); pkt->exchange_addr = atio->u.isp24.exchange_addr; temp = atio->u.isp24.attr << 9; pkt->u.status0.flags |= cpu_to_le16(temp); @@ -3117,9 +3093,7 @@ qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm) pkt->handle |= CTIO_COMPLETION_HANDLE_MARK; pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id); pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); - pkt->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; - pkt->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; - pkt->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; + pkt->initiator_id = be_id_to_le(atio->u.isp24.fcp_hdr.s_id); pkt->exchange_addr = atio->u.isp24.exchange_addr; /* silence compile warning */ @@ -3669,9 +3643,7 @@ static int __qlt_send_term_exchange(struct qla_qpair *qpair, ctio24->nport_handle = CTIO7_NHANDLE_UNRECOGNIZED; ctio24->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); ctio24->vp_index = vha->vp_idx; - ctio24->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; - ctio24->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; - ctio24->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; + ctio24->initiator_id = be_id_to_le(atio->u.isp24.fcp_hdr.s_id); ctio24->exchange_addr = atio->u.isp24.exchange_addr; temp = (atio->u.isp24.attr << 9) | CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_TERMINATE; @@ -4347,9 +4319,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, return -ENODEV; } - id.b.al_pa = atio->u.isp24.fcp_hdr.s_id[2]; - id.b.area = atio->u.isp24.fcp_hdr.s_id[1]; - id.b.domain = atio->u.isp24.fcp_hdr.s_id[0]; + id = be_to_port_id(atio->u.isp24.fcp_hdr.s_id); if (IS_SW_RESV_ADDR(id)) return -EBUSY; @@ -5305,10 +5275,7 @@ static int __qlt_send_busy(struct qla_qpair *qpair, u16 temp; port_id_t id; - id.b.al_pa = atio->u.isp24.fcp_hdr.s_id[2]; - id.b.area = atio->u.isp24.fcp_hdr.s_id[1]; - id.b.domain = atio->u.isp24.fcp_hdr.s_id[0]; - id.b.rsvd_1 = 0; + id = be_to_port_id(atio->u.isp24.fcp_hdr.s_id); spin_lock_irqsave(&ha->tgt.sess_lock, flags); sess = qla2x00_find_fcport_by_nportid(vha, &id, 1); @@ -5336,9 +5303,7 @@ static int __qlt_send_busy(struct qla_qpair *qpair, ctio24->nport_handle = sess->loop_id; ctio24->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); ctio24->vp_index = vha->vp_idx; - ctio24->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; - ctio24->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; - ctio24->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; + ctio24->initiator_id = be_id_to_le(atio->u.isp24.fcp_hdr.s_id); ctio24->exchange_addr = atio->u.isp24.exchange_addr; temp = (atio->u.isp24.attr << 9) | CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS | @@ -6124,21 +6089,21 @@ static fc_port_t *qlt_get_port_database(struct scsi_qla_host *vha, /* Must be called under tgt_mutex */ static struct fc_port *qlt_make_local_sess(struct scsi_qla_host *vha, - uint8_t *s_id) + be_id_t s_id) { struct fc_port *sess = NULL; fc_port_t *fcport = NULL; int rc, global_resets; uint16_t loop_id = 0; - if ((s_id[0] == 0xFF) && (s_id[1] == 0xFC)) { + if (s_id.domain == 0xFF && s_id.area == 0xFC) { /* * This is Domain Controller, so it should be * OK to drop SCSI commands from it. */ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf042, "Unable to find initiator with S_ID %x:%x:%x", - s_id[0], s_id[1], s_id[2]); + s_id.domain, s_id.area, s_id.al_pa); return NULL; } @@ -6155,13 +6120,12 @@ retry: ql_log(ql_log_info, vha, 0xf071, "qla_target(%d): Unable to find " "initiator with S_ID %x:%x:%x", - vha->vp_idx, s_id[0], s_id[1], - s_id[2]); + vha->vp_idx, s_id.domain, s_id.area, s_id.al_pa); if (rc == -ENOENT) { qlt_port_logo_t logo; - sid_to_portid(s_id, &logo.id); + logo.id = be_to_port_id(s_id); logo.cmd_count = 1; qlt_send_first_logo(vha, &logo); } @@ -6200,7 +6164,7 @@ static void qlt_abort_work(struct qla_tgt *tgt, struct qla_hw_data *ha = vha->hw; struct fc_port *sess = NULL; unsigned long flags = 0, flags2 = 0; - uint8_t s_id[3]; + be_id_t s_id; int rc; spin_lock_irqsave(&ha->tgt.sess_lock, flags2); @@ -6208,9 +6172,7 @@ static void qlt_abort_work(struct qla_tgt *tgt, if (tgt->tgt_stop) goto out_term2; - s_id[0] = prm->abts.fcp_hdr_le.s_id[2]; - s_id[1] = prm->abts.fcp_hdr_le.s_id[1]; - s_id[2] = prm->abts.fcp_hdr_le.s_id[0]; + s_id = le_id_to_be(prm->abts.fcp_hdr_le.s_id); sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id); if (!sess) { @@ -6264,7 +6226,7 @@ static void qlt_tmr_work(struct qla_tgt *tgt, struct qla_hw_data *ha = vha->hw; struct fc_port *sess; unsigned long flags; - uint8_t *s_id = NULL; /* to hide compiler warnings */ + be_id_t s_id; int rc; u64 unpacked_lun; int fn; @@ -6806,7 +6768,7 @@ qlt_24xx_process_atio_queue(struct scsi_qla_host *vha, uint8_t ha_locked) */ ql_log(ql_log_warn, vha, 0xd03c, "corrupted fcp frame SID[%3phN] OXID[%04x] EXCG[%x] %64phN\n", - pkt->u.isp24.fcp_hdr.s_id, + &pkt->u.isp24.fcp_hdr.s_id, be16_to_cpu(pkt->u.isp24.fcp_hdr.ox_id), le32_to_cpu(pkt->u.isp24.exchange_addr), pkt); diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 29d98757acff..d006f0a97b8c 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -247,9 +247,9 @@ struct ctio_to_2xxx { struct fcp_hdr { uint8_t r_ctl; - uint8_t d_id[3]; + be_id_t d_id; uint8_t cs_ctl; - uint8_t s_id[3]; + be_id_t s_id; uint8_t type; uint8_t f_ctl[3]; uint8_t seq_id; @@ -261,9 +261,9 @@ struct fcp_hdr { } __packed; struct fcp_hdr_le { - uint8_t d_id[3]; + le_id_t d_id; uint8_t r_ctl; - uint8_t s_id[3]; + le_id_t s_id; uint8_t cs_ctl; uint8_t f_ctl[3]; uint8_t type; @@ -402,7 +402,7 @@ struct ctio7_to_24xx { uint16_t dseg_count; /* Data segment count. */ uint8_t vp_index; uint8_t add_flags; - uint8_t initiator_id[3]; + le_id_t initiator_id; uint8_t reserved; uint32_t exchange_addr; union { @@ -498,7 +498,7 @@ struct ctio_crc2_to_fw { uint8_t add_flags; /* additional flags */ #define CTIO_CRC2_AF_DIF_DSD_ENA BIT_3 - uint8_t initiator_id[3]; /* initiator ID */ + le_id_t initiator_id; /* initiator ID */ uint8_t reserved1; uint32_t exchange_addr; /* rcv exchange address */ uint16_t reserved2; @@ -682,7 +682,7 @@ struct qla_tgt_func_tmpl { struct fc_port *(*find_sess_by_loop_id)(struct scsi_qla_host *, const uint16_t); struct fc_port *(*find_sess_by_s_id)(struct scsi_qla_host *, - const uint8_t *); + const be_id_t); void (*clear_nacl_from_fcport_map)(struct fc_port *); void (*put_sess)(struct fc_port *); void (*shutdown_sess)(struct fc_port *); @@ -1030,22 +1030,11 @@ static inline bool qla_dual_mode_enabled(struct scsi_qla_host *ha) return (ha->host->active_mode == MODE_DUAL); } -static inline uint32_t sid_to_key(const uint8_t *s_id) +static inline uint32_t sid_to_key(const be_id_t s_id) { - uint32_t key; - - key = (((unsigned long)s_id[0] << 16) | - ((unsigned long)s_id[1] << 8) | - (unsigned long)s_id[2]); - return key; -} - -static inline void sid_to_portid(const uint8_t *s_id, port_id_t *p) -{ - memset(p, 0, sizeof(*p)); - p->b.domain = s_id[0]; - p->b.area = s_id[1]; - p->b.al_pa = s_id[2]; + return s_id.domain << 16 | + s_id.area << 8 | + s_id.al_pa; } /* diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index d15412d3d9bd..963c220f8ba8 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -1136,9 +1136,8 @@ static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg(struct se_wwn *wwn, /* * Expected to be called with struct qla_hw_data->tgt.sess_lock held */ -static struct fc_port *tcm_qla2xxx_find_sess_by_s_id( - scsi_qla_host_t *vha, - const uint8_t *s_id) +static struct fc_port *tcm_qla2xxx_find_sess_by_s_id(scsi_qla_host_t *vha, + const be_id_t s_id) { struct tcm_qla2xxx_lport *lport; struct se_node_acl *se_nacl; @@ -1181,7 +1180,7 @@ static void tcm_qla2xxx_set_sess_by_s_id( struct tcm_qla2xxx_nacl *nacl, struct se_session *se_sess, struct fc_port *fc_port, - uint8_t *s_id) + be_id_t s_id) { u32 key; void *slot; @@ -1348,14 +1347,9 @@ static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *lport, struct tcm_qla2xxx_nacl *nacl, struct fc_port *sess) { struct se_session *se_sess = sess->se_sess; - unsigned char be_sid[3]; - - be_sid[0] = sess->d_id.b.domain; - be_sid[1] = sess->d_id.b.area; - be_sid[2] = sess->d_id.b.al_pa; tcm_qla2xxx_set_sess_by_s_id(lport, NULL, nacl, se_sess, - sess, be_sid); + sess, port_id_to_be_id(sess->d_id)); tcm_qla2xxx_set_sess_by_loop_id(lport, NULL, nacl, se_sess, sess, sess->loop_id); } @@ -1401,19 +1395,14 @@ static int tcm_qla2xxx_session_cb(struct se_portal_group *se_tpg, struct fc_port *qlat_sess = p; uint16_t loop_id = qlat_sess->loop_id; unsigned long flags; - unsigned char be_sid[3]; - - be_sid[0] = qlat_sess->d_id.b.domain; - be_sid[1] = qlat_sess->d_id.b.area; - be_sid[2] = qlat_sess->d_id.b.al_pa; /* * And now setup se_nacl and session pointers into HW lport internal * mappings for fabric S_ID and LOOP_ID. */ spin_lock_irqsave(&ha->tgt.sess_lock, flags); - tcm_qla2xxx_set_sess_by_s_id(lport, se_nacl, nacl, - se_sess, qlat_sess, be_sid); + tcm_qla2xxx_set_sess_by_s_id(lport, se_nacl, nacl, se_sess, qlat_sess, + port_id_to_be_id(qlat_sess->d_id)); tcm_qla2xxx_set_sess_by_loop_id(lport, se_nacl, nacl, se_sess, qlat_sess, loop_id); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); -- cgit v1.2.3-59-g8ed1b From c43e7832ee77daadf147876b93f23035b89fa028 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:01:59 -0700 Subject: scsi: qla2xxx: Change the return type of qla24xx_read_flash_data() This change makes it easier to detect qla24xx_read_flash_data() failures and also to handle such failures. This change does not modify the behavior of the driver since all callers ignore the qla24xx_read_flash_data() return value. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_gbl.h | 2 +- drivers/scsi/qla2xxx/qla_sup.c | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 2d9664086f15..aac664da419b 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -554,7 +554,7 @@ fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8); * Global Function Prototypes in qla_sup.c source file. */ extern void qla2x00_release_nvram_protection(scsi_qla_host_t *); -extern uint32_t *qla24xx_read_flash_data(scsi_qla_host_t *, uint32_t *, +extern int qla24xx_read_flash_data(scsi_qla_host_t *, uint32_t *, uint32_t, uint32_t); extern uint8_t *qla2x00_read_nvram_data(scsi_qla_host_t *, void *, uint32_t, uint32_t); diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 1eb82384d933..764e1bb0f695 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -473,22 +473,24 @@ qla24xx_read_flash_dword(struct qla_hw_data *ha, uint32_t addr, uint32_t *data) return QLA_FUNCTION_TIMEOUT; } -uint32_t * +int qla24xx_read_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, uint32_t dwords) { ulong i; + int ret = QLA_SUCCESS; struct qla_hw_data *ha = vha->hw; /* Dword reads to flash. */ faddr = flash_data_addr(ha, faddr); for (i = 0; i < dwords; i++, faddr++, dwptr++) { - if (qla24xx_read_flash_dword(ha, faddr, dwptr)) + ret = qla24xx_read_flash_dword(ha, faddr, dwptr); + if (ret != QLA_SUCCESS) break; cpu_to_le32s(dwptr); } - return dwptr; + return ret; } static int -- cgit v1.2.3-59-g8ed1b From 0597fe601a3a7d103c35b922046251906e0349b3 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:00 -0700 Subject: scsi: qla2xxx: Check secondary image if reading the primary image fails This patch fixes several Coverity complaints about reading data that has not been initialized. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 5258d2486e25..a6a66b5d36a3 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -7562,8 +7562,12 @@ qla27xx_get_active_image(struct scsi_qla_host *vha, goto check_sec_image; } - qla24xx_read_flash_data(vha, (void *)(&pri_image_status), - ha->flt_region_img_status_pri, sizeof(pri_image_status) >> 2); + if (qla24xx_read_flash_data(vha, (void *)(&pri_image_status), + ha->flt_region_img_status_pri, sizeof(pri_image_status) >> 2) != + QLA_SUCCESS) { + WARN_ON_ONCE(true); + goto check_sec_image; + } qla27xx_print_image(vha, "Primary image", &pri_image_status); if (qla27xx_check_image_status_signature(&pri_image_status)) { -- cgit v1.2.3-59-g8ed1b From 9933c050fe919ed42408a6e0198e3d7e7d3278a8 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:01 -0700 Subject: scsi: qla2xxx: Make it explicit that ELS pass-through IOCBs use little endian According to the firmware documentation the firmware expects all ELS pass-through IOCB parameters in little endian format. Make this explicit. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_fw.h | 8 ++++---- drivers/scsi/qla2xxx/qla_iocb.c | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index df079a8c2b33..732bb871c433 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -761,13 +761,13 @@ struct els_entry_24xx { #define ECF_CLR_PASSTHRU_PEND BIT_12 #define ECF_INCL_FRAME_HDR BIT_11 - uint32_t rx_byte_count; - uint32_t tx_byte_count; + __le32 rx_byte_count; + __le32 tx_byte_count; __le64 tx_address __packed; /* Data segment 0 address. */ - uint32_t tx_len; /* Data segment 0 length. */ + __le32 tx_len; /* Data segment 0 length. */ __le64 rx_address __packed; /* Data segment 1 address. */ - uint32_t rx_len; /* Data segment 1 length. */ + __le32 rx_len; /* Data segment 1 length. */ }; struct els_sts_entry_24xx { diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 6b120254f414..c7b91827c1e7 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -2704,12 +2704,12 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) if (elsio->u.els_logo.els_cmd == ELS_DCMD_PLOGI) { els_iocb->tx_byte_count = els_iocb->tx_len = - sizeof(struct els_plogi_payload); + cpu_to_le32(sizeof(struct els_plogi_payload)); put_unaligned_le64(elsio->u.els_plogi.els_plogi_pyld_dma, &els_iocb->tx_address); els_iocb->rx_dsd_count = 1; els_iocb->rx_byte_count = els_iocb->rx_len = - sizeof(struct els_plogi_payload); + cpu_to_le32(sizeof(struct els_plogi_payload)); put_unaligned_le64(elsio->u.els_plogi.els_resp_pyld_dma, &els_iocb->rx_address); @@ -2718,7 +2718,8 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) ql_dump_buffer(ql_log_info, vha, 0x0109, (uint8_t *)els_iocb, 0x70); } else { - els_iocb->tx_byte_count = sizeof(struct els_logo_payload); + els_iocb->tx_byte_count = + cpu_to_le32(sizeof(struct els_logo_payload)); put_unaligned_le64(elsio->u.els_logo.els_logo_pyld_dma, &els_iocb->tx_address); els_iocb->tx_len = cpu_to_le32(sizeof(struct els_logo_payload)); -- cgit v1.2.3-59-g8ed1b From 0f8243e64682b270bad6c58a136a1acd777fcfc3 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:02 -0700 Subject: scsi: qla2xxx: Set the responder mode if appropriate for ELS pass-through IOCBs According to the firmware documentation responder mode must be set for ELS pass-through IOCBs if a response is expected. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_iocb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index c7b91827c1e7..2da7c92e320b 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -2700,9 +2700,9 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) els_iocb->s_id[0] = vha->d_id.b.al_pa; els_iocb->s_id[1] = vha->d_id.b.area; els_iocb->s_id[2] = vha->d_id.b.domain; - els_iocb->control_flags = 0; if (elsio->u.els_logo.els_cmd == ELS_DCMD_PLOGI) { + els_iocb->control_flags = 0; els_iocb->tx_byte_count = els_iocb->tx_len = cpu_to_le32(sizeof(struct els_plogi_payload)); put_unaligned_le64(elsio->u.els_plogi.els_plogi_pyld_dma, @@ -2718,6 +2718,7 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) ql_dump_buffer(ql_log_info, vha, 0x0109, (uint8_t *)els_iocb, 0x70); } else { + els_iocb->control_flags = 1 << 13; els_iocb->tx_byte_count = cpu_to_le32(sizeof(struct els_logo_payload)); put_unaligned_le64(elsio->u.els_logo.els_logo_pyld_dma, -- cgit v1.2.3-59-g8ed1b From aa20e38bf567ff81a7778c769be6f5cea098174b Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:03 -0700 Subject: scsi: qla2xxx: Rework key encoding in qlt_find_host_by_d_id() Use the same approach for encoding the destination ID as the approach used by qlt_update_vp_map(). Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 3dd897d3e400..f7b72d1d4862 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -191,16 +191,14 @@ struct scsi_qla_host *qlt_find_host_by_d_id(struct scsi_qla_host *vha, be_id_t d_id) { struct scsi_qla_host *host; - uint32_t key = 0; + uint32_t key; if (vha->d_id.b.area == d_id.area && vha->d_id.b.domain == d_id.domain && vha->d_id.b.al_pa == d_id.al_pa) return vha; - key = d_id.domain << 16; - key |= d_id.area << 8; - key |= d_id.al_pa; + key = be_to_port_id(d_id).b24; host = btree_lookup32(&vha->hw->tgt.host_map, key); if (!host) -- cgit v1.2.3-59-g8ed1b From 6c18a43e3c82b0b67531a1cdec7ba31540fe6424 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:04 -0700 Subject: scsi: qla2xxx: Enable type checking for the SRB free and done callback functions Since all pointers passed to the srb_t.done() and srb_t.free() functions have type srb_t, change the type of the first argument of these functions from void * into struct srb *. This allows the compiler to verify the argument types for these functions. This patch does not change any functionality. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_bsg.c | 8 ++------ drivers/scsi/qla2xxx/qla_def.h | 14 ++++++++++++-- drivers/scsi/qla2xxx/qla_gbl.h | 14 +++++++------- drivers/scsi/qla2xxx/qla_gs.c | 21 +++++++------------- drivers/scsi/qla2xxx/qla_init.c | 40 ++++++++++----------------------------- drivers/scsi/qla2xxx/qla_iocb.c | 12 +++--------- drivers/scsi/qla2xxx/qla_mbx.c | 4 +--- drivers/scsi/qla2xxx/qla_mid.c | 4 +--- drivers/scsi/qla2xxx/qla_mr.c | 4 +--- drivers/scsi/qla2xxx/qla_nvme.c | 11 ++++------- drivers/scsi/qla2xxx/qla_nvme.h | 2 +- drivers/scsi/qla2xxx/qla_os.c | 16 ++++------------ drivers/scsi/qla2xxx/qla_target.c | 4 +--- 13 files changed, 54 insertions(+), 100 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 240b07b0098a..28d587a89ba6 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -12,10 +12,8 @@ #include /* BSG support for ELS/CT pass through */ -void -qla2x00_bsg_job_done(void *ptr, int res) +void qla2x00_bsg_job_done(srb_t *sp, int res) { - srb_t *sp = ptr; struct bsg_job *bsg_job = sp->u.bsg_job; struct fc_bsg_reply *bsg_reply = bsg_job->reply; @@ -25,10 +23,8 @@ qla2x00_bsg_job_done(void *ptr, int res) sp->free(sp); } -void -qla2x00_bsg_sp_free(void *ptr) +void qla2x00_bsg_sp_free(srb_t *sp) { - srb_t *sp = ptr; struct qla_hw_data *ha = sp->vha->hw; struct bsg_job *bsg_job = sp->u.bsg_job; struct fc_bsg_request *bsg_request = bsg_job->request; diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 779bf3fcab0f..65d79bcb7ccf 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -614,8 +614,18 @@ typedef struct srb { struct bsg_job *bsg_job; struct srb_cmd scmd; } u; - void (*done)(void *, int); - void (*free)(void *); + /* + * Report completion status @res and call sp_put(@sp). @res is + * an NVMe status code, a SCSI result (e.g. DID_OK << 16) or a + * QLA_* status value. + */ + void (*done)(struct srb *sp, int res); + /* Stop the timer and free @sp. Only used by the FCP code. */ + void (*free)(struct srb *sp); + /* + * Call nvme_private->fd->done() and free @sp. Only used by the NVMe + * code. + */ void (*put_fn)(struct kref *kref); } srb_t; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index aac664da419b..bbfbe3a34a7e 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -213,9 +213,9 @@ extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32); extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32); extern void qla2x00_disable_board_on_pci_error(struct work_struct *); -extern void qla2x00_sp_compl(void *, int); -extern void qla2xxx_qpair_sp_free_dma(void *); -extern void qla2xxx_qpair_sp_compl(void *, int); +extern void qla2x00_sp_compl(srb_t *sp, int); +extern void qla2xxx_qpair_sp_free_dma(srb_t *sp); +extern void qla2xxx_qpair_sp_compl(srb_t *sp, int); extern void qla24xx_sched_upd_fcport(fc_port_t *); void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *, uint16_t *); @@ -244,7 +244,7 @@ extern void qla2x00_do_dpc_all_vps(scsi_qla_host_t *); extern int qla24xx_vport_create_req_sanity_check(struct fc_vport *); extern scsi_qla_host_t *qla24xx_create_vhost(struct fc_vport *); -extern void qla2x00_sp_free_dma(void *); +extern void qla2x00_sp_free_dma(srb_t *sp); extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *); extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int); @@ -790,10 +790,10 @@ extern int qla82xx_restart_isp(scsi_qla_host_t *); /* IOCB related functions */ extern int qla82xx_start_scsi(srb_t *); -extern void qla2x00_sp_free(void *); +extern void qla2x00_sp_free(srb_t *sp); extern void qla2x00_sp_timeout(struct timer_list *); -extern void qla2x00_bsg_job_done(void *, int); -extern void qla2x00_bsg_sp_free(void *); +extern void qla2x00_bsg_job_done(srb_t *sp, int); +extern void qla2x00_bsg_sp_free(srb_t *sp); extern void qla2x00_start_iocbs(struct scsi_qla_host *, struct req_que *); /* Interrupt related */ diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 18117b5f32bc..35e1f36c9366 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -499,9 +499,8 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list) return (rval); } -static void qla2x00_async_sns_sp_done(void *s, int rc) +static void qla2x00_async_sns_sp_done(srb_t *sp, int rc) { - struct srb *sp = s; struct scsi_qla_host *vha = sp->vha; struct ct_sns_pkt *ct_sns; struct qla_work_evt *e; @@ -2989,9 +2988,8 @@ void qla24xx_handle_gpsc_event(scsi_qla_host_t *vha, struct event_arg *ea) qla_post_iidma_work(vha, fcport); } -static void qla24xx_async_gpsc_sp_done(void *s, int res) +static void qla24xx_async_gpsc_sp_done(srb_t *sp, int res) { - struct srb *sp = s; struct scsi_qla_host *vha = sp->vha; struct qla_hw_data *ha = vha->hw; fc_port_t *fcport = sp->fcport; @@ -3258,9 +3256,8 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea) } } -static void qla2x00_async_gpnid_sp_done(void *s, int res) +static void qla2x00_async_gpnid_sp_done(srb_t *sp, int res) { - struct srb *sp = s; struct scsi_qla_host *vha = sp->vha; struct ct_sns_req *ct_req = (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req; @@ -3446,9 +3443,8 @@ void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea) qla24xx_post_gnl_work(vha, fcport); } -void qla24xx_async_gffid_sp_done(void *s, int res) +void qla24xx_async_gffid_sp_done(srb_t *sp, int res) { - struct srb *sp = s; struct scsi_qla_host *vha = sp->vha; fc_port_t *fcport = sp->fcport; struct ct_sns_rsp *ct_rsp; @@ -3872,9 +3868,8 @@ static void qla2x00_find_free_fcp_nvme_slot(struct scsi_qla_host *vha, } } -static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res) +static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res) { - struct srb *sp = s; struct scsi_qla_host *vha = sp->vha; struct ct_sns_req *ct_req = (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req; @@ -4251,9 +4246,8 @@ void qla24xx_handle_gnnid_event(scsi_qla_host_t *vha, struct event_arg *ea) qla24xx_post_gnl_work(vha, ea->fcport); } -static void qla2x00_async_gnnid_sp_done(void *s, int res) +static void qla2x00_async_gnnid_sp_done(srb_t *sp, int res) { - struct srb *sp = s; struct scsi_qla_host *vha = sp->vha; fc_port_t *fcport = sp->fcport; u8 *node_name = fcport->ct_desc.ct_sns->p.rsp.rsp.gnn_id.node_name; @@ -4384,9 +4378,8 @@ void qla24xx_handle_gfpnid_event(scsi_qla_host_t *vha, struct event_arg *ea) qla24xx_post_gpsc_work(vha, fcport); } -static void qla2x00_async_gfpnid_sp_done(void *s, int res) +static void qla2x00_async_gfpnid_sp_done(srb_t *sp, int res) { - struct srb *sp = s; struct scsi_qla_host *vha = sp->vha; fc_port_t *fcport = sp->fcport; u8 *fpn = fcport->ct_desc.ct_sns->p.rsp.rsp.gfpn_id.port_name; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index a6a66b5d36a3..3fa8ca63429c 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -63,10 +63,8 @@ qla2x00_sp_timeout(struct timer_list *t) iocb->timeout(sp); } -void -qla2x00_sp_free(void *ptr) +void qla2x00_sp_free(srb_t *sp) { - srb_t *sp = ptr; struct srb_iocb *iocb = &sp->u.iocb_cmd; del_timer(&iocb->timer); @@ -117,9 +115,8 @@ static void qla24xx_abort_iocb_timeout(void *data) sp->done(sp, QLA_OS_TIMER_EXPIRED); } -static void qla24xx_abort_sp_done(void *ptr, int res) +static void qla24xx_abort_sp_done(srb_t *sp, int res) { - srb_t *sp = ptr; struct srb_iocb *abt = &sp->u.iocb_cmd; del_timer(&sp->u.iocb_cmd.timer); @@ -249,10 +246,8 @@ qla2x00_async_iocb_timeout(void *data) } } -static void -qla2x00_async_login_sp_done(void *ptr, int res) +static void qla2x00_async_login_sp_done(srb_t *sp, int res) { - srb_t *sp = ptr; struct scsi_qla_host *vha = sp->vha; struct srb_iocb *lio = &sp->u.iocb_cmd; struct event_arg ea; @@ -358,11 +353,8 @@ done: return rval; } -static void -qla2x00_async_logout_sp_done(void *ptr, int res) +static void qla2x00_async_logout_sp_done(srb_t *sp, int res) { - srb_t *sp = ptr; - sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); sp->fcport->login_gen++; qlt_logo_completion_handler(sp->fcport, res); @@ -419,10 +411,8 @@ qla2x00_async_prlo_done(struct scsi_qla_host *vha, fc_port_t *fcport, qlt_logo_completion_handler(fcport, data[0]); } -static void -qla2x00_async_prlo_sp_done(void *s, int res) +static void qla2x00_async_prlo_sp_done(srb_t *sp, int res) { - srb_t *sp = (srb_t *)s; struct srb_iocb *lio = &sp->u.iocb_cmd; struct scsi_qla_host *vha = sp->vha; @@ -525,10 +515,8 @@ static int qla_post_els_plogi_work(struct scsi_qla_host *vha, fc_port_t *fcport) return qla2x00_post_work(vha, e); } -static void -qla2x00_async_adisc_sp_done(void *ptr, int res) +static void qla2x00_async_adisc_sp_done(srb_t *sp, int res) { - srb_t *sp = ptr; struct scsi_qla_host *vha = sp->vha; struct event_arg ea; struct srb_iocb *lio = &sp->u.iocb_cmd; @@ -931,10 +919,8 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, } } /* gnl_event */ -static void -qla24xx_async_gnl_sp_done(void *s, int res) +static void qla24xx_async_gnl_sp_done(srb_t *sp, int res) { - struct srb *sp = s; struct scsi_qla_host *vha = sp->vha; unsigned long flags; struct fc_port *fcport = NULL, *tf; @@ -1121,10 +1107,8 @@ int qla24xx_post_gnl_work(struct scsi_qla_host *vha, fc_port_t *fcport) return qla2x00_post_work(vha, e); } -static -void qla24xx_async_gpdb_sp_done(void *s, int res) +static void qla24xx_async_gpdb_sp_done(srb_t *sp, int res) { - struct srb *sp = s; struct scsi_qla_host *vha = sp->vha; struct qla_hw_data *ha = vha->hw; fc_port_t *fcport = sp->fcport; @@ -1168,10 +1152,8 @@ static int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport) return qla2x00_post_work(vha, e); } -static void -qla2x00_async_prli_sp_done(void *ptr, int res) +static void qla2x00_async_prli_sp_done(srb_t *sp, int res) { - srb_t *sp = ptr; struct scsi_qla_host *vha = sp->vha; struct srb_iocb *lio = &sp->u.iocb_cmd; struct event_arg ea; @@ -1808,10 +1790,8 @@ qla2x00_tmf_iocb_timeout(void *data) complete(&tmf->u.tmf.comp); } -static void -qla2x00_tmf_sp_done(void *ptr, int res) +static void qla2x00_tmf_sp_done(srb_t *sp, int res) { - srb_t *sp = ptr; struct srb_iocb *tmf = &sp->u.iocb_cmd; complete(&tmf->u.tmf.comp); diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 2da7c92e320b..59a0a778d31c 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -2544,10 +2544,8 @@ void qla2x00_init_timer(srb_t *sp, unsigned long tmo) sp->start_timer = 1; } -static void -qla2x00_els_dcmd_sp_free(void *data) +static void qla2x00_els_dcmd_sp_free(srb_t *sp) { - srb_t *sp = data; struct srb_iocb *elsio = &sp->u.iocb_cmd; kfree(sp->fcport); @@ -2577,10 +2575,8 @@ qla2x00_els_dcmd_iocb_timeout(void *data) complete(&lio->u.els_logo.comp); } -static void -qla2x00_els_dcmd_sp_done(void *ptr, int res) +static void qla2x00_els_dcmd_sp_done(srb_t *sp, int res) { - srb_t *sp = ptr; fc_port_t *fcport = sp->fcport; struct srb_iocb *lio = &sp->u.iocb_cmd; struct scsi_qla_host *vha = sp->vha; @@ -2758,10 +2754,8 @@ qla2x00_els_dcmd2_iocb_timeout(void *data) sp->done(sp, QLA_FUNCTION_TIMEOUT); } -static void -qla2x00_els_dcmd2_sp_done(void *ptr, int res) +static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res) { - srb_t *sp = ptr; fc_port_t *fcport = sp->fcport; struct srb_iocb *lio = &sp->u.iocb_cmd; struct scsi_qla_host *vha = sp->vha; diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 783a84606047..a82b6db2fa9d 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -6217,10 +6217,8 @@ qla26xx_dport_diagnostics(scsi_qla_host_t *vha, return rval; } -static void qla2x00_async_mb_sp_done(void *s, int res) +static void qla2x00_async_mb_sp_done(srb_t *sp, int res) { - struct srb *sp = s; - sp->u.iocb_cmd.u.mbx.rc = res; complete(&sp->u.iocb_cmd.u.mbx.comp); diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index b2977e49356b..1a9a11ae7285 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -901,10 +901,8 @@ failed: return 0; } -static void qla_ctrlvp_sp_done(void *s, int res) +static void qla_ctrlvp_sp_done(srb_t *sp, int res) { - struct srb *sp = s; - if (sp->comp) complete(sp->comp); /* don't free sp here. Let the caller do the free */ diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index 78b3679e1b9c..e8da3ec4db2c 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -1797,10 +1797,8 @@ qla2x00_fxdisc_iocb_timeout(void *data) complete(&lio->u.fxiocb.fxiocb_comp); } -static void -qla2x00_fxdisc_sp_done(void *ptr, int res) +static void qla2x00_fxdisc_sp_done(srb_t *sp, int res) { - srb_t *sp = ptr; struct srb_iocb *lio = &sp->u.iocb_cmd; complete(&lio->u.fxiocb.fxiocb_comp); diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index bba25c38a118..af6b46777602 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -180,10 +180,9 @@ static void qla_nvme_ls_complete(struct work_struct *work) kref_put(&priv->sp->cmd_kref, qla_nvme_release_ls_cmd_kref); } -static void qla_nvme_sp_ls_done(void *ptr, int res) +static void qla_nvme_sp_ls_done(srb_t *sp, int res) { - srb_t *sp = ptr; - struct nvme_private *priv; + struct nvme_private *priv = sp->priv; if (WARN_ON_ONCE(kref_read(&sp->cmd_kref) == 0)) return; @@ -191,17 +190,15 @@ static void qla_nvme_sp_ls_done(void *ptr, int res) if (res) res = -EINVAL; - priv = (struct nvme_private *)sp->priv; priv->comp_status = res; INIT_WORK(&priv->ls_work, qla_nvme_ls_complete); schedule_work(&priv->ls_work); } /* it assumed that QPair lock is held. */ -static void qla_nvme_sp_done(void *ptr, int res) +static void qla_nvme_sp_done(srb_t *sp, int res) { - srb_t *sp = ptr; - struct nvme_private *priv = (struct nvme_private *)sp->priv; + struct nvme_private *priv = sp->priv; priv->comp_status = res; kref_put(&sp->cmd_kref, qla_nvme_release_fcp_cmd_kref); diff --git a/drivers/scsi/qla2xxx/qla_nvme.h b/drivers/scsi/qla2xxx/qla_nvme.h index 68a8d09a36ef..25a2b82d5095 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.h +++ b/drivers/scsi/qla2xxx/qla_nvme.h @@ -144,5 +144,5 @@ int qla_nvme_register_remote(struct scsi_qla_host *, struct fc_port *); void qla_nvme_delete(struct scsi_qla_host *); void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *, struct pt_ls4_request *, struct req_que *); -void qla24xx_async_gffid_sp_done(void *, int); +void qla24xx_async_gffid_sp_done(struct srb *sp, int); #endif diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index a247dce0cb95..9ef59995f5d6 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -652,10 +652,8 @@ qla24xx_fw_version_str(struct scsi_qla_host *vha, char *str, size_t size) return str; } -void -qla2x00_sp_free_dma(void *ptr) +void qla2x00_sp_free_dma(srb_t *sp) { - srb_t *sp = ptr; struct qla_hw_data *ha = sp->vha->hw; struct scsi_cmnd *cmd = GET_CMD_SP(sp); void *ctx = GET_CMD_CTX_SP(sp); @@ -699,10 +697,8 @@ qla2x00_sp_free_dma(void *ptr) } } -void -qla2x00_sp_compl(void *ptr, int res) +void qla2x00_sp_compl(srb_t *sp, int res) { - srb_t *sp = ptr; struct scsi_cmnd *cmd = GET_CMD_SP(sp); struct completion *comp = sp->comp; @@ -720,10 +716,8 @@ qla2x00_sp_compl(void *ptr, int res) qla2x00_rel_sp(sp); } -void -qla2xxx_qpair_sp_free_dma(void *ptr) +void qla2xxx_qpair_sp_free_dma(srb_t *sp) { - srb_t *sp = (srb_t *)ptr; struct scsi_cmnd *cmd = GET_CMD_SP(sp); struct qla_hw_data *ha = sp->fcport->vha->hw; void *ctx = GET_CMD_CTX_SP(sp); @@ -804,10 +798,8 @@ qla2xxx_qpair_sp_free_dma(void *ptr) } } -void -qla2xxx_qpair_sp_compl(void *ptr, int res) +void qla2xxx_qpair_sp_compl(srb_t *sp, int res) { - srb_t *sp = ptr; struct scsi_cmnd *cmd = GET_CMD_SP(sp); struct completion *comp = sp->comp; diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index f7b72d1d4862..d25c3fa43601 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -559,10 +559,8 @@ static int qla24xx_post_nack_work(struct scsi_qla_host *vha, fc_port_t *fcport, return qla2x00_post_work(vha, e); } -static -void qla2x00_async_nack_sp_done(void *s, int res) +static void qla2x00_async_nack_sp_done(srb_t *sp, int res) { - struct srb *sp = (struct srb *)s; struct scsi_qla_host *vha = sp->vha; unsigned long flags; -- cgit v1.2.3-59-g8ed1b From bdb61b9b944d1e5b7cee5a9fe21014363c55b811 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:05 -0700 Subject: scsi: qla2xxx: Introduce the function qla2xxx_init_sp() This patch does not change any functionality but makes the next patch easier to read. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_inline.h | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index bf063c664352..0c3d907af769 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -152,6 +152,18 @@ qla2x00_chip_is_down(scsi_qla_host_t *vha) return (qla2x00_reset_active(vha) || !vha->hw->flags.fw_started); } +static void qla2xxx_init_sp(srb_t *sp, scsi_qla_host_t *vha, + struct qla_qpair *qpair, fc_port_t *fcport) +{ + memset(sp, 0, sizeof(*sp)); + sp->fcport = fcport; + sp->iocbs = 1; + sp->vha = vha; + sp->qpair = qpair; + sp->cmd_type = TYPE_SRB; + INIT_LIST_HEAD(&sp->elem); +} + static inline srb_t * qla2xxx_get_qpair_sp(scsi_qla_host_t *vha, struct qla_qpair *qpair, fc_port_t *fcport, gfp_t flag) @@ -164,19 +176,9 @@ qla2xxx_get_qpair_sp(scsi_qla_host_t *vha, struct qla_qpair *qpair, return NULL; sp = mempool_alloc(qpair->srb_mempool, flag); - if (!sp) - goto done; - - memset(sp, 0, sizeof(*sp)); - sp->fcport = fcport; - sp->iocbs = 1; - sp->vha = vha; - sp->qpair = qpair; - sp->cmd_type = TYPE_SRB; - INIT_LIST_HEAD(&sp->elem); - -done: - if (!sp) + if (sp) + qla2xxx_init_sp(sp, vha, qpair, fcport); + else QLA_QPAIR_MARK_NOT_BUSY(qpair); return sp; } -- cgit v1.2.3-59-g8ed1b From 85cffefa09e448906a6f0bc20f422d75a18675bd Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:06 -0700 Subject: scsi: qla2xxx: Fix a race condition between aborting and completing a SCSI command Instead of allocating a struct srb dynamically from inside .queuecommand(), set qla2xxx_driver_template.cmd_size such that struct scsi_cmnd and struct srb are contiguous. Do not call QLA_QPAIR_MARK_BUSY() / QLA_QPAIR_MARK_NOT_BUSY() for SRBs associated with SCSI commands. That is safe because scsi_remove_host() is called before queue pairs are deleted and scsi_remove_host() waits for all outstanding SCSI commands to finish. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 1 - drivers/scsi/qla2xxx/qla_os.c | 45 ++++++++---------------------------------- 2 files changed, 8 insertions(+), 38 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 65d79bcb7ccf..3ffe7661a25b 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -630,7 +630,6 @@ typedef struct srb { } srb_t; #define GET_CMD_SP(sp) (sp->u.scmd.cmd) -#define SET_CMD_SP(sp, cmd) (sp->u.scmd.cmd = cmd) #define GET_CMD_CTX_SP(sp) (sp->u.scmd.ctx) #define GET_CMD_SENSE_LEN(sp) \ diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 9ef59995f5d6..5ca7f7913258 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -713,7 +713,6 @@ void qla2x00_sp_compl(srb_t *sp, int res) cmd->scsi_done(cmd); if (comp) complete(comp); - qla2x00_rel_sp(sp); } void qla2xxx_qpair_sp_free_dma(srb_t *sp) @@ -814,7 +813,6 @@ void qla2xxx_qpair_sp_compl(srb_t *sp, int res) cmd->scsi_done(cmd); if (comp) complete(comp); - qla2xxx_rel_qpair_sp(sp->qpair, sp); } static int @@ -908,9 +906,8 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) else goto qc24_target_busy; - sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC); - if (!sp) - goto qc24_host_busy; + sp = scsi_cmd_priv(cmd); + qla2xxx_init_sp(sp, vha, vha->hw->base_qpair, fcport); sp->u.scmd.cmd = cmd; sp->type = SRB_SCSI_CMD; @@ -931,9 +928,6 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) qc24_host_busy_free_sp: sp->free(sp); -qc24_host_busy: - return SCSI_MLQUEUE_HOST_BUSY; - qc24_target_busy: return SCSI_MLQUEUE_TARGET_BUSY; @@ -994,9 +988,8 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd, else goto qc24_target_busy; - sp = qla2xxx_get_qpair_sp(vha, qpair, fcport, GFP_ATOMIC); - if (!sp) - goto qc24_host_busy; + sp = scsi_cmd_priv(cmd); + qla2xxx_init_sp(sp, vha, qpair, fcport); sp->u.scmd.cmd = cmd; sp->type = SRB_SCSI_CMD; @@ -1020,9 +1013,6 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd, qc24_host_busy_free_sp: sp->free(sp); -qc24_host_busy: - return SCSI_MLQUEUE_HOST_BUSY; - qc24_target_busy: return SCSI_MLQUEUE_TARGET_BUSY; @@ -1257,10 +1247,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) int ret; unsigned int id; uint64_t lun; - unsigned long flags; int rval; struct qla_hw_data *ha = vha->hw; - struct qla_qpair *qpair; if (qla2x00_isp_reg_stat(ha)) { ql_log(ql_log_info, vha, 0x8042, @@ -1272,32 +1260,14 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) if (ret != 0) return ret; - sp = (srb_t *) CMD_SP(cmd); - if (!sp) - return SUCCESS; - - qpair = sp->qpair; - if (!qpair) - return SUCCESS; + sp = scsi_cmd_priv(cmd); if (sp->fcport && sp->fcport->deleted) return SUCCESS; - spin_lock_irqsave(qpair->qp_lock_ptr, flags); - if (sp->type != SRB_SCSI_CMD || GET_CMD_SP(sp) != cmd) { - /* there's a chance an interrupt could clear - the ptr as part of done & free */ - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - return SUCCESS; - } - - /* Get a reference to the sp and drop the lock. */ - if (sp_get(sp)){ - /* ref_count is already 0 */ - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + /* Return if the command has already finished. */ + if (sp_get(sp)) return SUCCESS; - } - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); id = cmd->device->id; lun = cmd->device->lun; @@ -7159,6 +7129,7 @@ struct scsi_host_template qla2xxx_driver_template = { .supported_mode = MODE_INITIATOR, .track_queue_depth = 1, + .cmd_size = sizeof(srb_t), }; static const struct pci_error_handlers qla2xxx_err_handler = { -- cgit v1.2.3-59-g8ed1b From e752a04e1bd14ccff2762605004f515ad9b0d48a Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:07 -0700 Subject: scsi: qla2xxx: Make qlt_handle_abts_completion() more robust Avoid that this function crashes if mcmd == NULL. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index d25c3fa43601..cc0c99b5f3fb 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -5731,7 +5731,7 @@ static void qlt_handle_abts_completion(struct scsi_qla_host *vha, entry->error_subcode2); ha->tgt.tgt_ops->free_mcmd(mcmd); } - } else { + } else if (mcmd) { ha->tgt.tgt_ops->free_mcmd(mcmd); } } -- cgit v1.2.3-59-g8ed1b From 3cb5f3aeaf07215ba86f0ed45f084a9056968dd5 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:08 -0700 Subject: scsi: qla2xxx: Modify NVMe include directives Since struct sg_table is used in nvme-fc-driver.h, include from that header file. Since no definitions or declarations from are used in the qla_nvme.h header file, do not include from that header file. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_nvme.h | 1 - include/linux/nvme-fc-driver.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_nvme.h b/drivers/scsi/qla2xxx/qla_nvme.h index 25a2b82d5095..ef912902d4e5 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.h +++ b/drivers/scsi/qla2xxx/qla_nvme.h @@ -7,7 +7,6 @@ #ifndef __QLA_NVME_H #define __QLA_NVME_H -#include #include #include #include diff --git a/include/linux/nvme-fc-driver.h b/include/linux/nvme-fc-driver.h index 98d904961b33..10f81629b9ce 100644 --- a/include/linux/nvme-fc-driver.h +++ b/include/linux/nvme-fc-driver.h @@ -6,6 +6,8 @@ #ifndef _NVME_FC_DRIVER_H #define _NVME_FC_DRIVER_H 1 +#include + /* * ********************** LLDD FC-NVME Host API ******************** -- cgit v1.2.3-59-g8ed1b From bcc856574356df2eb5eb2d4491e7205339e55728 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:09 -0700 Subject: scsi: qla2xxx: Introduce qla2xxx_get_next_handle() This patch reduces code duplication. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_iocb.c | 128 ++++++++++++---------------------------- drivers/scsi/qla2xxx/qla_mr.c | 13 +--- drivers/scsi/qla2xxx/qla_nvme.c | 14 +---- 4 files changed, 42 insertions(+), 114 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index bbfbe3a34a7e..6b914942fad3 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -272,6 +272,7 @@ extern void qla2x00_build_scsi_iocbs_32(srb_t *, cmd_entry_t *, uint16_t); extern void qla2x00_build_scsi_iocbs_64(srb_t *, cmd_entry_t *, uint16_t); extern void qla24xx_build_scsi_iocbs(srb_t *, struct cmd_type_7 *, uint16_t, struct req_que *); +extern uint32_t qla2xxx_get_next_handle(struct req_que *req); extern int qla2x00_start_scsi(srb_t *sp); extern int qla24xx_start_scsi(srb_t *sp); int qla2x00_marker(struct scsi_qla_host *, struct qla_qpair *, diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 59a0a778d31c..22d875222321 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -292,6 +292,26 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, } } +/* + * Find the first handle that is not in use, starting from + * req->current_outstanding_cmd + 1. The caller must hold the lock that is + * associated with @req. + */ +uint32_t qla2xxx_get_next_handle(struct req_que *req) +{ + uint32_t index, handle = req->current_outstanding_cmd; + + for (index = 1; index < req->num_outstanding_cmds; index++) { + handle++; + if (handle == req->num_outstanding_cmds) + handle = 1; + if (!req->outstanding_cmds[handle]) + return handle; + } + + return 0; +} + /** * qla2x00_start_scsi() - Send a SCSI command to the ISP * @sp: command to send to the ISP @@ -306,7 +326,6 @@ qla2x00_start_scsi(srb_t *sp) scsi_qla_host_t *vha; struct scsi_cmnd *cmd; uint32_t *clr_ptr; - uint32_t index; uint32_t handle; cmd_entry_t *cmd_pkt; uint16_t cnt; @@ -339,16 +358,8 @@ qla2x00_start_scsi(srb_t *sp) /* Acquire ring specific lock */ spin_lock_irqsave(&ha->hardware_lock, flags); - /* Check for room in outstanding command list. */ - handle = req->current_outstanding_cmd; - for (index = 1; index < req->num_outstanding_cmds; index++) { - handle++; - if (handle == req->num_outstanding_cmds) - handle = 1; - if (!req->outstanding_cmds[handle]) - break; - } - if (index == req->num_outstanding_cmds) + handle = qla2xxx_get_next_handle(req); + if (handle == 0) goto queuing_error; /* Map the sg table so we have an accurate count of sg entries needed */ @@ -1584,7 +1595,6 @@ qla24xx_start_scsi(srb_t *sp) int nseg; unsigned long flags; uint32_t *clr_ptr; - uint32_t index; uint32_t handle; struct cmd_type_7 *cmd_pkt; uint16_t cnt; @@ -1612,16 +1622,8 @@ qla24xx_start_scsi(srb_t *sp) /* Acquire ring specific lock */ spin_lock_irqsave(&ha->hardware_lock, flags); - /* Check for room in outstanding command list. */ - handle = req->current_outstanding_cmd; - for (index = 1; index < req->num_outstanding_cmds; index++) { - handle++; - if (handle == req->num_outstanding_cmds) - handle = 1; - if (!req->outstanding_cmds[handle]) - break; - } - if (index == req->num_outstanding_cmds) + handle = qla2xxx_get_next_handle(req); + if (handle == 0) goto queuing_error; /* Map the sg table so we have an accurate count of sg entries needed */ @@ -1724,7 +1726,6 @@ qla24xx_dif_start_scsi(srb_t *sp) int nseg; unsigned long flags; uint32_t *clr_ptr; - uint32_t index; uint32_t handle; uint16_t cnt; uint16_t req_cnt = 0; @@ -1765,17 +1766,8 @@ qla24xx_dif_start_scsi(srb_t *sp) /* Acquire ring specific lock */ spin_lock_irqsave(&ha->hardware_lock, flags); - /* Check for room in outstanding command list. */ - handle = req->current_outstanding_cmd; - for (index = 1; index < req->num_outstanding_cmds; index++) { - handle++; - if (handle == req->num_outstanding_cmds) - handle = 1; - if (!req->outstanding_cmds[handle]) - break; - } - - if (index == req->num_outstanding_cmds) + handle = qla2xxx_get_next_handle(req); + if (handle == 0) goto queuing_error; /* Compute number of required data segments */ @@ -1920,7 +1912,6 @@ qla2xxx_start_scsi_mq(srb_t *sp) int nseg; unsigned long flags; uint32_t *clr_ptr; - uint32_t index; uint32_t handle; struct cmd_type_7 *cmd_pkt; uint16_t cnt; @@ -1951,16 +1942,8 @@ qla2xxx_start_scsi_mq(srb_t *sp) vha->marker_needed = 0; } - /* Check for room in outstanding command list. */ - handle = req->current_outstanding_cmd; - for (index = 1; index < req->num_outstanding_cmds; index++) { - handle++; - if (handle == req->num_outstanding_cmds) - handle = 1; - if (!req->outstanding_cmds[handle]) - break; - } - if (index == req->num_outstanding_cmds) + handle = qla2xxx_get_next_handle(req); + if (handle == 0) goto queuing_error; /* Map the sg table so we have an accurate count of sg entries needed */ @@ -2064,7 +2047,6 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp) int nseg; unsigned long flags; uint32_t *clr_ptr; - uint32_t index; uint32_t handle; uint16_t cnt; uint16_t req_cnt = 0; @@ -2119,17 +2101,8 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp) vha->marker_needed = 0; } - /* Check for room in outstanding command list. */ - handle = req->current_outstanding_cmd; - for (index = 1; index < req->num_outstanding_cmds; index++) { - handle++; - if (handle == req->num_outstanding_cmds) - handle = 1; - if (!req->outstanding_cmds[handle]) - break; - } - - if (index == req->num_outstanding_cmds) + handle = qla2xxx_get_next_handle(req); + if (handle == 0) goto queuing_error; /* Compute number of required data segments */ @@ -2276,7 +2249,7 @@ __qla2x00_alloc_iocbs(struct qla_qpair *qpair, srb_t *sp) struct qla_hw_data *ha = vha->hw; struct req_que *req = qpair->req; device_reg_t *reg = ISP_QUE_REG(ha, req->id); - uint32_t index, handle; + uint32_t handle; request_t *pkt; uint16_t cnt, req_cnt; @@ -2316,16 +2289,8 @@ __qla2x00_alloc_iocbs(struct qla_qpair *qpair, srb_t *sp) goto queuing_error; if (sp) { - /* Check for room in outstanding command list. */ - handle = req->current_outstanding_cmd; - for (index = 1; index < req->num_outstanding_cmds; index++) { - handle++; - if (handle == req->num_outstanding_cmds) - handle = 1; - if (!req->outstanding_cmds[handle]) - break; - } - if (index == req->num_outstanding_cmds) { + handle = qla2xxx_get_next_handle(req); + if (handle == 0) { ql_log(ql_log_warn, vha, 0x700b, "No room on outstanding cmd array.\n"); goto queuing_error; @@ -3112,7 +3077,6 @@ qla82xx_start_scsi(srb_t *sp) unsigned long flags; struct scsi_cmnd *cmd; uint32_t *clr_ptr; - uint32_t index; uint32_t handle; uint16_t cnt; uint16_t req_cnt; @@ -3152,16 +3116,8 @@ qla82xx_start_scsi(srb_t *sp) /* Acquire ring specific lock */ spin_lock_irqsave(&ha->hardware_lock, flags); - /* Check for room in outstanding command list. */ - handle = req->current_outstanding_cmd; - for (index = 1; index < req->num_outstanding_cmds; index++) { - handle++; - if (handle == req->num_outstanding_cmds) - handle = 1; - if (!req->outstanding_cmds[handle]) - break; - } - if (index == req->num_outstanding_cmds) + handle = qla2xxx_get_next_handle(req); + if (handle == 0) goto queuing_error; /* Map the sg table so we have an accurate count of sg entries needed */ @@ -3769,7 +3725,6 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds) struct qla_hw_data *ha = vha->hw; unsigned long flags; uint32_t handle; - uint32_t index; uint16_t req_cnt; uint16_t cnt; uint32_t *clr_ptr; @@ -3794,17 +3749,8 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds) /* Acquire ring specific lock */ spin_lock_irqsave(&ha->hardware_lock, flags); - /* Check for room in outstanding command list. */ - handle = req->current_outstanding_cmd; - for (index = 1; index < req->num_outstanding_cmds; index++) { - handle++; - if (handle == req->num_outstanding_cmds) - handle = 1; - if (!req->outstanding_cmds[handle]) - break; - } - - if (index == req->num_outstanding_cmds) { + handle = qla2xxx_get_next_handle(req); + if (handle == 0) { rval = EXT_STATUS_BUSY; goto queuing_error; } diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index e8da3ec4db2c..06985b2d48eb 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -3071,7 +3071,6 @@ qlafx00_start_scsi(srb_t *sp) { int nseg; unsigned long flags; - uint32_t index; uint32_t handle; uint16_t cnt; uint16_t req_cnt; @@ -3095,16 +3094,8 @@ qlafx00_start_scsi(srb_t *sp) /* Acquire ring specific lock */ spin_lock_irqsave(&ha->hardware_lock, flags); - /* Check for room in outstanding command list. */ - handle = req->current_outstanding_cmd; - for (index = 1; index < req->num_outstanding_cmds; index++) { - handle++; - if (handle == req->num_outstanding_cmds) - handle = 1; - if (!req->outstanding_cmds[handle]) - break; - } - if (index == req->num_outstanding_cmds) + handle = qla2xxx_get_next_handle(req); + if (handle == 0) goto queuing_error; /* Map the sg table so we have an accurate count of sg entries needed */ diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index af6b46777602..6cc19e060afc 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -353,7 +353,6 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp) { unsigned long flags; uint32_t *clr_ptr; - uint32_t index; uint32_t handle; struct cmd_nvme *cmd_pkt; uint16_t cnt, i; @@ -377,17 +376,8 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp) /* Acquire qpair specific lock */ spin_lock_irqsave(&qpair->qp_lock, flags); - /* Check for room in outstanding command list. */ - handle = req->current_outstanding_cmd; - for (index = 1; index < req->num_outstanding_cmds; index++) { - handle++; - if (handle == req->num_outstanding_cmds) - handle = 1; - if (!req->outstanding_cmds[handle]) - break; - } - - if (index == req->num_outstanding_cmds) { + handle = qla2xxx_get_next_handle(req); + if (handle == 0) { rval = -EBUSY; goto queuing_error; } -- cgit v1.2.3-59-g8ed1b From 0dcec41acb85da33841c2ab56dbf337ed00a3914 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:10 -0700 Subject: scsi: qla2xxx: Make sure that aborted commands are freed The LIO core requires that the target driver callback functions .queue_data_in() and .queue_status() call target_put_sess_cmd() or transport_generic_free_cmd(). These calls may happen synchronously or asynchronously. Make sure that one of these LIO functions is called in case a command has been aborted. This patch avoids that the code for removing a session hangs due to commands that do not make progress. Cc: Himanshu Madhani Fixes: 694833ee00c4 ("scsi: tcm_qla2xxx: Do not allow aborted cmd to advance.") # v4.13. Fixes: a07100e00ac4 ("qla2xxx: Fix TMR ABORT interaction issue between qla2xxx and TCM") # v4.5. Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.c | 13 ++++++++----- drivers/scsi/qla2xxx/tcm_qla2xxx.c | 4 ++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index cc0c99b5f3fb..0ffda6171614 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -3206,7 +3206,8 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, if (!qpair->fw_started || (cmd->reset_count != qpair->chip_reset) || (cmd->sess && cmd->sess->deleted)) { cmd->state = QLA_TGT_STATE_PROCESSED; - return 0; + res = 0; + goto free; } ql_dbg_qp(ql_dbg_tgt, qpair, 0xe018, @@ -3217,9 +3218,8 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status, &full_req_cnt); - if (unlikely(res != 0)) { - return res; - } + if (unlikely(res != 0)) + goto free; spin_lock_irqsave(qpair->qp_lock_ptr, flags); @@ -3239,7 +3239,8 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, vha->flags.online, qla2x00_reset_active(vha), cmd->reset_count, qpair->chip_reset); spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - return 0; + res = 0; + goto free; } /* Does F/W have an IOCBs for this request */ @@ -3342,6 +3343,8 @@ out_unmap_unlock: qlt_unmap_sg(vha, cmd); spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); +free: + vha->hw->tgt.tgt_ops->free_cmd(cmd); return res; } EXPORT_SYMBOL(qlt_xmit_response); diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 963c220f8ba8..042a24314edc 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -620,6 +620,7 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd) { struct qla_tgt_cmd *cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd); + struct scsi_qla_host *vha = cmd->vha; if (cmd->aborted) { /* Cmd can loop during Q-full. tcm_qla2xxx_aborted_task @@ -632,6 +633,7 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd) cmd->se_cmd.transport_state, cmd->se_cmd.t_state, cmd->se_cmd.se_cmd_flags); + vha->hw->tgt.tgt_ops->free_cmd(cmd); return 0; } @@ -659,6 +661,7 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd) { struct qla_tgt_cmd *cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd); + struct scsi_qla_host *vha = cmd->vha; int xmit_type = QLA_TGT_XMIT_STATUS; if (cmd->aborted) { @@ -672,6 +675,7 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd) cmd, kref_read(&cmd->se_cmd.cmd_kref), cmd->se_cmd.transport_state, cmd->se_cmd.t_state, cmd->se_cmd.se_cmd_flags); + vha->hw->tgt.tgt_ops->free_cmd(cmd); return 0; } cmd->bufflen = se_cmd->data_length; -- cgit v1.2.3-59-g8ed1b From 88263208dd23327b56fbd7c2858c389c1153b366 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:11 -0700 Subject: scsi: qla2xxx: Complain if sp->done() is not called from the completion path Not calling sp->done() from the command completion path is a severe bug. Hence complain loudly if that happens. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 4 ++++ drivers/scsi/qla2xxx/qla_isr.c | 4 ++++ drivers/scsi/qla2xxx/qla_mr.c | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 3fa8ca63429c..64c84e53011e 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -243,6 +243,10 @@ qla2x00_async_iocb_timeout(void *data) sp->done(sp, QLA_FUNCTION_TIMEOUT); } break; + default: + WARN_ON_ONCE(true); + sp->done(sp, QLA_FUNCTION_TIMEOUT); + break; } } diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 55eb51539cb0..7533e420e571 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -2786,6 +2786,8 @@ out: if (rsp->status_srb == NULL) sp->done(sp, res); + else + WARN_ON_ONCE(true); } /** @@ -2843,6 +2845,8 @@ qla2x00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt) if (sense_len == 0) { rsp->status_srb = NULL; sp->done(sp, cp->result); + } else { + WARN_ON_ONCE(true); } } diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index 06985b2d48eb..605b59c76c90 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -2539,6 +2539,8 @@ check_scsi_status: if (rsp->status_srb == NULL) sp->done(sp, res); + else + WARN_ON_ONCE(true); } /** @@ -2616,6 +2618,8 @@ qlafx00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt) if (sense_len == 0) { rsp->status_srb = NULL; sp->done(sp, cp->result); + } else { + WARN_ON_ONCE(true); } } -- cgit v1.2.3-59-g8ed1b From 5ec9f9040f61dfd0412a53fa2fc1e321727a5a61 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:12 -0700 Subject: scsi: qla2xxx: Let the compiler check the type of the SCSI command context pointer Split srb_cmd.ctx into two pointers such that the compiler can check the type of that pointer. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 4 ++-- drivers/scsi/qla2xxx/qla_iocb.c | 20 +++++++++----------- drivers/scsi/qla2xxx/qla_nx.c | 2 +- drivers/scsi/qla2xxx/qla_os.c | 24 ++++++++---------------- 4 files changed, 20 insertions(+), 30 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 3ffe7661a25b..527b2a2708a1 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -317,7 +317,8 @@ struct srb_cmd { uint32_t request_sense_length; uint32_t fw_sense_length; uint8_t *request_sense_ptr; - void *ctx; + struct ct6_dsd *ct6_ctx; + struct crc_context *crc_ctx; }; /* @@ -630,7 +631,6 @@ typedef struct srb { } srb_t; #define GET_CMD_SP(sp) (sp->u.scmd.cmd) -#define GET_CMD_CTX_SP(sp) (sp->u.scmd.ctx) #define GET_CMD_SENSE_LEN(sp) \ (sp->u.scmd.request_sense_length) diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 22d875222321..6acf92d19951 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -621,7 +621,7 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, } cur_seg = scsi_sglist(cmd); - ctx = GET_CMD_CTX_SP(sp); + ctx = sp->u.scmd.ct6_ctx; while (tot_dsds) { avail_dsds = (tot_dsds > QLA_DSDS_PER_IOCB) ? @@ -954,8 +954,7 @@ alloc_and_fill: if (sp) { list_add_tail(&dsd_ptr->list, - &((struct crc_context *) - sp->u.scmd.ctx)->dsd_list); + &sp->u.scmd.crc_ctx->dsd_list); sp->flags |= SRB_CRC_CTX_DSD_VALID; } else { @@ -1052,8 +1051,7 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, if (sp) { list_add_tail(&dsd_ptr->list, - &((struct crc_context *) - sp->u.scmd.ctx)->dsd_list); + &sp->u.scmd.crc_ctx->dsd_list); sp->flags |= SRB_CRC_CTX_DSD_VALID; } else { @@ -1099,7 +1097,7 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, sgl = scsi_prot_sglist(cmd); vha = sp->vha; - difctx = sp->u.scmd.ctx; + difctx = sp->u.scmd.crc_ctx; direction_to_device = cmd->sc_data_direction == DMA_TO_DEVICE; ql_dbg(ql_dbg_tgt + ql_dbg_verbose, vha, 0xe021, "%s: scsi_cmnd: %p, crc_ctx: %p, sp: %p\n", @@ -1439,7 +1437,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, bundling = 0; /* Allocate CRC context from global pool */ - crc_ctx_pkt = sp->u.scmd.ctx = + crc_ctx_pkt = sp->u.scmd.crc_ctx = dma_pool_zalloc(ha->dl_dma_pool, GFP_ATOMIC, &crc_ctx_dma); if (!crc_ctx_pkt) @@ -3188,7 +3186,7 @@ sufficient_dsds: goto queuing_error; } - ctx = sp->u.scmd.ctx = + ctx = sp->u.scmd.ct6_ctx = mempool_alloc(ha->ctx_mempool, GFP_ATOMIC); if (!ctx) { ql_log(ql_log_fatal, vha, 0x3010, @@ -3384,9 +3382,9 @@ queuing_error: if (tot_dsds) scsi_dma_unmap(cmd); - if (sp->u.scmd.ctx) { - mempool_free(sp->u.scmd.ctx, ha->ctx_mempool); - sp->u.scmd.ctx = NULL; + if (sp->u.scmd.crc_ctx) { + mempool_free(sp->u.scmd.crc_ctx, ha->ctx_mempool); + sp->u.scmd.crc_ctx = NULL; } spin_unlock_irqrestore(&ha->hardware_lock, flags); diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index a91d426add75..372355bfcbb6 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -3686,7 +3686,7 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha) for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) { sp = req->outstanding_cmds[cnt]; if (sp) { - if ((!sp->u.scmd.ctx || + if ((!sp->u.scmd.crc_ctx || (sp->flags & SRB_FCP_CMND_DMA_VALID)) && !ha->flags.isp82xx_fw_hung) { diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 5ca7f7913258..5cb0bb65ace3 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -656,7 +656,6 @@ void qla2x00_sp_free_dma(srb_t *sp) { struct qla_hw_data *ha = sp->vha->hw; struct scsi_cmnd *cmd = GET_CMD_SP(sp); - void *ctx = GET_CMD_CTX_SP(sp); if (sp->flags & SRB_DMA_VALID) { scsi_dma_unmap(cmd); @@ -669,24 +668,21 @@ void qla2x00_sp_free_dma(srb_t *sp) sp->flags &= ~SRB_CRC_PROT_DMA_VALID; } - if (!ctx) - return; - if (sp->flags & SRB_CRC_CTX_DSD_VALID) { /* List assured to be having elements */ - qla2x00_clean_dsd_pool(ha, ctx); + qla2x00_clean_dsd_pool(ha, sp->u.scmd.crc_ctx); sp->flags &= ~SRB_CRC_CTX_DSD_VALID; } if (sp->flags & SRB_CRC_CTX_DMA_VALID) { - struct crc_context *ctx0 = ctx; + struct crc_context *ctx0 = sp->u.scmd.crc_ctx; dma_pool_free(ha->dl_dma_pool, ctx0, ctx0->crc_ctx_dma); sp->flags &= ~SRB_CRC_CTX_DMA_VALID; } if (sp->flags & SRB_FCP_CMND_DMA_VALID) { - struct ct6_dsd *ctx1 = ctx; + struct ct6_dsd *ctx1 = sp->u.scmd.ct6_ctx; dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd, ctx1->fcp_cmnd_dma); @@ -719,7 +715,6 @@ void qla2xxx_qpair_sp_free_dma(srb_t *sp) { struct scsi_cmnd *cmd = GET_CMD_SP(sp); struct qla_hw_data *ha = sp->fcport->vha->hw; - void *ctx = GET_CMD_CTX_SP(sp); if (sp->flags & SRB_DMA_VALID) { scsi_dma_unmap(cmd); @@ -732,17 +727,14 @@ void qla2xxx_qpair_sp_free_dma(srb_t *sp) sp->flags &= ~SRB_CRC_PROT_DMA_VALID; } - if (!ctx) - return; - if (sp->flags & SRB_CRC_CTX_DSD_VALID) { /* List assured to be having elements */ - qla2x00_clean_dsd_pool(ha, ctx); + qla2x00_clean_dsd_pool(ha, sp->u.scmd.crc_ctx); sp->flags &= ~SRB_CRC_CTX_DSD_VALID; } if (sp->flags & SRB_DIF_BUNDL_DMA_VALID) { - struct crc_context *difctx = ctx; + struct crc_context *difctx = sp->u.scmd.crc_ctx; struct dsd_dma *dif_dsd, *nxt_dsd; list_for_each_entry_safe(dif_dsd, nxt_dsd, @@ -778,7 +770,7 @@ void qla2xxx_qpair_sp_free_dma(srb_t *sp) } if (sp->flags & SRB_FCP_CMND_DMA_VALID) { - struct ct6_dsd *ctx1 = ctx; + struct ct6_dsd *ctx1 = sp->u.scmd.ct6_ctx; dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd, ctx1->fcp_cmnd_dma); @@ -790,9 +782,9 @@ void qla2xxx_qpair_sp_free_dma(srb_t *sp) } if (sp->flags & SRB_CRC_CTX_DMA_VALID) { - struct crc_context *ctx0 = ctx; + struct crc_context *ctx0 = sp->u.scmd.crc_ctx; - dma_pool_free(ha->dl_dma_pool, ctx, ctx0->crc_ctx_dma); + dma_pool_free(ha->dl_dma_pool, ctx0, ctx0->crc_ctx_dma); sp->flags &= ~SRB_CRC_CTX_DMA_VALID; } } -- cgit v1.2.3-59-g8ed1b From 1a20719e074ada3e6d06ee065afd527779a6793b Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:13 -0700 Subject: scsi: qla2xxx: Remove superfluous sts_entry_* casts The C language supports implicit casting of void pointers to non-void pointers. Remove explicit sts_entry_* casts that are not necessary. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_isr.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 7533e420e571..5c65f2e67448 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1513,7 +1513,7 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req, if (comp_status == CS_DATA_UNDERRUN) { res = DID_OK << 16; bsg_reply->reply_payload_rcv_len = - le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len); + le16_to_cpu(pkt->rsp_info_len); ql_log(ql_log_warn, vha, 0x5048, "CT pass-through-%s error comp_status=0x%x total_byte=0x%x.\n", @@ -2256,11 +2256,8 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt, struct bsg_job *bsg_job = NULL; struct fc_bsg_request *bsg_request; struct fc_bsg_reply *bsg_reply; - sts_entry_t *sts; - struct sts_entry_24xx *sts24; - - sts = (sts_entry_t *) pkt; - sts24 = (struct sts_entry_24xx *) pkt; + sts_entry_t *sts = pkt; + struct sts_entry_24xx *sts24 = pkt; /* Validate handle. */ if (index >= req->num_outstanding_cmds) { @@ -2406,8 +2403,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) srb_t *sp; fc_port_t *fcport; struct scsi_cmnd *cp; - sts_entry_t *sts; - struct sts_entry_24xx *sts24; + sts_entry_t *sts = pkt; + struct sts_entry_24xx *sts24 = pkt; uint16_t comp_status; uint16_t scsi_status; uint16_t ox_id; @@ -2425,8 +2422,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) uint16_t state_flags = 0; uint16_t retry_delay = 0; - sts = (sts_entry_t *) pkt; - sts24 = (struct sts_entry_24xx *) pkt; if (IS_FWI2_CAPABLE(ha)) { comp_status = le16_to_cpu(sts24->comp_status); scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK; -- cgit v1.2.3-59-g8ed1b From 724361921f65a40ae5b80641dc1e92c0ff314d89 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:14 -0700 Subject: scsi: qla2xxx: Report invalid mailbox status codes It is easy to mix up the QLA_* and the MBS_* status codes. Complain loudly if that happens. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 5 +++++ drivers/scsi/qla2xxx/qla_init.c | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 527b2a2708a1..556376ce0259 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -990,6 +990,11 @@ struct mbx_cmd_32 { #define MBS_LINK_DOWN_ERROR 0x400B #define MBS_DIAG_ECHO_TEST_ERROR 0x400C +static inline bool qla2xxx_is_valid_mbs(unsigned int mbs) +{ + return MBS_COMMAND_COMPLETE <= mbs && mbs <= MBS_DIAG_ECHO_TEST_ERROR; +} + /* * ISP mailbox asynchronous event status codes */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 64c84e53011e..b3f1203bfe87 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -477,6 +477,9 @@ void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea) fcport->fw_login_state, ea->rc, fcport->login_gen, ea->sp->gen2, fcport->rscn_gen, ea->sp->gen1, fcport->loop_id); + WARN_ONCE(!qla2xxx_is_valid_mbs(ea->data[0]), "mbs: %#x\n", + ea->data[0]); + if (ea->data[0] != MBS_COMMAND_COMPLETE) { ql_dbg(ql_dbg_disc, vha, 0x2066, "%s %8phC: adisc fail: post delete\n", @@ -1893,6 +1896,9 @@ qla24xx_async_abort_command(srb_t *sp) static void qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea) { + WARN_ONCE(!qla2xxx_is_valid_mbs(ea->data[0]), "mbs: %#x\n", + ea->data[0]); + switch (ea->data[0]) { case MBS_COMMAND_COMPLETE: ql_dbg(ql_dbg_disc, vha, 0x2118, @@ -1978,6 +1984,9 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea) return; } + WARN_ONCE(!qla2xxx_is_valid_mbs(ea->data[0]), "mbs: %#x\n", + ea->data[0]); + switch (ea->data[0]) { case MBS_COMMAND_COMPLETE: /* -- cgit v1.2.3-59-g8ed1b From 897def2004213636ffe2e9ee6a75660c5b53b03d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:15 -0700 Subject: scsi: qla2xxx: Inline the qla2x00_fcport_event_handler() function Instead of calling qla2x00_fcport_event_handler() and letting the switch statement inside that function decide which other function to call, call the latter function directly. Remove the event member from the event_arg structure because it is no longer needed. Remove the qla_handle_els_plogi_done() function because it is never called. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 17 ------ drivers/scsi/qla2xxx/qla_gbl.h | 6 +- drivers/scsi/qla2xxx/qla_gs.c | 15 ++--- drivers/scsi/qla2xxx/qla_init.c | 131 ++++++++++------------------------------ drivers/scsi/qla2xxx/qla_iocb.c | 3 +- drivers/scsi/qla2xxx/qla_isr.c | 3 +- drivers/scsi/qla2xxx/qla_os.c | 3 +- 7 files changed, 45 insertions(+), 133 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 556376ce0259..a971d4245d89 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2363,22 +2363,6 @@ enum login_state { /* FW control Target side */ DSC_LS_LOGO_PEND, }; -enum fcport_mgt_event { - FCME_RELOGIN = 1, - FCME_RSCN, - FCME_PLOGI_DONE, /* Initiator side sent LLIOCB */ - FCME_PRLI_DONE, - FCME_GNL_DONE, - FCME_GPSC_DONE, - FCME_GPDB_DONE, - FCME_GPNID_DONE, - FCME_GFFID_DONE, - FCME_ADISC_DONE, - FCME_GNNID_DONE, - FCME_GFPNID_DONE, - FCME_ELS_PLOGI_DONE, -}; - enum rscn_addr_format { RSCN_PORT_ADDR, RSCN_AREA_ADDR, @@ -2496,7 +2480,6 @@ typedef struct fc_port { #define QLA_FCPORT_FOUND 2 struct event_arg { - enum fcport_mgt_event event; fc_port_t *fcport; srb_t *sp; port_id_t id; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 6b914942fad3..3f313eaf854b 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -96,7 +96,11 @@ extern int qla2x00_init_rings(scsi_qla_host_t *); extern struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *, int, int, bool); extern int qla2xxx_delete_qpair(struct scsi_qla_host *, struct qla_qpair *); -void qla2x00_fcport_event_handler(scsi_qla_host_t *, struct event_arg *); +void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea); +void qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, + struct event_arg *ea); +void qla24xx_handle_relogin_event(scsi_qla_host_t *vha, + struct event_arg *ea); int qla24xx_async_gpdb(struct scsi_qla_host *, fc_port_t *, u8); int qla24xx_async_prli(struct scsi_qla_host *, fc_port_t *); int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *, diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 35e1f36c9366..0e1df8232c75 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3031,11 +3031,10 @@ static void qla24xx_async_gpsc_sp_done(srb_t *sp, int res) be16_to_cpu(ct_rsp->rsp.gpsc.speed)); } memset(&ea, 0, sizeof(ea)); - ea.event = FCME_GPSC_DONE; ea.rc = res; ea.fcport = fcport; ea.sp = sp; - qla2x00_fcport_event_handler(vha, &ea); + qla24xx_handle_gpsc_event(vha, &ea); done: sp->free(sp); @@ -3283,7 +3282,6 @@ static void qla2x00_async_gpnid_sp_done(srb_t *sp, int res) ea.sp = sp; ea.id = be_to_port_id(ct_req->req.port_id.port_id); ea.rc = res; - ea.event = FCME_GPNID_DONE; spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); list_del(&sp->elem); @@ -3302,7 +3300,7 @@ static void qla2x00_async_gpnid_sp_done(srb_t *sp, int res) return; } - qla2x00_fcport_event_handler(vha, &ea); + qla24xx_handle_gpnid_event(vha, &ea); e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP); if (!e) { @@ -3481,9 +3479,8 @@ void qla24xx_async_gffid_sp_done(srb_t *sp, int res) ea.sp = sp; ea.fcport = sp->fcport; ea.rc = res; - ea.event = FCME_GFFID_DONE; - qla2x00_fcport_event_handler(vha, &ea); + qla24xx_handle_gffid_event(vha, &ea); sp->free(sp); } @@ -4263,13 +4260,12 @@ static void qla2x00_async_gnnid_sp_done(srb_t *sp, int res) ea.fcport = fcport; ea.sp = sp; ea.rc = res; - ea.event = FCME_GNNID_DONE; ql_dbg(ql_dbg_disc, vha, 0x204f, "Async done-%s res %x, WWPN %8phC %8phC\n", sp->name, res, fcport->port_name, fcport->node_name); - qla2x00_fcport_event_handler(vha, &ea); + qla24xx_handle_gnnid_event(vha, &ea); sp->free(sp); } @@ -4394,13 +4390,12 @@ static void qla2x00_async_gfpnid_sp_done(srb_t *sp, int res) ea.fcport = fcport; ea.sp = sp; ea.rc = res; - ea.event = FCME_GFPNID_DONE; ql_dbg(ql_dbg_disc, vha, 0x204f, "Async done-%s res %x, WWPN %8phC %8phC\n", sp->name, res, fcport->port_name, fcport->fabric_port_name); - qla2x00_fcport_event_handler(vha, &ea); + qla24xx_handle_gfpnid_event(vha, &ea); sp->free(sp); } diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index b3f1203bfe87..c9cb6856f82e 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -37,8 +37,8 @@ static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *); static int qla84xx_init_chip(scsi_qla_host_t *); static int qla25xx_init_queues(struct qla_hw_data *); static int qla24xx_post_prli_work(struct scsi_qla_host*, fc_port_t *); -static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *, - struct event_arg *); +static void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, + struct event_arg *ea); static void qla24xx_handle_prli_done_event(struct scsi_qla_host *, struct event_arg *); static void __qla24xx_handle_gpdb_event(scsi_qla_host_t *, struct event_arg *); @@ -263,14 +263,13 @@ static void qla2x00_async_login_sp_done(srb_t *sp, int res) if (!test_bit(UNLOADING, &vha->dpc_flags)) { memset(&ea, 0, sizeof(ea)); - ea.event = FCME_PLOGI_DONE; ea.fcport = sp->fcport; ea.data[0] = lio->u.logio.data[0]; ea.data[1] = lio->u.logio.data[1]; ea.iop[0] = lio->u.logio.iop[0]; ea.iop[1] = lio->u.logio.iop[1]; ea.sp = sp; - qla2x00_fcport_event_handler(vha, &ea); + qla24xx_handle_plogi_done_event(vha, &ea); } sp->free(sp); @@ -535,7 +534,6 @@ static void qla2x00_async_adisc_sp_done(srb_t *sp, int res) sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); memset(&ea, 0, sizeof(ea)); - ea.event = FCME_ADISC_DONE; ea.rc = res; ea.data[0] = lio->u.logio.data[0]; ea.data[1] = lio->u.logio.data[1]; @@ -544,7 +542,7 @@ static void qla2x00_async_adisc_sp_done(srb_t *sp, int res) ea.fcport = sp->fcport; ea.sp = sp; - qla2x00_fcport_event_handler(vha, &ea); + qla24xx_handle_adisc_event(vha, &ea); sp->free(sp); } @@ -950,7 +948,6 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res) memset(&ea, 0, sizeof(ea)); ea.sp = sp; ea.rc = res; - ea.event = FCME_GNL_DONE; if (sp->u.iocb_cmd.u.mbx.in_mb[1] >= sizeof(struct get_name_list_extended)) { @@ -989,7 +986,7 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res) spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); ea.fcport = fcport; - qla2x00_fcport_event_handler(vha, &ea); + qla24xx_handle_gnl_done_event(vha, &ea); } /* create new fcport if fw has knowledge of new sessions */ @@ -1134,11 +1131,10 @@ static void qla24xx_async_gpdb_sp_done(srb_t *sp, int res) fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); memset(&ea, 0, sizeof(ea)); - ea.event = FCME_GPDB_DONE; ea.fcport = fcport; ea.sp = sp; - qla2x00_fcport_event_handler(vha, &ea); + qla24xx_handle_gpdb_event(vha, &ea); dma_pool_free(ha->s_dma_pool, sp->u.iocb_cmd.u.mbx.in, sp->u.iocb_cmd.u.mbx.in_dma); @@ -1173,7 +1169,6 @@ static void qla2x00_async_prli_sp_done(srb_t *sp, int res) if (!test_bit(UNLOADING, &vha->dpc_flags)) { memset(&ea, 0, sizeof(ea)); - ea.event = FCME_PRLI_DONE; ea.fcport = sp->fcport; ea.data[0] = lio->u.logio.data[0]; ea.data[1] = lio->u.logio.data[1]; @@ -1181,7 +1176,7 @@ static void qla2x00_async_prli_sp_done(srb_t *sp, int res) ea.iop[1] = lio->u.logio.iop[1]; ea.sp = sp; - qla2x00_fcport_event_handler(vha, &ea); + qla24xx_handle_prli_done_event(vha, &ea); } sp->free(sp); @@ -1644,12 +1639,34 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id, return qla2x00_post_work(vha, e); } -static +void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea) +{ + fc_port_t *fcport; + unsigned long flags; + + fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1); + if (fcport) { + fcport->scan_needed = 1; + fcport->rscn_gen++; + } + + spin_lock_irqsave(&vha->work_lock, flags); + if (vha->scan.scan_flags == 0) { + ql_dbg(ql_dbg_disc, vha, 0xffff, "%s: schedule\n", __func__); + vha->scan.scan_flags |= SF_QUEUED; + schedule_delayed_work(&vha->scan.scan_work, 5); + } + spin_unlock_irqrestore(&vha->work_lock, flags); +} + void qla24xx_handle_relogin_event(scsi_qla_host_t *vha, struct event_arg *ea) { fc_port_t *fcport = ea->fcport; + if (test_bit(UNLOADING, &vha->dpc_flags)) + return; + ql_dbg(ql_dbg_disc, vha, 0x2102, "%s %8phC DS %d LS %d P %d del %d cnfl %p rscn %d|%d login %d|%d fl %x\n", __func__, fcport->port_name, fcport->disc_state, @@ -1680,89 +1697,6 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha, qla24xx_fcport_handle_login(vha, fcport); } - -static void qla_handle_els_plogi_done(scsi_qla_host_t *vha, - struct event_arg *ea) -{ - ql_dbg(ql_dbg_disc, vha, 0x2118, - "%s %d %8phC post PRLI\n", - __func__, __LINE__, ea->fcport->port_name); - qla24xx_post_prli_work(vha, ea->fcport); -} - -void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea) -{ - fc_port_t *fcport; - - switch (ea->event) { - case FCME_RELOGIN: - if (test_bit(UNLOADING, &vha->dpc_flags)) - return; - - qla24xx_handle_relogin_event(vha, ea); - break; - case FCME_RSCN: - if (test_bit(UNLOADING, &vha->dpc_flags)) - return; - { - unsigned long flags; - - fcport = qla2x00_find_fcport_by_nportid - (vha, &ea->id, 1); - if (fcport) { - fcport->scan_needed = 1; - fcport->rscn_gen++; - } - - spin_lock_irqsave(&vha->work_lock, flags); - if (vha->scan.scan_flags == 0) { - ql_dbg(ql_dbg_disc, vha, 0xffff, - "%s: schedule\n", __func__); - vha->scan.scan_flags |= SF_QUEUED; - schedule_delayed_work(&vha->scan.scan_work, 5); - } - spin_unlock_irqrestore(&vha->work_lock, flags); - } - break; - case FCME_GNL_DONE: - qla24xx_handle_gnl_done_event(vha, ea); - break; - case FCME_GPSC_DONE: - qla24xx_handle_gpsc_event(vha, ea); - break; - case FCME_PLOGI_DONE: /* Initiator side sent LLIOCB */ - qla24xx_handle_plogi_done_event(vha, ea); - break; - case FCME_PRLI_DONE: - qla24xx_handle_prli_done_event(vha, ea); - break; - case FCME_GPDB_DONE: - qla24xx_handle_gpdb_event(vha, ea); - break; - case FCME_GPNID_DONE: - qla24xx_handle_gpnid_event(vha, ea); - break; - case FCME_GFFID_DONE: - qla24xx_handle_gffid_event(vha, ea); - break; - case FCME_ADISC_DONE: - qla24xx_handle_adisc_event(vha, ea); - break; - case FCME_GNNID_DONE: - qla24xx_handle_gnnid_event(vha, ea); - break; - case FCME_GFPNID_DONE: - qla24xx_handle_gfpnid_event(vha, ea); - break; - case FCME_ELS_PLOGI_DONE: - qla_handle_els_plogi_done(vha, ea); - break; - default: - BUG_ON(1); - break; - } -} - /* * RSCN(s) came in for this fcport, but the RSCN(s) was not able * to be consumed by the fcport @@ -1780,10 +1714,9 @@ void qla_rscn_replay(fc_port_t *fcport) if (fcport->scan_needed) { memset(&ea, 0, sizeof(ea)); - ea.event = FCME_RSCN; ea.id = fcport->d_id; ea.id.b.rsvd_1 = RSCN_PORT_ADDR; - qla2x00_fcport_event_handler(fcport->vha, &ea); + qla2x00_handle_rscn(fcport->vha, &ea); } } @@ -1938,7 +1871,7 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea) } } -static void +void qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea) { port_id_t cid; /* conflict Nport id */ diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 6acf92d19951..39c7738c0a55 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -2741,8 +2741,7 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res) memset(&ea, 0, sizeof(ea)); ea.fcport = fcport; ea.rc = res; - ea.event = FCME_ELS_PLOGI_DONE; - qla2x00_fcport_event_handler(vha, &ea); + qla24xx_handle_plogi_done_event(vha, &ea); } e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP); diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 5c65f2e67448..cd39ac18c5fd 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1118,10 +1118,9 @@ global_port_update: struct event_arg ea; memset(&ea, 0, sizeof(ea)); - ea.event = FCME_RSCN; ea.id.b24 = rscn_entry; ea.id.b.rsvd_1 = rscn_entry >> 24; - qla2x00_fcport_event_handler(vha, &ea); + qla2x00_handle_rscn(vha, &ea); qla2x00_post_aen_work(vha, FCH_EVT_RSCN, rscn_entry); } break; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 5cb0bb65ace3..7d73b6a7cf41 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -5328,9 +5328,8 @@ void qla2x00_relogin(struct scsi_qla_host *vha) } else { if (vha->hw->current_topology != ISP_CFG_NL) { memset(&ea, 0, sizeof(ea)); - ea.event = FCME_RELOGIN; ea.fcport = fcport; - qla2x00_fcport_event_handler(vha, &ea); + qla24xx_handle_relogin_event(vha, &ea); } else if (vha->hw->current_topology == ISP_CFG_NL) { fcport->login_retry--; -- cgit v1.2.3-59-g8ed1b From c6e58160a2c0caf6a8079134f0807bef0ecec6b8 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:16 -0700 Subject: scsi: qla2xxx: Introduce qla2x00_els_dcmd2_free() This patch reduces code duplication. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 2 +- drivers/scsi/qla2xxx/qla_gbl.h | 2 ++ drivers/scsi/qla2xxx/qla_gs.c | 12 +----------- drivers/scsi/qla2xxx/qla_iocb.c | 40 +++++++++++++++++----------------------- 4 files changed, 21 insertions(+), 35 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index a971d4245d89..873a6aef1c5c 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -455,7 +455,7 @@ struct srb_iocb { struct els_logo_payload *els_logo_pyld; dma_addr_t els_logo_pyld_dma; } els_logo; - struct { + struct els_plogi { #define ELS_DCMD_PLOGI 0x3 uint32_t flags; uint32_t els_cmd; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 3f313eaf854b..d11416dcee4e 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -45,6 +45,8 @@ extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *); extern int qla24xx_els_dcmd_iocb(scsi_qla_host_t *, int, port_id_t); extern int qla24xx_els_dcmd2_iocb(scsi_qla_host_t *, int, fc_port_t *, bool); +extern void qla2x00_els_dcmd2_free(scsi_qla_host_t *vha, + struct els_plogi *els_plogi); extern void qla2x00_update_fcports(scsi_qla_host_t *); diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 0e1df8232c75..bf8b30c4827c 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3119,17 +3119,7 @@ void qla24xx_sp_unmap(scsi_qla_host_t *vha, srb_t *sp) switch (sp->type) { case SRB_ELS_DCMD: - if (c->u.els_plogi.els_plogi_pyld) - dma_free_coherent(&vha->hw->pdev->dev, - c->u.els_plogi.tx_size, - c->u.els_plogi.els_plogi_pyld, - c->u.els_plogi.els_plogi_pyld_dma); - - if (c->u.els_plogi.els_resp_pyld) - dma_free_coherent(&vha->hw->pdev->dev, - c->u.els_plogi.rx_size, - c->u.els_plogi.els_resp_pyld, - c->u.els_plogi.els_resp_pyld_dma); + qla2x00_els_dcmd2_free(vha, &c->u.els_plogi); break; case SRB_CT_PTHRU_CMD: default: diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 39c7738c0a55..7021fbeb6d23 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -2717,6 +2717,21 @@ qla2x00_els_dcmd2_iocb_timeout(void *data) sp->done(sp, QLA_FUNCTION_TIMEOUT); } +void qla2x00_els_dcmd2_free(scsi_qla_host_t *vha, struct els_plogi *els_plogi) +{ + if (els_plogi->els_plogi_pyld) + dma_free_coherent(&vha->hw->pdev->dev, + els_plogi->tx_size, + els_plogi->els_plogi_pyld, + els_plogi->els_plogi_pyld_dma); + + if (els_plogi->els_resp_pyld) + dma_free_coherent(&vha->hw->pdev->dev, + els_plogi->rx_size, + els_plogi->els_resp_pyld, + els_plogi->els_resp_pyld_dma); +} + static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res) { fc_port_t *fcport = sp->fcport; @@ -2748,17 +2763,7 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res) if (!e) { struct srb_iocb *elsio = &sp->u.iocb_cmd; - if (elsio->u.els_plogi.els_plogi_pyld) - dma_free_coherent(&sp->vha->hw->pdev->dev, - elsio->u.els_plogi.tx_size, - elsio->u.els_plogi.els_plogi_pyld, - elsio->u.els_plogi.els_plogi_pyld_dma); - - if (elsio->u.els_plogi.els_resp_pyld) - dma_free_coherent(&sp->vha->hw->pdev->dev, - elsio->u.els_plogi.rx_size, - elsio->u.els_plogi.els_resp_pyld, - elsio->u.els_plogi.els_resp_pyld_dma); + qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi); sp->free(sp); return; } @@ -2858,18 +2863,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, out: fcport->flags &= ~(FCF_ASYNC_SENT); - if (elsio->u.els_plogi.els_plogi_pyld) - dma_free_coherent(&sp->vha->hw->pdev->dev, - elsio->u.els_plogi.tx_size, - elsio->u.els_plogi.els_plogi_pyld, - elsio->u.els_plogi.els_plogi_pyld_dma); - - if (elsio->u.els_plogi.els_resp_pyld) - dma_free_coherent(&sp->vha->hw->pdev->dev, - elsio->u.els_plogi.rx_size, - elsio->u.els_plogi.els_resp_pyld, - elsio->u.els_plogi.els_resp_pyld_dma); - + qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi); sp->free(sp); done: return rval; -- cgit v1.2.3-59-g8ed1b From 1778a0e7bff8d4468658e7b4e5a16d99048cd7a8 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:17 -0700 Subject: scsi: qla2xxx: Remove two superfluous if-tests This patch fixes the following Coverity complaint: Null-checking sp->u.iocb_cmd.u.ctarg.rsp suggests that it may be null, but it has already been dereferenced on all paths leading to the check. See also commit e374f9f59281 ("scsi: qla2xxx: Migrate switch registration commands away from mailbox interface") # v4.16. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_gs.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index bf8b30c4827c..03f94eb372b6 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3295,20 +3295,17 @@ static void qla2x00_async_gpnid_sp_done(srb_t *sp, int res) e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP); if (!e) { /* please ignore kernel warning. otherwise, we have mem leak. */ - if (sp->u.iocb_cmd.u.ctarg.req) { - dma_free_coherent(&vha->hw->pdev->dev, - sp->u.iocb_cmd.u.ctarg.req_allocated_size, - sp->u.iocb_cmd.u.ctarg.req, - sp->u.iocb_cmd.u.ctarg.req_dma); - sp->u.iocb_cmd.u.ctarg.req = NULL; - } - if (sp->u.iocb_cmd.u.ctarg.rsp) { - dma_free_coherent(&vha->hw->pdev->dev, - sp->u.iocb_cmd.u.ctarg.rsp_allocated_size, - sp->u.iocb_cmd.u.ctarg.rsp, - sp->u.iocb_cmd.u.ctarg.rsp_dma); - sp->u.iocb_cmd.u.ctarg.rsp = NULL; - } + dma_free_coherent(&vha->hw->pdev->dev, + sp->u.iocb_cmd.u.ctarg.req_allocated_size, + sp->u.iocb_cmd.u.ctarg.req, + sp->u.iocb_cmd.u.ctarg.req_dma); + sp->u.iocb_cmd.u.ctarg.req = NULL; + + dma_free_coherent(&vha->hw->pdev->dev, + sp->u.iocb_cmd.u.ctarg.rsp_allocated_size, + sp->u.iocb_cmd.u.ctarg.rsp, + sp->u.iocb_cmd.u.ctarg.rsp_dma); + sp->u.iocb_cmd.u.ctarg.rsp = NULL; sp->free(sp); return; -- cgit v1.2.3-59-g8ed1b From fe6b52c9adbcce03c549d07c3db06b1694581225 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:18 -0700 Subject: scsi: qla2xxx: Simplify qla24xx_async_abort_cmd() Make the code easier to read by converting 'goto' statements into 'return' statements. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index c9cb6856f82e..535dc21ef56e 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -136,7 +136,7 @@ static int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait) sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp->fcport, GFP_ATOMIC); if (!sp) - goto done; + return rval; abt_iocb = &sp->u.iocb_cmd; sp->type = SRB_ABT_CMD; @@ -160,20 +160,18 @@ static int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait) cmd_sp->type); rval = qla2x00_start_sp(sp); - if (rval != QLA_SUCCESS) - goto done_free_sp; + if (rval != QLA_SUCCESS) { + sp->free(sp); + return rval; + } if (wait) { wait_for_completion(&abt_iocb->u.abt.comp); rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ? QLA_SUCCESS : QLA_FUNCTION_FAILED; - } else { - goto done; + sp->free(sp); } -done_free_sp: - sp->free(sp); -done: return rval; } -- cgit v1.2.3-59-g8ed1b From d1436e456b840162eb4d162f99055d2adb79a566 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 8 Aug 2019 20:02:19 -0700 Subject: scsi: qla2xxx: Fix a NULL pointer dereference BUG: KASAN: null-ptr-deref in qla24xx_handle_plogi_done_event+0x134/0x9f0 [qla2xxx] Read of size 4 at addr 00000000000000a0 by task swapper/2/0 CPU: 2 PID: 0 Comm: swapper/2 Not tainted 5.2.0-dbg+ #1 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 Call Trace: dump_stack+0x8a/0xd6 __kasan_report.cold+0x5/0x41 kasan_report+0x16/0x20 __asan_load4+0x7e/0x80 qla24xx_handle_plogi_done_event+0x134/0x9f0 [qla2xxx] qla2x00_els_dcmd2_sp_done+0x15f/0x230 [qla2xxx] qla24xx_els_ct_entry+0x3b3/0x610 [qla2xxx] qla24xx_process_response_queue+0x514/0x10e0 [qla2xxx] qla24xx_msix_rsp_q+0x80/0x100 [qla2xxx] __handle_irq_event_percpu+0x72/0x450 handle_irq_event_percpu+0x74/0xf0 handle_irq_event+0x5e/0x8f handle_edge_irq+0x13a/0x320 handle_irq+0x30/0x40 do_IRQ+0x91/0x190 common_interrupt+0xf/0xf RIP: 0010:default_idle+0x31/0x230 Fixes: 8777e4314d39 ("scsi: qla2xxx: Migrate NVME N2N handling into state machine") # v4.19. Cc: Himanshu Madhani Signed-off-by: Bart Van Assche Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_iocb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 7021fbeb6d23..e92e52aa6e9b 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -2755,7 +2755,8 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res) } else { memset(&ea, 0, sizeof(ea)); ea.fcport = fcport; - ea.rc = res; + ea.data[0] = MBS_COMMAND_COMPLETE; + ea.sp = sp; qla24xx_handle_plogi_done_event(vha, &ea); } -- cgit v1.2.3-59-g8ed1b From 9ab089d30bcf09d154c0da78920c13b581d23286 Mon Sep 17 00:00:00 2001 From: Chandrakanth Patil Date: Fri, 26 Jul 2019 13:02:14 +0530 Subject: scsi: megaraid_sas: Introduce module parameter for default queue depth This patch provides a module parameter and sysfs interface to select whether the queue depth for each device should be based on the value suggested by firmware (the default) or the maximum supported by the controller (can_queue). Although we have a sysfs interface per sdev to change the queue depth of individual scsi devices, this implementation provides a single sysfs entry per shost to switch between the controller max and the value reported by firmware. The module parameter can provide an interface for one time grub settings and provides persistent settings across the boot. [mkp: tweaked commit desc] Signed-off-by: Kashyap Desai Signed-off-by: Chandrakanth Patil Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas.h | 1 + drivers/scsi/megaraid/megaraid_sas_base.c | 112 ++++++++++++++++++++++++------ 2 files changed, 92 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index a14e8344822b..a6e788c02ff4 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -2429,6 +2429,7 @@ struct megasas_instance { u8 adapter_type; bool consistent_mask_64bit; bool support_nvme_passthru; + bool enable_sdev_max_qd; u8 task_abort_tmo; u8 max_reset_tmo; u8 snapdump_wait_time; diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index b2339d04a700..947da79c0977 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -109,6 +109,10 @@ int event_log_level = MFI_EVT_CLASS_CRITICAL; module_param(event_log_level, int, 0644); MODULE_PARM_DESC(event_log_level, "Asynchronous event logging level- range is: -2(CLASS_DEBUG) to 4(CLASS_DEAD), Default: 2(CLASS_CRITICAL)"); +unsigned int enable_sdev_max_qd; +module_param(enable_sdev_max_qd, int, 0444); +MODULE_PARM_DESC(enable_sdev_max_qd, "Enable sdev max qd as can_queue. Default: 0"); + MODULE_LICENSE("GPL"); MODULE_VERSION(MEGASAS_VERSION); MODULE_AUTHOR("megaraidlinux.pdl@broadcom.com"); @@ -1941,25 +1945,19 @@ megasas_set_nvme_device_properties(struct scsi_device *sdev, u32 max_io_size) blk_queue_virt_boundary(sdev->request_queue, mr_nvme_pg_size - 1); } - /* - * megasas_set_static_target_properties - - * Device property set by driver are static and it is not required to be - * updated after OCR. - * - * set io timeout - * set device queue depth - * set nvme device properties. see - megasas_set_nvme_device_properties + * megasas_set_fw_assisted_qd - + * set device queue depth to can_queue + * set device queue depth to fw assisted qd * * @sdev: scsi device * @is_target_prop true, if fw provided target properties. */ -static void megasas_set_static_target_properties(struct scsi_device *sdev, +static void megasas_set_fw_assisted_qd(struct scsi_device *sdev, bool is_target_prop) { u8 interface_type; u32 device_qd = MEGASAS_DEFAULT_CMD_PER_LUN; - u32 max_io_size_kb = MR_DEFAULT_NVME_MDTS_KB; u32 tgt_device_qd; struct megasas_instance *instance; struct MR_PRIV_DEVICE *mr_device_priv_data; @@ -1968,11 +1966,6 @@ static void megasas_set_static_target_properties(struct scsi_device *sdev, mr_device_priv_data = sdev->hostdata; interface_type = mr_device_priv_data->interface_type; - /* - * The RAID firmware may require extended timeouts. - */ - blk_queue_rq_timeout(sdev->request_queue, scmd_timeout * HZ); - switch (interface_type) { case SAS_PD: device_qd = MEGASAS_SAS_QD; @@ -1990,18 +1983,49 @@ static void megasas_set_static_target_properties(struct scsi_device *sdev, if (tgt_device_qd && (tgt_device_qd <= instance->host->can_queue)) device_qd = tgt_device_qd; + } - /* max_io_size_kb will be set to non zero for - * nvme based vd and syspd. - */ + if (instance->enable_sdev_max_qd && interface_type != UNKNOWN_DRIVE) + device_qd = instance->host->can_queue; + + scsi_change_queue_depth(sdev, device_qd); +} + +/* + * megasas_set_static_target_properties - + * Device property set by driver are static and it is not required to be + * updated after OCR. + * + * set io timeout + * set device queue depth + * set nvme device properties. see - megasas_set_nvme_device_properties + * + * @sdev: scsi device + * @is_target_prop true, if fw provided target properties. + */ +static void megasas_set_static_target_properties(struct scsi_device *sdev, + bool is_target_prop) +{ + u32 max_io_size_kb = MR_DEFAULT_NVME_MDTS_KB; + struct megasas_instance *instance; + + instance = megasas_lookup_instance(sdev->host->host_no); + + /* + * The RAID firmware may require extended timeouts. + */ + blk_queue_rq_timeout(sdev->request_queue, scmd_timeout * HZ); + + /* max_io_size_kb will be set to non zero for + * nvme based vd and syspd. + */ + if (is_target_prop) max_io_size_kb = le32_to_cpu(instance->tgt_prop->max_io_size_kb); - } if (instance->nvme_page_size && max_io_size_kb) megasas_set_nvme_device_properties(sdev, (max_io_size_kb << 10)); - scsi_change_queue_depth(sdev, device_qd); - + megasas_set_fw_assisted_qd(sdev, is_target_prop); } @@ -3281,6 +3305,48 @@ fw_cmds_outstanding_show(struct device *cdev, return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&instance->fw_outstanding)); } +static ssize_t +enable_sdev_max_qd_show(struct device *cdev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct megasas_instance *instance = (struct megasas_instance *)shost->hostdata; + + return snprintf(buf, PAGE_SIZE, "%d\n", instance->enable_sdev_max_qd); +} + +static ssize_t +enable_sdev_max_qd_store(struct device *cdev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct megasas_instance *instance = (struct megasas_instance *)shost->hostdata; + u32 val = 0; + bool is_target_prop; + int ret_target_prop = DCMD_FAILED; + struct scsi_device *sdev; + + if (kstrtou32(buf, 0, &val) != 0) { + pr_err("megasas: could not set enable_sdev_max_qd\n"); + return -EINVAL; + } + + mutex_lock(&instance->reset_mutex); + if (val) + instance->enable_sdev_max_qd = true; + else + instance->enable_sdev_max_qd = false; + + shost_for_each_device(sdev, shost) { + ret_target_prop = megasas_get_target_prop(instance, sdev); + is_target_prop = (ret_target_prop == DCMD_SUCCESS) ? true : false; + megasas_set_fw_assisted_qd(sdev, is_target_prop); + } + mutex_unlock(&instance->reset_mutex); + + return strlen(buf); +} + static ssize_t dump_system_regs_show(struct device *cdev, struct device_attribute *attr, char *buf) @@ -3310,6 +3376,7 @@ static DEVICE_ATTR_RW(fw_crash_state); static DEVICE_ATTR_RO(page_size); static DEVICE_ATTR_RO(ldio_outstanding); static DEVICE_ATTR_RO(fw_cmds_outstanding); +static DEVICE_ATTR_RW(enable_sdev_max_qd); static DEVICE_ATTR_RO(dump_system_regs); static DEVICE_ATTR_RO(raid_map_id); @@ -3320,6 +3387,7 @@ static struct device_attribute *megaraid_host_attrs[] = { &dev_attr_page_size, &dev_attr_ldio_outstanding, &dev_attr_fw_cmds_outstanding, + &dev_attr_enable_sdev_max_qd, &dev_attr_dump_system_regs, &dev_attr_raid_map_id, NULL, @@ -5891,6 +5959,8 @@ static int megasas_init_fw(struct megasas_instance *instance) MR_MAX_RAID_MAP_SIZE_MASK); } + instance->enable_sdev_max_qd = enable_sdev_max_qd; + switch (instance->adapter_type) { case VENTURA_SERIES: fusion->pcie_bw_limitation = true; -- cgit v1.2.3-59-g8ed1b From dbe447ac18aa99a15f462a63bc8016f3da139f23 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 6 Aug 2019 03:29:02 -0500 Subject: scsi: fas216: Mark expected switch fall-throughs Mark switch cases where we are expecting to fall through. Fix the following warnings (Building: rpc_defconfig arm): drivers/scsi/arm/fas216.c: In function fas216_disconnect_intr : drivers/scsi/arm/fas216.c:913:6: warning: this statement may fall through [-Wimplicit-fallthrough=] if (fas216_get_last_msg(info, info->scsi.msgin_fifo) == ABORT) { ^ drivers/scsi/arm/fas216.c:919:2: note: here default: /* huh? */ ^~~~~~~ drivers/scsi/arm/fas216.c: In function fas216_kick : drivers/scsi/arm/fas216.c:1959:3: warning: this statement may fall through [-Wimplicit-fallthrough=] fas216_allocate_tag(info, SCpnt); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/arm/fas216.c:1960:2: note: here case TYPE_OTHER: ^~~~ drivers/scsi/arm/fas216.c: In function fas216_busservice_intr : drivers/scsi/arm/fas216.c:1413:3: warning: this statement may fall through [-Wimplicit-fallthrough=] fas216_stoptransfer(info); ^~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/arm/fas216.c:1414:2: note: here case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps -> Status */ ^~~~ drivers/scsi/arm/fas216.c:1424:3: warning: this statement may fall through [-Wimplicit-fallthrough=] fas216_stoptransfer(info); ^~~~~~~~~~~~~~~~~~~~~~~~~ drivers/scsi/arm/fas216.c:1425:2: note: here case STATE(STAT_MESGIN, PHASE_COMMAND): /* Command -> Message In */ ^~~~ drivers/scsi/arm/fas216.c: In function fas216_funcdone_intr : drivers/scsi/arm/fas216.c:1573:6: warning: this statement may fall through [-Wimplicit-fallthrough=] if ((stat & STAT_BUSMASK) == STAT_MESGIN) { ^ drivers/scsi/arm/fas216.c:1579:2: note: here default: ^~~~~~~ drivers/scsi/arm/fas216.c: In function fas216_handlesync : drivers/scsi/arm/fas216.c:605:20: warning: this statement may fall through [-Wimplicit-fallthrough=] info->scsi.phase = PHASE_MSGOUT_EXPECT; ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~ drivers/scsi/arm/fas216.c:607:2: note: here case async: ^~~~ Signed-off-by: Gustavo A. R. Silva Signed-off-by: Martin K. Petersen --- drivers/scsi/arm/fas216.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c index aea4fd73c862..6c68c2303638 100644 --- a/drivers/scsi/arm/fas216.c +++ b/drivers/scsi/arm/fas216.c @@ -603,6 +603,7 @@ static void fas216_handlesync(FAS216_Info *info, char *msg) msgqueue_flush(&info->scsi.msgs); msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); info->scsi.phase = PHASE_MSGOUT_EXPECT; + /* fall through */ case async: dev->period = info->ifcfg.asyncperiod / 4; @@ -915,6 +916,7 @@ static void fas216_disconnect_intr(FAS216_Info *info) fas216_done(info, DID_ABORT); break; } + /* else, fall through */ default: /* huh? */ printk(KERN_ERR "scsi%d.%c: unexpected disconnect in phase %s\n", @@ -1411,6 +1413,8 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out -> Status */ case STATE(STAT_STATUS, PHASE_DATAIN): /* Data In -> Status */ fas216_stoptransfer(info); + /* fall through */ + case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps -> Status */ case STATE(STAT_STATUS, PHASE_MSGOUT): /* Message Out -> Status */ case STATE(STAT_STATUS, PHASE_COMMAND): /* Command -> Status */ @@ -1422,6 +1426,8 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne case STATE(STAT_MESGIN, PHASE_DATAOUT): /* Data Out -> Message In */ case STATE(STAT_MESGIN, PHASE_DATAIN): /* Data In -> Message In */ fas216_stoptransfer(info); + /* fall through */ + case STATE(STAT_MESGIN, PHASE_COMMAND): /* Command -> Message In */ case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In */ case STATE(STAT_MESGIN, PHASE_MSGOUT): /* Message Out -> Message In */ @@ -1575,6 +1581,7 @@ static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned fas216_message(info); break; } + /* else, fall through */ default: fas216_log(info, 0, "internal phase %s for function done?" @@ -1957,6 +1964,7 @@ static void fas216_kick(FAS216_Info *info) switch (where_from) { case TYPE_QUEUE: fas216_allocate_tag(info, SCpnt); + /* fall through */ case TYPE_OTHER: fas216_start_command(info, SCpnt); break; -- cgit v1.2.3-59-g8ed1b From 18daf910ed6ff408767b8d35aaa2f9f11119cd6d Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Fri, 9 Aug 2019 17:02:14 +0200 Subject: scsi: pmcraid: Fix a typo - pcmraid --> pmcraid This should be 'pmcraid', not 'pcmraid' Signed-off-by: Christophe JAILLET Signed-off-by: Martin K. Petersen --- drivers/scsi/pmcraid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 71ff3936da4f..398d2af60832 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -5841,7 +5841,7 @@ out_disable_device: } /* - * PCI driver structure of pcmraid driver + * PCI driver structure of pmcraid driver */ static struct pci_driver pmcraid_driver = { .name = PMCRAID_DRIVER_NAME, -- cgit v1.2.3-59-g8ed1b From 1d4f4a5e507f5879af56370380df600dd9119030 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 9 Aug 2019 18:59:32 +0100 Subject: scsi: sym53c8xx_2: remove redundant assignment to retv Variable retv is initialized to a value that is never read and it is re-assigned later. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Acked-by: Matthew Wilcox (Oracle) Signed-off-by: Martin K. Petersen --- drivers/scsi/sym53c8xx_2/sym_nvram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.c b/drivers/scsi/sym53c8xx_2/sym_nvram.c index dd3f07b31612..9dc17f1288f9 100644 --- a/drivers/scsi/sym53c8xx_2/sym_nvram.c +++ b/drivers/scsi/sym53c8xx_2/sym_nvram.c @@ -648,7 +648,7 @@ static int sym_read_T93C46_nvram(struct sym_device *np, Tekram_nvram *nvram) { u_char gpcntl, gpreg; u_char old_gpcntl, old_gpreg; - int retv = 1; + int retv; /* save current state of GPCNTL and GPREG */ old_gpreg = INB(np, nc_gpreg); -- cgit v1.2.3-59-g8ed1b From 3e76ca9561ce6bd245793edebd36e718bff89d3e Mon Sep 17 00:00:00 2001 From: Frederick Lawler Date: Wed, 17 Jul 2019 21:07:43 -0500 Subject: scsi: csiostor: Prefer pcie_capability_read_word() Commit 8c0d3a02c130 ("PCI: Add accessors for PCI Express Capability") added accessors for the PCI Express Capability so that drivers didn't need to be aware of differences between v1 and v2 of the PCI Express Capability. Replace pci_read_config_word() and pci_write_config_word() calls with pcie_capability_read_word() and pcie_capability_write_word(). Signed-off-by: Frederick Lawler Signed-off-by: Martin K. Petersen --- drivers/scsi/csiostor/csio_wr.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/csiostor/csio_wr.c b/drivers/scsi/csiostor/csio_wr.c index 03bd896cdbb9..0ca695110f54 100644 --- a/drivers/scsi/csiostor/csio_wr.c +++ b/drivers/scsi/csiostor/csio_wr.c @@ -1316,7 +1316,6 @@ csio_wr_fixup_host_params(struct csio_hw *hw) u32 fl_align = clsz < 32 ? 32 : clsz; u32 pack_align; u32 ingpad, ingpack; - int pcie_cap; csio_wr_reg32(hw, HOSTPAGESIZEPF0_V(s_hps) | HOSTPAGESIZEPF1_V(s_hps) | HOSTPAGESIZEPF2_V(s_hps) | HOSTPAGESIZEPF3_V(s_hps) | @@ -1347,8 +1346,7 @@ csio_wr_fixup_host_params(struct csio_hw *hw) * multiple of the Maximum Payload Size. */ pack_align = fl_align; - pcie_cap = pci_find_capability(hw->pdev, PCI_CAP_ID_EXP); - if (pcie_cap) { + if (pci_is_pcie(hw->pdev)) { u32 mps, mps_log; u16 devctl; @@ -1356,9 +1354,7 @@ csio_wr_fixup_host_params(struct csio_hw *hw) * [bits 7:5] encodes sizes as powers of 2 starting at * 128 bytes. */ - pci_read_config_word(hw->pdev, - pcie_cap + PCI_EXP_DEVCTL, - &devctl); + pcie_capability_read_word(hw->pdev, PCI_EXP_DEVCTL, &devctl); mps_log = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5) + 7; mps = 1 << mps_log; if (mps > pack_align) -- cgit v1.2.3-59-g8ed1b From 2b4f4cb93ae32f40dc232f8699b125541f494b3d Mon Sep 17 00:00:00 2001 From: Frederick Lawler Date: Wed, 17 Jul 2019 21:07:44 -0500 Subject: scsi: esas2r: Prefer pcie_capability_read_word() Commit 8c0d3a02c130 ("PCI: Add accessors for PCI Express Capability") added accessors for the PCI Express Capability so that drivers didn't need to be aware of differences between v1 and v2 of the PCI Express Capability. Replace pci_read_config_word() and pci_write_config_word() calls with pcie_capability_read_word() and pcie_capability_write_word(). Signed-off-by: Frederick Lawler Signed-off-by: Martin K. Petersen --- drivers/scsi/esas2r/esas2r_init.c | 13 ++++--------- drivers/scsi/esas2r/esas2r_ioctl.c | 14 +++++--------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/esas2r/esas2r_init.c b/drivers/scsi/esas2r/esas2r_init.c index 950cd92df2ff..eb7d139ffc00 100644 --- a/drivers/scsi/esas2r/esas2r_init.c +++ b/drivers/scsi/esas2r/esas2r_init.c @@ -762,14 +762,10 @@ u32 esas2r_get_uncached_size(struct esas2r_adapter *a) static void esas2r_init_pci_cfg_space(struct esas2r_adapter *a) { - int pcie_cap_reg; - - pcie_cap_reg = pci_find_capability(a->pcid, PCI_CAP_ID_EXP); - if (pcie_cap_reg) { + if (pci_is_pcie(a->pcid)) { u16 devcontrol; - pci_read_config_word(a->pcid, pcie_cap_reg + PCI_EXP_DEVCTL, - &devcontrol); + pcie_capability_read_word(a->pcid, PCI_EXP_DEVCTL, &devcontrol); if ((devcontrol & PCI_EXP_DEVCTL_READRQ) > PCI_EXP_DEVCTL_READRQ_512B) { @@ -778,9 +774,8 @@ static void esas2r_init_pci_cfg_space(struct esas2r_adapter *a) devcontrol &= ~PCI_EXP_DEVCTL_READRQ; devcontrol |= PCI_EXP_DEVCTL_READRQ_512B; - pci_write_config_word(a->pcid, - pcie_cap_reg + PCI_EXP_DEVCTL, - devcontrol); + pcie_capability_write_word(a->pcid, PCI_EXP_DEVCTL, + devcontrol); } } } diff --git a/drivers/scsi/esas2r/esas2r_ioctl.c b/drivers/scsi/esas2r/esas2r_ioctl.c index 3d130523c288..442c5e70a7b4 100644 --- a/drivers/scsi/esas2r/esas2r_ioctl.c +++ b/drivers/scsi/esas2r/esas2r_ioctl.c @@ -757,7 +757,6 @@ static int hba_ioctl_callback(struct esas2r_adapter *a, struct atto_hba_get_adapter_info *gai = &hi->data.get_adap_info; - int pcie_cap_reg; if (hi->flags & HBAF_TUNNEL) { hi->status = ATTO_STS_UNSUPPORTED; @@ -784,17 +783,14 @@ static int hba_ioctl_callback(struct esas2r_adapter *a, gai->pci.dev_num = PCI_SLOT(a->pcid->devfn); gai->pci.func_num = PCI_FUNC(a->pcid->devfn); - pcie_cap_reg = pci_find_capability(a->pcid, PCI_CAP_ID_EXP); - if (pcie_cap_reg) { + if (pci_is_pcie(a->pcid)) { u16 stat; u32 caps; - pci_read_config_word(a->pcid, - pcie_cap_reg + PCI_EXP_LNKSTA, - &stat); - pci_read_config_dword(a->pcid, - pcie_cap_reg + PCI_EXP_LNKCAP, - &caps); + pcie_capability_read_word(a->pcid, PCI_EXP_LNKSTA, + &stat); + pcie_capability_read_dword(a->pcid, PCI_EXP_LNKCAP, + &caps); gai->pci.link_speed_curr = (u8)(stat & PCI_EXP_LNKSTA_CLS); -- cgit v1.2.3-59-g8ed1b From 075c2b6bf654bdba977795e95bba130113156a35 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 21 Jul 2019 23:25:02 +0900 Subject: scsi: use __u{8,16,32,64} instead of uint{8,16,32,64}_t in uapi headers When CONFIG_UAPI_HEADER_TEST=y, exported headers are compile-tested to make sure they can be included from user-space. Currently, scsi_bsg_fc.h, scsi_netlink.h, and scsi_netlink_fc.h are excluded from the test coverage. To make them join the compile-test, we need to fix the build errors attached below. For a case like this, we decided to use __u{8,16,32,64} variable types in this discussion: https://lkml.org/lkml/2019/6/5/18 Build log: CC usr/include/scsi/scsi_netlink_fc.h.s CC usr/include/scsi/scsi_netlink.h.s CC usr/include/scsi/scsi_bsg_fc.h.s In file included from ./usr/include/scsi/scsi_netlink_fc.h:10:0, from :32: ./usr/include/scsi/scsi_netlink.h:29:2: error: unknown type name uint8_t uint8_t version; ^~~~~~~ ./usr/include/scsi/scsi_netlink.h:30:2: error: unknown type name uint8_t uint8_t transport; ^~~~~~~ ./usr/include/scsi/scsi_netlink.h:31:2: error: unknown type name uint16_t uint16_t magic; ^~~~~~~~ ./usr/include/scsi/scsi_netlink.h:32:2: error: unknown type name uint16_t uint16_t msgtype; ^~~~~~~~ CC usr/include/rdma/vmw_pvrdma-abi.h.s ./usr/include/scsi/scsi_netlink.h:33:2: error: unknown type name uint16_t uint16_t msglen; ^~~~~~~~ ./usr/include/scsi/scsi_netlink.h:34:33: error: uint64_t undeclared here (not in a function); did you mean __uint128_t ? } __attribute__((aligned(sizeof(uint64_t)))); ^~~~~~~~ __uint128_t ./usr/include/scsi/scsi_netlink.h:78:2: error: expected specifier-qualifier-list before uint64_t uint64_t vendor_id; ^~~~~~~~ In file included from :32:0: ./usr/include/scsi/scsi_netlink_fc.h:46:2: error: expected specifier-qualifier-list before uint64_t uint64_t seconds; ^~~~~~~~ make[2]: *** [scripts/Makefile.build;302: usr/include/scsi/scsi_netlink_fc.h.s] Error 1 make[2]: *** Waiting for unfinished jobs.... In file included from :32:0: ./usr/include/scsi/scsi_netlink.h:29:2: error: unknown type name uint8_t uint8_t version; ^~~~~~~ ./usr/include/scsi/scsi_netlink.h:30:2: error: unknown type name uint8_t uint8_t transport; ^~~~~~~ ./usr/include/scsi/scsi_netlink.h:31:2: error: unknown type name uint16_t uint16_t magic; ^~~~~~~~ ./usr/include/scsi/scsi_netlink.h:32:2: error: unknown type name uint16_t uint16_t msgtype; ^~~~~~~~ ./usr/include/scsi/scsi_netlink.h:33:2: error: unknown type name uint16_t uint16_t msglen; ^~~~~~~~ ./usr/include/scsi/scsi_netlink.h:34:33: error: uint64_t undeclared here (not in a function); did you mean __uint128_t ? } __attribute__((aligned(sizeof(uint64_t)))); ^~~~~~~~ __uint128_t ./usr/include/scsi/scsi_netlink.h:78:2: error: expected specifier-qualifier-list before uint64_t uint64_t vendor_id; ^~~~~~~~ make[2]: *** [scripts/Makefile.build;302: usr/include/scsi/scsi_netlink.h.s] Error 1 In file included from :32:0: ./usr/include/scsi/scsi_bsg_fc.h:69:2: error: unknown type name uint8_t uint8_t reserved; ^~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:72:2: error: unknown type name uint8_t uint8_t port_id[3]; ^~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:90:2: error: unknown type name uint8_t uint8_t reserved; ^~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:93:2: error: unknown type name uint8_t uint8_t port_id[3]; ^~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:114:2: error: unknown type name uint8_t uint8_t command_code; ^~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:117:2: error: unknown type name uint8_t uint8_t port_id[3]; ^~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:154:2: error: unknown type name uint32_t uint32_t status; /* See FC_CTELS_STATUS_xxx */ ^~~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:158:3: error: unknown type name uint8_t uint8_t action; /* fragment_id for CT REJECT */ ^~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:159:3: error: unknown type name uint8_t uint8_t reason_code; ^~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:160:3: error: unknown type name uint8_t uint8_t reason_explanation; ^~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:161:3: error: unknown type name uint8_t uint8_t vendor_unique; ^~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:177:2: error: unknown type name uint8_t uint8_t reserved; ^~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:180:2: error: unknown type name uint8_t uint8_t port_id[3]; ^~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:185:2: error: unknown type name uint32_t uint32_t preamble_word0; /* revision & IN_ID */ ^~~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:186:2: error: unknown type name uint32_t uint32_t preamble_word1; /* GS_Type, GS_SubType, Options, Rsvd */ ^~~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:187:2: error: unknown type name uint32_t uint32_t preamble_word2; /* Cmd Code, Max Size */ ^~~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:207:2: error: unknown type name uint64_t uint64_t vendor_id; ^~~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:210:2: error: unknown type name uint32_t uint32_t vendor_cmd[0]; ^~~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:217:2: error: unknown type name uint32_t uint32_t vendor_rsp[0]; ^~~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:236:2: error: unknown type name uint8_t uint8_t els_code; ^~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:254:2: error: unknown type name uint32_t uint32_t preamble_word0; /* revision & IN_ID */ ^~~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:255:2: error: unknown type name uint32_t uint32_t preamble_word1; /* GS_Type, GS_SubType, Options, Rsvd */ ^~~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:256:2: error: unknown type name uint32_t uint32_t preamble_word2; /* Cmd Code, Max Size */ ^~~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:268:2: error: unknown type name uint32_t uint32_t msgcode; ^~~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:292:2: error: unknown type name uint32_t uint32_t result; ^~~~~~~~ ./usr/include/scsi/scsi_bsg_fc.h:295:2: error: unknown type name uint32_t uint32_t reply_payload_rcv_len; ^~~~~~~~ Signed-off-by: Masahiro Yamada Signed-off-by: Martin K. Petersen --- include/uapi/scsi/scsi_bsg_fc.h | 54 +++++++++++++++++++------------------ include/uapi/scsi/scsi_netlink.h | 20 +++++++------- include/uapi/scsi/scsi_netlink_fc.h | 17 ++++++------ 3 files changed, 47 insertions(+), 44 deletions(-) diff --git a/include/uapi/scsi/scsi_bsg_fc.h b/include/uapi/scsi/scsi_bsg_fc.h index 52f32a60d056..3ae65e93235c 100644 --- a/include/uapi/scsi/scsi_bsg_fc.h +++ b/include/uapi/scsi/scsi_bsg_fc.h @@ -8,6 +8,8 @@ #ifndef SCSI_BSG_FC_H #define SCSI_BSG_FC_H +#include + /* * This file intended to be included by both kernel and user space */ @@ -66,10 +68,10 @@ * with the transport upon completion of the login. */ struct fc_bsg_host_add_rport { - uint8_t reserved; + __u8 reserved; /* FC Address Identier of the remote port to login to */ - uint8_t port_id[3]; + __u8 port_id[3]; }; /* Response: @@ -87,10 +89,10 @@ struct fc_bsg_host_add_rport { * remain logged in with the remote port. */ struct fc_bsg_host_del_rport { - uint8_t reserved; + __u8 reserved; /* FC Address Identier of the remote port to logout of */ - uint8_t port_id[3]; + __u8 port_id[3]; }; /* Response: @@ -111,10 +113,10 @@ struct fc_bsg_host_els { * ELS Command Code being sent (must be the same as byte 0 * of the payload) */ - uint8_t command_code; + __u8 command_code; /* FC Address Identier of the remote port to send the ELS to */ - uint8_t port_id[3]; + __u8 port_id[3]; }; /* Response: @@ -151,14 +153,14 @@ struct fc_bsg_ctels_reply { * Note: x_RJT/BSY status will indicae that the rjt_data field * is valid and contains the reason/explanation values. */ - uint32_t status; /* See FC_CTELS_STATUS_xxx */ + __u32 status; /* See FC_CTELS_STATUS_xxx */ /* valid if status is not FC_CTELS_STATUS_OK */ struct { - uint8_t action; /* fragment_id for CT REJECT */ - uint8_t reason_code; - uint8_t reason_explanation; - uint8_t vendor_unique; + __u8 action; /* fragment_id for CT REJECT */ + __u8 reason_code; + __u8 reason_explanation; + __u8 vendor_unique; } rjt_data; }; @@ -174,17 +176,17 @@ struct fc_bsg_ctels_reply { * and whether to tear it down after the request. */ struct fc_bsg_host_ct { - uint8_t reserved; + __u8 reserved; /* FC Address Identier of the remote port to send the ELS to */ - uint8_t port_id[3]; + __u8 port_id[3]; /* * We need words 0-2 of the generic preamble for the LLD's */ - uint32_t preamble_word0; /* revision & IN_ID */ - uint32_t preamble_word1; /* GS_Type, GS_SubType, Options, Rsvd */ - uint32_t preamble_word2; /* Cmd Code, Max Size */ + __u32 preamble_word0; /* revision & IN_ID */ + __u32 preamble_word1; /* GS_Type, GS_SubType, Options, Rsvd */ + __u32 preamble_word2; /* Cmd Code, Max Size */ }; /* Response: @@ -204,17 +206,17 @@ struct fc_bsg_host_vendor { * Identifies the vendor that the message is formatted for. This * should be the recipient of the message. */ - uint64_t vendor_id; + __u64 vendor_id; /* start of vendor command area */ - uint32_t vendor_cmd[0]; + __u32 vendor_cmd[0]; }; /* Response: */ struct fc_bsg_host_vendor_reply { /* start of vendor response area */ - uint32_t vendor_rsp[0]; + __u32 vendor_rsp[0]; }; @@ -233,7 +235,7 @@ struct fc_bsg_rport_els { * ELS Command Code being sent (must be the same as * byte 0 of the payload) */ - uint8_t els_code; + __u8 els_code; }; /* Response: @@ -251,9 +253,9 @@ struct fc_bsg_rport_ct { /* * We need words 0-2 of the generic preamble for the LLD's */ - uint32_t preamble_word0; /* revision & IN_ID */ - uint32_t preamble_word1; /* GS_Type, GS_SubType, Options, Rsvd */ - uint32_t preamble_word2; /* Cmd Code, Max Size */ + __u32 preamble_word0; /* revision & IN_ID */ + __u32 preamble_word1; /* GS_Type, GS_SubType, Options, Rsvd */ + __u32 preamble_word2; /* Cmd Code, Max Size */ }; /* Response: * @@ -265,7 +267,7 @@ struct fc_bsg_rport_ct { /* request (CDB) structure of the sg_io_v4 */ struct fc_bsg_request { - uint32_t msgcode; + __u32 msgcode; union { struct fc_bsg_host_add_rport h_addrport; struct fc_bsg_host_del_rport h_delrport; @@ -289,10 +291,10 @@ struct fc_bsg_reply { * msg and status fields. The per-msgcode reply structure * will contain valid data. */ - uint32_t result; + __u32 result; /* If there was reply_payload, how much was recevied ? */ - uint32_t reply_payload_rcv_len; + __u32 reply_payload_rcv_len; union { struct fc_bsg_host_vendor_reply vendor_reply; diff --git a/include/uapi/scsi/scsi_netlink.h b/include/uapi/scsi/scsi_netlink.h index 5dd382054e45..1b1737c3c9d8 100644 --- a/include/uapi/scsi/scsi_netlink.h +++ b/include/uapi/scsi/scsi_netlink.h @@ -26,12 +26,12 @@ /* SCSI_TRANSPORT_MSG event message header */ struct scsi_nl_hdr { - uint8_t version; - uint8_t transport; - uint16_t magic; - uint16_t msgtype; - uint16_t msglen; -} __attribute__((aligned(sizeof(uint64_t)))); + __u8 version; + __u8 transport; + __u16 magic; + __u16 msgtype; + __u16 msglen; +} __attribute__((aligned(sizeof(__u64)))); /* scsi_nl_hdr->version value */ #define SCSI_NL_VERSION 1 @@ -75,10 +75,10 @@ struct scsi_nl_hdr { */ struct scsi_nl_host_vendor_msg { struct scsi_nl_hdr snlh; /* must be 1st element ! */ - uint64_t vendor_id; - uint16_t host_no; - uint16_t vmsg_datalen; -} __attribute__((aligned(sizeof(uint64_t)))); + __u64 vendor_id; + __u16 host_no; + __u16 vmsg_datalen; +} __attribute__((aligned(sizeof(__u64)))); /* diff --git a/include/uapi/scsi/scsi_netlink_fc.h b/include/uapi/scsi/scsi_netlink_fc.h index a39023579051..7535253f1a96 100644 --- a/include/uapi/scsi/scsi_netlink_fc.h +++ b/include/uapi/scsi/scsi_netlink_fc.h @@ -7,6 +7,7 @@ #ifndef SCSI_NETLINK_FC_H #define SCSI_NETLINK_FC_H +#include #include /* @@ -43,14 +44,14 @@ */ struct fc_nl_event { struct scsi_nl_hdr snlh; /* must be 1st element ! */ - uint64_t seconds; - uint64_t vendor_id; - uint16_t host_no; - uint16_t event_datalen; - uint32_t event_num; - uint32_t event_code; - uint32_t event_data; -} __attribute__((aligned(sizeof(uint64_t)))); + __u64 seconds; + __u64 vendor_id; + __u16 host_no; + __u16 event_datalen; + __u32 event_num; + __u32 event_code; + __u32 event_data; +} __attribute__((aligned(sizeof(__u64)))); #endif /* SCSI_NETLINK_FC_H */ -- cgit v1.2.3-59-g8ed1b From edbd56472a636ab396f5ee6783e8438fa725a6ee Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Wed, 14 Aug 2019 13:28:27 +0000 Subject: scsi: qla2xxx: qla2x00_alloc_fw_dump: set ha->eft In qla2x00_alloc_fw_dump(), an existing EFT buffer (e.g. from previous invocation of qla2x00_alloc_offload_mem()) is freed. The buffer is then re-allocated, but without setting the eft and eft_dma fields to the new values. Fixes: a28d9e4ef997 ("scsi: qla2xxx: Add support for multiple fwdump templates/segments") Cc: Joe Carnuccio Cc: Quinn Tran Cc: Himanshu Madhani Cc: Bart Van Assche Signed-off-by: Martin Wilck Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 535dc21ef56e..6dd68be611ef 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3197,6 +3197,8 @@ try_eft: ql_dbg(ql_dbg_init, vha, 0x00c3, "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024); eft_size = EFT_SIZE; + ha->eft_dma = tc_dma; + ha->eft = tc; } if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { -- cgit v1.2.3-59-g8ed1b From 3cf92f4bfccbb3e378cd86dc46e09c2bc18cda26 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Wed, 14 Aug 2019 13:28:29 +0000 Subject: scsi: qla2xxx: cleanup trace buffer initialization Avoid code duplication between qla2x00_alloc_offload_mem() and qla2x00_alloc_fw_dump() by moving the FCE and EFT buffer allocation and initialization to separate functions. Cleanly track failure and success by making sure that the ha->eft, ha->fce and respective eft_dma, fce_dma members are set if and only if the buffers are properly allocated and initialized. Avoid pointless buffer reallocation. Eliminate some goto statements. Make sure the fce_enabled flag is cleared when the FCE buffer is freed. Fixes: ad0a0b01f088 ("scsi: qla2xxx: Fix Firmware dump size for Extended login and Exchange Offload") Fixes: a28d9e4ef997 ("scsi: qla2xxx: Add support for multiple fwdump templates/segments") Cc: Joe Carnuccio Cc: Quinn Tran Cc: Himanshu Madhani Cc: Bart Van Assche Signed-off-by: Martin Wilck Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 214 ++++++++++++++++++---------------------- drivers/scsi/qla2xxx/qla_os.c | 1 + 2 files changed, 99 insertions(+), 116 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 6dd68be611ef..4a89ec58fb41 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3032,103 +3032,113 @@ qla24xx_chip_diag(scsi_qla_host_t *vha) } static void -qla2x00_alloc_offload_mem(scsi_qla_host_t *vha) +qla2x00_init_fce_trace(scsi_qla_host_t *vha) { int rval; dma_addr_t tc_dma; void *tc; struct qla_hw_data *ha = vha->hw; - if (ha->eft) { + if (!IS_FWI2_CAPABLE(ha)) + return; + + if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) && + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + return; + + if (ha->fce) { ql_dbg(ql_dbg_init, vha, 0x00bd, - "%s: Offload Mem is already allocated.\n", - __func__); + "%s: FCE Mem is already allocated.\n", + __func__); return; } - if (IS_FWI2_CAPABLE(ha)) { - /* Allocate memory for Fibre Channel Event Buffer. */ - if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) && - !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) - goto try_eft; + /* Allocate memory for Fibre Channel Event Buffer. */ + tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma, + GFP_KERNEL); + if (!tc) { + ql_log(ql_log_warn, vha, 0x00be, + "Unable to allocate (%d KB) for FCE.\n", + FCE_SIZE / 1024); + return; + } - if (ha->fce) - dma_free_coherent(&ha->pdev->dev, - FCE_SIZE, ha->fce, ha->fce_dma); + rval = qla2x00_enable_fce_trace(vha, tc_dma, FCE_NUM_BUFFERS, + ha->fce_mb, &ha->fce_bufs); + if (rval) { + ql_log(ql_log_warn, vha, 0x00bf, + "Unable to initialize FCE (%d).\n", rval); + dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc, tc_dma); + return; + } - /* Allocate memory for Fibre Channel Event Buffer. */ - tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma, - GFP_KERNEL); - if (!tc) { - ql_log(ql_log_warn, vha, 0x00be, - "Unable to allocate (%d KB) for FCE.\n", - FCE_SIZE / 1024); - goto try_eft; - } - - rval = qla2x00_enable_fce_trace(vha, tc_dma, FCE_NUM_BUFFERS, - ha->fce_mb, &ha->fce_bufs); - if (rval) { - ql_log(ql_log_warn, vha, 0x00bf, - "Unable to initialize FCE (%d).\n", rval); - dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc, - tc_dma); - ha->flags.fce_enabled = 0; - goto try_eft; - } - ql_dbg(ql_dbg_init, vha, 0x00c0, - "Allocate (%d KB) for FCE...\n", FCE_SIZE / 1024); - - ha->flags.fce_enabled = 1; - ha->fce_dma = tc_dma; - ha->fce = tc; - -try_eft: - if (ha->eft) - dma_free_coherent(&ha->pdev->dev, - EFT_SIZE, ha->eft, ha->eft_dma); + ql_dbg(ql_dbg_init, vha, 0x00c0, + "Allocated (%d KB) for FCE...\n", FCE_SIZE / 1024); - /* Allocate memory for Extended Trace Buffer. */ - tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma, - GFP_KERNEL); - if (!tc) { - ql_log(ql_log_warn, vha, 0x00c1, - "Unable to allocate (%d KB) for EFT.\n", - EFT_SIZE / 1024); - goto eft_err; - } + ha->flags.fce_enabled = 1; + ha->fce_dma = tc_dma; + ha->fce = tc; +} - rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS); - if (rval) { - ql_log(ql_log_warn, vha, 0x00c2, - "Unable to initialize EFT (%d).\n", rval); - dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc, - tc_dma); - goto eft_err; - } - ql_dbg(ql_dbg_init, vha, 0x00c3, - "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024); +static void +qla2x00_init_eft_trace(scsi_qla_host_t *vha) +{ + int rval; + dma_addr_t tc_dma; + void *tc; + struct qla_hw_data *ha = vha->hw; + + if (!IS_FWI2_CAPABLE(ha)) + return; - ha->eft_dma = tc_dma; - ha->eft = tc; + if (ha->eft) { + ql_dbg(ql_dbg_init, vha, 0x00bd, + "%s: EFT Mem is already allocated.\n", + __func__); + return; } -eft_err: - return; + /* Allocate memory for Extended Trace Buffer. */ + tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma, + GFP_KERNEL); + if (!tc) { + ql_log(ql_log_warn, vha, 0x00c1, + "Unable to allocate (%d KB) for EFT.\n", + EFT_SIZE / 1024); + return; + } + + rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS); + if (rval) { + ql_log(ql_log_warn, vha, 0x00c2, + "Unable to initialize EFT (%d).\n", rval); + dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc, tc_dma); + return; + } + + ql_dbg(ql_dbg_init, vha, 0x00c3, + "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024); + + ha->eft_dma = tc_dma; + ha->eft = tc; +} + +static void +qla2x00_alloc_offload_mem(scsi_qla_host_t *vha) +{ + qla2x00_init_fce_trace(vha); + qla2x00_init_eft_trace(vha); } void qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) { - int rval; uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size, eft_size, fce_size, mq_size; struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; struct rsp_que *rsp = ha->rsp_q_map[0]; struct qla2xxx_fw_dump *fw_dump; - dma_addr_t tc_dma; - void *tc; dump_size = fixed_size = mem_size = eft_size = fce_size = mq_size = 0; req_q_size = rsp_q_size = 0; @@ -3166,39 +3176,13 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) } if (ha->tgt.atio_ring) mq_size += ha->tgt.atio_q_length * sizeof(request_t); - /* Allocate memory for Fibre Channel Event Buffer. */ - if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) && - !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) - goto try_eft; - fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE; -try_eft: + qla2x00_init_fce_trace(vha); + if (ha->fce) + fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE; + qla2x00_init_eft_trace(vha); if (ha->eft) - dma_free_coherent(&ha->pdev->dev, - EFT_SIZE, ha->eft, ha->eft_dma); - - /* Allocate memory for Extended Trace Buffer. */ - tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma, - GFP_KERNEL); - if (!tc) { - ql_log(ql_log_warn, vha, 0x00c1, - "Unable to allocate (%d KB) for EFT.\n", - EFT_SIZE / 1024); - goto allocate; - } - - rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS); - if (rval) { - ql_log(ql_log_warn, vha, 0x00c2, - "Unable to initialize EFT (%d).\n", rval); - dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc, - tc_dma); - } - ql_dbg(ql_dbg_init, vha, 0x00c3, - "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024); - eft_size = EFT_SIZE; - ha->eft_dma = tc_dma; - ha->eft = tc; + eft_size = EFT_SIZE; } if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { @@ -3220,24 +3204,22 @@ try_eft: j, fwdt->dump_size); dump_size += fwdt->dump_size; } - goto allocate; + } else { + req_q_size = req->length * sizeof(request_t); + rsp_q_size = rsp->length * sizeof(response_t); + dump_size = offsetof(struct qla2xxx_fw_dump, isp); + dump_size += fixed_size + mem_size + req_q_size + rsp_q_size + + eft_size; + ha->chain_offset = dump_size; + dump_size += mq_size + fce_size; + if (ha->exchoffld_buf) + dump_size += sizeof(struct qla2xxx_offld_chain) + + ha->exchoffld_size; + if (ha->exlogin_buf) + dump_size += sizeof(struct qla2xxx_offld_chain) + + ha->exlogin_size; } - req_q_size = req->length * sizeof(request_t); - rsp_q_size = rsp->length * sizeof(response_t); - dump_size = offsetof(struct qla2xxx_fw_dump, isp); - dump_size += fixed_size + mem_size + req_q_size + rsp_q_size + eft_size; - ha->chain_offset = dump_size; - dump_size += mq_size + fce_size; - - if (ha->exchoffld_buf) - dump_size += sizeof(struct qla2xxx_offld_chain) + - ha->exchoffld_size; - if (ha->exlogin_buf) - dump_size += sizeof(struct qla2xxx_offld_chain) + - ha->exlogin_size; - -allocate: if (!ha->fw_dump_len || dump_size > ha->fw_dump_alloc_len) { ql_dbg(ql_dbg_init, vha, 0x00c5, diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 7d73b6a7cf41..51154c049385 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -4577,6 +4577,7 @@ qla2x00_free_fw_dump(struct qla_hw_data *ha) ha->fce = NULL; ha->fce_dma = 0; + ha->flags.fce_enabled = 0; ha->eft = NULL; ha->eft_dma = 0; ha->fw_dumped = 0; -- cgit v1.2.3-59-g8ed1b From 9730ddfb123db3f37ace7571176661257712c99b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 13 Aug 2019 14:23:49 +0100 Subject: scsi: fnic: remove redundant assignment of variable rc Variable ret is initialized to a value that is never read and it is re-assigned later and immediately returns. Clean up the code by removing rc and just returning 0. [mkp: typo] Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Acked-by: Karan Tilak Kumar Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic_debugfs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/scsi/fnic/fnic_debugfs.c b/drivers/scsi/fnic/fnic_debugfs.c index 21991c99db7c..13f7d88d6e57 100644 --- a/drivers/scsi/fnic/fnic_debugfs.c +++ b/drivers/scsi/fnic/fnic_debugfs.c @@ -52,7 +52,6 @@ static struct fc_trace_flag_type *fc_trc_flag; */ int fnic_debugfs_init(void) { - int rc = -1; fnic_trace_debugfs_root = debugfs_create_dir("fnic", NULL); fnic_stats_debugfs_root = debugfs_create_dir("statistics", @@ -70,8 +69,7 @@ int fnic_debugfs_init(void) fc_trc_flag->fc_clear = 4; } - rc = 0; - return rc; + return 0; } /* -- cgit v1.2.3-59-g8ed1b From ee9a256cd8d0f7d23d7dd310d7fdc23f28cada0d Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Thu, 8 Aug 2019 09:35:25 +0800 Subject: scsi: lpfc: remove redundant code Remove the redundant initialization code. Signed-off-by: Fuqian Huang Reviewed-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_bsg.c | 1 - drivers/scsi/lpfc/lpfc_sli.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index c7f66239ca70..251504cd575f 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -1569,7 +1569,6 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag, "2722 Xmit CT response on exchange x%x Data: x%x x%x x%x\n", icmd->ulpContext, icmd->ulpIoTag, tag, phba->link_state); - ctiocb->iocb_cmpl = NULL; ctiocb->iocb_flag |= LPFC_IO_LIBDFC; ctiocb->vport = phba->pport; ctiocb->context1 = dd_data; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index f9e6a135d656..156224c14cc7 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -17445,7 +17445,6 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport, icmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; ctiocb->context1 = lpfc_nlp_get(ndlp); - ctiocb->iocb_cmpl = NULL; ctiocb->vport = phba->pport; ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_rsp_cmpl; ctiocb->sli4_lxritag = NO_XRI; -- cgit v1.2.3-59-g8ed1b From 78d4b1327d8bd60b58f422f6df02853c33558b11 Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Mon, 12 Aug 2019 16:31:34 +0800 Subject: scsi: lpfc: use spin_lock_irqsave in IRQ context As spin_unlock_irq will enable interrupts. Function lpfc_findnode_rpi is called from lpfc_sli_abts_err_handler (./drivers/scsi/lpfc/lpfc_sli.c) <- lpfc_sli_async_event_handler <- lpfc_sli_process_unsol_iocb <- lpfc_sli_handle_fast_ring_event <- lpfc_sli_fp_intr_handler <- lpfc_sli_intr_handler and lpfc_sli_intr_handler is an interrupt handler. Interrupts are enabled in interrupt handler. Use spin_lock_irqsave/spin_unlock_irqrestore instead of spin_(un)lock_irq in IRQ context to avoid this. Signed-off-by: Fuqian Huang Reviewed-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hbadisc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 28ecaa7fc715..cf02c352b324 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -6065,10 +6065,11 @@ lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi) { struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_nodelist *ndlp; + unsigned long flags; - spin_lock_irq(shost->host_lock); + spin_lock_irqsave(shost->host_lock, flags); ndlp = __lpfc_findnode_rpi(vport, rpi); - spin_unlock_irq(shost->host_lock); + spin_unlock_irqrestore(shost->host_lock, flags); return ndlp; } -- cgit v1.2.3-59-g8ed1b From d508e31df10ff1f309fddb88d7e830315bdbb93a Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 19 Aug 2019 13:25:57 +0530 Subject: scsi: ufs-qcom: Make structure ufs_hba_qcom_vops constant Static structure ufs_hba_qcom_vops, of type ufs_hba_variant_ops, is used only once, when it is passed as the second argument to function ufshcd_pltfrm_init(). In the definition of ufshcd_pltfrm_init(), its second parameter (corresponding to ufs_hba_qcom_vops) is declared as constant. Hence declare ufs_hba_qcom_vops itself constant as well to protect it from unintended modification. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Reviewed-by: Vivek Gautam Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-qcom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index ee4b1da1e223..4473f339cbc0 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1551,7 +1551,7 @@ static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba) * The variant operations configure the necessary controller and PHY * handshake during initialization. */ -static struct ufs_hba_variant_ops ufs_hba_qcom_vops = { +static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = { .name = "qcom", .init = ufs_qcom_init, .exit = ufs_qcom_exit, -- cgit v1.2.3-59-g8ed1b From a967783300bf2ba55a29255c0a591a554c651993 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Sun, 21 Jul 2019 17:12:29 +0530 Subject: scsi: lpfc: remove NULL check before some freeing functions As dma_pool_destroy and mempool_destroy functions has NULL check. We may not need NULL check before calling them. Fix below warnings reported by coccicheck ./drivers/scsi/lpfc/lpfc_mem.c:252:2-18: WARNING: NULL check before some freeing functions is not needed. ./drivers/scsi/lpfc/lpfc_mem.c:255:2-18: WARNING: NULL check before some freeing functions is not needed. ./drivers/scsi/lpfc/lpfc_mem.c:258:2-18: WARNING: NULL check before some freeing functions is not needed. ./drivers/scsi/lpfc/lpfc_mem.c:261:2-18: WARNING: NULL check before some freeing functions is not needed. ./drivers/scsi/lpfc/lpfc_mem.c:265:2-18: WARNING: NULL check before some freeing functions is not needed. ./drivers/scsi/lpfc/lpfc_mem.c:269:2-17: WARNING: NULL check before some freeing functions is not needed. Signed-off-by: Hariprasad Kelam Reviewed-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_mem.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 66191fa35f63..9bdb4a0a9f24 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c @@ -248,25 +248,22 @@ lpfc_mem_free(struct lpfc_hba *phba) /* Free HBQ pools */ lpfc_sli_hbqbuf_free_all(phba); - if (phba->lpfc_nvmet_drb_pool) - dma_pool_destroy(phba->lpfc_nvmet_drb_pool); + dma_pool_destroy(phba->lpfc_nvmet_drb_pool); phba->lpfc_nvmet_drb_pool = NULL; - if (phba->lpfc_drb_pool) - dma_pool_destroy(phba->lpfc_drb_pool); + + dma_pool_destroy(phba->lpfc_drb_pool); phba->lpfc_drb_pool = NULL; - if (phba->lpfc_hrb_pool) - dma_pool_destroy(phba->lpfc_hrb_pool); + + dma_pool_destroy(phba->lpfc_hrb_pool); phba->lpfc_hrb_pool = NULL; - if (phba->txrdy_payload_pool) - dma_pool_destroy(phba->txrdy_payload_pool); + + dma_pool_destroy(phba->txrdy_payload_pool); phba->txrdy_payload_pool = NULL; - if (phba->lpfc_hbq_pool) - dma_pool_destroy(phba->lpfc_hbq_pool); + dma_pool_destroy(phba->lpfc_hbq_pool); phba->lpfc_hbq_pool = NULL; - if (phba->rrq_pool) - mempool_destroy(phba->rrq_pool); + mempool_destroy(phba->rrq_pool); phba->rrq_pool = NULL; /* Free NLP memory pool */ -- cgit v1.2.3-59-g8ed1b From 31f06d2e73726160645f8d9976a0b3f42e136da7 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:31 -0700 Subject: scsi: lpfc: Limit xri count for kdump environment scsi-mq operation inherently performs pre-allocation of resources for blk-mq request queues. Even though the kdump environment reduces the configuration to a single CPU, thus 1 hardware queue, which helps significantly, the resources are still rather large due to the per request allocations. blk-mq pre-allocations can be over 4KB per request. With adapter can_queue values in the 4k or 8k range, this can easily be 32MBs before any other driver memory is factored in. Driver SGL DMA buffer allocation can be up to 8KB per request as well adding an additional 64MB. Totals are well over 100MB for a single shost. Given kdump memory auto-sizing utilities don't accommodate this amount of memory well, it's very possible for kdump to fail due to lack of memory. Fix by having the driver recognize that it is booting within a kdump context and reduce the number of requests it will support to a more reasonable value. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index faf43b1d3dbe..a109895bf360 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -8307,6 +8308,10 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) bf_get(lpfc_mbx_rd_conf_extnts_inuse, rd_config); phba->sli4_hba.max_cfg_param.max_xri = bf_get(lpfc_mbx_rd_conf_xri_count, rd_config); + /* Reduce resource usage in kdump environment */ + if (is_kdump_kernel() && + phba->sli4_hba.max_cfg_param.max_xri > 512) + phba->sli4_hba.max_cfg_param.max_xri = 512; phba->sli4_hba.max_cfg_param.xri_base = bf_get(lpfc_mbx_rd_conf_xri_base, rd_config); phba->sli4_hba.max_cfg_param.max_vpi = -- cgit v1.2.3-59-g8ed1b From 4f1a2fef2af6b8c746bc965e5f87cd3cdaf5f1f8 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:32 -0700 Subject: scsi: lpfc: Fix PLOGI failure with high remoteport count When connected to a high number of remote ports, the driver is encountering PLOGI errors. The errors are due to adapter detected failures indicating illegal field values. Turns out the driver was prematurely clearing an RPI bitmask before waiting for an UNREG_RPI mailbox completion. This allowed the RPI to be reused before it was actually available. Fix by clearing RPI bitmask only after UNREG_RPI mailbox completion. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_disc.h | 1 + drivers/scsi/lpfc/lpfc_hbadisc.c | 8 ++++++-- drivers/scsi/lpfc/lpfc_sli.c | 12 ++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 1c89c9f314fa..49bb0b180b19 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h @@ -157,6 +157,7 @@ struct lpfc_node_rrq { /* Defines for nlp_flag (uint32) */ #define NLP_IGNR_REG_CMPL 0x00000001 /* Rcvd rscn before we cmpl reg login */ #define NLP_REG_LOGIN_SEND 0x00000002 /* sent reglogin to adapter */ +#define NLP_RELEASE_RPI 0x00000004 /* Release RPI to free pool */ #define NLP_SUPPRESS_RSP 0x00000010 /* Remote NPort supports suppress rsp */ #define NLP_PLOGI_SND 0x00000020 /* sent PLOGI request for this entry */ #define NLP_PRLI_SND 0x00000040 /* sent PRLI request for this entry */ diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index cf02c352b324..c413f8c51aa8 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -4805,6 +4805,10 @@ lpfc_nlp_logo_unreg(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ndlp->nlp_defer_did = NLP_EVT_NOTHING_PENDING; lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); } else { + if (ndlp->nlp_flag & NLP_RELEASE_RPI) { + lpfc_sli4_free_rpi(vport->phba, ndlp->nlp_rpi); + ndlp->nlp_flag &= ~NLP_RELEASE_RPI; + } ndlp->nlp_flag &= ~NLP_UNREG_INP; } } @@ -5104,6 +5108,8 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) list_del_init(&ndlp->els_retry_evt.evt_listp); list_del_init(&ndlp->dev_loss_evt.evt_listp); lpfc_cleanup_vports_rrqs(vport, ndlp); + if (phba->sli_rev == LPFC_SLI_REV4) + ndlp->nlp_flag |= NLP_RELEASE_RPI; lpfc_unreg_rpi(vport, ndlp); return 0; @@ -6201,8 +6207,6 @@ lpfc_nlp_release(struct kref *kref) spin_lock_irqsave(&phba->ndlp_lock, flags); NLP_CLR_NODE_ACT(ndlp); spin_unlock_irqrestore(&phba->ndlp_lock, flags); - if (phba->sli_rev == LPFC_SLI_REV4) - lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi); /* free ndlp memory for final ndlp release */ if (NLP_CHK_FREE_REQ(ndlp)) { diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 156224c14cc7..bb41affdb1ba 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2507,6 +2507,11 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ndlp->nlp_defer_did = NLP_EVT_NOTHING_PENDING; lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); } else { + if (ndlp->nlp_flag & NLP_RELEASE_RPI) { + lpfc_sli4_free_rpi(vport->phba, + ndlp->nlp_rpi); + ndlp->nlp_flag &= ~NLP_RELEASE_RPI; + } ndlp->nlp_flag &= ~NLP_UNREG_INP; } pmb->ctx_ndlp = NULL; @@ -2582,6 +2587,13 @@ lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_issue_els_plogi( vport, ndlp->nlp_DID, 0); } else { + if (ndlp->nlp_flag & NLP_RELEASE_RPI) { + lpfc_sli4_free_rpi( + vport->phba, + ndlp->nlp_rpi); + ndlp->nlp_flag &= + ~NLP_RELEASE_RPI; + } ndlp->nlp_flag &= ~NLP_UNREG_INP; } } -- cgit v1.2.3-59-g8ed1b From 1d755d6477cafea1d371ecc841e22adda0a43d27 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:33 -0700 Subject: scsi: lpfc: Fix ELS field alignments After seeing some interoperability issues with ADISC, it was determined the ELS definitions in lpfc were using types that allowed the compiler to add pad to the structure, causing the structure to no longer be per spec. The offending structures are ADISC, FAN, and RNID. This patch implements the simple fix of eliminating the pad by forcing the compiler to pack the structure. Care was taken to ensure field accesses won't be by operations that would hit a bad field alignment. The better solution would be to convert to the uapi fc header definitions, but the number of changes required to do is rather intrusive so this course of action was deferred. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hw.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 5b439a6dcde1..436cdc8c5ef4 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -843,7 +843,7 @@ typedef struct _ADISC { /* Structure is in Big Endian format */ struct lpfc_name portName; struct lpfc_name nodeName; uint32_t DID; -} ADISC; +} __packed ADISC; typedef struct _FARP { /* Structure is in Big Endian format */ uint32_t Mflags:8; @@ -873,7 +873,7 @@ typedef struct _FAN { /* Structure is in Big Endian format */ uint32_t Fdid; struct lpfc_name FportName; struct lpfc_name FnodeName; -} FAN; +} __packed FAN; typedef struct _SCR { /* Structure is in Big Endian format */ uint8_t resvd1; @@ -917,7 +917,7 @@ typedef struct _RNID { /* Structure is in Big Endian format */ union { RNID_TOP_DISC topologyDisc; /* topology disc (0xdf) */ } un; -} RNID; +} __packed RNID; typedef struct _RPS { /* Structure is in Big Endian format */ union { -- cgit v1.2.3-59-g8ed1b From 3cee98db2610fb633fcbdd0f85385f60dabbaf75 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:34 -0700 Subject: scsi: lpfc: Fix crash on driver unload in wq free If a timer routine uses workqueues, it could fire before the workqueue is allocated. Fix by allocating the workqueue before the timer routines are setup Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index a109895bf360..f9986efa0aa3 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -6413,6 +6413,11 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) if (rc) return -ENODEV; + /* Allocate all driver workqueues here */ + + /* The lpfc_wq workqueue for deferred irq use */ + phba->wq = alloc_workqueue("lpfc_wq", WQ_MEM_RECLAIM, 0); + /* * Initialize timers used by driver */ @@ -6996,12 +7001,6 @@ lpfc_setup_driver_resource_phase2(struct lpfc_hba *phba) return error; } - /* The lpfc_wq workqueue for deferred irq use, is only used for SLI4 */ - if (phba->sli_rev == LPFC_SLI_REV4) - phba->wq = alloc_workqueue("lpfc_wq", WQ_MEM_RECLAIM, 0); - else - phba->wq = NULL; - return 0; } -- cgit v1.2.3-59-g8ed1b From 8d34a59caecda9a7ce0cad108ee64c37aa0c9812 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:35 -0700 Subject: scsi: lpfc: Fix failure to clear non-zero eq_delay after io rate reduction Unusually high IO latency can be observed with little IO in progress. The latency may remain high regardless of amount of IO and can only be cleared by forcing lpfc_fcp_imax values to non-zero and then back to zero. The driver's eq_delay mechanism that scales the interrupt coalescing based on io completion load failed to reduce or turn off coalescing when load decreased. Specifically, if no io completed on a cpu within an eq_delay polling window, the eq delay processing was skipped and no change was made to the coalescing values. This left the coalescing values set when they were no longer applicable. Fix by always clearing the percpu counters for each time period and always run the eq_delay calculations if an eq has a non-zero coalescing value. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index f9986efa0aa3..d04d00dea901 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1262,6 +1262,7 @@ lpfc_hb_eq_delay_work(struct work_struct *work) unsigned char *eqcnt = NULL; uint32_t usdelay; int i; + bool update = false; if (!phba->cfg_auto_imax || phba->pport->load_flag & FC_UNLOADING) return; @@ -1275,20 +1276,29 @@ lpfc_hb_eq_delay_work(struct work_struct *work) if (!eqcnt) goto requeue; - /* Loop thru all IRQ vectors */ - for (i = 0; i < phba->cfg_irq_chann; i++) { - /* Get the EQ corresponding to the IRQ vector */ - eq = phba->sli4_hba.hba_eq_hdl[i].eq; - if (eq && eqcnt[eq->last_cpu] < 2) - eqcnt[eq->last_cpu]++; - continue; - } + if (phba->cfg_irq_chann > 1) { + /* Loop thru all IRQ vectors */ + for (i = 0; i < phba->cfg_irq_chann; i++) { + /* Get the EQ corresponding to the IRQ vector */ + eq = phba->sli4_hba.hba_eq_hdl[i].eq; + if (!eq) + continue; + if (eq->q_mode) { + update = true; + break; + } + if (eqcnt[eq->last_cpu] < 2) + eqcnt[eq->last_cpu]++; + } + } else + update = true; for_each_present_cpu(i) { - if (phba->cfg_irq_chann > 1 && eqcnt[i] < 2) - continue; - eqi = per_cpu_ptr(phba->sli4_hba.eq_info, i); + if (!update && eqcnt[i] < 2) { + eqi->icnt = 0; + continue; + } usdelay = (eqi->icnt / LPFC_IMAX_THRESHOLD) * LPFC_EQ_DELAY_STEP; -- cgit v1.2.3-59-g8ed1b From 296012285c908f6aacea83913ab9eaf273225d57 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:36 -0700 Subject: scsi: lpfc: Fix leak of ELS completions on adapter reset If the adapter is reset while there are outstanding ELS's, subsequent reinitialization of the adapter will fail as it has not recovered all of the io contexts relative to the ELS's. If an ELS timed out or otherwise failed and an the ELS was attempted to be aborted (which changes the ELS completion context), in causes where the driver generates completions for the outstanding IO as the adapter would not due to being reset, the driver released only the ELS context and failed to release the abort context. When the adapter went to reinit, as it had not received all of the contexts, it failed to reinit. Fix by having the ELS completion handler identify the driver-generated completion status and release the abort context. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_sli.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index bb41affdb1ba..b453d10ef36e 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -11097,6 +11097,9 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, irsp->ulpStatus, irsp->un.ulpWord[4]); spin_unlock_irq(&phba->hbalock); + if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT && + irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) + lpfc_sli_release_iocbq(phba, abort_iocb); } release_iocb: lpfc_sli_release_iocbq(phba, cmdiocb); -- cgit v1.2.3-59-g8ed1b From 57178b9275508e59d6daf89b874c03d597342776 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:37 -0700 Subject: scsi: lpfc: Fix port relogin failure due to GID_FT interaction In cases of remote-port-side cable pull/replug, there happens to be a target that upon replug will send the port a PLOGI, a PRLI, and a LOGO. When this sequence is received by the driver, the PLOGI accepted and a GFT_ID is issued to find the protocol support for the remote port. While the GFT_ID is outstanding, a LOGO is received. The driver logs the remote port out and unregisters the RPI and schedules a new PLOGI transmission. However, the GFT_ID was not terminated. When it completed, the driver attempted to transition the remote port to PRLI transmission, which cancels the PLOGI scheduling. The PRLI transmit attempt is rejected by the adapter as the remote port is not logged in. No retry is attempted as it's expected the logout is noted and the supposedly scheduled PLOGI should address the state. As there is no PLOGI, the remote port does not get re-discovered. Fix by aborting the outstanding GFT_ID if the related remote port is logged out. Ensure a PRLI transmit attempt only occurs if the remote port is logging in. This avoids the incorrect attempt while logged out. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_ct.c | 15 ++++++++++----- drivers/scsi/lpfc/lpfc_nportdisc.c | 8 ++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index ec72c39997d2..3246942ff2ff 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -1210,13 +1210,18 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ndlp->nlp_fc4_type |= NLP_FC4_NVME; lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "3064 Setting ndlp %p, DID x%06x with " - "FC4 x%08x, Data: x%08x x%08x\n", + "FC4 x%08x, Data: x%08x x%08x %d\n", ndlp, did, ndlp->nlp_fc4_type, - FC_TYPE_FCP, FC_TYPE_NVME); - ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; + FC_TYPE_FCP, FC_TYPE_NVME, + ndlp->nlp_state); - lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE); - lpfc_issue_els_prli(vport, ndlp, 0); + if (ndlp->nlp_state == NLP_STE_REG_LOGIN_ISSUE) { + ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; + + lpfc_nlp_set_state(vport, ndlp, + NLP_STE_PRLI_ISSUE); + lpfc_issue_els_prli(vport, ndlp, 0); + } } } else lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 59252bfca14e..c58000cd744f 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -1661,6 +1661,7 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport, LPFC_MBOXQ_t *mb; LPFC_MBOXQ_t *nextmb; struct lpfc_dmabuf *mp; + struct lpfc_nodelist *ns_ndlp; cmdiocb = (struct lpfc_iocbq *) arg; @@ -1693,6 +1694,13 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport, } spin_unlock_irq(&phba->hbalock); + /* software abort if any GID_FT is outstanding */ + if (vport->cfg_enable_fc4_type != LPFC_ENABLE_FCP) { + ns_ndlp = lpfc_findnode_did(vport, NameServer_DID); + if (ns_ndlp && NLP_CHK_NODE_ACT(ns_ndlp)) + lpfc_els_abort(phba, ns_ndlp); + } + lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO); return ndlp->nlp_state; } -- cgit v1.2.3-59-g8ed1b From 7f20c1cb236afd75237f1302e60daef8b90b818b Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:38 -0700 Subject: scsi: lpfc: Fix discovery when target has no GID_FT information Some remote ports may be slow in registering their GID_FT protocol information with the fabric. If the remote port is an initiator, it may send PLOGI to the port before the GID_FT logic is complete. Meaning, after accepting the PLOGI, when the driver may see no response to the GID_FT that is issued after the login to determine the protocols supported so that proper PRLI's may be transmit. If the driver has no fc4 information, it currently stops and the remote port is not discovered. Fix by issuing a LOGO when there is no GID_FT information. The LOGO completion handling will attempt to re-login if the nport_id is still present. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_ct.c | 16 +++++++++++++++- drivers/scsi/lpfc/lpfc_nportdisc.c | 6 +++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 3246942ff2ff..c2ac6cb730e8 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -1215,12 +1215,26 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, FC_TYPE_FCP, FC_TYPE_NVME, ndlp->nlp_state); - if (ndlp->nlp_state == NLP_STE_REG_LOGIN_ISSUE) { + if (ndlp->nlp_state == NLP_STE_REG_LOGIN_ISSUE && + ndlp->nlp_fc4_type) { ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE); lpfc_issue_els_prli(vport, ndlp, 0); + } else if (!ndlp->nlp_fc4_type) { + /* If fc4 type is still unknown, then LOGO */ + lpfc_printf_vlog(vport, KERN_INFO, + LOG_DISCOVERY, + "6443 Sending LOGO ndlp x%px," + "DID x%06x with fc4_type: " + "x%08x, state: %d\n", + ndlp, did, ndlp->nlp_fc4_type, + ndlp->nlp_state); + lpfc_issue_els_logo(vport, ndlp, 0); + ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; + lpfc_nlp_set_state(vport, ndlp, + NLP_STE_NPR_NODE); } } } else diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index c58000cd744f..d76d76081d1a 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -1822,7 +1822,11 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE); - lpfc_issue_els_prli(vport, ndlp, 0); + if (lpfc_issue_els_prli(vport, ndlp, 0)) { + lpfc_issue_els_logo(vport, ndlp, 0); + ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; + lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); + } } else { if ((vport->fc_flag & FC_PT2PT) && phba->nvmet_support) phba->targetport->port_id = vport->fc_myDID; -- cgit v1.2.3-59-g8ed1b From 26d824ca45a80f7a95e7afe578e54680cef5236f Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:39 -0700 Subject: scsi: lpfc: Fix ADISC reception terminating login state if a NVME target If a target issues an ADISC to the port and the target is a NVME target, the driver is inadvertantly invalidating the login and marking the remote port as logged out. Communication with the target is lost. Revise the ADISC check so that FCP or NVME targets will be marked valid at the end of ADISC processing. Enhance logging to recognize condition better. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nportdisc.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index d76d76081d1a..f4eea52c66f5 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -614,7 +614,7 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, } out: /* If we are authenticated, move to the proper state */ - if (ndlp->nlp_type & NLP_FCP_TARGET) + if (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET)) lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE); else lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); @@ -2903,18 +2903,21 @@ lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, uint32_t(*func) (struct lpfc_vport *, struct lpfc_nodelist *, void *, uint32_t); uint32_t got_ndlp = 0; + uint32_t data1; if (lpfc_nlp_get(ndlp)) got_ndlp = 1; cur_state = ndlp->nlp_state; + data1 = (((uint32_t)ndlp->nlp_fc4_type << 16) | + ((uint32_t)ndlp->nlp_type)); /* DSM in event on NPort in state */ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "0211 DSM in event x%x on NPort x%x in " "state %d rpi x%x Data: x%x x%x\n", evt, ndlp->nlp_DID, cur_state, ndlp->nlp_rpi, - ndlp->nlp_flag, ndlp->nlp_fc4_type); + ndlp->nlp_flag, data1); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM, "DSM in: evt:%d ste:%d did:x%x", @@ -2925,10 +2928,13 @@ lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, /* DSM out state on NPort */ if (got_ndlp) { + data1 = (((uint32_t)ndlp->nlp_fc4_type << 16) | + ((uint32_t)ndlp->nlp_type)); lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "0212 DSM out state %d on NPort x%x " - "rpi x%x Data: x%x\n", - rc, ndlp->nlp_DID, ndlp->nlp_rpi, ndlp->nlp_flag); + "rpi x%x Data: x%x x%x\n", + rc, ndlp->nlp_DID, ndlp->nlp_rpi, ndlp->nlp_flag, + data1); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM, "DSM out: ste:%d did:x%x flg:x%x", -- cgit v1.2.3-59-g8ed1b From 08180db2542b94e93cbdffd2a42cac2db147114a Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:40 -0700 Subject: scsi: lpfc: Fix issuing init_vpi mbox on SLI-3 card The driver is inadvertently trying to issue an INIT_VPI mailbox command on an SLI-3 driver. The command is specific to SLI-4. When the call is made to send the command, if on an SLI-3 adapter, an array pointer is NULL and the driver will oops. Fix by restricting the command to SLI-4 adapters only. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_vport.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 343bc71d4615..b76646357980 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -527,9 +527,11 @@ disable_vport(struct fc_vport *fc_vport) * scsi_host_put() to release the vport. */ lpfc_mbx_unreg_vpi(vport); - spin_lock_irq(shost->host_lock); - vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; - spin_unlock_irq(shost->host_lock); + if (phba->sli_rev == LPFC_SLI_REV4) { + spin_lock_irq(shost->host_lock); + vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; + spin_unlock_irq(shost->host_lock); + } lpfc_vport_set_state(vport, FC_VPORT_DISABLED); lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, -- cgit v1.2.3-59-g8ed1b From 61184f1742c901160ceead85b3f1b3d03038f1d0 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:41 -0700 Subject: scsi: lpfc: Fix Oops in nvme_register with target logout/login lpfc_nvme_register_port hit a null prev_ndlp pointer in a test with lots of target ports swapping addresses. The oldport value was stale, thus it's ndlp (prev_ndlp set to it) was used. Fix by moving oldrport pointer checks, and if used prev_ndlp pointer assignment, to be done while the lock is held. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nvme.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 946642cee3df..9746808cf94f 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -2317,9 +2317,13 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) spin_lock_irq(&vport->phba->hbalock); oldrport = lpfc_ndlp_get_nrport(ndlp); - spin_unlock_irq(&vport->phba->hbalock); - if (!oldrport) + if (oldrport) { + prev_ndlp = oldrport->ndlp; + spin_unlock_irq(&vport->phba->hbalock); + } else { + spin_unlock_irq(&vport->phba->hbalock); lpfc_nlp_get(ndlp); + } ret = nvme_fc_register_remoteport(localport, &rpinfo, &remote_port); if (!ret) { @@ -2338,7 +2342,6 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) /* New remoteport record does not guarantee valid * host private memory area. */ - prev_ndlp = oldrport->ndlp; if (oldrport == remote_port->private) { /* Same remoteport - ndlp should match. * Just reuse. @@ -2352,7 +2355,7 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) remote_port->port_name, remote_port->port_id, remote_port->port_role, - prev_ndlp, + oldrport->ndlp, ndlp, ndlp->nlp_type, ndlp->nlp_DID); -- cgit v1.2.3-59-g8ed1b From 4b0a42be26dd89cefaac89330070222ac8e14c01 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:42 -0700 Subject: scsi: lpfc: Fix irq raising in lpfc_sli_hba_down The adapter reset path (lpfc_sli_hba_down) is taking/releasing a lock with irq. But, the path is already under the hbalock which raised irq so it's unnecessary. Convert to simple lock/unlock. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_sli.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index b453d10ef36e..7c4bca47496a 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -10808,9 +10808,9 @@ lpfc_sli_hba_down(struct lpfc_hba *phba) pring = qp->pring; if (!pring) continue; - spin_lock_irq(&pring->ring_lock); + spin_lock(&pring->ring_lock); list_splice_init(&pring->txq, &completions); - spin_unlock_irq(&pring->ring_lock); + spin_unlock(&pring->ring_lock); if (pring == phba->sli4_hba.els_wq->pring) { pring->flag |= LPFC_DEFERRED_RING_EVENT; /* Set the lpfc data pending flag */ -- cgit v1.2.3-59-g8ed1b From 3ad348d94452d6ab3aa0316105fb9f34f8ed3140 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:43 -0700 Subject: scsi: lpfc: Fix oops when fewer hdwqs than cpus When tearing down the adapter for a reset, online/offline, or driver unload, the queue free routine would hit a GPF oops. This only occurs on conditions where the number of hardware queues created is fewer than the number of cpus in the system. In this condition cpus share a hardware queue. And of course, it's the 2nd cpu that shares a hardware that attempted to free it a second time and hit the oops. Fix by reworking the cpu to hardware queue mapping such that: Assignment of hardware queues to cpus occur in two passes: first pass: is first time assignment of a hardware queue to a cpu. This will set the LPFC_CPU_FIRST_IRQ flag for the cpu. second pass: for cpus that did not get a hardware queue they will be assigned one from a primary cpu (one set in first pass). Deletion of hardware queues is driven by cpu itteration, and queues will only be deleted if the LPFC_CPU_FIRST_IRQ flag is set. Also contains a few small cleanup fixes and a little better logging. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 144 ++++++++++++++++++++++++++---------------- 1 file changed, 89 insertions(+), 55 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index d04d00dea901..8e889ea26203 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -8876,7 +8876,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) } qdesc->qe_valid = 1; qdesc->hdwq = cpup->hdwq; - qdesc->chann = cpu; /* First CPU this EQ is affinitised to */ + qdesc->chann = cpu; /* First CPU this EQ is affinitized to */ qdesc->last_cpu = qdesc->chann; /* Save the allocated EQ in the Hardware Queue */ @@ -10723,7 +10723,7 @@ lpfc_find_hyper(struct lpfc_hba *phba, int cpu, static void lpfc_cpu_affinity_check(struct lpfc_hba *phba, int vectors) { - int i, cpu, idx, new_cpu, start_cpu, first_cpu; + int i, cpu, idx, next_idx, new_cpu, start_cpu, first_cpu; int max_phys_id, min_phys_id; int max_core_id, min_core_id; struct lpfc_vector_map_info *cpup; @@ -10765,8 +10765,8 @@ lpfc_cpu_affinity_check(struct lpfc_hba *phba, int vectors) #endif lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "3328 CPU physid %d coreid %d\n", - cpup->phys_id, cpup->core_id); + "3328 CPU %d physid %d coreid %d flag x%x\n", + cpu, cpup->phys_id, cpup->core_id, cpup->flag); if (cpup->phys_id > max_phys_id) max_phys_id = cpup->phys_id; @@ -10805,17 +10805,17 @@ lpfc_cpu_affinity_check(struct lpfc_hba *phba, int vectors) cpup->eq = idx; cpup->irq = pci_irq_vector(phba->pcidev, idx); - lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "3336 Set Affinity: CPU %d " - "irq %d eq %d\n", - cpu, cpup->irq, cpup->eq); - /* If this is the first CPU thats assigned to this * vector, set LPFC_CPU_FIRST_IRQ. */ if (!i) cpup->flag |= LPFC_CPU_FIRST_IRQ; i++; + + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, + "3336 Set Affinity: CPU %d " + "irq %d eq %d flag x%x\n", + cpu, cpup->irq, cpup->eq, cpup->flag); } } @@ -10929,69 +10929,103 @@ found_any: } } + /* Assign hdwq indices that are unique across all cpus in the map + * that are also FIRST_CPUs. + */ + idx = 0; + for_each_present_cpu(cpu) { + cpup = &phba->sli4_hba.cpu_map[cpu]; + + /* Only FIRST IRQs get a hdwq index assignment. */ + if (!(cpup->flag & LPFC_CPU_FIRST_IRQ)) + continue; + + /* 1 to 1, the first LPFC_CPU_FIRST_IRQ cpus to a unique hdwq */ + cpup->hdwq = idx; + idx++; + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3333 Set Affinity: CPU %d (phys %d core %d): " + "hdwq %d eq %d irq %d flg x%x\n", + cpu, cpup->phys_id, cpup->core_id, + cpup->hdwq, cpup->eq, cpup->irq, cpup->flag); + } /* Finally we need to associate a hdwq with each cpu_map entry * This will be 1 to 1 - hdwq to cpu, unless there are less * hardware queues then CPUs. For that case we will just round-robin * the available hardware queues as they get assigned to CPUs. + * The next_idx is the idx from the FIRST_CPU loop above to account + * for irq_chann < hdwq. The idx is used for round-robin assignments + * and needs to start at 0. */ - idx = 0; + next_idx = idx; start_cpu = 0; + idx = 0; for_each_present_cpu(cpu) { cpup = &phba->sli4_hba.cpu_map[cpu]; - if (idx >= phba->cfg_hdw_queue) { - /* We need to reuse a Hardware Queue for another CPU, - * so be smart about it and pick one that has its - * IRQ/EQ mapped to the same phys_id (CPU package). - * and core_id. - */ - new_cpu = start_cpu; - for (i = 0; i < phba->sli4_hba.num_present_cpu; i++) { - new_cpup = &phba->sli4_hba.cpu_map[new_cpu]; - if ((new_cpup->hdwq != LPFC_VECTOR_MAP_EMPTY) && - (new_cpup->phys_id == cpup->phys_id) && - (new_cpup->core_id == cpup->core_id)) - goto found_hdwq; - new_cpu = cpumask_next( - new_cpu, cpu_present_mask); - if (new_cpu == nr_cpumask_bits) - new_cpu = first_cpu; - } - /* If we can't match both phys_id and core_id, - * settle for just a phys_id match. - */ - new_cpu = start_cpu; - for (i = 0; i < phba->sli4_hba.num_present_cpu; i++) { - new_cpup = &phba->sli4_hba.cpu_map[new_cpu]; - if ((new_cpup->hdwq != LPFC_VECTOR_MAP_EMPTY) && - (new_cpup->phys_id == cpup->phys_id)) - goto found_hdwq; - new_cpu = cpumask_next( - new_cpu, cpu_present_mask); - if (new_cpu == nr_cpumask_bits) - new_cpu = first_cpu; + /* FIRST cpus are already mapped. */ + if (cpup->flag & LPFC_CPU_FIRST_IRQ) + continue; + + /* If the cfg_irq_chann < cfg_hdw_queue, set the hdwq + * of the unassigned cpus to the next idx so that all + * hdw queues are fully utilized. + */ + if (next_idx < phba->cfg_hdw_queue) { + cpup->hdwq = next_idx; + next_idx++; + continue; + } + + /* Not a First CPU and all hdw_queues are used. Reuse a + * Hardware Queue for another CPU, so be smart about it + * and pick one that has its IRQ/EQ mapped to the same phys_id + * (CPU package) and core_id. + */ + new_cpu = start_cpu; + for (i = 0; i < phba->sli4_hba.num_present_cpu; i++) { + new_cpup = &phba->sli4_hba.cpu_map[new_cpu]; + if (new_cpup->hdwq != LPFC_VECTOR_MAP_EMPTY && + new_cpup->phys_id == cpup->phys_id && + new_cpup->core_id == cpup->core_id) { + goto found_hdwq; } + new_cpu = cpumask_next(new_cpu, cpu_present_mask); + if (new_cpu == nr_cpumask_bits) + new_cpu = first_cpu; + } - /* Otherwise just round robin on cfg_hdw_queue */ - cpup->hdwq = idx % phba->cfg_hdw_queue; - goto logit; -found_hdwq: - /* We found an available entry, copy the IRQ info */ - start_cpu = cpumask_next(new_cpu, cpu_present_mask); - if (start_cpu == nr_cpumask_bits) - start_cpu = first_cpu; - cpup->hdwq = new_cpup->hdwq; - } else { - /* 1 to 1, CPU to hdwq */ - cpup->hdwq = idx; + /* If we can't match both phys_id and core_id, + * settle for just a phys_id match. + */ + new_cpu = start_cpu; + for (i = 0; i < phba->sli4_hba.num_present_cpu; i++) { + new_cpup = &phba->sli4_hba.cpu_map[new_cpu]; + if (new_cpup->hdwq != LPFC_VECTOR_MAP_EMPTY && + new_cpup->phys_id == cpup->phys_id) + goto found_hdwq; + + new_cpu = cpumask_next(new_cpu, cpu_present_mask); + if (new_cpu == nr_cpumask_bits) + new_cpu = first_cpu; } -logit: + + /* Otherwise just round robin on cfg_hdw_queue */ + cpup->hdwq = idx % phba->cfg_hdw_queue; + idx++; + goto logit; + found_hdwq: + /* We found an available entry, copy the IRQ info */ + start_cpu = cpumask_next(new_cpu, cpu_present_mask); + if (start_cpu == nr_cpumask_bits) + start_cpu = first_cpu; + cpup->hdwq = new_cpup->hdwq; + logit: lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "3335 Set Affinity: CPU %d (phys %d core %d): " "hdwq %d eq %d irq %d flg x%x\n", cpu, cpup->phys_id, cpup->core_id, cpup->hdwq, cpup->eq, cpup->irq, cpup->flag); - idx++; } /* The cpu_map array will be used later during initialization -- cgit v1.2.3-59-g8ed1b From 6ede2ddd8bdd28bdaf43d15e70dc0ef38c5448db Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:44 -0700 Subject: scsi: lpfc: Fix FLOGI handling across multiple link up/down conditions It's possible for the driver to initiate an FLOGI and before it completes, another link down/up transition occurs requiring a new FLOGI. Currently, nothing is done to abort/noop the older FLOGI request to the adapter, so if this transition occurs and the FLOGI completion is received after the link down/up transition, the driver may erroneously act on the older FLOGI. In most cases, the adapter properly terminates/fails the FLOGI, but there is a timing condition where the FLOGI may complete on the wire prior to the transition, but the response may not be seen/processed by the driver before the driver sees the link transition. Fix by having the link down handler in the driver run through any outstanding ELS's and change the completion handler of the ELS so that it will be no-op'd and released. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 75 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index f12780f4cfbb..8103635adc38 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1206,6 +1206,39 @@ out: lpfc_els_free_iocb(phba, cmdiocb); } +/** + * lpfc_cmpl_els_link_down - Completion callback function for ELS command + * aborted during a link down + * @phba: pointer to lpfc hba data structure. + * @cmdiocb: pointer to lpfc command iocb data structure. + * @rspiocb: pointer to lpfc response iocb data structure. + * + */ +static void +lpfc_cmpl_els_link_down(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + struct lpfc_iocbq *rspiocb) +{ + IOCB_t *irsp; + uint32_t *pcmd; + uint32_t cmd; + + pcmd = (uint32_t *)(((struct lpfc_dmabuf *)cmdiocb->context2)->virt); + cmd = *pcmd; + irsp = &rspiocb->iocb; + + lpfc_printf_log(phba, KERN_INFO, LOG_ELS, + "6445 ELS completes after LINK_DOWN: " + " Status %x/%x cmd x%x flg x%x\n", + irsp->ulpStatus, irsp->un.ulpWord[4], cmd, + cmdiocb->iocb_flag); + + if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) { + cmdiocb->iocb_flag &= ~LPFC_IO_FABRIC; + atomic_dec(&phba->fabric_iocb_count); + } + lpfc_els_free_iocb(phba, cmdiocb); +} + /** * lpfc_issue_els_flogi - Issue an flogi iocb command for a vport * @vport: pointer to a host virtual N_Port data structure. @@ -7960,18 +7993,40 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) if (phba->sli_rev == LPFC_SLI_REV4) spin_lock(&pring->ring_lock); + /* First we need to issue aborts to outstanding cmds on txcmpl */ list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { if (piocb->iocb_flag & LPFC_IO_LIBDFC) continue; if (piocb->vport != vport) continue; - list_add_tail(&piocb->dlist, &abort_list); + + /* On the ELS ring we can have ELS_REQUESTs or + * GEN_REQUESTs waiting for a response. + */ + cmd = &piocb->iocb; + if (cmd->ulpCommand == CMD_ELS_REQUEST64_CR) { + list_add_tail(&piocb->dlist, &abort_list); + + /* If the link is down when flushing ELS commands + * the firmware will not complete them till after + * the link comes back up. This may confuse + * discovery for the new link up, so we need to + * change the compl routine to just clean up the iocb + * and avoid any retry logic. + */ + if (phba->link_state == LPFC_LINK_DOWN) + piocb->iocb_cmpl = lpfc_cmpl_els_link_down; + } + if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) + list_add_tail(&piocb->dlist, &abort_list); } + if (phba->sli_rev == LPFC_SLI_REV4) spin_unlock(&pring->ring_lock); spin_unlock_irq(&phba->hbalock); - /* Abort each iocb on the aborted list and remove the dlist links. */ + + /* Abort each txcmpl iocb on aborted list and remove the dlist links. */ list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) { spin_lock_irq(&phba->hbalock); list_del_init(&piocb->dlist); @@ -7987,6 +8042,9 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) if (phba->sli_rev == LPFC_SLI_REV4) spin_lock(&pring->ring_lock); + /* No need to abort the txq list, + * just queue them up for lpfc_sli_cancel_iocbs + */ list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) { cmd = &piocb->iocb; @@ -8007,11 +8065,22 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) list_del_init(&piocb->list); list_add_tail(&piocb->list, &abort_list); } + + /* The same holds true for any FLOGI/FDISC on the fabric_iocb_list */ + if (vport == phba->pport) { + list_for_each_entry_safe(piocb, tmp_iocb, + &phba->fabric_iocb_list, list) { + cmd = &piocb->iocb; + list_del_init(&piocb->list); + list_add_tail(&piocb->list, &abort_list); + } + } + if (phba->sli_rev == LPFC_SLI_REV4) spin_unlock(&pring->ring_lock); spin_unlock_irq(&phba->hbalock); - /* Cancell all the IOCBs from the completions list */ + /* Cancel all the IOCBs from the completions list */ lpfc_sli_cancel_iocbs(phba, &abort_list, IOSTAT_LOCAL_REJECT, IOERR_SLI_ABORTED); -- cgit v1.2.3-59-g8ed1b From 07f50997d66c3273121dd6b8a7d433cdfb5395c1 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:45 -0700 Subject: scsi: lpfc: Fix null ptr oops updating lpfc_devloss_tmo via sysfs attribute If an admin updates lpfc's devloss_tmo sysfs attribute, the kernel will oops. Coding of a loop allowed a new value (rport) to be set/checked for null followed by an older value (remoteport) checked for null to allow progress where the new value, even though null, will be referenced. Rework the logic to validate and prevent any reference to the null ptr. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index ea62322ffe2b..0e71348bf3a3 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -3682,8 +3682,8 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport) if (rport) remoteport = rport->remoteport; spin_unlock(&vport->phba->hbalock); - if (remoteport) - nvme_fc_set_remoteport_devloss(rport->remoteport, + if (rport && remoteport) + nvme_fc_set_remoteport_devloss(remoteport, vport->cfg_devloss_tmo); #endif } -- cgit v1.2.3-59-g8ed1b From 96d156f95c92eb1d8a8bfae84ceb70396a036f43 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:46 -0700 Subject: scsi: lpfc: Fix devices that don't return after devloss followed by rediscovery If a remote port is removed and remains removed for devloss_tmo, if an RSCN is subsequently received indicating the presence of the remte port, the driver does not login to and rediscovery the remote port. Currently, in order to for a port to be rediscovered post an RSCN, the node state must be NPR to reflect not logged in. When devloss expires, the node state is marked UNUSED. When an RSCN occurs, the nodes referenced by the RSCN will have a NPR_2B_DISC flag set, but the re-login will only be attempted if the node is in NPR_NODE state. Thus the node is skipped over. Fix by recognizing the NPR_2B_DISC and UNUSED and transition the node back to NPR state to allow the re-login to take place. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_ct.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index c2ac6cb730e8..7649903d4134 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -480,10 +480,20 @@ lpfc_prep_node_fc4type(struct lpfc_vport *vport, uint32_t Did, uint8_t fc4_type) lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "0238 Process x%06x NameServer Rsp " - "Data: x%x x%x x%x x%x\n", Did, + "Data: x%x x%x x%x x%x x%x\n", Did, ndlp->nlp_flag, ndlp->nlp_fc4_type, - vport->fc_flag, + ndlp->nlp_state, vport->fc_flag, vport->fc_rscn_id_cnt); + + /* if ndlp needs to be discovered and prior + * state of ndlp hit devloss, change state to + * allow rediscovery. + */ + if (ndlp->nlp_flag & NLP_NPR_2B_DISC && + ndlp->nlp_state == NLP_STE_UNUSED_NODE) { + lpfc_nlp_set_state(vport, ndlp, + NLP_STE_NPR_NODE); + } } else { lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, "Skip1 GID_FTrsp: did:x%x flg:x%x cnt:%d", @@ -751,9 +761,11 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (CTrsp->CommandResponse.bits.CmdRsp == cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) { lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, - "0208 NameServer Rsp Data: x%x x%x\n", + "0208 NameServer Rsp Data: x%x x%x " + "sz x%x\n", vport->fc_flag, - CTreq->un.gid.Fc4Type); + CTreq->un.gid.Fc4Type, + irsp->un.genreq64.bdl.bdeSize); lpfc_ns_rsp(vport, outp, @@ -814,6 +826,11 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } vport->gidft_inp--; } + + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "4216 GID_FT cmpl inp %d disc %d\n", + vport->gidft_inp, vport->num_disc_nodes); + /* Link up / RSCN discovery */ if ((vport->num_disc_nodes == 0) && (vport->gidft_inp == 0)) { -- cgit v1.2.3-59-g8ed1b From b95b21193c85db1b2797e38eea4f0fa72c7a087c Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:47 -0700 Subject: scsi: lpfc: Fix loss of remote port after devloss due to lack of RPIs In tests with remote ports contantly logging out/logging coupled with occassional local link bounce, if a remote port is disocnnected for longer than devloss_tmo and then subsequently reconnected, eventually the test will fail to login with the remote port and remote port connectivity is lost. When devloss_tmo expires, the driver does not free the node struct until the port or npiv instances is being deleted. The node is left allocated but the state set to UNUSED. If the node was in the process of logging in when the local link drop occurred, meaning the RPI was allocated for the node in order to send the ELS, but not yet registered which comes after successful login, the node is moved to the NPR state, and if devloss expires, to UNUSED state. If the remote port comes back, the node associated with it is restarted and this path happens to allocate a new RPI and overwrites the prior RPI value. In the cases where the port was logged in and loggs out, the path did release the RPI but did not set the node rpi value. In the cases where the remote port never finished logging in, the path never did the call to release the rpi. In this latter case, when the node is subsequently restore, the new rpi allocation overwrites the rpi that was not released, and the rpi is now leaked. Eventually the port will run out of RPI resources to log into new remote ports. Fix by following changes: - When an rpi is released, do so under locks and ensure the node rpi value is set to a non-allocated value (LPFC_RPI_ALLOC_ERROR). Note: refactored to a small service routine to avoid indentation issues. - When re-enabling a node, check the rpi value to determine if a new allocation is necessary. If already set, use the prior rpi. Enhanced logging to help in the future. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_ct.c | 7 ++++--- drivers/scsi/lpfc/lpfc_hbadisc.c | 41 +++++++++++++++++++++++++++++++--------- drivers/scsi/lpfc/lpfc_sli.c | 34 +++++++++++++++++++-------------- 3 files changed, 56 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 7649903d4134..c52d5edf4d44 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -462,6 +462,7 @@ lpfc_prep_node_fc4type(struct lpfc_vport *vport, uint32_t Did, uint8_t fc4_type) struct lpfc_nodelist *ndlp; if ((vport->port_type != LPFC_NPIV_PORT) || + (fc4_type == FC_TYPE_FCP) || !(vport->ct_flags & FC_CT_RFF_ID) || !vport->cfg_restrict_login) { ndlp = lpfc_setup_disc_node(vport, Did); @@ -501,9 +502,9 @@ lpfc_prep_node_fc4type(struct lpfc_vport *vport, uint32_t Did, uint8_t fc4_type) lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "0239 Skip x%06x NameServer Rsp " - "Data: x%x x%x\n", Did, - vport->fc_flag, - vport->fc_rscn_id_cnt); + "Data: x%x x%x %p\n", + Did, vport->fc_flag, + vport->fc_rscn_id_cnt, ndlp); } } else { if (!(vport->fc_flag & FC_RSCN_MODE) || diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index c413f8c51aa8..22b6fd08e7f5 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -4480,9 +4480,21 @@ lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, return NULL; if (phba->sli_rev == LPFC_SLI_REV4) { - rpi = lpfc_sli4_alloc_rpi(vport->phba); - if (rpi == LPFC_RPI_ALLOC_ERROR) + if (ndlp->nlp_rpi == LPFC_RPI_ALLOC_ERROR) + rpi = lpfc_sli4_alloc_rpi(vport->phba); + else + rpi = ndlp->nlp_rpi; + + if (rpi == LPFC_RPI_ALLOC_ERROR) { + lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE, + "0359 %s: ndlp:x%px " + "usgmap:x%x refcnt:%d FAILED RPI " + " ALLOC\n", + __func__, + (void *)ndlp, ndlp->nlp_usg_map, + kref_read(&ndlp->kref)); return NULL; + } } spin_lock_irqsave(&phba->ndlp_lock, flags); @@ -4541,6 +4553,14 @@ lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (state != NLP_STE_UNUSED_NODE) lpfc_nlp_set_state(vport, ndlp, state); + else + lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, + "0013 rpi:%x DID:%x flg:%x refcnt:%d " + "map:%x x%px STATE=UNUSED\n", + ndlp->nlp_rpi, ndlp->nlp_DID, + ndlp->nlp_flag, + kref_read(&ndlp->kref), + ndlp->nlp_usg_map, ndlp); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE, "node enable: did:x%x", @@ -5249,15 +5269,15 @@ __lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did) list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { if (lpfc_matchdid(vport, ndlp, did)) { - data1 = (((uint32_t) ndlp->nlp_state << 24) | - ((uint32_t) ndlp->nlp_xri << 16) | - ((uint32_t) ndlp->nlp_type << 8) | - ((uint32_t) ndlp->nlp_rpi & 0xff)); + data1 = (((uint32_t)ndlp->nlp_state << 24) | + ((uint32_t)ndlp->nlp_xri << 16) | + ((uint32_t)ndlp->nlp_type << 8) | + ((uint32_t)ndlp->nlp_usg_map & 0xff)); lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, "0929 FIND node DID " - "Data: x%p x%x x%x x%x %p\n", + "Data: x%px x%x x%x x%x x%x x%px\n", ndlp, ndlp->nlp_DID, - ndlp->nlp_flag, data1, + ndlp->nlp_flag, data1, ndlp->nlp_rpi, ndlp->active_rrqs_xri_bitmap); return ndlp; } @@ -5342,8 +5362,11 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did) if (vport->phba->nvmet_support) return NULL; ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_NPR_NODE); - if (!ndlp) + if (!ndlp) { + lpfc_printf_vlog(vport, KERN_WARNING, LOG_SLI, + "0014 Could not enable ndlp\n"); return NULL; + } spin_lock_irq(shost->host_lock); ndlp->nlp_flag |= NLP_NPR_2B_DISC; spin_unlock_irq(shost->host_lock); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 7c4bca47496a..8449f7f9cb64 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2426,6 +2426,20 @@ lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) return; } +static void +__lpfc_sli_rpi_release(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) +{ + unsigned long iflags; + + if (ndlp->nlp_flag & NLP_RELEASE_RPI) { + lpfc_sli4_free_rpi(vport->phba, ndlp->nlp_rpi); + spin_lock_irqsave(&vport->phba->ndlp_lock, iflags); + ndlp->nlp_flag &= ~NLP_RELEASE_RPI; + ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR; + spin_unlock_irqrestore(&vport->phba->ndlp_lock, iflags); + } + ndlp->nlp_flag &= ~NLP_UNREG_INP; +} /** * lpfc_sli_def_mbox_cmpl - Default mailbox completion handler @@ -2507,12 +2521,7 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ndlp->nlp_defer_did = NLP_EVT_NOTHING_PENDING; lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); } else { - if (ndlp->nlp_flag & NLP_RELEASE_RPI) { - lpfc_sli4_free_rpi(vport->phba, - ndlp->nlp_rpi); - ndlp->nlp_flag &= ~NLP_RELEASE_RPI; - } - ndlp->nlp_flag &= ~NLP_UNREG_INP; + __lpfc_sli_rpi_release(vport, ndlp); } pmb->ctx_ndlp = NULL; } @@ -2587,14 +2596,7 @@ lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_issue_els_plogi( vport, ndlp->nlp_DID, 0); } else { - if (ndlp->nlp_flag & NLP_RELEASE_RPI) { - lpfc_sli4_free_rpi( - vport->phba, - ndlp->nlp_rpi); - ndlp->nlp_flag &= - ~NLP_RELEASE_RPI; - } - ndlp->nlp_flag &= ~NLP_UNREG_INP; + __lpfc_sli_rpi_release(vport, ndlp); } } } @@ -18225,6 +18227,10 @@ __lpfc_sli4_free_rpi(struct lpfc_hba *phba, int rpi) if (test_and_clear_bit(rpi, phba->sli4_hba.rpi_bmask)) { phba->sli4_hba.rpi_count--; phba->sli4_hba.max_cfg_param.rpi_used--; + } else { + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "2016 rpi %x not inuse\n", + rpi); } } -- cgit v1.2.3-59-g8ed1b From a643c6de1441e5cdab88452c46fe7c38b318009e Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:48 -0700 Subject: scsi: lpfc: Fix propagation of devloss_tmo setting to nvme transport If admin changes the devloss_tmo on an rport via the fc_remote_port rport dev_loss_tmo attribute, the value is on set on scsi stack. The change is not propagated to NVMe. The set routine in the lldd lacks the call to nvme_fc_set_remoteport_devloss() to set the value. Fix by adding the call to the lldd set routine. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 0e71348bf3a3..b527cc60e939 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -6845,10 +6845,31 @@ lpfc_get_starget_port_name(struct scsi_target *starget) static void lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) { + struct lpfc_rport_data *rdata = rport->dd_data; + struct lpfc_nodelist *ndlp = rdata->pnode; +#if (IS_ENABLED(CONFIG_NVME_FC)) + struct lpfc_nvme_rport *nrport = NULL; +#endif + if (timeout) rport->dev_loss_tmo = timeout; else rport->dev_loss_tmo = 1; + + if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { + dev_info(&rport->dev, "Cannot find remote node to " + "set rport dev loss tmo, port_id x%x\n", + rport->port_id); + return; + } + +#if (IS_ENABLED(CONFIG_NVME_FC)) + nrport = lpfc_ndlp_get_nrport(ndlp); + + if (nrport && nrport->remoteport) + nvme_fc_set_remoteport_devloss(nrport->remoteport, + rport->dev_loss_tmo); +#endif } /** -- cgit v1.2.3-59-g8ed1b From c26c265b168bb09013922846a51447603bcdfdc4 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:49 -0700 Subject: scsi: lpfc: Fix sg_seg_cnt for HBAs that don't support NVME On an SLI-3 adapter which does not support NVMe, but with the driver global attribute to enable nvme on any adapter if it does support NVMe (e.g. module parameter lpfc_enable_fc4_type=3), the SGL and total SGE values are being munged by the protocol enablement when it shouldn't be. Correct by changing the location of where the NVME sgl information is being applied, which will avoid any SLI-3-based adapter. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 10 ---------- drivers/scsi/lpfc/lpfc_init.c | 9 +++++++++ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index b527cc60e939..7bfebecf03bb 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -7181,16 +7181,6 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) lpfc_ras_fwlog_level_init(phba, lpfc_ras_fwlog_level); lpfc_ras_fwlog_func_init(phba, lpfc_ras_fwlog_func); - - /* If the NVME FC4 type is enabled, scale the sg_seg_cnt to - * accommodate 512K and 1M IOs in a single nvme buf and supply - * enough NVME LS iocb buffers for larger connectivity counts. - */ - if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { - phba->cfg_sg_seg_cnt = LPFC_MAX_NVME_SEG_CNT; - phba->cfg_iocb_cnt = 5; - } - return; } diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 8e889ea26203..8429de65d490 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -11681,6 +11681,15 @@ fcponly: } } + /* If the NVME FC4 type is enabled, scale the sg_seg_cnt to + * accommodate 512K and 1M IOs in a single nvme buf and supply + * enough NVME LS iocb buffers for larger connectivity counts. + */ + if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { + phba->cfg_sg_seg_cnt = LPFC_MAX_NVME_SEG_CNT; + phba->cfg_iocb_cnt = 5; + } + /* Only embed PBDE for if_type 6, PBDE support requires xib be set */ if ((bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != LPFC_SLI_INTF_IF_TYPE_6) || (!bf_get(cfg_xib, mbx_sli4_parameters))) -- cgit v1.2.3-59-g8ed1b From a6d10f24a04d658078582fc0a89b20f050c0ae68 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:50 -0700 Subject: scsi: lpfc: Fix driver nvme rescan logging In situations where zoning is not being used, thus NVMe initiators see other NVMe initiators as well as NVMe targets, a link bounce on an initiator will cause the NVMe initiators to spew "6169" State Error messages. The driver is not qualifying whether the remote port is a NVMe targer or not before calling the lpfc_nvme_rescan_port(), which validates the role and prints the message if its only an NVMe initiator. Fix by the following: - Before calling lpfc_nvme_rescan_port() ensure that the node is a NVMe storage target or a NVMe discovery controller. - Clean up implementation of lpfc_nvme_rescan_port. remoteport pointer will always be NULL if a NVMe initiator only. But, grabbing of remoteport pointer should be done under lock to coincide with the registering of the remote port with the fc transport. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 12 ++++++++++-- drivers/scsi/lpfc/lpfc_nvme.c | 31 +++++++++++++++++-------------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 8103635adc38..d919f3161160 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -6360,7 +6360,11 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport) continue; } - if (ndlp->nlp_fc4_type & NLP_FC4_NVME) + /* Check to see if we need to NVME rescan this target + * remoteport. + */ + if (ndlp->nlp_fc4_type & NLP_FC4_NVME && + ndlp->nlp_type & (NLP_NVME_TARGET | NLP_NVME_DISCOVERY)) lpfc_nvme_rescan_port(vport, ndlp); lpfc_disc_state_machine(vport, ndlp, NULL, @@ -6474,7 +6478,11 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, *lp, vport->fc_flag, payload_len); lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); - if (ndlp->nlp_fc4_type & NLP_FC4_NVME) + /* Check to see if we need to NVME rescan this target + * remoteport. + */ + if (ndlp->nlp_fc4_type & NLP_FC4_NVME && + ndlp->nlp_type & (NLP_NVME_TARGET | NLP_NVME_DISCOVERY)) lpfc_nvme_rescan_port(vport, ndlp); return 0; } diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 9746808cf94f..e8924e90c4eb 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -2426,20 +2426,23 @@ void lpfc_nvme_rescan_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) { #if (IS_ENABLED(CONFIG_NVME_FC)) - struct lpfc_nvme_rport *rport; - struct nvme_fc_remote_port *remoteport; + struct lpfc_nvme_rport *nrport; + struct nvme_fc_remote_port *remoteport = NULL; - rport = ndlp->nrport; + spin_lock_irq(&vport->phba->hbalock); + nrport = lpfc_ndlp_get_nrport(ndlp); + if (nrport) + remoteport = nrport->remoteport; + spin_unlock_irq(&vport->phba->hbalock); lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, "6170 Rescan NPort DID x%06x type x%x " - "state x%x rport %p\n", - ndlp->nlp_DID, ndlp->nlp_type, ndlp->nlp_state, rport); - if (!rport) - goto input_err; - remoteport = rport->remoteport; - if (!remoteport) - goto input_err; + "state x%x nrport x%px remoteport x%px\n", + ndlp->nlp_DID, ndlp->nlp_type, ndlp->nlp_state, + nrport, remoteport); + + if (!nrport || !remoteport) + goto rescan_exit; /* Only rescan if we are an NVME target in the MAPPED state */ if (remoteport->port_role & FC_PORT_ROLE_NVME_DISCOVERY && @@ -2452,10 +2455,10 @@ lpfc_nvme_rescan_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ndlp->nlp_DID, remoteport->port_state); } return; -input_err: - lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC, - "6169 State error: lport %p, rport%p FCID x%06x\n", - vport->localport, ndlp->rport, ndlp->nlp_DID); + rescan_exit: + lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, + "6169 Skip NVME Rport Rescan, NVME remoteport " + "unregistered\n"); #endif } -- cgit v1.2.3-59-g8ed1b From 6825b7bd32030486cc94bdd4bb512756fcd5b901 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:51 -0700 Subject: scsi: lpfc: Fix error in remote port address change In a test with high nvme remote port counts connected via a multi-hop FC switch config where switches were systematically reset (e.g. fabric partitioning and re-establishment), the nvme remote ports would switch addresses based on the switch reconfiguration events. The driver would get into a situation where the nvme port changed address, PLOGI and PRLI would succeed nvme transport registration occurred, but subsequent LS requests by the nvme subsystem failed due to a bad ndlp state and connectivity to the device failed. The driver hit a race condition on multiple devices that address swapped simultaneously. In cases where the driver notices the remote port structure came back as the same value as previously (meaning a nvme_rport structure was re-enabled and did not go through devloss_tmo/connect_tmo_failures on all controllers) the driver would unconditionally exit assuming the ndlp information was correct. But, if the ndlp's had been swapped, the ndlp had stale port state information, which when used by the LS request commands, would fail the commands. Fix by checking whether a node swap had occurred, and only exit if no ndlp swap had occurred. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nvme.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index e8924e90c4eb..103708503592 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -2348,7 +2348,7 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) */ lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NVME_DISC, - "6014 Rebinding lport to " + "6014 Rebind lport to current " "remoteport %p wwpn 0x%llx, " "Data: x%x x%x %p %p x%x x%06x\n", remote_port, @@ -2359,7 +2359,16 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ndlp, ndlp->nlp_type, ndlp->nlp_DID); - return 0; + + /* It's a complete rebind only if the driver + * is registering with the same ndlp. Otherwise + * the driver likely executed a node swap + * prior to this registration and the ndlp to + * remoteport binding needs to be redone. + */ + if (prev_ndlp == ndlp) + return 0; + } /* Sever the ndlp<->rport association @@ -2393,8 +2402,8 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) spin_unlock_irq(&vport->phba->hbalock); lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC | LOG_NODE, - "6022 Binding new rport to " - "lport %p Remoteport %p rport %p WWNN 0x%llx, " + "6022 Bind lport x%px to remoteport x%px " + "rport x%px WWNN 0x%llx, " "Rport WWPN 0x%llx DID " "x%06x Role x%x, ndlp %p prev_ndlp %p\n", lport, remote_port, rport, -- cgit v1.2.3-59-g8ed1b From 894bb17f0cb07a6503d096dbbd156e38a3640822 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:52 -0700 Subject: scsi: lpfc: Fix deadlock on host_lock during cable pulls During cable pull testing a deadlock was seen between lpfc_nlp_counters() vs lpfc_mbox_process_link_up() vs lpfc_work_list_done(). They are all waiting on the shost->host_lock. Issue is all of these cases raise irq when taking out the lock but use spin_unlock_irq() when unlocking. The unlock path is will unconditionally re-enable interrupts in cases where irq state should be preserved. The re-enablement allowed the other paths to execute which then causes the deadlock. Fix by converting the lock/unlock to irqsave/irqrestore. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hbadisc.c | 47 ++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 22b6fd08e7f5..c8d14709343f 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -118,6 +118,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) struct lpfc_work_evt *evtp; int put_node; int put_rport; + unsigned long iflags; rdata = rport->dd_data; ndlp = rdata->pnode; @@ -170,22 +171,22 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) } shost = lpfc_shost_from_vport(vport); - spin_lock_irq(shost->host_lock); + spin_lock_irqsave(shost->host_lock, iflags); ndlp->nlp_flag |= NLP_IN_DEV_LOSS; - spin_unlock_irq(shost->host_lock); + spin_unlock_irqrestore(shost->host_lock, iflags); /* We need to hold the node by incrementing the reference * count until this queued work is done */ evtp->evt_arg1 = lpfc_nlp_get(ndlp); - spin_lock_irq(&phba->hbalock); + spin_lock_irqsave(&phba->hbalock, iflags); if (evtp->evt_arg1) { evtp->evt = LPFC_EVT_DEV_LOSS; list_add_tail(&evtp->evt_listp, &phba->work_list); lpfc_worker_wake_up(phba); } - spin_unlock_irq(&phba->hbalock); + spin_unlock_irqrestore(&phba->hbalock, iflags); return; } @@ -212,14 +213,15 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) int put_node; int warn_on = 0; int fcf_inuse = 0; + unsigned long iflags; rport = ndlp->rport; vport = ndlp->vport; shost = lpfc_shost_from_vport(vport); - spin_lock_irq(shost->host_lock); + spin_lock_irqsave(shost->host_lock, iflags); ndlp->nlp_flag &= ~NLP_IN_DEV_LOSS; - spin_unlock_irq(shost->host_lock); + spin_unlock_irqrestore(shost->host_lock, iflags); if (!rport) return fcf_inuse; @@ -3115,8 +3117,9 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) int rc; struct fcf_record *fcf_record; uint32_t fc_flags = 0; + unsigned long iflags; - spin_lock_irq(&phba->hbalock); + spin_lock_irqsave(&phba->hbalock, iflags); phba->fc_linkspeed = bf_get(lpfc_mbx_read_top_link_spd, la); if (!(phba->hba_flag & HBA_FCOE_MODE)) { @@ -3213,12 +3216,12 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) vport->fc_myDID = phba->fc_pref_DID; fc_flags |= FC_LBIT; } - spin_unlock_irq(&phba->hbalock); + spin_unlock_irqrestore(&phba->hbalock, iflags); if (fc_flags) { - spin_lock_irq(shost->host_lock); + spin_lock_irqsave(shost->host_lock, iflags); vport->fc_flag |= fc_flags; - spin_unlock_irq(shost->host_lock); + spin_unlock_irqrestore(shost->host_lock, iflags); } lpfc_linkup(phba); @@ -3292,22 +3295,22 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) * The driver is expected to do FIP/FCF. Call the port * and get the FCF Table. */ - spin_lock_irq(&phba->hbalock); + spin_lock_irqsave(&phba->hbalock, iflags); if (phba->hba_flag & FCF_TS_INPROG) { - spin_unlock_irq(&phba->hbalock); + spin_unlock_irqrestore(&phba->hbalock, iflags); return; } /* This is the initial FCF discovery scan */ phba->fcf.fcf_flag |= FCF_INIT_DISC; - spin_unlock_irq(&phba->hbalock); + spin_unlock_irqrestore(&phba->hbalock, iflags); lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, "2778 Start FCF table scan at linkup\n"); rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST); if (rc) { - spin_lock_irq(&phba->hbalock); + spin_lock_irqsave(&phba->hbalock, iflags); phba->fcf.fcf_flag &= ~FCF_INIT_DISC; - spin_unlock_irq(&phba->hbalock); + spin_unlock_irqrestore(&phba->hbalock, iflags); goto out; } /* Reset FCF roundrobin bmask for new discovery */ @@ -3366,6 +3369,7 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) MAILBOX_t *mb = &pmb->u.mb; struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf); uint8_t attn_type; + unsigned long iflags; /* Unblock ELS traffic */ pring = lpfc_phba_elsring(phba); @@ -3387,12 +3391,12 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) memcpy(&phba->alpa_map[0], mp->virt, 128); - spin_lock_irq(shost->host_lock); + spin_lock_irqsave(shost->host_lock, iflags); if (bf_get(lpfc_mbx_read_top_pb, la)) vport->fc_flag |= FC_BYPASSED_MODE; else vport->fc_flag &= ~FC_BYPASSED_MODE; - spin_unlock_irq(shost->host_lock); + spin_unlock_irqrestore(shost->host_lock, iflags); if (phba->fc_eventTag <= la->eventTag) { phba->fc_stat.LinkMultiEvent++; @@ -3403,12 +3407,12 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) phba->fc_eventTag = la->eventTag; if (phba->sli_rev < LPFC_SLI_REV4) { - spin_lock_irq(&phba->hbalock); + spin_lock_irqsave(&phba->hbalock, iflags); if (bf_get(lpfc_mbx_read_top_mm, la)) phba->sli.sli_flag |= LPFC_MENLO_MAINT; else phba->sli.sli_flag &= ~LPFC_MENLO_MAINT; - spin_unlock_irq(&phba->hbalock); + spin_unlock_irqrestore(&phba->hbalock, iflags); } phba->link_events++; @@ -4196,8 +4200,9 @@ static void lpfc_nlp_counters(struct lpfc_vport *vport, int state, int count) { struct Scsi_Host *shost = lpfc_shost_from_vport(vport); + unsigned long iflags; - spin_lock_irq(shost->host_lock); + spin_lock_irqsave(shost->host_lock, iflags); switch (state) { case NLP_STE_UNUSED_NODE: vport->fc_unused_cnt += count; @@ -4227,7 +4232,7 @@ lpfc_nlp_counters(struct lpfc_vport *vport, int state, int count) vport->fc_npr_cnt += count; break; } - spin_unlock_irq(shost->host_lock); + spin_unlock_irqrestore(shost->host_lock, iflags); } static void -- cgit v1.2.3-59-g8ed1b From 8c24a4f643edbcc7c8281b1f7527568f565dfbf8 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:53 -0700 Subject: scsi: lpfc: Fix crash due to port reset racing vs adapter error handling If the adapter encounters a condition which causes the adapter to fail (driver must detect the failure) simultaneously to a request to the driver to reset the adapter (such as a host_reset), the reset path will be racing with the asynchronously-detect adapter failure path. In the failing situation, one path has started to tear down the adapter data structures (io_wq's) while the other path has initiated a repeat of the teardown and is in the lpfc_sli_flush_xxx_rings path and attempting to access the just-freed data structures. Fix by the following: - In cases where an adapter failure is detected, rather than explicitly calling offline_eratt() to start the teardown, change the adapter state and let the later calls of posted work to the slowpath thread invoke the adapter recovery. In essence, this means all requests to reset are serialized on the slowpath thread. - Clean up the routine that restarts the adapter. If there is a failure from brdreset, don't immediately error and leave things in a partial state. Instead, ensure the adapter state is set and finish the teardown of structures before returning. - If in the scsi host reset handler and the board fails to reset and restart (which can be due to parallel reset/recovery paths), instead of hard failing and explicitly calling offline_eratt() (which gets into the redundant path), just fail out and let the asynchronous path resolve the adapter state. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 7 +++---- drivers/scsi/lpfc/lpfc_scsi.c | 16 +++++++++------- drivers/scsi/lpfc/lpfc_sli.c | 6 ++++-- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 8429de65d490..c549212a2b49 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1926,7 +1926,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "7624 Firmware not ready: Failing UE recovery," " waited %dSec", i); - lpfc_sli4_offline_eratt(phba); + phba->link_state = LPFC_HBA_ERROR; break; case LPFC_SLI_INTF_IF_TYPE_2: @@ -2000,9 +2000,8 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) } /* fall through for not able to recover */ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "3152 Unrecoverable error, bring the port " - "offline\n"); - lpfc_sli4_offline_eratt(phba); + "3152 Unrecoverable error\n"); + phba->link_state = LPFC_HBA_ERROR; break; case LPFC_SLI_INTF_IF_TYPE_1: default: diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index f9df800e7067..720a98266986 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -5295,18 +5295,20 @@ lpfc_host_reset_handler(struct scsi_cmnd *cmnd) lpfc_offline(phba); rc = lpfc_sli_brdrestart(phba); if (rc) - ret = FAILED; + goto error; + rc = lpfc_online(phba); if (rc) - ret = FAILED; + goto error; + lpfc_unblock_mgmt_io(phba); - if (ret == FAILED) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, - "3323 Failed host reset, bring it offline\n"); - lpfc_sli4_offline_eratt(phba); - } return ret; +error: + lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + "3323 Failed host reset\n"); + lpfc_unblock_mgmt_io(phba); + return FAILED; } /** diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 8449f7f9cb64..be89a86f9649 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -4509,7 +4509,7 @@ lpfc_sli_brdreset(struct lpfc_hba *phba) * checking during resets the device. The caller is not required to hold * any locks. * - * This function returns 0 always. + * This function returns 0 on success else returns negative error code. **/ int lpfc_sli4_brdreset(struct lpfc_hba *phba) @@ -4667,7 +4667,7 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba) rc = lpfc_sli4_brdreset(phba); if (rc) - return rc; + goto error; spin_lock_irq(&phba->hbalock); phba->pport->stopped = 0; @@ -4682,6 +4682,8 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba) if (hba_aer_enabled) pci_disable_pcie_error_reporting(phba->pcidev); +error: + phba->link_state = LPFC_HBA_ERROR; lpfc_hba_down_post(phba); lpfc_sli4_queue_destroy(phba); -- cgit v1.2.3-59-g8ed1b From 5e0e2318aa2a6fb8c2c693fb7ff995650e452054 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:54 -0700 Subject: scsi: lpfc: Fix too many sg segments spamming in kernel log This issue is specific to SLI-3 adapters, specifically when DIF is used. Once seen, this message floods the logs: 9064 BLKGRD: lpfc_scsi_prep_dma_buf_s3: Too many sg segments from dma_map_sg The driver, upon detecting an error such as too many elements in an sglist, misrepresents the error by treating it as a temporary resource issue by returning MLQUEUE_HOST_BUSY. In these cases, no retry will fix it and it should have been a hard error. The repeated retry was causing the spamming of the log. As for the initial reason of why an I/O encountered this issue at all is not clear as parameters set by the driver should have avoided this. The dm multipath maintainer has been notified of the issue. Fix by changing the return code for the dma mapping routines to indicate cases that are not retryable and return DID_ERROR on those cases. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_scsi.c | 79 ++++++++++++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 720a98266986..8ae24500806e 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -918,9 +918,10 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) "dma_map_sg. Config %d, seg_cnt %d\n", __func__, phba->cfg_sg_seg_cnt, lpfc_cmd->seg_cnt); + WARN_ON_ONCE(lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt); lpfc_cmd->seg_cnt = 0; scsi_dma_unmap(scsi_cmnd); - return 1; + return 2; } /* @@ -2430,7 +2431,10 @@ lpfc_bg_scsi_adjust_dl(struct lpfc_hba *phba, * * This is the protection/DIF aware version of * lpfc_scsi_prep_dma_buf(). It may be a good idea to combine the - * two functions eventually, but for now, it's here + * two functions eventually, but for now, it's here. + * RETURNS 0 - SUCCESS, + * 1 - Failed DMA map, retry. + * 2 - Invalid scsi cmd or prot-type. Do not rety. **/ static int lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, @@ -2444,6 +2448,7 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction; int prot_group_type = 0; int fcpdl; + int ret = 1; struct lpfc_vport *vport = phba->pport; /* @@ -2467,8 +2472,11 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, lpfc_cmd->seg_cnt = datasegcnt; /* First check if data segment count from SCSI Layer is good */ - if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) + if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { + WARN_ON_ONCE(lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt); + ret = 2; goto err; + } prot_group_type = lpfc_prot_group_type(phba, scsi_cmnd); @@ -2476,14 +2484,18 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, case LPFC_PG_TYPE_NO_DIF: /* Here we need to add a PDE5 and PDE6 to the count */ - if ((lpfc_cmd->seg_cnt + 2) > phba->cfg_total_seg_cnt) + if ((lpfc_cmd->seg_cnt + 2) > phba->cfg_total_seg_cnt) { + ret = 2; goto err; + } num_bde = lpfc_bg_setup_bpl(phba, scsi_cmnd, bpl, datasegcnt); /* we should have 2 or more entries in buffer list */ - if (num_bde < 2) + if (num_bde < 2) { + ret = 2; goto err; + } break; case LPFC_PG_TYPE_DIF_BUF: @@ -2507,15 +2519,19 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, * protection data segment. */ if ((lpfc_cmd->prot_seg_cnt * 4) > - (phba->cfg_total_seg_cnt - 2)) + (phba->cfg_total_seg_cnt - 2)) { + ret = 2; goto err; + } num_bde = lpfc_bg_setup_bpl_prot(phba, scsi_cmnd, bpl, datasegcnt, protsegcnt); /* we should have 3 or more entries in buffer list */ if ((num_bde < 3) || - (num_bde > phba->cfg_total_seg_cnt)) + (num_bde > phba->cfg_total_seg_cnt)) { + ret = 2; goto err; + } break; case LPFC_PG_TYPE_INVALID: @@ -2526,7 +2542,7 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, lpfc_printf_log(phba, KERN_ERR, LOG_FCP, "9022 Unexpected protection group %i\n", prot_group_type); - return 1; + return 2; } } @@ -2576,7 +2592,7 @@ err: lpfc_cmd->seg_cnt = 0; lpfc_cmd->prot_seg_cnt = 0; - return 1; + return ret; } /* @@ -2962,7 +2978,8 @@ out: * field of @lpfc_cmd for device with SLI-4 interface spec. * * Return codes: - * 1 - Error + * 2 - Error - Do not retry + * 1 - Error - Retry * 0 - Success **/ static int @@ -3012,9 +3029,10 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) "dma_map_sg. Config %d, seg_cnt %d\n", __func__, phba->cfg_sg_seg_cnt, lpfc_cmd->seg_cnt); + WARN_ON_ONCE(lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt); lpfc_cmd->seg_cnt = 0; scsi_dma_unmap(scsi_cmnd); - return 1; + return 2; } /* @@ -3110,6 +3128,10 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) * This is the protection/DIF aware version of * lpfc_scsi_prep_dma_buf(). It may be a good idea to combine the * two functions eventually, but for now, it's here + * Return codes: + * 2 - Error - Do not retry + * 1 - Error - Retry + * 0 - Success **/ static int lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, @@ -3123,6 +3145,7 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction; int prot_group_type = 0; int fcpdl; + int ret = 1; struct lpfc_vport *vport = phba->pport; /* @@ -3152,23 +3175,30 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, lpfc_cmd->seg_cnt = datasegcnt; /* First check if data segment count from SCSI Layer is good */ - if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) + if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { + WARN_ON_ONCE(lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt); + ret = 2; goto err; + } prot_group_type = lpfc_prot_group_type(phba, scsi_cmnd); switch (prot_group_type) { case LPFC_PG_TYPE_NO_DIF: /* Here we need to add a DISEED to the count */ - if ((lpfc_cmd->seg_cnt + 1) > phba->cfg_total_seg_cnt) + if ((lpfc_cmd->seg_cnt + 1) > phba->cfg_total_seg_cnt) { + ret = 2; goto err; + } num_sge = lpfc_bg_setup_sgl(phba, scsi_cmnd, sgl, datasegcnt); /* we should have 2 or more entries in buffer list */ - if (num_sge < 2) + if (num_sge < 2) { + ret = 2; goto err; + } break; case LPFC_PG_TYPE_DIF_BUF: @@ -3191,16 +3221,20 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, * protection data segment. */ if ((lpfc_cmd->prot_seg_cnt * 3) > - (phba->cfg_total_seg_cnt - 2)) + (phba->cfg_total_seg_cnt - 2)) { + ret = 2; goto err; + } num_sge = lpfc_bg_setup_sgl_prot(phba, scsi_cmnd, sgl, datasegcnt, protsegcnt); /* we should have 3 or more entries in buffer list */ if ((num_sge < 3) || - (num_sge > phba->cfg_total_seg_cnt)) + (num_sge > phba->cfg_total_seg_cnt)) { + ret = 2; goto err; + } break; case LPFC_PG_TYPE_INVALID: @@ -3211,7 +3245,7 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, lpfc_printf_log(phba, KERN_ERR, LOG_FCP, "9083 Unexpected protection group %i\n", prot_group_type); - return 1; + return 2; } } @@ -3273,7 +3307,7 @@ err: lpfc_cmd->seg_cnt = 0; lpfc_cmd->prot_seg_cnt = 0; - return 1; + return ret; } /** @@ -4454,8 +4488,12 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) err = lpfc_scsi_prep_dma_buf(phba, lpfc_cmd); } - if (err) + if (err == 2) { + cmnd->result = DID_ERROR << 16; + goto out_fail_command_release_buf; + } else if (err) { goto out_host_busy_free_buf; + } lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp); @@ -4526,6 +4564,9 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) out_tgt_busy: return SCSI_MLQUEUE_TARGET_BUSY; + out_fail_command_release_buf: + lpfc_release_scsi_buf(phba, lpfc_cmd); + out_fail_command: cmnd->scsi_done(cmnd); return 0; -- cgit v1.2.3-59-g8ed1b From 84f2ddf8cf317afcfd92e06ed5a25aea48dc200e Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:55 -0700 Subject: scsi: lpfc: Fix hang when downloading fw on port enabled for nvme As part of firmware download, the adapter is reset. On the adapter the reset causes the function to stop and all outstanding io is terminated (without responses). The reset path then starts teardown of the adapter, starting with deregistration of the remote ports with the nvme-fc transport. The local port is then deregistered and the driver waits for local port deregistration. This never finishes. The remote port deregistrations terminated the nvme controllers, causing them to send aborts for all the outstanding io. The aborts were serviced in the driver, but stalled due to its state. The nvme layer then stops to reclaim it's outstanding io before continuing. The io must be returned before the reset on the controller is deemed complete and the controller delete performed. The remote port deregistration won't complete until all the controllers are terminated. And the local port deregistration won't complete until all controllers and remote ports are terminated. Thus things hang. The issue is the reset which stopped the adapter also stopped all the responses that would drive i/o completions, and the aborts were also stopped that stopped i/o completions. The driver, when resetting the adapter like this, needs to be generating the completions as part of the adapter reset so that I/O complete (in error), and any aborts are not queued. Fix by adding flush routines whenever the adapter port has been reset or discovered in error. The flush routines will generate the completions for the scsi and nvme outstanding io. The abort ios, if waiting, will be caught and flushed as well. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_crtn.h | 1 + drivers/scsi/lpfc/lpfc_init.c | 4 ++++ drivers/scsi/lpfc/lpfc_nvme.c | 47 +++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/lpfc/lpfc_sli.c | 9 ++++++--- 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 68e9f96242d3..bee27bb7123c 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -595,6 +595,7 @@ void lpfc_release_io_buf(struct lpfc_hba *phba, struct lpfc_io_buf *ncmd, struct lpfc_sli4_hdw_queue *qp); void lpfc_nvme_cmd_template(void); void lpfc_nvmet_cmd_template(void); +void lpfc_nvme_cancel_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn); extern int lpfc_enable_nvmet_cnt; extern unsigned long long lpfc_enable_nvmet[]; extern int lpfc_no_hba_reset_cnt; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index c549212a2b49..8c0fb9baf723 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1546,6 +1546,8 @@ lpfc_sli4_offline_eratt(struct lpfc_hba *phba) spin_unlock_irq(&phba->hbalock); lpfc_offline_prep(phba, LPFC_MBX_NO_WAIT); + lpfc_sli_flush_fcp_rings(phba); + lpfc_sli_flush_nvme_rings(phba); lpfc_offline(phba); lpfc_hba_down_post(phba); lpfc_unblock_mgmt_io(phba); @@ -1807,6 +1809,8 @@ lpfc_sli4_port_sta_fn_reset(struct lpfc_hba *phba, int mbx_action, "2887 Reset Needed: Attempting Port " "Recovery...\n"); lpfc_offline_prep(phba, mbx_action); + lpfc_sli_flush_fcp_rings(phba); + lpfc_sli_flush_nvme_rings(phba); lpfc_offline(phba); /* release interrupt for possible resource change */ lpfc_sli4_disable_intr(phba); diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 103708503592..c7f5b50c3820 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -2668,3 +2668,50 @@ lpfc_nvme_wait_for_io_drain(struct lpfc_hba *phba) } } } + +void +lpfc_nvme_cancel_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn) +{ +#if (IS_ENABLED(CONFIG_NVME_FC)) + struct lpfc_io_buf *lpfc_ncmd; + struct nvmefc_fcp_req *nCmd; + struct lpfc_nvme_fcpreq_priv *freqpriv; + + if (!pwqeIn->context1) { + lpfc_sli_release_iocbq(phba, pwqeIn); + return; + } + /* For abort iocb just return, IO iocb will do a done call */ + if (bf_get(wqe_cmnd, &pwqeIn->wqe.gen_req.wqe_com) == + CMD_ABORT_XRI_CX) { + lpfc_sli_release_iocbq(phba, pwqeIn); + return; + } + lpfc_ncmd = (struct lpfc_io_buf *)pwqeIn->context1; + + spin_lock(&lpfc_ncmd->buf_lock); + if (!lpfc_ncmd->nvmeCmd) { + spin_unlock(&lpfc_ncmd->buf_lock); + lpfc_release_nvme_buf(phba, lpfc_ncmd); + return; + } + + nCmd = lpfc_ncmd->nvmeCmd; + lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR, + "6194 NVME Cancel xri %x\n", + lpfc_ncmd->cur_iocbq.sli4_xritag); + + nCmd->transferred_length = 0; + nCmd->rcv_rsplen = 0; + nCmd->status = NVME_SC_INTERNAL; + freqpriv = nCmd->private; + freqpriv->nvme_buf = NULL; + lpfc_ncmd->nvmeCmd = NULL; + + spin_unlock(&lpfc_ncmd->buf_lock); + nCmd->done(nCmd); + + /* Call release with XB=1 to queue the IO into the abort list. */ + lpfc_release_nvme_buf(phba, lpfc_ncmd); +#endif +} diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index be89a86f9649..c8db7ec31afb 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1391,9 +1391,12 @@ lpfc_sli_cancel_iocbs(struct lpfc_hba *phba, struct list_head *iocblist, while (!list_empty(iocblist)) { list_remove_head(iocblist, piocb, struct lpfc_iocbq, list); - if (!piocb->iocb_cmpl) - lpfc_sli_release_iocbq(phba, piocb); - else { + if (!piocb->iocb_cmpl) { + if (piocb->iocb_flag & LPFC_IO_NVME) + lpfc_nvme_cancel_iocb(phba, piocb); + else + lpfc_sli_release_iocbq(phba, piocb); + } else { piocb->iocb.ulpStatus = ulpstatus; piocb->iocb.un.ulpWord[4] = ulpWord4; (piocb->iocb_cmpl) (phba, piocb, piocb); -- cgit v1.2.3-59-g8ed1b From 005d8eb92847e6823d9fea6041f7c6f26b6cf2da Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:56 -0700 Subject: scsi: lpfc: Fix nvme target mode ABTSing a received ABTS If an unsolicited ABTS was received, the driver looks up the exchange it references. It it does various searches looking for the exchange context. When one is eventually matched and it is associated with an XRI context, the driver sends an ABORT WQE to terminate the exchange. Current code looks at whether the transport had taken action on the XRI yet or not (no action if set to LPFC_NVMET_STE_RCV; action if non-LPFC_NVMET_STE_RCV). Based on action or not one of two (sol vs unsol) issue abort routines are called. The unsol version cheats and transmits a sequence containing an ABTS with no interaction with the adapter. The sol version issues an Abort WQE and lets the adapter manage whether the ABTS is sent to not. The issue is the unsol version is sending ABTS unconditionally for the exchange that received the ABTS. It's unnecessary. Remove the conditional and just call the adapter command-based routine to let the adapter manage the ABTS. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nvmet.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index faa596f9e861..f0840e3182c0 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -1790,12 +1790,8 @@ lpfc_nvmet_rcv_unsol_abort(struct lpfc_vport *vport, lpfc_nvmet_defer_release(phba, ctxp); spin_unlock_irqrestore(&ctxp->ctxlock, iflag); } - if (ctxp->state == LPFC_NVMET_STE_RCV) - lpfc_nvmet_unsol_fcp_issue_abort(phba, ctxp, ctxp->sid, - ctxp->oxid); - else - lpfc_nvmet_sol_fcp_issue_abort(phba, ctxp, ctxp->sid, - ctxp->oxid); + lpfc_nvmet_sol_fcp_issue_abort(phba, ctxp, ctxp->sid, + ctxp->oxid); lpfc_sli4_seq_abort_rsp(vport, fc_hdr, 1); return 0; -- cgit v1.2.3-59-g8ed1b From 6a224b47fd019d299037e14381ddff438f2d34c8 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:57 -0700 Subject: scsi: lpfc: Fix nvme sg_seg_cnt display if HBA does not support NVME The driver is currently reporting a non-zero nvme sg_seg_cnt value of 256 when nvme is disabled. It should be zero. Fix by ensuring the value is cleared. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 8c0fb9baf723..f1e1e8faaec1 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -11676,6 +11676,7 @@ fcponly: phba->nvme_support = 0; phba->nvmet_support = 0; phba->cfg_nvmet_mrq = 0; + phba->cfg_nvme_seg_cnt = 0; /* If no FC4 type support, move to just SCSI support */ if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP)) -- cgit v1.2.3-59-g8ed1b From 07b1b91412c801030752da3d32a543c5522a79d6 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:58 -0700 Subject: scsi: lpfc: Fix sli4 adapter initialization with MSI When forcing the use of MSI (vs MSI-X) the driver is crashing in pci_irq_get_affinity. The driver was not using the new pci_alloc_irq_vectors interface in the MSI path. Fix by using pci_alloc_irq_vectors() with PCI_RQ_MSI in the MSI path. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index f1e1e8faaec1..82a5166afe18 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -11119,10 +11119,10 @@ vec_fail_out: * @phba: pointer to lpfc hba data structure. * * This routine is invoked to enable the MSI interrupt mode to device with - * SLI-4 interface spec. The kernel function pci_enable_msi() is called - * to enable the MSI vector. The device driver is responsible for calling - * the request_irq() to register MSI vector with a interrupt the handler, - * which is done in this function. + * SLI-4 interface spec. The kernel function pci_alloc_irq_vectors() is + * called to enable the MSI vector. The device driver is responsible for + * calling the request_irq() to register MSI vector with a interrupt the + * handler, which is done in this function. * * Return codes * 0 - successful @@ -11133,20 +11133,21 @@ lpfc_sli4_enable_msi(struct lpfc_hba *phba) { int rc, index; - rc = pci_enable_msi(phba->pcidev); - if (!rc) + rc = pci_alloc_irq_vectors(phba->pcidev, 1, 1, + PCI_IRQ_MSI | PCI_IRQ_AFFINITY); + if (rc > 0) lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "0487 PCI enable MSI mode success.\n"); else { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "0488 PCI enable MSI mode failed (%d)\n", rc); - return rc; + return rc ? rc : -1; } rc = request_irq(phba->pcidev->irq, lpfc_sli4_intr_handler, 0, LPFC_DRIVER_NAME, phba); if (rc) { - pci_disable_msi(phba->pcidev); + pci_free_irq_vectors(phba->pcidev); lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, "0490 MSI request_irq failed (%d)\n", rc); return rc; -- cgit v1.2.3-59-g8ed1b From 6db51abb8dc3919b85c5d2afd35b3871399e8a81 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:56:59 -0700 Subject: scsi: lpfc: Fix upcall to bsg done in non-success cases The scsi transport fc bsg interface does not expect the bsg_job_done() callback to be done if the bsg request call returns failure. Several of the HST_VENDOR cases in the driver unconditionally call bsg_job_done() regardless of the returning value. Fix the code to only call bsg_job_done() if the call to lpfc_bsg_request() will return success. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_bsg.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 251504cd575f..0d2535c177e9 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -5448,7 +5448,9 @@ ras_job_error: bsg_reply->result = rc; /* complete the job back to userspace */ - bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); + if (!rc) + bsg_job_done(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rc; } @@ -5527,8 +5529,9 @@ ras_job_error: bsg_reply->result = rc; /* complete the job back to userspace */ - bsg_job_done(job, bsg_reply->result, - bsg_reply->reply_payload_rcv_len); + if (!rc) + bsg_job_done(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rc; } @@ -5588,7 +5591,9 @@ ras_job_error: bsg_reply->result = rc; /* complete the job back to userspace */ - bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); + if (!rc) + bsg_job_done(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rc; } @@ -5670,7 +5675,9 @@ lpfc_bsg_get_ras_fwlog(struct bsg_job *job) ras_job_error: bsg_reply->result = rc; - bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); + if (!rc) + bsg_job_done(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rc; } @@ -5741,8 +5748,9 @@ lpfc_get_trunk_info(struct bsg_job *job) phba->sli4_hba.link_state.logical_speed / 1000; job_error: bsg_reply->result = rc; - bsg_job_done(job, bsg_reply->result, - bsg_reply->reply_payload_rcv_len); + if (!rc) + bsg_job_done(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rc; } -- cgit v1.2.3-59-g8ed1b From f98b2fd796d0f3dfa472e1ff977d38180301c982 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:57:00 -0700 Subject: scsi: lpfc: Fix Max Frame Size value shown in fdmishow output Max Frame Size value is shown as 34816 in fdmishow from Switch. The driver uses bbRcvSize in common service param which is obtained from the READ_SPARM mailbox command. The bbRcvSize field which is displayed is a three nibble field but the driver is printing a full four nibbles. Fix by masking off the upper nibble. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_ct.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index c52d5edf4d44..1717f3403a97 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -2552,7 +2552,7 @@ lpfc_fdmi_port_attr_max_frame(struct lpfc_vport *vport, ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; hsp = (struct serv_parm *)&vport->fc_sparam; - ae->un.AttrInt = (((uint32_t) hsp->cmn.bbRcvSizeMsb) << 8) | + ae->un.AttrInt = (((uint32_t) hsp->cmn.bbRcvSizeMsb & 0x0F) << 8) | (uint32_t) hsp->cmn.bbRcvSizeLsb; ae->un.AttrInt = cpu_to_be32(ae->un.AttrInt); size = FOURBYTES + sizeof(uint32_t); -- cgit v1.2.3-59-g8ed1b From 845d0327bf0885e7d2fb6cb18e800491be793250 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:57:01 -0700 Subject: scsi: lpfc: Fix reported physical link speed on a disabled trunked link GetTrunkInfo is displaying an incorrect link speed when the link is a trunk and the link has gone down. The driver is not clearing the logical speed as part of the link down transition. Fix by setting the logical speed to UNKNOWN SPEED when the link goes down. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hbadisc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index c8d14709343f..dc3763114d76 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -905,6 +905,8 @@ lpfc_linkdown(struct lpfc_hba *phba) phba->trunk_link.link1.state = 0; phba->trunk_link.link2.state = 0; phba->trunk_link.link3.state = 0; + phba->sli4_hba.link_state.logical_speed = + LPFC_LINK_SPEED_UNKNOWN; } spin_lock_irq(shost->host_lock); phba->pport->fc_flag &= ~FC_LBIT; -- cgit v1.2.3-59-g8ed1b From 4945c0f95bbfb35e230148f226c46868f4fdd55f Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:57:02 -0700 Subject: scsi: lpfc: Fix BlockGuard enablement on FCoE adapters The driver is allowing the user to change lpfc_enable_bg while loading the driver against a FCoE adapter. This is not supported. No check is made for the adapter type when applying the blockguard enablement value. Fix by verifying the adapter type before setting the enablement flag. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 7bfebecf03bb..e36b4827c64e 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -7065,6 +7065,21 @@ struct fc_function_template lpfc_vport_transport_functions = { .set_vport_symbolic_name = lpfc_set_vport_symbolic_name, }; +/** + * lpfc_get_hba_function_mode - Used to determine the HBA function in FCoE + * Mode + * @phba: lpfc_hba pointer. + **/ +static void +lpfc_get_hba_function_mode(struct lpfc_hba *phba) +{ + /* If it's a SkyHawk FCoE adapter */ + if (phba->pcidev->device == PCI_DEVICE_ID_SKYHAWK) + phba->hba_flag |= HBA_FCOE_MODE; + else + phba->hba_flag &= ~HBA_FCOE_MODE; +} + /** * lpfc_get_cfgparam - Used during probe_one to init the adapter structure * @phba: lpfc_hba pointer. @@ -7121,8 +7136,18 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) else phba->cfg_poll = lpfc_poll; - if (phba->cfg_enable_bg) + /* Get the function mode */ + lpfc_get_hba_function_mode(phba); + + /* BlockGuard allowed for FC only. */ + if (phba->cfg_enable_bg && phba->hba_flag & HBA_FCOE_MODE) { + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, + "0581 BlockGuard feature not supported\n"); + /* If set, clear the BlockGuard support param */ + phba->cfg_enable_bg = 0; + } else if (phba->cfg_enable_bg) { phba->sli3_options |= LPFC_SLI3_BG_ENABLED; + } lpfc_suppress_rsp_init(phba, lpfc_suppress_rsp); -- cgit v1.2.3-59-g8ed1b From db197bc4699b3f0347367d25345fe681fe73f1f6 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:57:03 -0700 Subject: scsi: lpfc: Fix nvme first burst module parameter description modinfo for lpfc_nvme_enable_fb is incorrect. FirstBurst on lpfc target is not fully supported. Update the attribute description Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index e36b4827c64e..798ec5f3a2c7 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -5467,15 +5467,12 @@ LPFC_ATTR_RW(nvmet_fb_size, 0, 0, 65536, * lpfc_nvme_enable_fb: Enable NVME first burst on I and T functions. * For the Initiator (I), enabling this parameter means that an NVMET * PRLI response with FBA enabled and an FB_SIZE set to a nonzero value will be - * processed by the initiator for subsequent NVME FCP IO. For the target - * function (T), enabling this parameter qualifies the lpfc_nvmet_fb_size - * driver parameter as the target function's first burst size returned to the - * initiator in the target's NVME PRLI response. Parameter supported on physical - * port only - no NPIV support. + * processed by the initiator for subsequent NVME FCP IO. + * Currently, this feature is not supported on the NVME target * Value range is [0,1]. Default value is 0 (disabled). */ LPFC_ATTR_RW(nvme_enable_fb, 0, 0, 1, - "Enable First Burst feature on I and T functions."); + "Enable First Burst feature for NVME Initiator."); /* # lpfc_max_scsicmpl_time: Use scsi command completion time to control I/O queue -- cgit v1.2.3-59-g8ed1b From d9f492a1a1ab2f3847e2c65b87a738f3831e6751 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:57:04 -0700 Subject: scsi: lpfc: Fix coverity warnings Running on Coverity produced the following errors: - coding style (indentation) - memset size mismatch errors note: comment cases where it is purposely a mismatch Fix the errors. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 10 +++++----- drivers/scsi/lpfc/lpfc_nvme.c | 5 +++-- drivers/scsi/lpfc/lpfc_nvmet.c | 2 +- drivers/scsi/lpfc/lpfc_sli.c | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index d919f3161160..54ec7f0822e5 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -5667,16 +5667,16 @@ lpfc_rdp_res_attach_port_names(struct fc_rdp_port_name_desc *desc, desc->tag = cpu_to_be32(RDP_PORT_NAMES_DESC_TAG); if (vport->fc_flag & FC_FABRIC) { memcpy(desc->port_names.wwnn, &vport->fabric_nodename, - sizeof(desc->port_names.wwnn)); + sizeof(desc->port_names.wwnn)); memcpy(desc->port_names.wwpn, &vport->fabric_portname, - sizeof(desc->port_names.wwpn)); + sizeof(desc->port_names.wwpn)); } else { /* Point to Point */ memcpy(desc->port_names.wwnn, &ndlp->nlp_nodename, - sizeof(desc->port_names.wwnn)); + sizeof(desc->port_names.wwnn)); - memcpy(desc->port_names.wwnn, &ndlp->nlp_portname, - sizeof(desc->port_names.wwpn)); + memcpy(desc->port_names.wwpn, &ndlp->nlp_portname, + sizeof(desc->port_names.wwpn)); } desc->length = cpu_to_be32(sizeof(desc->port_names)); diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index c7f5b50c3820..41b124b69947 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -436,6 +436,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, return 1; wqe = &genwqe->wqe; + /* Initialize only 64 bytes */ memset(wqe, 0, sizeof(union lpfc_wqe)); genwqe->context3 = (uint8_t *)bmp; @@ -1855,7 +1856,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, /* WQEs are reused. Clear stale data and set key fields to * zero like ia, iaab, iaar, xri_tag, and ctxt_tag. */ - memset(abts_wqe, 0, sizeof(union lpfc_wqe)); + memset(abts_wqe, 0, sizeof(*abts_wqe)); bf_set(abort_cmd_criteria, &abts_wqe->abort_cmd, T_XRI_TAG); /* word 7 */ @@ -1982,7 +1983,7 @@ lpfc_get_nvme_buf(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, sgl->word2 = cpu_to_le32(sgl->word2); /* Fill in word 3 / sgl_len during cmd submission */ - /* Initialize WQE */ + /* Initialize 64 bytes only */ memset(wqe, 0, sizeof(union lpfc_wqe)); if (lpfc_ndlp_check_qdepth(phba, ndlp)) { diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index f0840e3182c0..f42cc3150c6f 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -3330,7 +3330,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba, /* WQEs are reused. Clear stale data and set key fields to * zero like ia, iaab, iaar, xri_tag, and ctxt_tag. */ - memset(abts_wqe, 0, sizeof(union lpfc_wqe)); + memset(abts_wqe, 0, sizeof(*abts_wqe)); /* word 3 */ bf_set(abort_cmd_criteria, &abts_wqe->abort_cmd, T_XRI_TAG); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index c8db7ec31afb..a21fe4612a4e 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -9815,7 +9815,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, * we re-construct this WQE here based on information in * iocbq from scratch. */ - memset(wqe, 0, sizeof(union lpfc_wqe)); + memset(wqe, 0, sizeof(*wqe)); /* OX_ID is invariable to who sent ABTS to CT exchange */ bf_set(xmit_bls_rsp64_oxid, &wqe->xmit_bls_rsp, bf_get(lpfc_abts_oxid, &iocbq->iocb.un.bls_rsp)); -- cgit v1.2.3-59-g8ed1b From 1df09449902d1d4023a46ad02eab16483c54c49b Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:57:05 -0700 Subject: scsi: lpfc: Add simple unlikely optimizations to reduce NVME latency While performing code review, several relatively simple optimizations can be done in the fast path. Add these optimizations (unlikely designators). Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nvme.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 41b124b69947..106aef82620d 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -999,9 +999,9 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, idx = lpfc_ncmd->cur_iocbq.hba_wqidx; phba->sli4_hba.hdwq[idx].nvme_cstat.io_cmpls++; - if (vport->localport) { + if (unlikely(status && vport->localport)) { lport = (struct lpfc_nvme_lport *)vport->localport->private; - if (lport && status) { + if (lport) { if (bf_get(lpfc_wcqe_c_xb, wcqe)) atomic_inc(&lport->cmpl_fcp_xb); atomic_inc(&lport->cmpl_fcp_err); @@ -1141,7 +1141,7 @@ out_err: phba->ktime_last_cmd = lpfc_ncmd->ts_data_nvme; lpfc_nvme_ktime(phba, lpfc_ncmd); } - if (phba->cpucheck_on & LPFC_CHECK_NVME_IO) { + if (unlikely(phba->cpucheck_on & LPFC_CHECK_NVME_IO)) { uint32_t cpu; idx = lpfc_ncmd->cur_iocbq.hba_wqidx; cpu = raw_smp_processor_id(); @@ -1475,7 +1475,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport, goto out_fail; } - if (vport->load_flag & FC_UNLOADING) { + if (unlikely(vport->load_flag & FC_UNLOADING)) { lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR, "6124 Fail IO, Driver unload\n"); atomic_inc(&lport->xmt_fcp_err); -- cgit v1.2.3-59-g8ed1b From 32350664497279f4ddd96164caafc8a1b573ca2a Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:57:06 -0700 Subject: scsi: lpfc: Migrate to %px and %pf in kernel print calls In order to see real addresses, convert %p with %px for kernel addresses and replace %p with %pf for functions. While converting, standardize on "x%px" throughout (not %px or 0x%px). Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_bsg.c | 2 +- drivers/scsi/lpfc/lpfc_ct.c | 5 ++- drivers/scsi/lpfc/lpfc_debugfs.c | 4 +- drivers/scsi/lpfc/lpfc_els.c | 4 +- drivers/scsi/lpfc/lpfc_hbadisc.c | 78 +++++++++++++++++---------------- drivers/scsi/lpfc/lpfc_init.c | 18 ++++---- drivers/scsi/lpfc/lpfc_nportdisc.c | 2 +- drivers/scsi/lpfc/lpfc_nvme.c | 90 +++++++++++++++++++------------------- drivers/scsi/lpfc/lpfc_nvmet.c | 10 ++--- drivers/scsi/lpfc/lpfc_scsi.c | 16 +++---- drivers/scsi/lpfc/lpfc_sli.c | 16 +++---- 11 files changed, 125 insertions(+), 120 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 0d2535c177e9..39a736b887b1 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -1040,7 +1040,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, if (!dmabuf) { lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, "2616 No dmabuf " - "found for iocbq 0x%p\n", + "found for iocbq x%px\n", iocbq); kfree(evt_dat->data); kfree(evt_dat); diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 1717f3403a97..25e86706e207 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -1227,8 +1227,9 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (fc4_data_1 & LPFC_FC4_TYPE_BITMASK) ndlp->nlp_fc4_type |= NLP_FC4_NVME; lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, - "3064 Setting ndlp %p, DID x%06x with " - "FC4 x%08x, Data: x%08x x%08x %d\n", + "3064 Setting ndlp x%px, DID x%06x " + "with FC4 x%08x, Data: x%08x x%08x " + "%d\n", ndlp, did, ndlp->nlp_fc4_type, FC_TYPE_FCP, FC_TYPE_NVME, ndlp->nlp_state); diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 1ee857d9d165..75055ee59e91 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -361,7 +361,7 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) phys = ((uint64_t)hbq_buf->dbuf.phys & 0xffffffff); if (phys == le32_to_cpu(hbqe->bde.addrLow)) { len += scnprintf(buf+len, size-len, - "Buf%d: %p %06x\n", i, + "Buf%d: x%px %06x\n", i, hbq_buf->dbuf.virt, hbq_buf->tag); found = 1; break; @@ -2210,7 +2210,7 @@ lpfc_debugfs_dumpDif_open(struct inode *inode, struct file *file) goto out; /* Round to page boundary */ - pr_err("9060 BLKGRD: %s: _dump_buf_dif=0x%p file=%pD\n", + pr_err("9060 BLKGRD: %s: _dump_buf_dif=x%px file=%pD\n", __func__, _dump_buf_dif, file); debug->buffer = _dump_buf_dif; if (!debug->buffer) { diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 54ec7f0822e5..aaad1c74bb98 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -2140,7 +2140,7 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) !(vport->fc_flag & FC_OFFLINE_MODE)) { lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "4110 Issue PLOGI x%x deferred " - "on NPort x%x rpi x%x Data: %p\n", + "on NPort x%x rpi x%x Data: x%px\n", ndlp->nlp_defer_did, ndlp->nlp_DID, ndlp->nlp_rpi, ndlp); @@ -4236,7 +4236,7 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) mempool_free(pmb, phba->mbox_mem_pool); if (ndlp) { lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, - "0006 rpi%x DID:%x flg:%x %d map:%x %p\n", + "0006 rpi%x DID:%x flg:%x %d map:%x x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref), ndlp->nlp_usg_map, ndlp); diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index dc3763114d76..e7463d561f30 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -133,7 +133,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, - "3181 dev_loss_callbk x%06x, rport %p flg x%x\n", + "3181 dev_loss_callbk x%06x, rport x%px flg x%x\n", ndlp->nlp_DID, ndlp->rport, ndlp->nlp_flag); /* Don't defer this if we are in the process of deleting the vport @@ -237,7 +237,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ndlp->nlp_DID, ndlp->nlp_type, rport->scsi_target_id); lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, - "3182 dev_loss_tmo_handler x%06x, rport %p flg x%x\n", + "3182 dev_loss_tmo_handler x%06x, rport x%px flg x%x\n", ndlp->nlp_DID, ndlp->rport, ndlp->nlp_flag); /* @@ -3323,7 +3323,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) out: lpfc_vport_set_state(vport, FC_VPORT_FAILED); lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, - "0263 Discovery Mailbox error: state: 0x%x : %p %p\n", + "0263 Discovery Mailbox error: state: 0x%x : x%px x%px\n", vport->port_state, sparam_mbox, cfglink_mbox); lpfc_issue_clear_la(phba, vport); return; @@ -3535,7 +3535,7 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) pmb->ctx_ndlp = NULL; lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, - "0002 rpi:%x DID:%x flg:%x %d map:%x %p\n", + "0002 rpi:%x DID:%x flg:%x %d map:%x x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref), ndlp->nlp_usg_map, ndlp); @@ -4047,7 +4047,7 @@ out: ndlp->nlp_type |= NLP_FABRIC; lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, - "0003 rpi:%x DID:%x flg:%x %d map%x %p\n", + "0003 rpi:%x DID:%x flg:%x %d map%x x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref), ndlp->nlp_usg_map, ndlp); @@ -4166,7 +4166,7 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) fc_remote_port_rolechg(rport, rport_ids.roles); lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, - "3183 rport register x%06x, rport %p role x%x\n", + "3183 rport register x%06x, rport x%px role x%x\n", ndlp->nlp_DID, rport, rport_ids.roles); if ((rport->scsi_target_id != -1) && @@ -4190,7 +4190,7 @@ lpfc_unregister_remote_port(struct lpfc_nodelist *ndlp) ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, - "3184 rport unregister x%06x, rport %p\n", + "3184 rport unregister x%06x, rport x%px\n", ndlp->nlp_DID, rport); fc_remote_port_delete(rport); @@ -4509,9 +4509,9 @@ lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (NLP_CHK_FREE_REQ(ndlp)) { spin_unlock_irqrestore(&phba->ndlp_lock, flags); lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE, - "0277 lpfc_enable_node: ndlp:x%p " + "0277 %s: ndlp:x%px " "usgmap:x%x refcnt:%d\n", - (void *)ndlp, ndlp->nlp_usg_map, + __func__, (void *)ndlp, ndlp->nlp_usg_map, kref_read(&ndlp->kref)); goto free_rpi; } @@ -4519,9 +4519,9 @@ lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (NLP_CHK_NODE_ACT(ndlp)) { spin_unlock_irqrestore(&phba->ndlp_lock, flags); lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE, - "0278 lpfc_enable_node: ndlp:x%p " + "0278 %s: ndlp:x%px " "usgmap:x%x refcnt:%d\n", - (void *)ndlp, ndlp->nlp_usg_map, + __func__, (void *)ndlp, ndlp->nlp_usg_map, kref_read(&ndlp->kref)); goto free_rpi; } @@ -4551,7 +4551,7 @@ lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ndlp->nlp_rpi = rpi; lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, "0008 rpi:%x DID:%x flg:%x refcnt:%d " - "map:%x %p\n", ndlp->nlp_rpi, ndlp->nlp_DID, + "map:%x x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref), ndlp->nlp_usg_map, ndlp); @@ -4824,7 +4824,7 @@ lpfc_nlp_logo_unreg(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) (ndlp->nlp_defer_did != NLP_EVT_NOTHING_PENDING)) { lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "1434 UNREG cmpl deferred logo x%x " - "on NPort x%x Data: x%x %p\n", + "on NPort x%x Data: x%x x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_defer_did, ndlp); @@ -4874,7 +4874,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "1436 unreg_rpi SKIP UNREG x%x on " "NPort x%x deferred x%x flg x%x " - "Data: %p\n", + "Data: x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_defer_did, ndlp->nlp_flag, ndlp); @@ -4924,7 +4924,8 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "1433 unreg_rpi UNREG x%x on " - "NPort x%x deferred flg x%x Data:%p\n", + "NPort x%x deferred flg x%x " + "Data:x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, ndlp); @@ -5065,16 +5066,16 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ndlp->nlp_state, ndlp->nlp_rpi); if (NLP_CHK_FREE_REQ(ndlp)) { lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE, - "0280 lpfc_cleanup_node: ndlp:x%p " + "0280 %s: ndlp:x%px " "usgmap:x%x refcnt:%d\n", - (void *)ndlp, ndlp->nlp_usg_map, + __func__, (void *)ndlp, ndlp->nlp_usg_map, kref_read(&ndlp->kref)); lpfc_dequeue_node(vport, ndlp); } else { lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE, - "0281 lpfc_cleanup_node: ndlp:x%p " + "0281 %s: ndlp:x%px " "usgmap:x%x refcnt:%d\n", - (void *)ndlp, ndlp->nlp_usg_map, + __func__, (void *)ndlp, ndlp->nlp_usg_map, kref_read(&ndlp->kref)); lpfc_disable_node(vport, ndlp); } @@ -5165,7 +5166,7 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) * allocated by the firmware. */ lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, - "0005 rpi:%x DID:%x flg:%x %d map:%x %p\n", + "0005 rpi:%x DID:%x flg:%x %d map:%x x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref), ndlp->nlp_usg_map, ndlp); @@ -5201,8 +5202,8 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) * for registered rport so need to cleanup rport */ lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE, - "0940 removed node x%p DID x%x " - " rport not null %p\n", + "0940 removed node x%px DID x%x " + " rport not null x%px\n", ndlp, ndlp->nlp_DID, ndlp->rport); rport = ndlp->rport; rdata = rport->dd_data; @@ -5329,7 +5330,7 @@ lpfc_findnode_mapped(struct lpfc_vport *vport) spin_unlock_irqrestore(shost->host_lock, iflags); lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, "2025 FIND node DID " - "Data: x%p x%x x%x x%x %p\n", + "Data: x%px x%x x%x x%x x%px\n", ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1, ndlp->active_rrqs_xri_bitmap); @@ -5996,7 +5997,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ndlp->nlp_type |= NLP_FABRIC; lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, - "0004 rpi:%x DID:%x flg:%x %d map:%x %p\n", + "0004 rpi:%x DID:%x flg:%x %d map:%x x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref), ndlp->nlp_usg_map, ndlp); @@ -6050,8 +6051,8 @@ __lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param) list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { if (filter(ndlp, param)) { lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, - "3185 FIND node filter %p DID " - "ndlp %p did x%x flg x%x st x%x " + "3185 FIND node filter %pf DID " + "ndlp x%px did x%x flg x%x st x%x " "xri x%x type x%x rpi x%x\n", filter, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, @@ -6061,7 +6062,7 @@ __lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param) } } lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, - "3186 FIND node filter %p NOT FOUND.\n", filter); + "3186 FIND node filter %pf NOT FOUND.\n", filter); return NULL; } @@ -6186,7 +6187,7 @@ lpfc_nlp_init(struct lpfc_vport *vport, uint32_t did) ndlp->nlp_rpi = rpi; lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, "0007 rpi:%x DID:%x flg:%x refcnt:%d " - "map:%x %p\n", ndlp->nlp_rpi, ndlp->nlp_DID, + "map:%x x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref), ndlp->nlp_usg_map, ndlp); @@ -6224,8 +6225,9 @@ lpfc_nlp_release(struct kref *kref) ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, - "0279 lpfc_nlp_release: ndlp:x%p did %x " + "0279 %s: ndlp:x%px did %x " "usgmap:x%x refcnt:%d rpi:%x\n", + __func__, (void *)ndlp, ndlp->nlp_DID, ndlp->nlp_usg_map, kref_read(&ndlp->kref), ndlp->nlp_rpi); @@ -6272,9 +6274,9 @@ lpfc_nlp_get(struct lpfc_nodelist *ndlp) if (!NLP_CHK_NODE_ACT(ndlp) || NLP_CHK_FREE_ACK(ndlp)) { spin_unlock_irqrestore(&phba->ndlp_lock, flags); lpfc_printf_vlog(ndlp->vport, KERN_WARNING, LOG_NODE, - "0276 lpfc_nlp_get: ndlp:x%p " + "0276 %s: ndlp:x%px " "usgmap:x%x refcnt:%d\n", - (void *)ndlp, ndlp->nlp_usg_map, + __func__, (void *)ndlp, ndlp->nlp_usg_map, kref_read(&ndlp->kref)); return NULL; } else @@ -6300,9 +6302,9 @@ lpfc_nlp_put(struct lpfc_nodelist *ndlp) return 1; lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE, - "node put: did:x%x flg:x%x refcnt:x%x", - ndlp->nlp_DID, ndlp->nlp_flag, - kref_read(&ndlp->kref)); + "node put: did:x%x flg:x%x refcnt:x%x", + ndlp->nlp_DID, ndlp->nlp_flag, + kref_read(&ndlp->kref)); phba = ndlp->phba; spin_lock_irqsave(&phba->ndlp_lock, flags); /* Check the ndlp memory free acknowledge flag to avoid the @@ -6312,9 +6314,9 @@ lpfc_nlp_put(struct lpfc_nodelist *ndlp) if (NLP_CHK_FREE_ACK(ndlp)) { spin_unlock_irqrestore(&phba->ndlp_lock, flags); lpfc_printf_vlog(ndlp->vport, KERN_WARNING, LOG_NODE, - "0274 lpfc_nlp_put: ndlp:x%p " + "0274 %s: ndlp:x%px " "usgmap:x%x refcnt:%d\n", - (void *)ndlp, ndlp->nlp_usg_map, + __func__, (void *)ndlp, ndlp->nlp_usg_map, kref_read(&ndlp->kref)); return 1; } @@ -6325,9 +6327,9 @@ lpfc_nlp_put(struct lpfc_nodelist *ndlp) if (NLP_CHK_IACT_REQ(ndlp)) { spin_unlock_irqrestore(&phba->ndlp_lock, flags); lpfc_printf_vlog(ndlp->vport, KERN_WARNING, LOG_NODE, - "0275 lpfc_nlp_put: ndlp:x%p " + "0275 %s: ndlp:x%px " "usgmap:x%x refcnt:%d\n", - (void *)ndlp, ndlp->nlp_usg_map, + __func__, (void *)ndlp, ndlp->nlp_usg_map, kref_read(&ndlp->kref)); return 1; } diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 82a5166afe18..6b39bfb73104 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -2877,7 +2877,7 @@ lpfc_cleanup(struct lpfc_vport *vport) &vport->fc_nodes, nlp_listp) { lpfc_printf_vlog(ndlp->vport, KERN_ERR, LOG_NODE, - "0282 did:x%x ndlp:x%p " + "0282 did:x%x ndlp:x%px " "usgmap:x%x refcnt:%d\n", ndlp->nlp_DID, (void *)ndlp, ndlp->nlp_usg_map, @@ -3081,7 +3081,7 @@ lpfc_sli4_node_prep(struct lpfc_hba *phba) ndlp->nlp_rpi = rpi; lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, "0009 rpi:%x DID:%x " - "flg:%x map:%x %p\n", ndlp->nlp_rpi, + "flg:%x map:%x x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_usg_map, ndlp); } @@ -3505,7 +3505,7 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action) lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, "0011 lpfc_offline: " - "ndlp:x%p did %x " + "ndlp:x%px did %x " "usgmap:x%x rpi:%x\n", ndlp, ndlp->nlp_DID, ndlp->nlp_usg_map, @@ -7620,7 +7620,7 @@ lpfc_setup_bg(struct lpfc_hba *phba, struct Scsi_Host *shost) if (_dump_buf_data) { lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9043 BLKGRD: allocated %d pages for " - "_dump_buf_data at 0x%p\n", + "_dump_buf_data at x%px\n", (1 << pagecnt), _dump_buf_data); _dump_buf_data_order = pagecnt; memset(_dump_buf_data, 0, @@ -7635,7 +7635,7 @@ lpfc_setup_bg(struct lpfc_hba *phba, struct Scsi_Host *shost) "memory for hexdump\n"); } else lpfc_printf_log(phba, KERN_ERR, LOG_BG, - "9045 BLKGRD: already allocated _dump_buf_data=0x%p" + "9045 BLKGRD: already allocated _dump_buf_data=x%px" "\n", _dump_buf_data); if (!_dump_buf_dif) { while (pagecnt) { @@ -7644,7 +7644,7 @@ lpfc_setup_bg(struct lpfc_hba *phba, struct Scsi_Host *shost) if (_dump_buf_dif) { lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9046 BLKGRD: allocated %d pages for " - "_dump_buf_dif at 0x%p\n", + "_dump_buf_dif at x%px\n", (1 << pagecnt), _dump_buf_dif); _dump_buf_dif_order = pagecnt; memset(_dump_buf_dif, 0, @@ -7659,7 +7659,7 @@ lpfc_setup_bg(struct lpfc_hba *phba, struct Scsi_Host *shost) "memory for hexdump\n"); } else lpfc_printf_log(phba, KERN_ERR, LOG_BG, - "9048 BLKGRD: already allocated _dump_buf_dif=0x%p\n", + "9048 BLKGRD: already allocated _dump_buf_dif=x%px\n", _dump_buf_dif); } @@ -13573,14 +13573,14 @@ lpfc_exit(void) fc_release_transport(lpfc_vport_transport_template); if (_dump_buf_data) { printk(KERN_ERR "9062 BLKGRD: freeing %lu pages for " - "_dump_buf_data at 0x%p\n", + "_dump_buf_data at x%px\n", (1L << _dump_buf_data_order), _dump_buf_data); free_pages((unsigned long)_dump_buf_data, _dump_buf_data_order); } if (_dump_buf_dif) { printk(KERN_ERR "9049 BLKGRD: freeing %lu pages for " - "_dump_buf_dif at 0x%p\n", + "_dump_buf_dif at x%px\n", (1L << _dump_buf_dif_order), _dump_buf_dif); free_pages((unsigned long)_dump_buf_dif, _dump_buf_dif_order); } diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index f4eea52c66f5..41ac07b99739 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -885,7 +885,7 @@ lpfc_release_rpi(struct lpfc_hba *phba, struct lpfc_vport *vport, lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "1435 release_rpi SKIP UNREG x%x on " "NPort x%x deferred x%x flg x%x " - "Data: %p\n", + "Data: x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_defer_did, ndlp->nlp_flag, ndlp); diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 106aef82620d..b599ddc40c6b 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -247,7 +247,7 @@ lpfc_nvme_create_queue(struct nvme_fc_local_port *pnvme_lport, lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME, "6073 Binding %s HdwQueue %d (cpu %d) to " - "hdw_queue %d qhandle %p\n", str, + "hdw_queue %d qhandle x%px\n", str, qidx, qhandle->cpu_id, qhandle->index, qhandle); *handle = (void *)qhandle; return 0; @@ -282,7 +282,7 @@ lpfc_nvme_delete_queue(struct nvme_fc_local_port *pnvme_lport, vport = lport->vport; lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME, - "6001 ENTER. lpfc_pnvme %p, qidx x%x qhandle %p\n", + "6001 ENTER. lpfc_pnvme x%px, qidx x%x qhandle x%px\n", lport, qidx, handle); kfree(handle); } @@ -293,7 +293,7 @@ lpfc_nvme_localport_delete(struct nvme_fc_local_port *localport) struct lpfc_nvme_lport *lport = localport->private; lpfc_printf_vlog(lport->vport, KERN_INFO, LOG_NVME, - "6173 localport %p delete complete\n", + "6173 localport x%px delete complete\n", lport); /* release any threads waiting for the unreg to complete */ @@ -332,7 +332,7 @@ lpfc_nvme_remoteport_delete(struct nvme_fc_remote_port *remoteport) * calling state machine to remove the node. */ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, - "6146 remoteport delete of remoteport %p\n", + "6146 remoteport delete of remoteport x%px\n", remoteport); spin_lock_irq(&vport->phba->hbalock); @@ -383,8 +383,8 @@ lpfc_nvme_cmpl_gen_req(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, ndlp = (struct lpfc_nodelist *)cmdwqe->context1; lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, "6047 nvme cmpl Enter " - "Data %p DID %x Xri: %x status %x reason x%x cmd:%p " - "lsreg:%p bmp:%p ndlp:%p\n", + "Data %px DID %x Xri: %x status %x reason x%x " + "cmd:x%px lsreg:x%px bmp:x%px ndlp:x%px\n", pnvme_lsreq, ndlp ? ndlp->nlp_DID : 0, cmdwqe->sli4_xritag, status, (wcqe->parameter & 0xffff), @@ -404,7 +404,7 @@ lpfc_nvme_cmpl_gen_req(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, else lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC, "6046 nvme cmpl without done call back? " - "Data %p DID %x Xri: %x status %x\n", + "Data %px DID %x Xri: %x status %x\n", pnvme_lsreq, ndlp ? ndlp->nlp_DID : 0, cmdwqe->sli4_xritag, status); if (ndlp) { @@ -517,7 +517,8 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, /* Issue GEN REQ WQE for NPORT */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "6050 Issue GEN REQ WQE to NPORT x%x " - "Data: x%x x%x wq:%p lsreq:%p bmp:%p xmit:%d 1st:%d\n", + "Data: x%x x%x wq:x%px lsreq:x%px bmp:x%px " + "xmit:%d 1st:%d\n", ndlp->nlp_DID, genwqe->iotag, vport->port_state, genwqe, pnvme_lsreq, bmp, xmit_len, first_len); @@ -595,7 +596,7 @@ lpfc_nvme_ls_req(struct nvme_fc_local_port *pnvme_lport, ndlp = rport->ndlp; if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE | LOG_NVME_IOERR, - "6051 Remoteport %p, rport has invalid ndlp. " + "6051 Remoteport x%px, rport has invalid ndlp. " "Failing LS Req\n", pnvme_rport); return -ENODEV; } @@ -647,10 +648,10 @@ lpfc_nvme_ls_req(struct nvme_fc_local_port *pnvme_lport, /* Expand print to include key fields. */ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, - "6149 Issue LS Req to DID 0x%06x lport %p, rport %p " - "lsreq%p rqstlen:%d rsplen:%d %pad %pad\n", - ndlp->nlp_DID, - pnvme_lport, pnvme_rport, + "6149 Issue LS Req to DID 0x%06x lport x%px, " + "rport x%px lsreq x%px rqstlen:%d rsplen:%d " + "%pad %pad\n", + ndlp->nlp_DID, pnvme_lport, pnvme_rport, pnvme_lsreq, pnvme_lsreq->rqstlen, pnvme_lsreq->rsplen, &pnvme_lsreq->rqstdma, &pnvme_lsreq->rspdma); @@ -666,8 +667,8 @@ lpfc_nvme_ls_req(struct nvme_fc_local_port *pnvme_lport, if (ret != WQE_SUCCESS) { atomic_inc(&lport->xmt_ls_err); lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC, - "6052 EXIT. issue ls wqe failed lport %p, " - "rport %p lsreq%p Status %x DID %x\n", + "6052 EXIT. issue ls wqe failed lport x%px, " + "rport x%px lsreq x%px Status %x DID %x\n", pnvme_lport, pnvme_rport, pnvme_lsreq, ret, ndlp->nlp_DID); lpfc_mbuf_free(vport->phba, bmp->virt, bmp->phys); @@ -724,7 +725,7 @@ lpfc_nvme_ls_abort(struct nvme_fc_local_port *pnvme_lport, /* Expand print to include key fields. */ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_ABTS, - "6040 ENTER. lport %p, rport %p lsreq %p rqstlen:%d " + "6040 ENTER. lport x%px, rport x%px lsreq x%px rqstlen:%d " "rsplen:%d %pad %pad\n", pnvme_lport, pnvme_rport, pnvme_lsreq, pnvme_lsreq->rqstlen, @@ -985,8 +986,8 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, if (!lpfc_ncmd->nvmeCmd) { spin_unlock(&lpfc_ncmd->buf_lock); lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE | LOG_NVME_IOERR, - "6066 Missing cmpl ptrs: lpfc_ncmd %p, " - "nvmeCmd %p\n", + "6066 Missing cmpl ptrs: lpfc_ncmd x%px, " + "nvmeCmd x%px\n", lpfc_ncmd, lpfc_ncmd->nvmeCmd); /* Release the lpfc_ncmd regardless of the missing elements. */ @@ -1101,8 +1102,8 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, if (lpfc_ncmd->result == IOERR_ABORT_REQUESTED) lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR, - "6032 Delay Aborted cmd %p " - "nvme cmd %p, xri x%x, " + "6032 Delay Aborted cmd x%px " + "nvme cmd x%px, xri x%x, " "xb %d\n", lpfc_ncmd, nCmd, lpfc_ncmd->cur_iocbq.sli4_xritag, @@ -1506,8 +1507,8 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport, ndlp = rport->ndlp; if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_NVME_IOERR, - "6053 Fail IO, ndlp not ready: rport %p " - "ndlp %p, DID x%06x\n", + "6053 Busy IO, ndlp not ready: rport x%px " + "ndlp x%px, DID x%06x\n", rport, ndlp, pnvme_rport->port_id); atomic_inc(&lport->xmt_fcp_err); ret = -EBUSY; @@ -1759,7 +1760,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, /* Announce entry to new IO submit field. */ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_ABTS, "6002 Abort Request to rport DID x%06x " - "for nvme_fc_req %p\n", + "for nvme_fc_req x%px\n", pnvme_rport->port_id, pnvme_fcreq); @@ -1806,8 +1807,8 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, if (lpfc_nbuf->nvmeCmd != pnvme_fcreq) { lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS, "6143 NVME req mismatch: " - "lpfc_nbuf %p nvmeCmd %p, " - "pnvme_fcreq %p. Skipping Abort xri x%x\n", + "lpfc_nbuf x%px nvmeCmd x%px, " + "pnvme_fcreq x%px. Skipping Abort xri x%x\n", lpfc_nbuf, lpfc_nbuf->nvmeCmd, pnvme_fcreq, nvmereq_wqe->sli4_xritag); goto out_unlock; @@ -1816,7 +1817,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, /* Don't abort IOs no longer on the pending queue. */ if (!(nvmereq_wqe->iocb_flag & LPFC_IO_ON_TXCMPLQ)) { lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS, - "6142 NVME IO req %p not queued - skipping " + "6142 NVME IO req x%px not queued - skipping " "abort req xri x%x\n", pnvme_fcreq, nvmereq_wqe->sli4_xritag); goto out_unlock; @@ -1831,8 +1832,8 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, if (nvmereq_wqe->iocb_flag & LPFC_DRIVER_ABORTED) { lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS, "6144 Outstanding NVME I/O Abort Request " - "still pending on nvme_fcreq %p, " - "lpfc_ncmd %p xri x%x\n", + "still pending on nvme_fcreq x%px, " + "lpfc_ncmd %px xri x%x\n", pnvme_fcreq, lpfc_nbuf, nvmereq_wqe->sli4_xritag); goto out_unlock; @@ -1842,7 +1843,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, if (!abts_buf) { lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS, "6136 No available abort wqes. Skipping " - "Abts req for nvme_fcreq %p xri x%x\n", + "Abts req for nvme_fcreq x%px xri x%x\n", pnvme_fcreq, nvmereq_wqe->sli4_xritag); goto out_unlock; } @@ -1893,7 +1894,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, if (ret_val) { lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS, "6137 Failed abts issue_wqe with status x%x " - "for nvme_fcreq %p.\n", + "for nvme_fcreq x%px.\n", ret_val, pnvme_fcreq); lpfc_sli_release_iocbq(phba, abts_buf); return; @@ -2096,8 +2097,8 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport) if (!ret) { lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME | LOG_NVME_DISC, "6005 Successfully registered local " - "NVME port num %d, localP %p, private %p, " - "sg_seg %d\n", + "NVME port num %d, localP x%px, private " + "x%px, sg_seg %d\n", localport->port_num, localport, localport->private, lpfc_nvme_template.max_sgl_segments); @@ -2165,7 +2166,7 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport, pending += pring->txcmplq_cnt; } lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_IOERR, - "6176 Lport %p Localport %p wait " + "6176 Lport x%px Localport x%px wait " "timed out. Pending %d. Renewing.\n", lport, vport->localport, pending); continue; @@ -2173,7 +2174,7 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport, break; } lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR, - "6177 Lport %p Localport %p Complete Success\n", + "6177 Lport x%px Localport x%px Complete Success\n", lport, vport->localport); } #endif @@ -2204,7 +2205,7 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport) lport = (struct lpfc_nvme_lport *)localport->private; lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME, - "6011 Destroying NVME localport %p\n", + "6011 Destroying NVME localport x%px\n", localport); /* lport's rport list is clear. Unregister @@ -2254,12 +2255,12 @@ lpfc_nvme_update_localport(struct lpfc_vport *vport) lport = (struct lpfc_nvme_lport *)localport->private; if (!lport) { lpfc_printf_vlog(vport, KERN_WARNING, LOG_NVME, - "6171 Update NVME fail. localP %p, No lport\n", + "6171 Update NVME fail. localP x%px, No lport\n", localport); return; } lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME, - "6012 Update NVME lport %p did x%x\n", + "6012 Update NVME lport x%px did x%x\n", localport, vport->fc_myDID); localport->port_id = vport->fc_myDID; @@ -2269,7 +2270,7 @@ lpfc_nvme_update_localport(struct lpfc_vport *vport) localport->port_role = FC_PORT_ROLE_NVME_INITIATOR; lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, - "6030 bound lport %p to DID x%06x\n", + "6030 bound lport x%px to DID x%06x\n", lport, localport->port_id); #endif } @@ -2350,8 +2351,9 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NVME_DISC, "6014 Rebind lport to current " - "remoteport %p wwpn 0x%llx, " - "Data: x%x x%x %p %p x%x x%06x\n", + "remoteport x%px wwpn 0x%llx, " + "Data: x%x x%x x%px x%px x%x " + " x%06x\n", remote_port, remote_port->port_name, remote_port->port_id, @@ -2406,7 +2408,7 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) "6022 Bind lport x%px to remoteport x%px " "rport x%px WWNN 0x%llx, " "Rport WWPN 0x%llx DID " - "x%06x Role x%x, ndlp %p prev_ndlp %p\n", + "x%06x Role x%x, ndlp %p prev_ndlp x%px\n", lport, remote_port, rport, rpinfo.node_name, rpinfo.port_name, rpinfo.port_id, rpinfo.port_role, @@ -2515,7 +2517,7 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) goto input_err; lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, - "6033 Unreg nvme remoteport %p, portname x%llx, " + "6033 Unreg nvme remoteport x%px, portname x%llx, " "port_id x%06x, portstate x%x port type x%x\n", remoteport, remoteport->port_name, remoteport->port_id, remoteport->port_state, @@ -2553,7 +2555,7 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) input_err: #endif lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC, - "6168 State error: lport %p, rport%p FCID x%06x\n", + "6168 State error: lport x%px, rport x%px FCID x%06x\n", vport->localport, ndlp->rport, ndlp->nlp_DID); } @@ -2597,7 +2599,7 @@ lpfc_sli4_nvme_xri_aborted(struct lpfc_hba *phba, lpfc_sli4_abts_err_handler(phba, ndlp, axri); lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS, - "6311 nvme_cmd %p xri x%x tag x%x " + "6311 nvme_cmd x%px xri x%x tag x%x " "abort complete and xri released\n", lpfc_ncmd->nvmeCmd, xri, lpfc_ncmd->cur_iocbq.iotag); diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index f42cc3150c6f..253a9fdd245e 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -1437,7 +1437,7 @@ lpfc_nvmet_setup_io_context(struct lpfc_hba *phba) infop = lpfc_get_ctx_list(phba, i, j); lpfc_printf_log(phba, KERN_INFO, LOG_NVME | LOG_INIT, "6408 TOTAL NVMET ctx for CPU %d " - "MRQ %d: cnt %d nextcpu %p\n", + "MRQ %d: cnt %d nextcpu x%px\n", i, j, infop->nvmet_ctx_list_cnt, infop->nvmet_ctx_next_cpu); } @@ -1500,7 +1500,7 @@ lpfc_nvmet_create_targetport(struct lpfc_hba *phba) lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC, "6026 Registered NVME " - "targetport: %p, private %p " + "targetport: x%px, private x%px " "portnm %llx nodenm %llx segs %d qs %d\n", phba->targetport, tgtp, pinfo.port_name, pinfo.node_name, @@ -1555,7 +1555,7 @@ lpfc_nvmet_update_targetport(struct lpfc_hba *phba) return 0; lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME, - "6007 Update NVMET port %p did x%x\n", + "6007 Update NVMET port x%px did x%x\n", phba->targetport, vport->fc_myDID); phba->targetport->port_id = vport->fc_myDID; @@ -1926,7 +1926,7 @@ lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba) if (!wait_for_completion_timeout(tgtp->tport_unreg_cmp, msecs_to_jiffies(LPFC_NVMET_WAIT_TMO))) lpfc_printf_log(phba, KERN_ERR, LOG_NVME, - "6179 Unreg targetport %p timeout " + "6179 Unreg targetport x%px timeout " "reached.\n", phba->targetport); lpfc_nvmet_cleanup_io_context(phba); } @@ -3109,7 +3109,7 @@ lpfc_nvmet_xmt_ls_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, atomic_inc(&tgtp->xmt_ls_abort_cmpl); lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS, - "6083 Abort cmpl: ctx %p WCQE:%08x %08x %08x %08x\n", + "6083 Abort cmpl: ctx x%px WCQE:%08x %08x %08x %08x\n", ctxp, wcqe->word0, wcqe->total_data_placed, result, wcqe->word3); diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 8ae24500806e..95ba5000d0ec 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -1775,7 +1775,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, if (!sgpe || !sgde) { lpfc_printf_log(phba, KERN_ERR, LOG_FCP, - "9020 Invalid s/g entry: data=0x%p prot=0x%p\n", + "9020 Invalid s/g entry: data=x%px prot=x%px\n", sgpe, sgde); return 0; } @@ -2154,7 +2154,7 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, if (!sgpe || !sgde) { lpfc_printf_log(phba, KERN_ERR, LOG_FCP, - "9082 Invalid s/g entry: data=0x%p prot=0x%p\n", + "9082 Invalid s/g entry: data=x%px prot=x%px\n", sgpe, sgde); return 0; } @@ -3873,7 +3873,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, uint32_t *lp = (uint32_t *)cmd->sense_buffer; lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, - "0710 Iodone <%d/%llu> cmd %p, error " + "0710 Iodone <%d/%llu> cmd x%px, error " "x%x SNS x%x x%x Data: x%x x%x\n", cmd->device->id, cmd->device->lun, cmd, cmd->result, *lp, *(lp + 3), cmd->retries, @@ -4997,7 +4997,7 @@ lpfc_chk_tgt_mapped(struct lpfc_vport *vport, struct scsi_cmnd *cmnd) rdata = lpfc_rport_data_from_scsi_device(cmnd->device); if (!rdata) { lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, - "0797 Tgt Map rport failure: rdata x%p\n", rdata); + "0797 Tgt Map rport failure: rdata x%px\n", rdata); return FAILED; } pnode = rdata->pnode; @@ -5095,7 +5095,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) rdata = lpfc_rport_data_from_scsi_device(cmnd->device); if (!rdata || !rdata->pnode) { lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, - "0798 Device Reset rdata failure: rdata x%p\n", + "0798 Device Reset rdata failure: rdata x%px\n", rdata); return FAILED; } @@ -5107,7 +5107,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) status = lpfc_chk_tgt_mapped(vport, cmnd); if (status == FAILED) { lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, - "0721 Device Reset rport failure: rdata x%p\n", rdata); + "0721 Device Reset rport failure: rdata x%px\n", rdata); return FAILED; } @@ -5166,7 +5166,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) rdata = lpfc_rport_data_from_scsi_device(cmnd->device); if (!rdata || !rdata->pnode) { lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, - "0799 Target Reset rdata failure: rdata x%p\n", + "0799 Target Reset rdata failure: rdata x%px\n", rdata); return FAILED; } @@ -5178,7 +5178,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) status = lpfc_chk_tgt_mapped(vport, cmnd); if (status == FAILED) { lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, - "0722 Target Reset rport failure: rdata x%p\n", rdata); + "0722 Target Reset rport failure: rdata x%px\n", rdata); if (pnode) { spin_lock_irq(shost->host_lock); pnode->nlp_flag &= ~NLP_NPR_ADISC; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index a21fe4612a4e..03404dbd6ddf 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2514,7 +2514,7 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) vport, KERN_INFO, LOG_MBOX | LOG_DISCOVERY, "1438 UNREG cmpl deferred mbox x%x " - "on NPort x%x Data: x%x x%x %p\n", + "on NPort x%x Data: x%x x%x %px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_defer_did, ndlp); @@ -2572,7 +2572,7 @@ lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) vport, KERN_INFO, LOG_MBOX | LOG_SLI, "0010 UNREG_LOGIN vpi:%x " "rpi:%x DID:%x defer x%x flg x%x " - "map:%x %p\n", + "map:%x %px\n", vport->vpi, ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_defer_did, ndlp->nlp_flag, @@ -2590,7 +2590,7 @@ lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) vport, KERN_INFO, LOG_DISCOVERY, "4111 UNREG cmpl deferred " "clr x%x on " - "NPort x%x Data: x%x %p\n", + "NPort x%x Data: x%x x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_defer_did, ndlp); ndlp->nlp_flag &= ~NLP_UNREG_INP; @@ -2712,7 +2712,7 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba) /* Mailbox cmd Cmpl */ lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "(%d):0307 Mailbox cmd x%x (x%x/x%x) Cmpl x%p " + "(%d):0307 Mailbox cmd x%x (x%x/x%x) Cmpl %pf " "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x " "x%x x%x x%x\n", pmb->vport ? pmb->vport->vpi : 0, @@ -7991,7 +7991,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) /* Mbox cmd timeout */ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, - "0310 Mailbox command x%x timeout Data: x%x x%x x%p\n", + "0310 Mailbox command x%x timeout Data: x%x x%x x%px\n", mb->mbxCommand, phba->pport->port_state, phba->sli.sli_flag, @@ -10998,7 +10998,7 @@ lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, spin_unlock_irq(&phba->hbalock); lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0402 Cannot find virtual addr for buffer tag on " - "ring %d Data x%lx x%p x%p x%x\n", + "ring %d Data x%lx x%px x%px x%x\n", pring->ringno, (unsigned long) tag, slp->next, slp->prev, pring->postbufq_cnt); @@ -11042,7 +11042,7 @@ lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, spin_unlock_irq(&phba->hbalock); lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0410 Cannot find virtual addr for mapped buf on " - "ring %d Data x%llx x%p x%p x%x\n", + "ring %d Data x%llx x%px x%px x%x\n", pring->ringno, (unsigned long long)phys, slp->next, slp->prev, pring->postbufq_cnt); return NULL; @@ -11097,7 +11097,7 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, abort_iocb = phba->sli.iocbq_lookup[abort_context]; lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_SLI, - "0327 Cannot abort els iocb %p " + "0327 Cannot abort els iocb x%px " "with tag %x context %x, abort status %x, " "abort code %x\n", abort_iocb, abort_iotag, abort_context, -- cgit v1.2.3-59-g8ed1b From ec76242f3be73e5cbb950a7ac99d4fba7e226e2e Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:57:07 -0700 Subject: scsi: lpfc: Add first and second level hardware revisions to sysfs reporting To aid better hardware detection when there are issues, report the first and second level hardware revisions from the READ_REV command. Add the elements to the existing hardware id string. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 798ec5f3a2c7..0a8caa12a30d 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -841,7 +841,8 @@ lpfc_hdw_show(struct device *dev, struct device_attribute *attr, char *buf) lpfc_vpd_t *vp = &phba->vpd; lpfc_jedec_to_ascii(vp->rev.biuRev, hdw); - return scnprintf(buf, PAGE_SIZE, "%s\n", hdw); + return scnprintf(buf, PAGE_SIZE, "%s %08x %08x\n", hdw, + vp->rev.smRev, vp->rev.smFwRev); } /** -- cgit v1.2.3-59-g8ed1b From e62245d923caebc02582b12ce861c3d780b4106f Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:57:08 -0700 Subject: scsi: lpfc: Add MDS driver loopback diagnostics support Added code to support driver loopback with MDS Diagnostics. This style of diagnostics passes frames from the fabric to the driver who then echo them back out the link. SEND_FRAME WQEs are used to transmit the frames. Added the SOF and EOF field location definitions for use by SEND_FRAME. Also ensure that enable_mds_diags is a RW parameter. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 2 +- drivers/scsi/lpfc/lpfc_els.c | 11 ++++++----- drivers/scsi/lpfc/lpfc_hw4.h | 6 ++++++ drivers/scsi/lpfc/lpfc_sli.c | 30 +++++++++++++++++++++++++----- 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 0a8caa12a30d..bd7a72f6cdbe 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -5912,7 +5912,7 @@ lpfc_sg_seg_cnt_init(struct lpfc_hba *phba, int val) * 1 = MDS Diagnostics enabled * Value range is [0,1]. Default value is 0. */ -LPFC_ATTR_R(enable_mds_diags, 0, 0, 1, "Enable MDS Diagnostics"); +LPFC_ATTR_RW(enable_mds_diags, 0, 0, 1, "Enable MDS Diagnostics"); /* * lpfc_ras_fwlog_buffsize: Firmware logging host buffer size diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index aaad1c74bb98..30bbfa3f6086 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1052,17 +1052,18 @@ stop_rr_fcf_flogi: if (lpfc_els_retry(phba, cmdiocb, rspiocb)) goto out; + lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS, + "0150 FLOGI failure Status:x%x/x%x " + "xri x%x TMO:x%x\n", + irsp->ulpStatus, irsp->un.ulpWord[4], + cmdiocb->sli4_xritag, irsp->ulpTimeout); + /* If this is not a loop open failure, bail out */ if (!(irsp->ulpStatus == IOSTAT_LOCAL_REJECT && ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) == IOERR_LOOP_OPEN_FAILURE))) goto flogifail; - lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS, - "0150 FLOGI failure Status:x%x/x%x xri x%x TMO:x%x\n", - irsp->ulpStatus, irsp->un.ulpWord[4], - cmdiocb->sli4_xritag, irsp->ulpTimeout); - /* FLOGI failed, so there is no fabric */ spin_lock_irq(shost->host_lock); vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 77f9a55a3f54..d89480b9eade 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -4314,6 +4314,12 @@ struct wqe_common { #define wqe_rcvoxid_SHIFT 16 #define wqe_rcvoxid_MASK 0x0000FFFF #define wqe_rcvoxid_WORD word9 +#define wqe_sof_SHIFT 24 +#define wqe_sof_MASK 0x000000FF +#define wqe_sof_WORD word9 +#define wqe_eof_SHIFT 16 +#define wqe_eof_MASK 0x000000FF +#define wqe_eof_WORD word9 uint32_t word10; #define wqe_ebde_cnt_SHIFT 0 #define wqe_ebde_cnt_MASK 0x0000000f diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 03404dbd6ddf..940dd82a265b 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -9352,11 +9352,9 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, memset(wqe, 0, sizeof(union lpfc_wqe128)); /* Some of the fields are in the right position already */ memcpy(wqe, &iocbq->iocb, sizeof(union lpfc_wqe)); - if (iocbq->iocb.ulpCommand != CMD_SEND_FRAME) { - /* The ct field has moved so reset */ - wqe->generic.wqe_com.word7 = 0; - wqe->generic.wqe_com.word10 = 0; - } + /* The ct field has moved so reset */ + wqe->generic.wqe_com.word7 = 0; + wqe->generic.wqe_com.word10 = 0; abort_tag = (uint32_t) iocbq->iotag; xritag = iocbq->sli4_xritag; @@ -9862,6 +9860,15 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, break; case CMD_SEND_FRAME: + bf_set(wqe_cmnd, &wqe->generic.wqe_com, CMD_SEND_FRAME); + bf_set(wqe_sof, &wqe->generic.wqe_com, 0x2E); /* SOF byte */ + bf_set(wqe_eof, &wqe->generic.wqe_com, 0x41); /* EOF byte */ + bf_set(wqe_lenloc, &wqe->generic.wqe_com, 1); + bf_set(wqe_xbl, &wqe->generic.wqe_com, 1); + bf_set(wqe_dbde, &wqe->generic.wqe_com, 1); + bf_set(wqe_xc, &wqe->generic.wqe_com, 1); + bf_set(wqe_cmd_type, &wqe->generic.wqe_com, 0xA); + bf_set(wqe_cqid, &wqe->generic.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag); bf_set(wqe_reqtag, &wqe->generic.wqe_com, iocbq->iotag); return 0; @@ -16940,6 +16947,8 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr) struct fc_vft_header *fc_vft_hdr; uint32_t *header = (uint32_t *) fc_hdr; +#define FC_RCTL_MDS_DIAGS 0xF4 + switch (fc_hdr->fh_r_ctl) { case FC_RCTL_DD_UNCAT: /* uncategorized information */ case FC_RCTL_DD_SOL_DATA: /* solicited data */ @@ -17949,6 +17958,17 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba, fcfi = bf_get(lpfc_rcqe_fcf_id, &dmabuf->cq_event.cqe.rcqe_cmpl); + if (fc_hdr->fh_r_ctl == 0xF4 && fc_hdr->fh_type == 0xFF) { + vport = phba->pport; + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "2023 MDS Loopback %d bytes\n", + bf_get(lpfc_rcqe_length, + &dmabuf->cq_event.cqe.rcqe_cmpl)); + /* Handle MDS Loopback frames */ + lpfc_sli4_handle_mds_loopback(vport, dmabuf); + return; + } + /* d_id this frame is directed to */ did = sli4_did_from_fc_hdr(fc_hdr); -- cgit v1.2.3-59-g8ed1b From d79c9e9d4b3d9330ee38f392a7c98e0fc494f7f8 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:57:09 -0700 Subject: scsi: lpfc: Support dynamic unbounded SGL lists on G7 hardware. Typical SLI-4 hardware supports up to 2 4KB pages to be registered per XRI to contain the exchanges Scatter/Gather List. This caps the number of SGL elements that can be in the SGL. There are not extensions to extend the list out of the 2 pages. The G7 hardware adds a SGE type that allows the SGL to be vectored to a different scatter/gather list segment. And that segment can contain a SGE to go to another segment and so on. The initial segment must still be pre-registered for the XRI, but it can be a much smaller amount (256Bytes) as it can now be dynamically grown. This much smaller allocation can handle the SG list for most normal I/O, and the dynamic aspect allows it to support many MB's if needed. The implementation creates a pool which contains "segments" and which is initially sized to hold the initial small segment per xri. If an I/O requires additional segments, they are allocated from the pool. If the pool has no more segments, the pool is grown based on what is now needed. After the I/O completes, the additional segments are returned to the pool for use by other I/Os. Once allocated, the additional segments are not released under the assumption of "if needed once, it will be needed again". Pools are kept on a per-hardware queue basis, which is typically 1:1 per cpu, but may be shared by multiple cpus. The switch to the smaller initial allocation significantly reduces the memory footprint of the driver (which only grows if large ios are issued). Based on the several K of XRIs for the adapter, the 8KB->256B reduction can conserve 32MBs or more. It has been observed with per-cpu resource pools that allocating a resource on CPU A, may be put back on CPU B. While the get routines are distributed evenly, only a limited subset of CPUs may be handling the put routines. This can put a strain on the lpfc_put_cmd_rsp_buf_per_cpu routine because all the resources are being put on a limited subset of CPUs. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 5 + drivers/scsi/lpfc/lpfc_hw4.h | 20 +++ drivers/scsi/lpfc/lpfc_init.c | 313 +++++++++++++++++++++++-------------- drivers/scsi/lpfc/lpfc_mem.c | 44 ++---- drivers/scsi/lpfc/lpfc_nvme.c | 94 ++++++++--- drivers/scsi/lpfc/lpfc_scsi.c | 355 ++++++++++++++++++++++++++++++++---------- drivers/scsi/lpfc/lpfc_sli.c | 292 ++++++++++++++++++++++++++++++++++ drivers/scsi/lpfc/lpfc_sli.h | 11 +- drivers/scsi/lpfc/lpfc_sli4.h | 18 +++ 9 files changed, 904 insertions(+), 248 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 2c3bb8a966e5..b738639fdf3f 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -51,6 +51,8 @@ struct lpfc_sli2_slim; cmnd for menlo needs nearly twice as for firmware downloads using bsg */ +#define LPFC_DEFAULT_XPSGL_SIZE 256 +#define LPFC_MAX_SG_TABLESIZE 0xffff #define LPFC_MIN_SG_SLI4_BUF_SZ 0x800 /* based on LPFC_DEFAULT_SG_SEG_CNT */ #define LPFC_MAX_BG_SLI4_SEG_CNT_DIF 128 /* sg element count for BlockGuard */ #define LPFC_MAX_SG_SEG_CNT_DIF 512 /* sg element count per scsi cmnd */ @@ -799,6 +801,7 @@ struct lpfc_hba { /* HBA Config Parameters */ uint32_t cfg_ack0; uint32_t cfg_xri_rebalancing; + uint32_t cfg_xpsgl; uint32_t cfg_enable_npiv; uint32_t cfg_enable_rrq; uint32_t cfg_topology; @@ -904,6 +907,7 @@ struct lpfc_hba { wait_queue_head_t work_waitq; struct task_struct *worker_thread; unsigned long data_flags; + uint32_t border_sge_num; uint32_t hbq_in_use; /* HBQs in use flag */ uint32_t hbq_count; /* Count of configured HBQs */ @@ -986,6 +990,7 @@ struct lpfc_hba { struct dma_pool *lpfc_nvmet_drb_pool; /* data receive buffer pool */ struct dma_pool *lpfc_hbq_pool; /* SLI3 hbq buffer pool */ struct dma_pool *txrdy_payload_pool; + struct dma_pool *lpfc_cmd_rsp_buf_pool; struct lpfc_dma_pool lpfc_mbuf_safety_pool; mempool_t *mbox_mem_pool; diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index d89480b9eade..e198de8eda32 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -2050,6 +2050,23 @@ struct sli4_sge { /* SLI-4 */ uint32_t sge_len; }; +struct sli4_hybrid_sgl { + struct list_head list_node; + struct sli4_sge *dma_sgl; + dma_addr_t dma_phys_sgl; +}; + +struct fcp_cmd_rsp_buf { + struct list_head list_node; + + /* for storing cmd/rsp dma alloc'ed virt_addr */ + struct fcp_cmnd *fcp_cmnd; + struct fcp_rsp *fcp_rsp; + + /* for storing this cmd/rsp's dma mapped phys addr from per CPU pool */ + dma_addr_t fcp_cmd_rsp_dma_handle; +}; + struct sli4_sge_diseed { /* SLI-4 */ uint32_t ref_tag; uint32_t ref_tag_tran; @@ -3449,6 +3466,9 @@ struct lpfc_sli4_parameters { #define cfg_xib_SHIFT 4 #define cfg_xib_MASK 0x00000001 #define cfg_xib_WORD word19 +#define cfg_xpsgl_SHIFT 6 +#define cfg_xpsgl_MASK 0x00000001 +#define cfg_xpsgl_WORD word19 #define cfg_eqdr_SHIFT 8 #define cfg_eqdr_MASK 0x00000001 #define cfg_eqdr_WORD word19 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 6b39bfb73104..fa3741f12089 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -3650,6 +3650,9 @@ lpfc_io_free(struct lpfc_hba *phba) qp->put_io_bufs--; dma_pool_free(phba->lpfc_sg_dma_buf_pool, lpfc_ncmd->data, lpfc_ncmd->dma_handle); + if (phba->cfg_xpsgl && !phba->nvmet_support) + lpfc_put_sgl_per_hdwq(phba, lpfc_ncmd); + lpfc_put_cmd_rsp_buf_per_hdwq(phba, lpfc_ncmd); kfree(lpfc_ncmd); qp->total_io_bufs--; } @@ -3663,6 +3666,9 @@ lpfc_io_free(struct lpfc_hba *phba) qp->get_io_bufs--; dma_pool_free(phba->lpfc_sg_dma_buf_pool, lpfc_ncmd->data, lpfc_ncmd->dma_handle); + if (phba->cfg_xpsgl && !phba->nvmet_support) + lpfc_put_sgl_per_hdwq(phba, lpfc_ncmd); + lpfc_put_cmd_rsp_buf_per_hdwq(phba, lpfc_ncmd); kfree(lpfc_ncmd); qp->total_io_bufs--; } @@ -4138,22 +4144,30 @@ lpfc_new_io_buf(struct lpfc_hba *phba, int num_to_alloc) break; } - /* - * 4K Page alignment is CRITICAL to BlockGuard, double check - * to be sure. - */ - if ((phba->sli3_options & LPFC_SLI3_BG_ENABLED) && - (((unsigned long)(lpfc_ncmd->data) & - (unsigned long)(SLI4_PAGE_SIZE - 1)) != 0)) { - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, - "3369 Memory alignment err: addr=%lx\n", - (unsigned long)lpfc_ncmd->data); - dma_pool_free(phba->lpfc_sg_dma_buf_pool, - lpfc_ncmd->data, lpfc_ncmd->dma_handle); - kfree(lpfc_ncmd); - break; + if (phba->cfg_xpsgl && !phba->nvmet_support) { + INIT_LIST_HEAD(&lpfc_ncmd->dma_sgl_xtra_list); + } else { + /* + * 4K Page alignment is CRITICAL to BlockGuard, double + * check to be sure. + */ + if ((phba->sli3_options & LPFC_SLI3_BG_ENABLED) && + (((unsigned long)(lpfc_ncmd->data) & + (unsigned long)(SLI4_PAGE_SIZE - 1)) != 0)) { + lpfc_printf_log(phba, KERN_ERR, LOG_FCP, + "3369 Memory alignment err: " + "addr=%lx\n", + (unsigned long)lpfc_ncmd->data); + dma_pool_free(phba->lpfc_sg_dma_buf_pool, + lpfc_ncmd->data, + lpfc_ncmd->dma_handle); + kfree(lpfc_ncmd); + break; + } } + INIT_LIST_HEAD(&lpfc_ncmd->dma_cmd_rsp_list); + lxri = lpfc_sli4_next_xritag(phba); if (lxri == NO_XRI) { dma_pool_free(phba->lpfc_sg_dma_buf_pool, @@ -4330,7 +4344,11 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev) shost->dma_boundary = phba->sli4_hba.pc_sli4_params.sge_supp_len-1; - shost->sg_tablesize = phba->cfg_scsi_seg_cnt; + + if (phba->cfg_xpsgl && !phba->nvmet_support) + shost->sg_tablesize = LPFC_MAX_SG_TABLESIZE; + else + shost->sg_tablesize = phba->cfg_scsi_seg_cnt; } else /* SLI-3 has a limited number of hardware queues (3), * thus there is only one for FCP processing. @@ -6348,6 +6366,24 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba) if (lpfc_mem_alloc(phba, BPL_ALIGN_SZ)) return -ENOMEM; + phba->lpfc_sg_dma_buf_pool = + dma_pool_create("lpfc_sg_dma_buf_pool", + &phba->pcidev->dev, phba->cfg_sg_dma_buf_size, + BPL_ALIGN_SZ, 0); + + if (!phba->lpfc_sg_dma_buf_pool) + goto fail_free_mem; + + phba->lpfc_cmd_rsp_buf_pool = + dma_pool_create("lpfc_cmd_rsp_buf_pool", + &phba->pcidev->dev, + sizeof(struct fcp_cmnd) + + sizeof(struct fcp_rsp), + BPL_ALIGN_SZ, 0); + + if (!phba->lpfc_cmd_rsp_buf_pool) + goto fail_free_dma_buf_pool; + /* * Enable sr-iov virtual functions if supported and configured * through the module parameter. @@ -6366,6 +6402,13 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba) } return 0; + +fail_free_dma_buf_pool: + dma_pool_destroy(phba->lpfc_sg_dma_buf_pool); + phba->lpfc_sg_dma_buf_pool = NULL; +fail_free_mem: + lpfc_mem_free(phba); + return -ENOMEM; } /** @@ -6465,102 +6508,6 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) * The WQ create will allocate the ring. */ - /* - * 1 for cmd, 1 for rsp, NVME adds an extra one - * for boundary conditions in its max_sgl_segment template. - */ - extra = 2; - if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) - extra++; - - /* - * It doesn't matter what family our adapter is in, we are - * limited to 2 Pages, 512 SGEs, for our SGL. - * There are going to be 2 reserved SGEs: 1 FCP cmnd + 1 FCP rsp - */ - max_buf_size = (2 * SLI4_PAGE_SIZE); - - /* - * Since lpfc_sg_seg_cnt is module param, the sg_dma_buf_size - * used to create the sg_dma_buf_pool must be calculated. - */ - if (phba->sli3_options & LPFC_SLI3_BG_ENABLED) { - /* - * The scsi_buf for a T10-DIF I/O holds the FCP cmnd, - * the FCP rsp, and a SGE. Sice we have no control - * over how many protection segments the SCSI Layer - * will hand us (ie: there could be one for every block - * in the IO), just allocate enough SGEs to accomidate - * our max amount and we need to limit lpfc_sg_seg_cnt - * to minimize the risk of running out. - */ - phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) + - sizeof(struct fcp_rsp) + max_buf_size; - - /* Total SGEs for scsi_sg_list and scsi_sg_prot_list */ - phba->cfg_total_seg_cnt = LPFC_MAX_SGL_SEG_CNT; - - /* - * If supporting DIF, reduce the seg count for scsi to - * allow room for the DIF sges. - */ - if (phba->cfg_enable_bg && - phba->cfg_sg_seg_cnt > LPFC_MAX_BG_SLI4_SEG_CNT_DIF) - phba->cfg_scsi_seg_cnt = LPFC_MAX_BG_SLI4_SEG_CNT_DIF; - else - phba->cfg_scsi_seg_cnt = phba->cfg_sg_seg_cnt; - - } else { - /* - * The scsi_buf for a regular I/O holds the FCP cmnd, - * the FCP rsp, a SGE for each, and a SGE for up to - * cfg_sg_seg_cnt data segments. - */ - phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) + - sizeof(struct fcp_rsp) + - ((phba->cfg_sg_seg_cnt + extra) * - sizeof(struct sli4_sge)); - - /* Total SGEs for scsi_sg_list */ - phba->cfg_total_seg_cnt = phba->cfg_sg_seg_cnt + extra; - phba->cfg_scsi_seg_cnt = phba->cfg_sg_seg_cnt; - - /* - * NOTE: if (phba->cfg_sg_seg_cnt + extra) <= 256 we only - * need to post 1 page for the SGL. - */ - } - - /* Limit to LPFC_MAX_NVME_SEG_CNT for NVME. */ - if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { - if (phba->cfg_sg_seg_cnt > LPFC_MAX_NVME_SEG_CNT) { - lpfc_printf_log(phba, KERN_INFO, LOG_NVME | LOG_INIT, - "6300 Reducing NVME sg segment " - "cnt to %d\n", - LPFC_MAX_NVME_SEG_CNT); - phba->cfg_nvme_seg_cnt = LPFC_MAX_NVME_SEG_CNT; - } else - phba->cfg_nvme_seg_cnt = phba->cfg_sg_seg_cnt; - } - - /* Initialize the host templates with the updated values. */ - lpfc_vport_template.sg_tablesize = phba->cfg_scsi_seg_cnt; - lpfc_template.sg_tablesize = phba->cfg_scsi_seg_cnt; - lpfc_template_no_hr.sg_tablesize = phba->cfg_scsi_seg_cnt; - - if (phba->cfg_sg_dma_buf_size <= LPFC_MIN_SG_SLI4_BUF_SZ) - phba->cfg_sg_dma_buf_size = LPFC_MIN_SG_SLI4_BUF_SZ; - else - phba->cfg_sg_dma_buf_size = - SLI4_PAGE_ALIGN(phba->cfg_sg_dma_buf_size); - - lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_FCP, - "9087 sg_seg_cnt:%d dmabuf_size:%d " - "total:%d scsi:%d nvme:%d\n", - phba->cfg_sg_seg_cnt, phba->cfg_sg_dma_buf_size, - phba->cfg_total_seg_cnt, phba->cfg_scsi_seg_cnt, - phba->cfg_nvme_seg_cnt); - /* Initialize buffer queue management fields */ INIT_LIST_HEAD(&phba->hbqs[LPFC_ELS_HBQ].hbq_buffer_list); phba->hbqs[LPFC_ELS_HBQ].hbq_alloc_buffer = lpfc_sli4_rb_alloc; @@ -6781,6 +6728,131 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) } } + /* + * 1 for cmd, 1 for rsp, NVME adds an extra one + * for boundary conditions in its max_sgl_segment template. + */ + extra = 2; + if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) + extra++; + + /* + * It doesn't matter what family our adapter is in, we are + * limited to 2 Pages, 512 SGEs, for our SGL. + * There are going to be 2 reserved SGEs: 1 FCP cmnd + 1 FCP rsp + */ + max_buf_size = (2 * SLI4_PAGE_SIZE); + + /* + * Since lpfc_sg_seg_cnt is module param, the sg_dma_buf_size + * used to create the sg_dma_buf_pool must be calculated. + */ + if (phba->sli3_options & LPFC_SLI3_BG_ENABLED) { + /* Both cfg_enable_bg and cfg_external_dif code paths */ + + /* + * The scsi_buf for a T10-DIF I/O holds the FCP cmnd, + * the FCP rsp, and a SGE. Sice we have no control + * over how many protection segments the SCSI Layer + * will hand us (ie: there could be one for every block + * in the IO), just allocate enough SGEs to accomidate + * our max amount and we need to limit lpfc_sg_seg_cnt + * to minimize the risk of running out. + */ + phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) + + sizeof(struct fcp_rsp) + max_buf_size; + + /* Total SGEs for scsi_sg_list and scsi_sg_prot_list */ + phba->cfg_total_seg_cnt = LPFC_MAX_SGL_SEG_CNT; + + /* + * If supporting DIF, reduce the seg count for scsi to + * allow room for the DIF sges. + */ + if (phba->cfg_enable_bg && + phba->cfg_sg_seg_cnt > LPFC_MAX_BG_SLI4_SEG_CNT_DIF) + phba->cfg_scsi_seg_cnt = LPFC_MAX_BG_SLI4_SEG_CNT_DIF; + else + phba->cfg_scsi_seg_cnt = phba->cfg_sg_seg_cnt; + + } else { + /* + * The scsi_buf for a regular I/O holds the FCP cmnd, + * the FCP rsp, a SGE for each, and a SGE for up to + * cfg_sg_seg_cnt data segments. + */ + phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) + + sizeof(struct fcp_rsp) + + ((phba->cfg_sg_seg_cnt + extra) * + sizeof(struct sli4_sge)); + + /* Total SGEs for scsi_sg_list */ + phba->cfg_total_seg_cnt = phba->cfg_sg_seg_cnt + extra; + phba->cfg_scsi_seg_cnt = phba->cfg_sg_seg_cnt; + + /* + * NOTE: if (phba->cfg_sg_seg_cnt + extra) <= 256 we only + * need to post 1 page for the SGL. + */ + } + + if (phba->cfg_xpsgl && !phba->nvmet_support) + phba->cfg_sg_dma_buf_size = LPFC_DEFAULT_XPSGL_SIZE; + else if (phba->cfg_sg_dma_buf_size <= LPFC_MIN_SG_SLI4_BUF_SZ) + phba->cfg_sg_dma_buf_size = LPFC_MIN_SG_SLI4_BUF_SZ; + else + phba->cfg_sg_dma_buf_size = + SLI4_PAGE_ALIGN(phba->cfg_sg_dma_buf_size); + + phba->border_sge_num = phba->cfg_sg_dma_buf_size / + sizeof(struct sli4_sge); + + /* Limit to LPFC_MAX_NVME_SEG_CNT for NVME. */ + if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { + if (phba->cfg_sg_seg_cnt > LPFC_MAX_NVME_SEG_CNT) { + lpfc_printf_log(phba, KERN_INFO, LOG_NVME | LOG_INIT, + "6300 Reducing NVME sg segment " + "cnt to %d\n", + LPFC_MAX_NVME_SEG_CNT); + phba->cfg_nvme_seg_cnt = LPFC_MAX_NVME_SEG_CNT; + } else + phba->cfg_nvme_seg_cnt = phba->cfg_sg_seg_cnt; + } + + /* Initialize the host templates with the updated values. */ + lpfc_vport_template.sg_tablesize = phba->cfg_scsi_seg_cnt; + lpfc_template.sg_tablesize = phba->cfg_scsi_seg_cnt; + lpfc_template_no_hr.sg_tablesize = phba->cfg_scsi_seg_cnt; + + lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_FCP, + "9087 sg_seg_cnt:%d dmabuf_size:%d " + "total:%d scsi:%d nvme:%d\n", + phba->cfg_sg_seg_cnt, phba->cfg_sg_dma_buf_size, + phba->cfg_total_seg_cnt, phba->cfg_scsi_seg_cnt, + phba->cfg_nvme_seg_cnt); + + if (phba->cfg_sg_dma_buf_size < SLI4_PAGE_SIZE) + i = phba->cfg_sg_dma_buf_size; + else + i = SLI4_PAGE_SIZE; + + phba->lpfc_sg_dma_buf_pool = + dma_pool_create("lpfc_sg_dma_buf_pool", + &phba->pcidev->dev, + phba->cfg_sg_dma_buf_size, + i, 0); + if (!phba->lpfc_sg_dma_buf_pool) + goto out_free_bsmbx; + + phba->lpfc_cmd_rsp_buf_pool = + dma_pool_create("lpfc_cmd_rsp_buf_pool", + &phba->pcidev->dev, + sizeof(struct fcp_cmnd) + + sizeof(struct fcp_rsp), + i, 0); + if (!phba->lpfc_cmd_rsp_buf_pool) + goto out_free_sg_dma_buf; + mempool_free(mboxq, phba->mbox_mem_pool); /* Verify OAS is supported */ @@ -6792,12 +6864,12 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) /* Verify all the SLI4 queues */ rc = lpfc_sli4_queue_verify(phba); if (rc) - goto out_free_bsmbx; + goto out_free_cmd_rsp_buf; /* Create driver internal CQE event pool */ rc = lpfc_sli4_cq_event_pool_create(phba); if (rc) - goto out_free_bsmbx; + goto out_free_cmd_rsp_buf; /* Initialize sgl lists per host */ lpfc_init_sgl_list(phba); @@ -6888,6 +6960,12 @@ out_free_active_sgl: lpfc_free_active_sgl(phba); out_destroy_cq_event_pool: lpfc_sli4_cq_event_pool_destroy(phba); +out_free_cmd_rsp_buf: + dma_pool_destroy(phba->lpfc_cmd_rsp_buf_pool); + phba->lpfc_cmd_rsp_buf_pool = NULL; +out_free_sg_dma_buf: + dma_pool_destroy(phba->lpfc_sg_dma_buf_pool); + phba->lpfc_sg_dma_buf_pool = NULL; out_free_bsmbx: lpfc_destroy_bootstrap_mbox(phba); out_free_mem: @@ -8814,6 +8892,9 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) spin_lock_init(&qp->abts_nvme_buf_list_lock); INIT_LIST_HEAD(&qp->lpfc_abts_nvme_buf_list); qp->abts_nvme_io_bufs = 0; + INIT_LIST_HEAD(&qp->sgl_list); + INIT_LIST_HEAD(&qp->cmd_rsp_buf_list); + spin_lock_init(&qp->hdwq_lock); } } @@ -9188,6 +9269,9 @@ lpfc_sli4_release_hdwq(struct lpfc_hba *phba) hdwq[idx].nvme_cq = NULL; hdwq[idx].fcp_wq = NULL; hdwq[idx].nvme_wq = NULL; + if (phba->cfg_xpsgl && !phba->nvmet_support) + lpfc_free_sgl_per_hdwq(phba, &hdwq[idx]); + lpfc_free_cmd_rsp_buf_per_hdwq(phba, &hdwq[idx]); } /* Loop thru all IRQ vectors */ for (idx = 0; idx < phba->cfg_irq_chann; idx++) { @@ -11647,6 +11731,9 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) phba->sli4_hba.extents_in_use = bf_get(cfg_ext, mbx_sli4_parameters); phba->sli4_hba.rpi_hdrs_in_use = bf_get(cfg_hdrr, mbx_sli4_parameters); + /* Check for Extended Pre-Registered SGL support */ + phba->cfg_xpsgl = bf_get(cfg_xpsgl, mbx_sli4_parameters); + /* Check for firmware nvme support */ rc = (bf_get(cfg_nvme, mbx_sli4_parameters) && bf_get(cfg_xib, mbx_sli4_parameters)); diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 9bdb4a0a9f24..ae09bb863497 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c @@ -72,8 +72,8 @@ lpfc_mem_alloc_active_rrq_pool_s4(struct lpfc_hba *phba) { * lpfc_mem_alloc - create and allocate all PCI and memory pools * @phba: HBA to allocate pools for * - * Description: Creates and allocates PCI pools lpfc_sg_dma_buf_pool, - * lpfc_mbuf_pool, lpfc_hrb_pool. Creates and allocates kmalloc-backed mempools + * Description: Creates and allocates PCI pools lpfc_mbuf_pool, + * lpfc_hrb_pool. Creates and allocates kmalloc-backed mempools * for LPFC_MBOXQ_t and lpfc_nodelist. Also allocates the VPI bitmask. * * Notes: Not interrupt-safe. Must be called with no locks held. If any @@ -89,36 +89,12 @@ lpfc_mem_alloc(struct lpfc_hba *phba, int align) struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; int i; - if (phba->sli_rev == LPFC_SLI_REV4) { - /* Calculate alignment */ - if (phba->cfg_sg_dma_buf_size < SLI4_PAGE_SIZE) - i = phba->cfg_sg_dma_buf_size; - else - i = SLI4_PAGE_SIZE; - - phba->lpfc_sg_dma_buf_pool = - dma_pool_create("lpfc_sg_dma_buf_pool", - &phba->pcidev->dev, - phba->cfg_sg_dma_buf_size, - i, 0); - if (!phba->lpfc_sg_dma_buf_pool) - goto fail; - - } else { - phba->lpfc_sg_dma_buf_pool = - dma_pool_create("lpfc_sg_dma_buf_pool", - &phba->pcidev->dev, phba->cfg_sg_dma_buf_size, - align, 0); - - if (!phba->lpfc_sg_dma_buf_pool) - goto fail; - } phba->lpfc_mbuf_pool = dma_pool_create("lpfc_mbuf_pool", &phba->pcidev->dev, LPFC_BPL_SIZE, align, 0); if (!phba->lpfc_mbuf_pool) - goto fail_free_dma_buf_pool; + goto fail; pool->elements = kmalloc_array(LPFC_MBUF_POOL_SIZE, sizeof(struct lpfc_dmabuf), @@ -208,9 +184,6 @@ fail_free_drb_pool: fail_free_lpfc_mbuf_pool: dma_pool_destroy(phba->lpfc_mbuf_pool); phba->lpfc_mbuf_pool = NULL; - fail_free_dma_buf_pool: - dma_pool_destroy(phba->lpfc_sg_dma_buf_pool); - phba->lpfc_sg_dma_buf_pool = NULL; fail: return -ENOMEM; } @@ -287,10 +260,6 @@ lpfc_mem_free(struct lpfc_hba *phba) dma_pool_destroy(phba->lpfc_mbuf_pool); phba->lpfc_mbuf_pool = NULL; - /* Free DMA buffer memory pool */ - dma_pool_destroy(phba->lpfc_sg_dma_buf_pool); - phba->lpfc_sg_dma_buf_pool = NULL; - /* Free Device Data memory pool */ if (phba->device_data_mem_pool) { /* Ensure all objects have been returned to the pool */ @@ -363,6 +332,13 @@ lpfc_mem_free_all(struct lpfc_hba *phba) /* Free and destroy all the allocated memory pools */ lpfc_mem_free(phba); + /* Free DMA buffer memory pool */ + dma_pool_destroy(phba->lpfc_sg_dma_buf_pool); + phba->lpfc_sg_dma_buf_pool = NULL; + + dma_pool_destroy(phba->lpfc_cmd_rsp_buf_pool); + phba->lpfc_cmd_rsp_buf_pool = NULL; + /* Free the iocb lookup array */ kfree(psli->iocbq_lookup); psli->iocbq_lookup = NULL; diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index b599ddc40c6b..5e48318eb7a9 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -1306,14 +1306,16 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport, struct nvmefc_fcp_req *nCmd = lpfc_ncmd->nvmeCmd; union lpfc_wqe128 *wqe = &lpfc_ncmd->cur_iocbq.wqe; struct sli4_sge *sgl = lpfc_ncmd->dma_sgl; + struct sli4_hybrid_sgl *sgl_xtra = NULL; struct scatterlist *data_sg; struct sli4_sge *first_data_sgl; struct ulp_bde64 *bde; - dma_addr_t physaddr; + dma_addr_t physaddr = 0; uint32_t num_bde = 0; - uint32_t dma_len; + uint32_t dma_len = 0; uint32_t dma_offset = 0; - int nseg, i; + int nseg, i, j; + bool lsp_just_set = false; /* Fix up the command and response DMA stuff. */ lpfc_nvme_adj_fcp_sgls(vport, lpfc_ncmd, nCmd); @@ -1350,6 +1352,9 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport, */ nseg = nCmd->sg_cnt; data_sg = nCmd->first_sgl; + + /* for tracking the segment boundaries */ + j = 2; for (i = 0; i < nseg; i++) { if (data_sg == NULL) { lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, @@ -1358,23 +1363,76 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport, lpfc_ncmd->seg_cnt = 0; return 1; } - physaddr = data_sg->dma_address; - dma_len = data_sg->length; - sgl->addr_lo = cpu_to_le32(putPaddrLow(physaddr)); - sgl->addr_hi = cpu_to_le32(putPaddrHigh(physaddr)); - sgl->word2 = le32_to_cpu(sgl->word2); - if ((num_bde + 1) == nseg) + + sgl->word2 = 0; + if ((num_bde + 1) == nseg) { bf_set(lpfc_sli4_sge_last, sgl, 1); - else + bf_set(lpfc_sli4_sge_type, sgl, + LPFC_SGE_TYPE_DATA); + } else { bf_set(lpfc_sli4_sge_last, sgl, 0); - bf_set(lpfc_sli4_sge_offset, sgl, dma_offset); - bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_DATA); - sgl->word2 = cpu_to_le32(sgl->word2); - sgl->sge_len = cpu_to_le32(dma_len); - - dma_offset += dma_len; - data_sg = sg_next(data_sg); - sgl++; + + /* expand the segment */ + if (!lsp_just_set && + !((j + 1) % phba->border_sge_num) && + ((nseg - 1) != i)) { + /* set LSP type */ + bf_set(lpfc_sli4_sge_type, sgl, + LPFC_SGE_TYPE_LSP); + + sgl_xtra = lpfc_get_sgl_per_hdwq( + phba, lpfc_ncmd); + + if (unlikely(!sgl_xtra)) { + lpfc_ncmd->seg_cnt = 0; + return 1; + } + sgl->addr_lo = cpu_to_le32(putPaddrLow( + sgl_xtra->dma_phys_sgl)); + sgl->addr_hi = cpu_to_le32(putPaddrHigh( + sgl_xtra->dma_phys_sgl)); + + } else { + bf_set(lpfc_sli4_sge_type, sgl, + LPFC_SGE_TYPE_DATA); + } + } + + if (!(bf_get(lpfc_sli4_sge_type, sgl) & + LPFC_SGE_TYPE_LSP)) { + if ((nseg - 1) == i) + bf_set(lpfc_sli4_sge_last, sgl, 1); + + physaddr = data_sg->dma_address; + dma_len = data_sg->length; + sgl->addr_lo = cpu_to_le32( + putPaddrLow(physaddr)); + sgl->addr_hi = cpu_to_le32( + putPaddrHigh(physaddr)); + + bf_set(lpfc_sli4_sge_offset, sgl, dma_offset); + sgl->word2 = cpu_to_le32(sgl->word2); + sgl->sge_len = cpu_to_le32(dma_len); + + dma_offset += dma_len; + data_sg = sg_next(data_sg); + + sgl++; + + lsp_just_set = false; + } else { + sgl->word2 = cpu_to_le32(sgl->word2); + + sgl->sge_len = cpu_to_le32( + phba->cfg_sg_dma_buf_size); + + sgl = (struct sli4_sge *)sgl_xtra->dma_sgl; + i = i - 1; + + lsp_just_set = true; + } + + j++; } if (phba->cfg_enable_pbde) { /* Use PBDE support for first SGL only, offset == 0 */ diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 95ba5000d0ec..fb7df209c0aa 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -685,8 +685,9 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, IOCB_t *iocb; dma_addr_t pdma_phys_fcp_rsp; dma_addr_t pdma_phys_fcp_cmd; - uint32_t sgl_size, cpu, idx; + uint32_t cpu, idx; int tag; + struct fcp_cmd_rsp_buf *tmp = NULL; cpu = raw_smp_processor_id(); if (cmnd && phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_HDWQ) { @@ -704,9 +705,6 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, return NULL; } - sgl_size = phba->cfg_sg_dma_buf_size - - (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp)); - /* Setup key fields in buffer that may have been changed * if other protocols used this buffer. */ @@ -721,9 +719,12 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, #ifdef CONFIG_SCSI_LPFC_DEBUG_FS lpfc_cmd->prot_data_type = 0; #endif - lpfc_cmd->fcp_cmnd = (lpfc_cmd->data + sgl_size); - lpfc_cmd->fcp_rsp = (struct fcp_rsp *)((uint8_t *)lpfc_cmd->fcp_cmnd + - sizeof(struct fcp_cmnd)); + tmp = lpfc_get_cmd_rsp_buf_per_hdwq(phba, lpfc_cmd); + if (!tmp) + return NULL; + + lpfc_cmd->fcp_cmnd = tmp->fcp_cmnd; + lpfc_cmd->fcp_rsp = tmp->fcp_rsp; /* * The first two SGEs are the FCP_CMD and FCP_RSP. @@ -731,7 +732,7 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, * first two and leave the rest for queuecommand. */ sgl = (struct sli4_sge *)lpfc_cmd->dma_sgl; - pdma_phys_fcp_cmd = (lpfc_cmd->dma_handle + sgl_size); + pdma_phys_fcp_cmd = tmp->fcp_cmd_rsp_dma_handle; sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_cmd)); sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_cmd)); sgl->word2 = le32_to_cpu(sgl->word2); @@ -1990,7 +1991,8 @@ out: **/ static int lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc, - struct sli4_sge *sgl, int datasegcnt) + struct sli4_sge *sgl, int datasegcnt, + struct lpfc_io_buf *lpfc_cmd) { struct scatterlist *sgde = NULL; /* s/g data entry */ struct sli4_sge_diseed *diseed = NULL; @@ -2004,6 +2006,9 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc, uint32_t checking = 1; uint32_t dma_len; uint32_t dma_offset = 0; + struct sli4_hybrid_sgl *sgl_xtra = NULL; + int j; + bool lsp_just_set = false; status = lpfc_sc_to_bg_opcodes(phba, sc, &txop, &rxop); if (status) @@ -2063,23 +2068,64 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc, sgl++; /* assumption: caller has already run dma_map_sg on command data */ - scsi_for_each_sg(sc, sgde, datasegcnt, i) { - physaddr = sg_dma_address(sgde); - dma_len = sg_dma_len(sgde); - sgl->addr_lo = cpu_to_le32(putPaddrLow(physaddr)); - sgl->addr_hi = cpu_to_le32(putPaddrHigh(physaddr)); - if ((i + 1) == datasegcnt) - bf_set(lpfc_sli4_sge_last, sgl, 1); - else - bf_set(lpfc_sli4_sge_last, sgl, 0); - bf_set(lpfc_sli4_sge_offset, sgl, dma_offset); - bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_DATA); + sgde = scsi_sglist(sc); + j = 3; + for (i = 0; i < datasegcnt; i++) { + /* clear it */ + sgl->word2 = 0; - sgl->sge_len = cpu_to_le32(dma_len); - dma_offset += dma_len; + /* do we need to expand the segment */ + if (!lsp_just_set && !((j + 1) % phba->border_sge_num) && + ((datasegcnt - 1) != i)) { + /* set LSP type */ + bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_LSP); + + sgl_xtra = lpfc_get_sgl_per_hdwq(phba, lpfc_cmd); + + if (unlikely(!sgl_xtra)) { + lpfc_cmd->seg_cnt = 0; + return 0; + } + sgl->addr_lo = cpu_to_le32(putPaddrLow( + sgl_xtra->dma_phys_sgl)); + sgl->addr_hi = cpu_to_le32(putPaddrHigh( + sgl_xtra->dma_phys_sgl)); + + } else { + bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_DATA); + } + + if (!(bf_get(lpfc_sli4_sge_type, sgl) & LPFC_SGE_TYPE_LSP)) { + if ((datasegcnt - 1) == i) + bf_set(lpfc_sli4_sge_last, sgl, 1); + physaddr = sg_dma_address(sgde); + dma_len = sg_dma_len(sgde); + sgl->addr_lo = cpu_to_le32(putPaddrLow(physaddr)); + sgl->addr_hi = cpu_to_le32(putPaddrHigh(physaddr)); + + bf_set(lpfc_sli4_sge_offset, sgl, dma_offset); + sgl->word2 = cpu_to_le32(sgl->word2); + sgl->sge_len = cpu_to_le32(dma_len); + + dma_offset += dma_len; + sgde = sg_next(sgde); + + sgl++; + num_sge++; + lsp_just_set = false; + + } else { + sgl->word2 = cpu_to_le32(sgl->word2); + sgl->sge_len = cpu_to_le32(phba->cfg_sg_dma_buf_size); + + sgl = (struct sli4_sge *)sgl_xtra->dma_sgl; + i = i - 1; + + lsp_just_set = true; + } + + j++; - sgl++; - num_sge++; } out: @@ -2125,7 +2171,8 @@ out: **/ static int lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, - struct sli4_sge *sgl, int datacnt, int protcnt) + struct sli4_sge *sgl, int datacnt, int protcnt, + struct lpfc_io_buf *lpfc_cmd) { struct scatterlist *sgde = NULL; /* s/g data entry */ struct scatterlist *sgpe = NULL; /* s/g prot entry */ @@ -2147,7 +2194,8 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, #endif uint32_t checking = 1; uint32_t dma_offset = 0; - int num_sge = 0; + int num_sge = 0, j = 2; + struct sli4_hybrid_sgl *sgl_xtra = NULL; sgpe = scsi_prot_sglist(sc); sgde = scsi_sglist(sc); @@ -2180,9 +2228,37 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, split_offset = 0; do { /* Check to see if we ran out of space */ - if (num_sge >= (phba->cfg_total_seg_cnt - 2)) + if ((num_sge >= (phba->cfg_total_seg_cnt - 2)) && + !(phba->cfg_xpsgl)) return num_sge + 3; + /* DISEED and DIF have to be together */ + if (!((j + 1) % phba->border_sge_num) || + !((j + 2) % phba->border_sge_num) || + !((j + 3) % phba->border_sge_num)) { + sgl->word2 = 0; + + /* set LSP type */ + bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_LSP); + + sgl_xtra = lpfc_get_sgl_per_hdwq(phba, lpfc_cmd); + + if (unlikely(!sgl_xtra)) { + goto out; + } else { + sgl->addr_lo = cpu_to_le32(putPaddrLow( + sgl_xtra->dma_phys_sgl)); + sgl->addr_hi = cpu_to_le32(putPaddrHigh( + sgl_xtra->dma_phys_sgl)); + } + + sgl->word2 = cpu_to_le32(sgl->word2); + sgl->sge_len = cpu_to_le32(phba->cfg_sg_dma_buf_size); + + sgl = (struct sli4_sge *)sgl_xtra->dma_sgl; + j = 0; + } + /* setup DISEED with what we have */ diseed = (struct sli4_sge_diseed *) sgl; memset(diseed, 0, sizeof(struct sli4_sge_diseed)); @@ -2229,7 +2305,9 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, /* advance sgl and increment bde count */ num_sge++; + sgl++; + j++; /* setup the first BDE that points to protection buffer */ protphysaddr = sg_dma_address(sgpe) + protgroup_offset; @@ -2244,6 +2322,7 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, sgl->addr_hi = le32_to_cpu(putPaddrHigh(protphysaddr)); sgl->addr_lo = le32_to_cpu(putPaddrLow(protphysaddr)); sgl->word2 = cpu_to_le32(sgl->word2); + sgl->sge_len = 0; protgrp_blks = protgroup_len / 8; protgrp_bytes = protgrp_blks * blksize; @@ -2264,9 +2343,14 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, /* setup SGE's for data blocks associated with DIF data */ pgdone = 0; subtotal = 0; /* total bytes processed for current prot grp */ + + sgl++; + j++; + while (!pgdone) { /* Check to see if we ran out of space */ - if (num_sge >= phba->cfg_total_seg_cnt) + if ((num_sge >= phba->cfg_total_seg_cnt) && + !phba->cfg_xpsgl) return num_sge + 1; if (!sgde) { @@ -2275,60 +2359,101 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, __func__); return 0; } - sgl++; - dataphysaddr = sg_dma_address(sgde) + split_offset; - remainder = sg_dma_len(sgde) - split_offset; + if (!((j + 1) % phba->border_sge_num)) { + sgl->word2 = 0; - if ((subtotal + remainder) <= protgrp_bytes) { - /* we can use this whole buffer */ - dma_len = remainder; - split_offset = 0; + /* set LSP type */ + bf_set(lpfc_sli4_sge_type, sgl, + LPFC_SGE_TYPE_LSP); - if ((subtotal + remainder) == protgrp_bytes) - pgdone = 1; + sgl_xtra = lpfc_get_sgl_per_hdwq(phba, + lpfc_cmd); + + if (unlikely(!sgl_xtra)) { + goto out; + } else { + sgl->addr_lo = cpu_to_le32( + putPaddrLow(sgl_xtra->dma_phys_sgl)); + sgl->addr_hi = cpu_to_le32( + putPaddrHigh(sgl_xtra->dma_phys_sgl)); + } + + sgl->word2 = cpu_to_le32(sgl->word2); + sgl->sge_len = cpu_to_le32( + phba->cfg_sg_dma_buf_size); + + sgl = (struct sli4_sge *)sgl_xtra->dma_sgl; } else { - /* must split this buffer with next prot grp */ - dma_len = protgrp_bytes - subtotal; - split_offset += dma_len; - } + dataphysaddr = sg_dma_address(sgde) + + split_offset; - subtotal += dma_len; + remainder = sg_dma_len(sgde) - split_offset; - sgl->addr_lo = cpu_to_le32(putPaddrLow(dataphysaddr)); - sgl->addr_hi = cpu_to_le32(putPaddrHigh(dataphysaddr)); - bf_set(lpfc_sli4_sge_last, sgl, 0); - bf_set(lpfc_sli4_sge_offset, sgl, dma_offset); - bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_DATA); + if ((subtotal + remainder) <= protgrp_bytes) { + /* we can use this whole buffer */ + dma_len = remainder; + split_offset = 0; - sgl->sge_len = cpu_to_le32(dma_len); - dma_offset += dma_len; + if ((subtotal + remainder) == + protgrp_bytes) + pgdone = 1; + } else { + /* must split this buffer with next + * prot grp + */ + dma_len = protgrp_bytes - subtotal; + split_offset += dma_len; + } - num_sge++; - curr_data++; + subtotal += dma_len; - if (split_offset) - break; + sgl->word2 = 0; + sgl->addr_lo = cpu_to_le32(putPaddrLow( + dataphysaddr)); + sgl->addr_hi = cpu_to_le32(putPaddrHigh( + dataphysaddr)); + bf_set(lpfc_sli4_sge_last, sgl, 0); + bf_set(lpfc_sli4_sge_offset, sgl, dma_offset); + bf_set(lpfc_sli4_sge_type, sgl, + LPFC_SGE_TYPE_DATA); - /* Move to the next s/g segment if possible */ - sgde = sg_next(sgde); + sgl->sge_len = cpu_to_le32(dma_len); + dma_offset += dma_len; + + num_sge++; + curr_data++; + + if (split_offset) { + sgl++; + j++; + break; + } + + /* Move to the next s/g segment if possible */ + sgde = sg_next(sgde); + + sgl++; + } + + j++; } if (protgroup_offset) { /* update the reference tag */ reftag += protgrp_blks; - sgl++; continue; } /* are we done ? */ if (curr_prot == protcnt) { + /* mark the last SGL */ + sgl--; bf_set(lpfc_sli4_sge_last, sgl, 1); alldone = 1; } else if (curr_prot < protcnt) { /* advance to next prot buffer */ sgpe = sg_next(sgpe); - sgl++; /* update the reference tag */ reftag += protgrp_blks; @@ -2995,8 +3120,10 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) uint32_t num_bde = 0; uint32_t dma_len; uint32_t dma_offset = 0; - int nseg; + int nseg, i, j; struct ulp_bde64 *bde; + bool lsp_just_set = false; + struct sli4_hybrid_sgl *sgl_xtra = NULL; /* * There are three possibilities here - use scatter-gather segment, use @@ -3023,7 +3150,8 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) sgl += 1; first_data_sgl = sgl; lpfc_cmd->seg_cnt = nseg; - if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { + if (!phba->cfg_xpsgl && + lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9074 BLKGRD:" " %s: Too many sg segments from " "dma_map_sg. Config %d, seg_cnt %d\n", @@ -3044,22 +3172,80 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) * the IOCB. If it can't then the BDEs get added to a BPL as it * does for SLI-2 mode. */ - scsi_for_each_sg(scsi_cmnd, sgel, nseg, num_bde) { - physaddr = sg_dma_address(sgel); - dma_len = sg_dma_len(sgel); - sgl->addr_lo = cpu_to_le32(putPaddrLow(physaddr)); - sgl->addr_hi = cpu_to_le32(putPaddrHigh(physaddr)); - sgl->word2 = le32_to_cpu(sgl->word2); - if ((num_bde + 1) == nseg) + + /* for tracking segment boundaries */ + sgel = scsi_sglist(scsi_cmnd); + j = 2; + for (i = 0; i < nseg; i++) { + sgl->word2 = 0; + if ((num_bde + 1) == nseg) { bf_set(lpfc_sli4_sge_last, sgl, 1); - else + bf_set(lpfc_sli4_sge_type, sgl, + LPFC_SGE_TYPE_DATA); + } else { bf_set(lpfc_sli4_sge_last, sgl, 0); - bf_set(lpfc_sli4_sge_offset, sgl, dma_offset); - bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_DATA); - sgl->word2 = cpu_to_le32(sgl->word2); - sgl->sge_len = cpu_to_le32(dma_len); - dma_offset += dma_len; - sgl++; + + /* do we need to expand the segment */ + if (!lsp_just_set && + !((j + 1) % phba->border_sge_num) && + ((nseg - 1) != i)) { + /* set LSP type */ + bf_set(lpfc_sli4_sge_type, sgl, + LPFC_SGE_TYPE_LSP); + + sgl_xtra = lpfc_get_sgl_per_hdwq( + phba, lpfc_cmd); + + if (unlikely(!sgl_xtra)) { + lpfc_cmd->seg_cnt = 0; + scsi_dma_unmap(scsi_cmnd); + return 1; + } + sgl->addr_lo = cpu_to_le32(putPaddrLow( + sgl_xtra->dma_phys_sgl)); + sgl->addr_hi = cpu_to_le32(putPaddrHigh( + sgl_xtra->dma_phys_sgl)); + + } else { + bf_set(lpfc_sli4_sge_type, sgl, + LPFC_SGE_TYPE_DATA); + } + } + + if (!(bf_get(lpfc_sli4_sge_type, sgl) & + LPFC_SGE_TYPE_LSP)) { + if ((nseg - 1) == i) + bf_set(lpfc_sli4_sge_last, sgl, 1); + + physaddr = sg_dma_address(sgel); + dma_len = sg_dma_len(sgel); + sgl->addr_lo = cpu_to_le32(putPaddrLow( + physaddr)); + sgl->addr_hi = cpu_to_le32(putPaddrHigh( + physaddr)); + + bf_set(lpfc_sli4_sge_offset, sgl, dma_offset); + sgl->word2 = cpu_to_le32(sgl->word2); + sgl->sge_len = cpu_to_le32(dma_len); + + dma_offset += dma_len; + sgel = sg_next(sgel); + + sgl++; + lsp_just_set = false; + + } else { + sgl->word2 = cpu_to_le32(sgl->word2); + sgl->sge_len = cpu_to_le32( + phba->cfg_sg_dma_buf_size); + + sgl = (struct sli4_sge *)sgl_xtra->dma_sgl; + i = i - 1; + + lsp_just_set = true; + } + + j++; } /* * Setup the first Payload BDE. For FCoE we just key off @@ -3175,7 +3361,8 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, lpfc_cmd->seg_cnt = datasegcnt; /* First check if data segment count from SCSI Layer is good */ - if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { + if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt && + !phba->cfg_xpsgl) { WARN_ON_ONCE(lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt); ret = 2; goto err; @@ -3186,13 +3373,15 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, switch (prot_group_type) { case LPFC_PG_TYPE_NO_DIF: /* Here we need to add a DISEED to the count */ - if ((lpfc_cmd->seg_cnt + 1) > phba->cfg_total_seg_cnt) { + if (((lpfc_cmd->seg_cnt + 1) > + phba->cfg_total_seg_cnt) && + !phba->cfg_xpsgl) { ret = 2; goto err; } num_sge = lpfc_bg_setup_sgl(phba, scsi_cmnd, sgl, - datasegcnt); + datasegcnt, lpfc_cmd); /* we should have 2 or more entries in buffer list */ if (num_sge < 2) { @@ -3220,18 +3409,20 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, * There is a minimun of 3 SGEs used for every * protection data segment. */ - if ((lpfc_cmd->prot_seg_cnt * 3) > - (phba->cfg_total_seg_cnt - 2)) { + if (((lpfc_cmd->prot_seg_cnt * 3) > + (phba->cfg_total_seg_cnt - 2)) && + !phba->cfg_xpsgl) { ret = 2; goto err; } num_sge = lpfc_bg_setup_sgl_prot(phba, scsi_cmnd, sgl, - datasegcnt, protsegcnt); + datasegcnt, protsegcnt, lpfc_cmd); /* we should have 3 or more entries in buffer list */ - if ((num_sge < 3) || - (num_sge > phba->cfg_total_seg_cnt)) { + if (num_sge < 3 || + (num_sge > phba->cfg_total_seg_cnt && + !phba->cfg_xpsgl)) { ret = 2; goto err; } @@ -5913,7 +6104,7 @@ struct scsi_host_template lpfc_template_no_hr = { .sg_tablesize = LPFC_DEFAULT_SG_SEG_CNT, .cmd_per_lun = LPFC_CMD_PER_LUN, .shost_attrs = lpfc_hba_attrs, - .max_sectors = 0xFFFF, + .max_sectors = 0xFFFFFFFF, .vendor_id = LPFC_NL_VENDOR_ID, .change_queue_depth = scsi_change_queue_depth, .track_queue_depth = 1, diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 940dd82a265b..f4beb9104d3a 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -20233,6 +20233,13 @@ void lpfc_release_io_buf(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_ncmd, spin_unlock_irqrestore(&qp->io_buf_list_put_lock, iflag); } + + if (phba->cfg_xpsgl && !phba->nvmet_support && + !list_empty(&lpfc_ncmd->dma_sgl_xtra_list)) + lpfc_put_sgl_per_hdwq(phba, lpfc_ncmd); + + if (!list_empty(&lpfc_ncmd->dma_cmd_rsp_list)) + lpfc_put_cmd_rsp_buf_per_hdwq(phba, lpfc_ncmd); } /** @@ -20447,3 +20454,288 @@ struct lpfc_io_buf *lpfc_get_io_buf(struct lpfc_hba *phba, return lpfc_cmd; } + +/** + * lpfc_get_sgl_per_hdwq - Get one SGL chunk from hdwq's pool + * @phba: The HBA for which this call is being executed. + * @lpfc_buf: IO buf structure to append the SGL chunk + * + * This routine gets one SGL chunk buffer from hdwq's SGL chunk pool, + * and will allocate an SGL chunk if the pool is empty. + * + * Return codes: + * NULL - Error + * Pointer to sli4_hybrid_sgl - Success + **/ +struct sli4_hybrid_sgl * +lpfc_get_sgl_per_hdwq(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_buf) +{ + struct sli4_hybrid_sgl *list_entry = NULL; + struct sli4_hybrid_sgl *tmp = NULL; + struct sli4_hybrid_sgl *allocated_sgl = NULL; + struct lpfc_sli4_hdw_queue *hdwq = lpfc_buf->hdwq; + struct list_head *buf_list = &hdwq->sgl_list; + + spin_lock_irq(&hdwq->hdwq_lock); + + if (likely(!list_empty(buf_list))) { + /* break off 1 chunk from the sgl_list */ + list_for_each_entry_safe(list_entry, tmp, + buf_list, list_node) { + list_move_tail(&list_entry->list_node, + &lpfc_buf->dma_sgl_xtra_list); + break; + } + } else { + /* allocate more */ + spin_unlock_irq(&hdwq->hdwq_lock); + tmp = kmalloc_node(sizeof(*tmp), GFP_ATOMIC, + cpu_to_node(smp_processor_id())); + if (!tmp) { + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "8353 error kmalloc memory for HDWQ " + "%d %s\n", + lpfc_buf->hdwq_no, __func__); + return NULL; + } + + tmp->dma_sgl = dma_pool_alloc(phba->lpfc_sg_dma_buf_pool, + GFP_ATOMIC, &tmp->dma_phys_sgl); + if (!tmp->dma_sgl) { + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "8354 error pool_alloc memory for HDWQ " + "%d %s\n", + lpfc_buf->hdwq_no, __func__); + kfree(tmp); + return NULL; + } + + spin_lock_irq(&hdwq->hdwq_lock); + list_add_tail(&tmp->list_node, &lpfc_buf->dma_sgl_xtra_list); + } + + allocated_sgl = list_last_entry(&lpfc_buf->dma_sgl_xtra_list, + struct sli4_hybrid_sgl, + list_node); + + spin_unlock_irq(&hdwq->hdwq_lock); + + return allocated_sgl; +} + +/** + * lpfc_put_sgl_per_hdwq - Put one SGL chunk into hdwq pool + * @phba: The HBA for which this call is being executed. + * @lpfc_buf: IO buf structure with the SGL chunk + * + * This routine puts one SGL chunk buffer into hdwq's SGL chunk pool. + * + * Return codes: + * 0 - Success + * -EINVAL - Error + **/ +int +lpfc_put_sgl_per_hdwq(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_buf) +{ + int rc = 0; + struct sli4_hybrid_sgl *list_entry = NULL; + struct sli4_hybrid_sgl *tmp = NULL; + struct lpfc_sli4_hdw_queue *hdwq = lpfc_buf->hdwq; + struct list_head *buf_list = &hdwq->sgl_list; + + spin_lock_irq(&hdwq->hdwq_lock); + + if (likely(!list_empty(&lpfc_buf->dma_sgl_xtra_list))) { + list_for_each_entry_safe(list_entry, tmp, + &lpfc_buf->dma_sgl_xtra_list, + list_node) { + list_move_tail(&list_entry->list_node, + buf_list); + } + } else { + rc = -EINVAL; + } + + spin_unlock_irq(&hdwq->hdwq_lock); + return rc; +} + +/** + * lpfc_free_sgl_per_hdwq - Free all SGL chunks of hdwq pool + * @phba: phba object + * @hdwq: hdwq to cleanup sgl buff resources on + * + * This routine frees all SGL chunks of hdwq SGL chunk pool. + * + * Return codes: + * None + **/ +void +lpfc_free_sgl_per_hdwq(struct lpfc_hba *phba, + struct lpfc_sli4_hdw_queue *hdwq) +{ + struct list_head *buf_list = &hdwq->sgl_list; + struct sli4_hybrid_sgl *list_entry = NULL; + struct sli4_hybrid_sgl *tmp = NULL; + + spin_lock_irq(&hdwq->hdwq_lock); + + /* Free sgl pool */ + list_for_each_entry_safe(list_entry, tmp, + buf_list, list_node) { + dma_pool_free(phba->lpfc_sg_dma_buf_pool, + list_entry->dma_sgl, + list_entry->dma_phys_sgl); + list_del(&list_entry->list_node); + kfree(list_entry); + } + + spin_unlock_irq(&hdwq->hdwq_lock); +} + +/** + * lpfc_get_cmd_rsp_buf_per_hdwq - Get one CMD/RSP buffer from hdwq + * @phba: The HBA for which this call is being executed. + * @lpfc_buf: IO buf structure to attach the CMD/RSP buffer + * + * This routine gets one CMD/RSP buffer from hdwq's CMD/RSP pool, + * and will allocate an CMD/RSP buffer if the pool is empty. + * + * Return codes: + * NULL - Error + * Pointer to fcp_cmd_rsp_buf - Success + **/ +struct fcp_cmd_rsp_buf * +lpfc_get_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba, + struct lpfc_io_buf *lpfc_buf) +{ + struct fcp_cmd_rsp_buf *list_entry = NULL; + struct fcp_cmd_rsp_buf *tmp = NULL; + struct fcp_cmd_rsp_buf *allocated_buf = NULL; + struct lpfc_sli4_hdw_queue *hdwq = lpfc_buf->hdwq; + struct list_head *buf_list = &hdwq->cmd_rsp_buf_list; + + spin_lock_irq(&hdwq->hdwq_lock); + + if (likely(!list_empty(buf_list))) { + /* break off 1 chunk from the list */ + list_for_each_entry_safe(list_entry, tmp, + buf_list, + list_node) { + list_move_tail(&list_entry->list_node, + &lpfc_buf->dma_cmd_rsp_list); + break; + } + } else { + /* allocate more */ + spin_unlock_irq(&hdwq->hdwq_lock); + tmp = kmalloc_node(sizeof(*tmp), GFP_ATOMIC, + cpu_to_node(smp_processor_id())); + if (!tmp) { + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "8355 error kmalloc memory for HDWQ " + "%d %s\n", + lpfc_buf->hdwq_no, __func__); + return NULL; + } + + tmp->fcp_cmnd = dma_pool_alloc(phba->lpfc_cmd_rsp_buf_pool, + GFP_ATOMIC, + &tmp->fcp_cmd_rsp_dma_handle); + + if (!tmp->fcp_cmnd) { + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "8356 error pool_alloc memory for HDWQ " + "%d %s\n", + lpfc_buf->hdwq_no, __func__); + kfree(tmp); + return NULL; + } + + tmp->fcp_rsp = (struct fcp_rsp *)((uint8_t *)tmp->fcp_cmnd + + sizeof(struct fcp_cmnd)); + + spin_lock_irq(&hdwq->hdwq_lock); + list_add_tail(&tmp->list_node, &lpfc_buf->dma_cmd_rsp_list); + } + + allocated_buf = list_last_entry(&lpfc_buf->dma_cmd_rsp_list, + struct fcp_cmd_rsp_buf, + list_node); + + spin_unlock_irq(&hdwq->hdwq_lock); + + return allocated_buf; +} + +/** + * lpfc_put_cmd_rsp_buf_per_hdwq - Put one CMD/RSP buffer into hdwq pool + * @phba: The HBA for which this call is being executed. + * @lpfc_buf: IO buf structure with the CMD/RSP buf + * + * This routine puts one CMD/RSP buffer into executing CPU's CMD/RSP pool. + * + * Return codes: + * 0 - Success + * -EINVAL - Error + **/ +int +lpfc_put_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba, + struct lpfc_io_buf *lpfc_buf) +{ + int rc = 0; + struct fcp_cmd_rsp_buf *list_entry = NULL; + struct fcp_cmd_rsp_buf *tmp = NULL; + struct lpfc_sli4_hdw_queue *hdwq = lpfc_buf->hdwq; + struct list_head *buf_list = &hdwq->cmd_rsp_buf_list; + + spin_lock_irq(&hdwq->hdwq_lock); + + if (likely(!list_empty(&lpfc_buf->dma_cmd_rsp_list))) { + list_for_each_entry_safe(list_entry, tmp, + &lpfc_buf->dma_cmd_rsp_list, + list_node) { + list_move_tail(&list_entry->list_node, + buf_list); + } + } else { + rc = -EINVAL; + } + + spin_unlock_irq(&hdwq->hdwq_lock); + return rc; +} + +/** + * lpfc_free_cmd_rsp_buf_per_hdwq - Free all CMD/RSP chunks of hdwq pool + * @phba: phba object + * @hdwq: hdwq to cleanup cmd rsp buff resources on + * + * This routine frees all CMD/RSP buffers of hdwq's CMD/RSP buf pool. + * + * Return codes: + * None + **/ +void +lpfc_free_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba, + struct lpfc_sli4_hdw_queue *hdwq) +{ + struct list_head *buf_list = &hdwq->cmd_rsp_buf_list; + struct fcp_cmd_rsp_buf *list_entry = NULL; + struct fcp_cmd_rsp_buf *tmp = NULL; + + spin_lock_irq(&hdwq->hdwq_lock); + + /* Free cmd_rsp buf pool */ + list_for_each_entry_safe(list_entry, tmp, + buf_list, + list_node) { + dma_pool_free(phba->lpfc_cmd_rsp_buf_pool, + list_entry->fcp_cmnd, + list_entry->fcp_cmd_rsp_dma_handle); + list_del(&list_entry->list_node); + kfree(list_entry); + } + + spin_unlock_irq(&hdwq->hdwq_lock); +} diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 467b8270f7fd..37fbcb46387e 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h @@ -365,9 +365,18 @@ struct lpfc_io_buf { /* Common fields */ struct list_head list; void *data; + dma_addr_t dma_handle; dma_addr_t dma_phys_sgl; - struct sli4_sge *dma_sgl; + + struct sli4_sge *dma_sgl; /* initial segment chunk */ + + /* linked list of extra sli4_hybrid_sge */ + struct list_head dma_sgl_xtra_list; + + /* list head for fcp_cmd_rsp buf */ + struct list_head dma_cmd_rsp_list; + struct lpfc_iocbq cur_iocbq; struct lpfc_sli4_hdw_queue *hdwq; uint16_t hdwq_no; diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 3aeca387b22a..3ec9cf4c6427 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -680,6 +680,13 @@ struct lpfc_sli4_hdw_queue { uint32_t cpucheck_xmt_io[LPFC_CHECK_CPU_CNT]; uint32_t cpucheck_cmpl_io[LPFC_CHECK_CPU_CNT]; #endif + + /* Per HDWQ pool resources */ + struct list_head sgl_list; + struct list_head cmd_rsp_buf_list; + + /* Lock for syncing Per HDWQ pool resources */ + spinlock_t hdwq_lock; }; #ifdef LPFC_HDWQ_LOCK_STAT @@ -1089,6 +1096,17 @@ int lpfc_sli4_post_status_check(struct lpfc_hba *); uint8_t lpfc_sli_config_mbox_subsys_get(struct lpfc_hba *, LPFC_MBOXQ_t *); uint8_t lpfc_sli_config_mbox_opcode_get(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_sli4_ras_dma_free(struct lpfc_hba *phba); +struct sli4_hybrid_sgl *lpfc_get_sgl_per_hdwq(struct lpfc_hba *phba, + struct lpfc_io_buf *buf); +struct fcp_cmd_rsp_buf *lpfc_get_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba, + struct lpfc_io_buf *buf); +int lpfc_put_sgl_per_hdwq(struct lpfc_hba *phba, struct lpfc_io_buf *buf); +int lpfc_put_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba, + struct lpfc_io_buf *buf); +void lpfc_free_sgl_per_hdwq(struct lpfc_hba *phba, + struct lpfc_sli4_hdw_queue *hdwq); +void lpfc_free_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba, + struct lpfc_sli4_hdw_queue *hdwq); static inline void *lpfc_sli4_qe(struct lpfc_queue *q, uint16_t idx) { return q->q_pgs[idx / q->entry_cnt_per_pg] + -- cgit v1.2.3-59-g8ed1b From 0d8af096430ed810aacade5f564e5b98347137d4 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:57:10 -0700 Subject: scsi: lpfc: Add NVMe sequence level error recovery support FC-NVMe-2 added support for sequence level error recovery in the FC-NVME protocol. This allows for the detection of errors and lost frames and immediate retransmission of data to avoid exchange termination, which escalates into NVMeoFC connection and association failures. A significant RAS improvement. The driver is modified to indicate support for SLER in the NVMe PRLI is issues and to check for support in the PRLI response. When both sides support it, the driver will set a bit in the WQE to enable the recovery behavior on the exchange. The adapter will take care of all detection and retransmission. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 1 + drivers/scsi/lpfc/lpfc_disc.h | 2 ++ drivers/scsi/lpfc/lpfc_els.c | 4 ++++ drivers/scsi/lpfc/lpfc_hw4.h | 8 ++++++++ drivers/scsi/lpfc/lpfc_init.c | 8 ++++++++ drivers/scsi/lpfc/lpfc_nportdisc.c | 13 ++++++++++++- drivers/scsi/lpfc/lpfc_nvme.c | 3 +++ 7 files changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index b738639fdf3f..c21d61ea82d9 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -797,6 +797,7 @@ struct lpfc_hba { uint8_t mds_diags_support; uint8_t bbcredit_support; uint8_t enab_exp_wqcq_pages; + u8 nsler; /* Firmware supports FC-NVMe-2 SLER */ /* HBA Config Parameters */ uint32_t cfg_ack0; diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 49bb0b180b19..482e4a888dae 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h @@ -112,6 +112,8 @@ struct lpfc_nodelist { uint8_t nlp_retry; /* used for ELS retries */ uint8_t nlp_fcp_info; /* class info, bits 0-3 */ #define NLP_FCP_2_DEVICE 0x10 /* FCP-2 device */ + u8 nlp_nvme_info; /* NVME NSLER Support */ +#define NLP_NVME_NSLER 0x1 /* NVME NSLER device */ uint16_t nlp_usg_map; /* ndlp management usage bitmap */ #define NLP_USG_NODE_ACT_BIT 0x1 /* Indicate ndlp is actively used */ diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 30bbfa3f6086..d5303994bfd6 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -2435,6 +2435,10 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, npr_nvme = (struct lpfc_nvme_prli *)pcmd; bf_set(prli_type_code, npr_nvme, PRLI_NVME_TYPE); bf_set(prli_estabImagePair, npr_nvme, 0); /* Should be 0 */ + if (phba->nsler) { + bf_set(prli_nsler, npr_nvme, 1); + bf_set(prli_conf, npr_nvme, 1); + } /* Only initiators request first burst. */ if ((phba->cfg_nvme_enable_fb) && diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index e198de8eda32..bd533475c86a 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -3480,6 +3480,10 @@ struct lpfc_sli4_parameters { #define cfg_bv1s_MASK 0x00000001 #define cfg_bv1s_WORD word19 +#define cfg_nsler_SHIFT 12 +#define cfg_nsler_MASK 0x00000001 +#define cfg_nsler_WORD word19 + uint32_t word20; #define cfg_max_tow_xri_SHIFT 0 #define cfg_max_tow_xri_MASK 0x0000ffff @@ -4621,6 +4625,7 @@ struct lpfc_nvme_prli { #define prli_type_code_WORD word1 uint32_t word_rsvd2; uint32_t word_rsvd3; + uint32_t word4; #define prli_fba_SHIFT 0 #define prli_fba_MASK 0x00000001 @@ -4637,6 +4642,9 @@ struct lpfc_nvme_prli { #define prli_conf_SHIFT 7 #define prli_conf_MASK 0x00000001 #define prli_conf_WORD word4 +#define prli_nsler_SHIFT 8 +#define prli_nsler_MASK 0x00000001 +#define prli_nsler_WORD word4 uint32_t word5; #define prli_fb_sz_SHIFT 0 #define prli_fb_sz_MASK 0x0000ffff diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index fa3741f12089..d71f1b066e30 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -11846,6 +11846,14 @@ fcponly: else phba->mds_diags_support = 0; + /* + * Check if the SLI port supports NSLER + */ + if (bf_get(cfg_nsler, mbx_sli4_parameters)) + phba->nsler = 1; + else + phba->nsler = 0; + return 0; } diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 41ac07b99739..f4b879d25fe9 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -799,9 +799,15 @@ lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (npr->writeXferRdyDis) ndlp->nlp_flag |= NLP_FIRSTBURST; } - if (npr->Retry) + if (npr->Retry && ndlp->nlp_type & + (NLP_FCP_INITIATOR | NLP_FCP_TARGET)) ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE; + if (npr->Retry && phba->nsler && + ndlp->nlp_type & (NLP_NVME_INITIATOR | NLP_NVME_TARGET)) + ndlp->nlp_nvme_info |= NLP_NVME_NSLER; + + /* If this driver is in nvme target mode, set the ndlp's fc4 * type to NVME provided the PRLI response claims NVME FC4 * type. Target mode does not issue gft_id so doesn't get @@ -2024,6 +2030,11 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (bf_get_be32(prli_init, nvpr)) ndlp->nlp_type |= NLP_NVME_INITIATOR; + if (phba->nsler && bf_get_be32(prli_nsler, nvpr)) + ndlp->nlp_nvme_info |= NLP_NVME_NSLER; + else + ndlp->nlp_nvme_info &= ~NLP_NVME_NSLER; + /* Target driver cannot solicit NVME FB. */ if (bf_get_be32(prli_tgt, nvpr)) { /* Complete the nvme target roles. The transport diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 5e48318eb7a9..f66859d928ac 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -1255,6 +1255,9 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport, sizeof(uint32_t) * 8); cstat->control_requests++; } + + if (pnode->nlp_nvme_info & NLP_NVME_NSLER) + bf_set(wqe_erp, &wqe->generic.wqe_com, 1); /* * Finish initializing those WQE fields that are independent * of the nvme_cmnd request_buffer -- cgit v1.2.3-59-g8ed1b From c00f62e6c5468ed0673c583f1ff284274e817410 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:57:11 -0700 Subject: scsi: lpfc: Merge per-protocol WQ/CQ pairs into single per-cpu pair Currently, each hardware queue, typically allocated per-cpu, consists of a WQ/CQ pair per protocol. Meaning if both SCSI and NVMe are supported 2 WQ/CQ pairs will exist for the hardware queue. Separate queues are unnecessary. The current implementation wastes memory backing the 2nd set of queues, and the use of double the SLI-4 WQ/CQ's means less hardware queues can be supported which means there may not always be enough to have a pair per cpu. If there is only 1 pair per cpu, more cpu's may get their own WQ/CQ. Rework the implementation to use a single WQ/CQ pair by both protocols. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 3 +- drivers/scsi/lpfc/lpfc_crtn.h | 2 +- drivers/scsi/lpfc/lpfc_debugfs.c | 92 ++---------- drivers/scsi/lpfc/lpfc_debugfs.h | 61 +++----- drivers/scsi/lpfc/lpfc_init.c | 296 ++++++++++----------------------------- drivers/scsi/lpfc/lpfc_nvme.c | 85 ++++------- drivers/scsi/lpfc/lpfc_nvmet.c | 8 +- drivers/scsi/lpfc/lpfc_scsi.c | 54 ++++--- drivers/scsi/lpfc/lpfc_sli.c | 145 +++++-------------- drivers/scsi/lpfc/lpfc_sli4.h | 29 ++-- 10 files changed, 218 insertions(+), 557 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index c21d61ea82d9..11873f0d521c 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -734,14 +734,13 @@ struct lpfc_hba { #define HBA_AER_ENABLED 0x1000 /* AER enabled with HBA */ #define HBA_DEVLOSS_TMO 0x2000 /* HBA in devloss timeout */ #define HBA_RRQ_ACTIVE 0x4000 /* process the rrq active list */ -#define HBA_FCP_IOQ_FLUSH 0x8000 /* FCP I/O queues being flushed */ +#define HBA_IOQ_FLUSH 0x8000 /* FCP/NVME I/O queues being flushed */ #define HBA_FW_DUMP_OP 0x10000 /* Skips fn reset before FW dump */ #define HBA_RECOVERABLE_UE 0x20000 /* Firmware supports recoverable UE */ #define HBA_FORCED_LINK_SPEED 0x40000 /* * Firmware supports Forced Link Speed * capability */ -#define HBA_NVME_IOQ_FLUSH 0x80000 /* NVME IO queues flushed. */ #define HBA_FLOGI_ISSUED 0x100000 /* FLOGI was issued */ uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/ diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index bee27bb7123c..8b84acc95a07 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -326,7 +326,7 @@ void lpfc_sli_bemem_bcopy(void *, void *, uint32_t); void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *); void lpfc_sli_abort_fcp_rings(struct lpfc_hba *phba); void lpfc_sli_hba_iocb_abort(struct lpfc_hba *); -void lpfc_sli_flush_fcp_rings(struct lpfc_hba *); +void lpfc_sli_flush_io_rings(struct lpfc_hba *phba); int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *, struct lpfc_dmabuf *); struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *, diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 75055ee59e91..45f431fbe0d2 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -416,8 +416,7 @@ lpfc_debugfs_commonxripools_data(struct lpfc_hba *phba, char *buf, int size) qp = &phba->sli4_hba.hdwq[lpfc_debugfs_last_xripool]; len += scnprintf(buf + len, size - len, "HdwQ %d Info ", i); - spin_lock_irqsave(&qp->abts_scsi_buf_list_lock, iflag); - spin_lock(&qp->abts_nvme_buf_list_lock); + spin_lock_irqsave(&qp->abts_io_buf_list_lock, iflag); spin_lock(&qp->io_buf_list_get_lock); spin_lock(&qp->io_buf_list_put_lock); out = qp->total_io_bufs - (qp->get_io_bufs + qp->put_io_bufs + @@ -430,8 +429,7 @@ lpfc_debugfs_commonxripools_data(struct lpfc_hba *phba, char *buf, int size) qp->abts_nvme_io_bufs, out); spin_unlock(&qp->io_buf_list_put_lock); spin_unlock(&qp->io_buf_list_get_lock); - spin_unlock(&qp->abts_nvme_buf_list_lock); - spin_unlock_irqrestore(&qp->abts_scsi_buf_list_lock, iflag); + spin_unlock_irqrestore(&qp->abts_io_buf_list_lock, iflag); lpfc_debugfs_last_xripool++; if (lpfc_debugfs_last_xripool >= phba->cfg_hdw_queue) @@ -533,9 +531,7 @@ lpfc_debugfs_multixripools_data(struct lpfc_hba *phba, char *buf, int size) continue; pbl_pool = &multixri_pool->pbl_pool; pvt_pool = &multixri_pool->pvt_pool; - txcmplq_cnt = qp->fcp_wq->pring->txcmplq_cnt; - if (qp->nvme_wq) - txcmplq_cnt += qp->nvme_wq->pring->txcmplq_cnt; + txcmplq_cnt = qp->io_wq->pring->txcmplq_cnt; scnprintf(tmp, sizeof(tmp), "%03d: %4d %4d %4d %4d | %10d %10d ", @@ -3786,23 +3782,13 @@ lpfc_idiag_wqs_for_cq(struct lpfc_hba *phba, char *wqtype, char *pbuffer, int qidx; for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) { - qp = phba->sli4_hba.hdwq[qidx].fcp_wq; + qp = phba->sli4_hba.hdwq[qidx].io_wq; if (qp->assoc_qid != cq_id) continue; *len = __lpfc_idiag_print_wq(qp, wqtype, pbuffer, *len); if (*len >= max_cnt) return 1; } - if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { - for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) { - qp = phba->sli4_hba.hdwq[qidx].nvme_wq; - if (qp->assoc_qid != cq_id) - continue; - *len = __lpfc_idiag_print_wq(qp, wqtype, pbuffer, *len); - if (*len >= max_cnt) - return 1; - } - } return 0; } @@ -3868,9 +3854,9 @@ lpfc_idiag_cqs_for_eq(struct lpfc_hba *phba, char *pbuffer, struct lpfc_queue *qp; int rc; - qp = phba->sli4_hba.hdwq[eqidx].fcp_cq; + qp = phba->sli4_hba.hdwq[eqidx].io_cq; - *len = __lpfc_idiag_print_cq(qp, "FCP", pbuffer, *len); + *len = __lpfc_idiag_print_cq(qp, "IO", pbuffer, *len); /* Reset max counter */ qp->CQ_max_cqe = 0; @@ -3878,28 +3864,11 @@ lpfc_idiag_cqs_for_eq(struct lpfc_hba *phba, char *pbuffer, if (*len >= max_cnt) return 1; - rc = lpfc_idiag_wqs_for_cq(phba, "FCP", pbuffer, len, + rc = lpfc_idiag_wqs_for_cq(phba, "IO", pbuffer, len, max_cnt, qp->queue_id); if (rc) return 1; - if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { - qp = phba->sli4_hba.hdwq[eqidx].nvme_cq; - - *len = __lpfc_idiag_print_cq(qp, "NVME", pbuffer, *len); - - /* Reset max counter */ - qp->CQ_max_cqe = 0; - - if (*len >= max_cnt) - return 1; - - rc = lpfc_idiag_wqs_for_cq(phba, "NVME", pbuffer, len, - max_cnt, qp->queue_id); - if (rc) - return 1; - } - if ((eqidx < phba->cfg_nvmet_mrq) && phba->nvmet_support) { /* NVMET CQset */ qp = phba->sli4_hba.nvmet_cqset[eqidx]; @@ -4348,7 +4317,7 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, if (phba->sli4_hba.hdwq) { for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) { - qp = phba->sli4_hba.hdwq[qidx].fcp_cq; + qp = phba->sli4_hba.hdwq[qidx].io_cq; if (qp && qp->queue_id == queid) { /* Sanity check */ rc = lpfc_idiag_que_param_check( @@ -4360,22 +4329,6 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, } } } - /* NVME complete queue */ - if (phba->sli4_hba.hdwq) { - qidx = 0; - do { - qp = phba->sli4_hba.hdwq[qidx].nvme_cq; - if (qp && qp->queue_id == queid) { - /* Sanity check */ - rc = lpfc_idiag_que_param_check( - qp, index, count); - if (rc) - goto error_out; - idiag.ptr_private = qp; - goto pass_check; - } - } while (++qidx < phba->cfg_hdw_queue); - } goto error_out; break; case LPFC_IDIAG_MQ: @@ -4419,20 +4372,7 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, if (phba->sli4_hba.hdwq) { /* FCP/SCSI work queue */ for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) { - qp = phba->sli4_hba.hdwq[qidx].fcp_wq; - if (qp && qp->queue_id == queid) { - /* Sanity check */ - rc = lpfc_idiag_que_param_check( - qp, index, count); - if (rc) - goto error_out; - idiag.ptr_private = qp; - goto pass_check; - } - } - /* NVME work queue */ - for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) { - qp = phba->sli4_hba.hdwq[qidx].nvme_wq; + qp = phba->sli4_hba.hdwq[qidx].io_wq; if (qp && qp->queue_id == queid) { /* Sanity check */ rc = lpfc_idiag_que_param_check( @@ -6442,12 +6382,7 @@ lpfc_debug_dump_all_queues(struct lpfc_hba *phba) lpfc_debug_dump_wq(phba, DUMP_NVMELS, 0); for (idx = 0; idx < phba->cfg_hdw_queue; idx++) - lpfc_debug_dump_wq(phba, DUMP_FCP, idx); - - if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { - for (idx = 0; idx < phba->cfg_hdw_queue; idx++) - lpfc_debug_dump_wq(phba, DUMP_NVME, idx); - } + lpfc_debug_dump_wq(phba, DUMP_IO, idx); lpfc_debug_dump_hdr_rq(phba); lpfc_debug_dump_dat_rq(phba); @@ -6459,12 +6394,7 @@ lpfc_debug_dump_all_queues(struct lpfc_hba *phba) lpfc_debug_dump_cq(phba, DUMP_NVMELS, 0); for (idx = 0; idx < phba->cfg_hdw_queue; idx++) - lpfc_debug_dump_cq(phba, DUMP_FCP, idx); - - if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { - for (idx = 0; idx < phba->cfg_hdw_queue; idx++) - lpfc_debug_dump_cq(phba, DUMP_NVME, idx); - } + lpfc_debug_dump_cq(phba, DUMP_IO, idx); /* * Dump Event Queues (EQs) diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h index 34070874616d..20f2537af511 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.h +++ b/drivers/scsi/lpfc/lpfc_debugfs.h @@ -291,8 +291,7 @@ struct lpfc_idiag { #define LPFC_DUMP_MULTIXRIPOOL_SIZE 8192 enum { - DUMP_FCP, - DUMP_NVME, + DUMP_IO, DUMP_MBX, DUMP_ELS, DUMP_NVMELS, @@ -415,12 +414,9 @@ lpfc_debug_dump_wq(struct lpfc_hba *phba, int qtype, int wqidx) struct lpfc_queue *wq; char *qtypestr; - if (qtype == DUMP_FCP) { - wq = phba->sli4_hba.hdwq[wqidx].fcp_wq; - qtypestr = "FCP"; - } else if (qtype == DUMP_NVME) { - wq = phba->sli4_hba.hdwq[wqidx].nvme_wq; - qtypestr = "NVME"; + if (qtype == DUMP_IO) { + wq = phba->sli4_hba.hdwq[wqidx].io_wq; + qtypestr = "IO"; } else if (qtype == DUMP_MBX) { wq = phba->sli4_hba.mbx_wq; qtypestr = "MBX"; @@ -433,7 +429,7 @@ lpfc_debug_dump_wq(struct lpfc_hba *phba, int qtype, int wqidx) } else return; - if (qtype == DUMP_FCP || qtype == DUMP_NVME) + if (qtype == DUMP_IO) pr_err("%s WQ: WQ[Idx:%d|Qid:%d]\n", qtypestr, wqidx, wq->queue_id); else @@ -459,17 +455,13 @@ lpfc_debug_dump_cq(struct lpfc_hba *phba, int qtype, int wqidx) char *qtypestr; int eqidx; - /* fcp/nvme wq and cq are 1:1, thus same indexes */ + /* io wq and cq are 1:1, thus same indexes */ eq = NULL; - if (qtype == DUMP_FCP) { - wq = phba->sli4_hba.hdwq[wqidx].fcp_wq; - cq = phba->sli4_hba.hdwq[wqidx].fcp_cq; - qtypestr = "FCP"; - } else if (qtype == DUMP_NVME) { - wq = phba->sli4_hba.hdwq[wqidx].nvme_wq; - cq = phba->sli4_hba.hdwq[wqidx].nvme_cq; - qtypestr = "NVME"; + if (qtype == DUMP_IO) { + wq = phba->sli4_hba.hdwq[wqidx].io_wq; + cq = phba->sli4_hba.hdwq[wqidx].io_cq; + qtypestr = "IO"; } else if (qtype == DUMP_MBX) { wq = phba->sli4_hba.mbx_wq; cq = phba->sli4_hba.mbx_cq; @@ -496,7 +488,7 @@ lpfc_debug_dump_cq(struct lpfc_hba *phba, int qtype, int wqidx) eq = phba->sli4_hba.hdwq[0].hba_eq; } - if (qtype == DUMP_FCP || qtype == DUMP_NVME) + if (qtype == DUMP_IO) pr_err("%s CQ: WQ[Idx:%d|Qid%d]->CQ[Idx%d|Qid%d]" "->EQ[Idx:%d|Qid:%d]:\n", qtypestr, wqidx, wq->queue_id, wqidx, cq->queue_id, @@ -572,20 +564,11 @@ lpfc_debug_dump_wq_by_id(struct lpfc_hba *phba, int qid) int wq_idx; for (wq_idx = 0; wq_idx < phba->cfg_hdw_queue; wq_idx++) - if (phba->sli4_hba.hdwq[wq_idx].fcp_wq->queue_id == qid) + if (phba->sli4_hba.hdwq[wq_idx].io_wq->queue_id == qid) break; if (wq_idx < phba->cfg_hdw_queue) { - pr_err("FCP WQ[Idx:%d|Qid:%d]\n", wq_idx, qid); - lpfc_debug_dump_q(phba->sli4_hba.hdwq[wq_idx].fcp_wq); - return; - } - - for (wq_idx = 0; wq_idx < phba->cfg_hdw_queue; wq_idx++) - if (phba->sli4_hba.hdwq[wq_idx].nvme_wq->queue_id == qid) - break; - if (wq_idx < phba->cfg_hdw_queue) { - pr_err("NVME WQ[Idx:%d|Qid:%d]\n", wq_idx, qid); - lpfc_debug_dump_q(phba->sli4_hba.hdwq[wq_idx].nvme_wq); + pr_err("IO WQ[Idx:%d|Qid:%d]\n", wq_idx, qid); + lpfc_debug_dump_q(phba->sli4_hba.hdwq[wq_idx].io_wq); return; } @@ -654,22 +637,12 @@ lpfc_debug_dump_cq_by_id(struct lpfc_hba *phba, int qid) int cq_idx; for (cq_idx = 0; cq_idx < phba->cfg_hdw_queue; cq_idx++) - if (phba->sli4_hba.hdwq[cq_idx].fcp_cq->queue_id == qid) - break; - - if (cq_idx < phba->cfg_hdw_queue) { - pr_err("FCP CQ[Idx:%d|Qid:%d]\n", cq_idx, qid); - lpfc_debug_dump_q(phba->sli4_hba.hdwq[cq_idx].fcp_cq); - return; - } - - for (cq_idx = 0; cq_idx < phba->cfg_hdw_queue; cq_idx++) - if (phba->sli4_hba.hdwq[cq_idx].nvme_cq->queue_id == qid) + if (phba->sli4_hba.hdwq[cq_idx].io_cq->queue_id == qid) break; if (cq_idx < phba->cfg_hdw_queue) { - pr_err("NVME CQ[Idx:%d|Qid:%d]\n", cq_idx, qid); - lpfc_debug_dump_q(phba->sli4_hba.hdwq[cq_idx].nvme_cq); + pr_err("IO CQ[Idx:%d|Qid:%d]\n", cq_idx, qid); + lpfc_debug_dump_q(phba->sli4_hba.hdwq[cq_idx].io_cq); return; } diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index d71f1b066e30..0bc04af1d2fb 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1082,8 +1082,8 @@ lpfc_hba_down_post_s4(struct lpfc_hba *phba) for (idx = 0; idx < phba->cfg_hdw_queue; idx++) { qp = &phba->sli4_hba.hdwq[idx]; - spin_lock(&qp->abts_scsi_buf_list_lock); - list_splice_init(&qp->lpfc_abts_scsi_buf_list, + spin_lock(&qp->abts_io_buf_list_lock); + list_splice_init(&qp->lpfc_abts_io_buf_list, &aborts); list_for_each_entry_safe(psb, psb_next, &aborts, list) { @@ -1094,29 +1094,11 @@ lpfc_hba_down_post_s4(struct lpfc_hba *phba) spin_lock(&qp->io_buf_list_put_lock); list_splice_init(&aborts, &qp->lpfc_io_buf_list_put); qp->put_io_bufs += qp->abts_scsi_io_bufs; + qp->put_io_bufs += qp->abts_nvme_io_bufs; qp->abts_scsi_io_bufs = 0; + qp->abts_nvme_io_bufs = 0; spin_unlock(&qp->io_buf_list_put_lock); - spin_unlock(&qp->abts_scsi_buf_list_lock); - - if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { - spin_lock(&qp->abts_nvme_buf_list_lock); - list_splice_init(&qp->lpfc_abts_nvme_buf_list, - &nvme_aborts); - list_for_each_entry_safe(psb, psb_next, &nvme_aborts, - list) { - psb->pCmd = NULL; - psb->status = IOSTAT_SUCCESS; - cnt++; - } - spin_lock(&qp->io_buf_list_put_lock); - qp->put_io_bufs += qp->abts_nvme_io_bufs; - qp->abts_nvme_io_bufs = 0; - list_splice_init(&nvme_aborts, - &qp->lpfc_io_buf_list_put); - spin_unlock(&qp->io_buf_list_put_lock); - spin_unlock(&qp->abts_nvme_buf_list_lock); - - } + spin_unlock(&qp->abts_io_buf_list_lock); } spin_unlock_irq(&phba->hbalock); @@ -1546,8 +1528,7 @@ lpfc_sli4_offline_eratt(struct lpfc_hba *phba) spin_unlock_irq(&phba->hbalock); lpfc_offline_prep(phba, LPFC_MBX_NO_WAIT); - lpfc_sli_flush_fcp_rings(phba); - lpfc_sli_flush_nvme_rings(phba); + lpfc_sli_flush_io_rings(phba); lpfc_offline(phba); lpfc_hba_down_post(phba); lpfc_unblock_mgmt_io(phba); @@ -1809,8 +1790,7 @@ lpfc_sli4_port_sta_fn_reset(struct lpfc_hba *phba, int mbx_action, "2887 Reset Needed: Attempting Port " "Recovery...\n"); lpfc_offline_prep(phba, mbx_action); - lpfc_sli_flush_fcp_rings(phba); - lpfc_sli_flush_nvme_rings(phba); + lpfc_sli_flush_io_rings(phba); lpfc_offline(phba); /* release interrupt for possible resource change */ lpfc_sli4_disable_intr(phba); @@ -3266,12 +3246,8 @@ static void lpfc_destroy_multixri_pools(struct lpfc_hba *phba) if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) lpfc_destroy_expedite_pool(phba); - if (!(phba->pport->load_flag & FC_UNLOADING)) { - lpfc_sli_flush_fcp_rings(phba); - - if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) - lpfc_sli_flush_nvme_rings(phba); - } + if (!(phba->pport->load_flag & FC_UNLOADING)) + lpfc_sli_flush_io_rings(phba); hwq_count = phba->cfg_hdw_queue; @@ -6516,11 +6492,9 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) /* * Initialize the SLI Layer to run with lpfc SLI4 HBAs. */ - if (phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP) { - /* Initialize the Abort scsi buffer list used by driver */ - spin_lock_init(&phba->sli4_hba.abts_scsi_buf_list_lock); - INIT_LIST_HEAD(&phba->sli4_hba.lpfc_abts_scsi_buf_list); - } + /* Initialize the Abort buffer list used by driver */ + spin_lock_init(&phba->sli4_hba.abts_io_buf_list_lock); + INIT_LIST_HEAD(&phba->sli4_hba.lpfc_abts_io_buf_list); if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { /* Initialize the Abort nvme buffer list used by driver */ @@ -8475,11 +8449,6 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) */ qmin -= 4; - /* If NVME is configured, double the number of CQ/WQs needed */ - if ((phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) && - !phba->nvmet_support) - qmin /= 2; - /* Check to see if there is enough for NVME */ if ((phba->cfg_irq_chann > qmin) || (phba->cfg_hdw_queue > qmin)) { @@ -8736,51 +8705,14 @@ lpfc_sli4_queue_verify(struct lpfc_hba *phba) } static int -lpfc_alloc_nvme_wq_cq(struct lpfc_hba *phba, int wqidx) -{ - struct lpfc_queue *qdesc; - int cpu; - - cpu = lpfc_find_cpu_handle(phba, wqidx, LPFC_FIND_BY_HDWQ); - qdesc = lpfc_sli4_queue_alloc(phba, LPFC_EXPANDED_PAGE_SIZE, - phba->sli4_hba.cq_esize, - LPFC_CQE_EXP_COUNT, cpu); - if (!qdesc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0508 Failed allocate fast-path NVME CQ (%d)\n", - wqidx); - return 1; - } - qdesc->qe_valid = 1; - qdesc->hdwq = wqidx; - qdesc->chann = cpu; - phba->sli4_hba.hdwq[wqidx].nvme_cq = qdesc; - - qdesc = lpfc_sli4_queue_alloc(phba, LPFC_EXPANDED_PAGE_SIZE, - LPFC_WQE128_SIZE, LPFC_WQE_EXP_COUNT, - cpu); - if (!qdesc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0509 Failed allocate fast-path NVME WQ (%d)\n", - wqidx); - return 1; - } - qdesc->hdwq = wqidx; - qdesc->chann = wqidx; - phba->sli4_hba.hdwq[wqidx].nvme_wq = qdesc; - list_add_tail(&qdesc->wq_list, &phba->sli4_hba.lpfc_wq_list); - return 0; -} - -static int -lpfc_alloc_fcp_wq_cq(struct lpfc_hba *phba, int wqidx) +lpfc_alloc_io_wq_cq(struct lpfc_hba *phba, int idx) { struct lpfc_queue *qdesc; - uint32_t wqesize; + u32 wqesize; int cpu; - cpu = lpfc_find_cpu_handle(phba, wqidx, LPFC_FIND_BY_HDWQ); - /* Create Fast Path FCP CQs */ + cpu = lpfc_find_cpu_handle(phba, idx, LPFC_FIND_BY_HDWQ); + /* Create Fast Path IO CQs */ if (phba->enab_exp_wqcq_pages) /* Increase the CQ size when WQEs contain an embedded cdb */ qdesc = lpfc_sli4_queue_alloc(phba, LPFC_EXPANDED_PAGE_SIZE, @@ -8793,15 +8725,15 @@ lpfc_alloc_fcp_wq_cq(struct lpfc_hba *phba, int wqidx) phba->sli4_hba.cq_ecount, cpu); if (!qdesc) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0499 Failed allocate fast-path FCP CQ (%d)\n", wqidx); + "0499 Failed allocate fast-path IO CQ (%d)\n", idx); return 1; } qdesc->qe_valid = 1; - qdesc->hdwq = wqidx; + qdesc->hdwq = idx; qdesc->chann = cpu; - phba->sli4_hba.hdwq[wqidx].fcp_cq = qdesc; + phba->sli4_hba.hdwq[idx].io_cq = qdesc; - /* Create Fast Path FCP WQs */ + /* Create Fast Path IO WQs */ if (phba->enab_exp_wqcq_pages) { /* Increase the WQ size when WQEs contain an embedded cdb */ wqesize = (phba->fcp_embed_io) ? @@ -8816,13 +8748,13 @@ lpfc_alloc_fcp_wq_cq(struct lpfc_hba *phba, int wqidx) if (!qdesc) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0503 Failed allocate fast-path FCP WQ (%d)\n", - wqidx); + "0503 Failed allocate fast-path IO WQ (%d)\n", + idx); return 1; } - qdesc->hdwq = wqidx; - qdesc->chann = wqidx; - phba->sli4_hba.hdwq[wqidx].fcp_wq = qdesc; + qdesc->hdwq = idx; + qdesc->chann = cpu; + phba->sli4_hba.hdwq[idx].io_wq = qdesc; list_add_tail(&qdesc->wq_list, &phba->sli4_hba.lpfc_wq_list); return 0; } @@ -8886,11 +8818,9 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) qp->get_io_bufs = 0; qp->put_io_bufs = 0; qp->total_io_bufs = 0; - spin_lock_init(&qp->abts_scsi_buf_list_lock); - INIT_LIST_HEAD(&qp->lpfc_abts_scsi_buf_list); + spin_lock_init(&qp->abts_io_buf_list_lock); + INIT_LIST_HEAD(&qp->lpfc_abts_io_buf_list); qp->abts_scsi_io_bufs = 0; - spin_lock_init(&qp->abts_nvme_buf_list_lock); - INIT_LIST_HEAD(&qp->lpfc_abts_nvme_buf_list); qp->abts_nvme_io_bufs = 0; INIT_LIST_HEAD(&qp->sgl_list); INIT_LIST_HEAD(&qp->cmd_rsp_buf_list); @@ -8991,41 +8921,31 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) qp->hba_eq = phba->sli4_hba.hdwq[eqcpup->hdwq].hba_eq; } - /* Allocate SCSI SLI4 CQ/WQs */ + /* Allocate IO Path SLI4 CQ/WQs */ for (idx = 0; idx < phba->cfg_hdw_queue; idx++) { - if (lpfc_alloc_fcp_wq_cq(phba, idx)) + if (lpfc_alloc_io_wq_cq(phba, idx)) goto out_error; } - /* Allocate NVME SLI4 CQ/WQs */ - if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { - for (idx = 0; idx < phba->cfg_hdw_queue; idx++) { - if (lpfc_alloc_nvme_wq_cq(phba, idx)) - goto out_error; - } - - if (phba->nvmet_support) { - for (idx = 0; idx < phba->cfg_nvmet_mrq; idx++) { - cpu = lpfc_find_cpu_handle(phba, idx, - LPFC_FIND_BY_HDWQ); - qdesc = lpfc_sli4_queue_alloc( - phba, + if (phba->nvmet_support) { + for (idx = 0; idx < phba->cfg_nvmet_mrq; idx++) { + cpu = lpfc_find_cpu_handle(phba, idx, + LPFC_FIND_BY_HDWQ); + qdesc = lpfc_sli4_queue_alloc(phba, LPFC_DEFAULT_PAGE_SIZE, phba->sli4_hba.cq_esize, phba->sli4_hba.cq_ecount, cpu); - if (!qdesc) { - lpfc_printf_log( - phba, KERN_ERR, LOG_INIT, + if (!qdesc) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "3142 Failed allocate NVME " "CQ Set (%d)\n", idx); - goto out_error; - } - qdesc->qe_valid = 1; - qdesc->hdwq = idx; - qdesc->chann = cpu; - phba->sli4_hba.nvmet_cqset[idx] = qdesc; + goto out_error; } + qdesc->qe_valid = 1; + qdesc->hdwq = idx; + qdesc->chann = cpu; + phba->sli4_hba.nvmet_cqset[idx] = qdesc; } } @@ -9056,7 +8976,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) goto out_error; } qdesc->qe_valid = 1; - qdesc->chann = 0; + qdesc->chann = cpu; phba->sli4_hba.els_cq = qdesc; @@ -9074,7 +8994,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) "0505 Failed allocate slow-path MQ\n"); goto out_error; } - qdesc->chann = 0; + qdesc->chann = cpu; phba->sli4_hba.mbx_wq = qdesc; /* @@ -9090,7 +9010,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) "0504 Failed allocate slow-path ELS WQ\n"); goto out_error; } - qdesc->chann = 0; + qdesc->chann = cpu; phba->sli4_hba.els_wq = qdesc; list_add_tail(&qdesc->wq_list, &phba->sli4_hba.lpfc_wq_list); @@ -9104,7 +9024,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) "6079 Failed allocate NVME LS CQ\n"); goto out_error; } - qdesc->chann = 0; + qdesc->chann = cpu; qdesc->qe_valid = 1; phba->sli4_hba.nvmels_cq = qdesc; @@ -9117,7 +9037,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) "6080 Failed allocate NVME LS WQ\n"); goto out_error; } - qdesc->chann = 0; + qdesc->chann = cpu; phba->sli4_hba.nvmels_wq = qdesc; list_add_tail(&qdesc->wq_list, &phba->sli4_hba.lpfc_wq_list); } @@ -9260,15 +9180,10 @@ lpfc_sli4_release_hdwq(struct lpfc_hba *phba) /* Loop thru all Hardware Queues */ for (idx = 0; idx < phba->cfg_hdw_queue; idx++) { /* Free the CQ/WQ corresponding to the Hardware Queue */ - lpfc_sli4_queue_free(hdwq[idx].fcp_cq); - lpfc_sli4_queue_free(hdwq[idx].nvme_cq); - lpfc_sli4_queue_free(hdwq[idx].fcp_wq); - lpfc_sli4_queue_free(hdwq[idx].nvme_wq); - hdwq[idx].hba_eq = NULL; - hdwq[idx].fcp_cq = NULL; - hdwq[idx].nvme_cq = NULL; - hdwq[idx].fcp_wq = NULL; - hdwq[idx].nvme_wq = NULL; + lpfc_sli4_queue_free(hdwq[idx].io_cq); + lpfc_sli4_queue_free(hdwq[idx].io_wq); + hdwq[idx].io_cq = NULL; + hdwq[idx].io_wq = NULL; if (phba->cfg_xpsgl && !phba->nvmet_support) lpfc_free_sgl_per_hdwq(phba, &hdwq[idx]); lpfc_free_cmd_rsp_buf_per_hdwq(phba, &hdwq[idx]); @@ -9471,8 +9386,7 @@ lpfc_setup_cq_lookup(struct lpfc_hba *phba) list_for_each_entry(childq, &eq->child_list, list) { if (childq->queue_id > phba->sli4_hba.cq_max) continue; - if ((childq->subtype == LPFC_FCP) || - (childq->subtype == LPFC_NVME)) + if (childq->subtype == LPFC_IO) phba->sli4_hba.cq_lookup[childq->queue_id] = childq; } @@ -9598,31 +9512,6 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) } /* Loop thru all Hardware Queues */ - if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { - for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) { - cpu = lpfc_find_cpu_handle(phba, qidx, - LPFC_FIND_BY_HDWQ); - cpup = &phba->sli4_hba.cpu_map[cpu]; - - /* Create the CQ/WQ corresponding to the - * Hardware Queue - */ - rc = lpfc_create_wq_cq(phba, - phba->sli4_hba.hdwq[cpup->hdwq].hba_eq, - qp[qidx].nvme_cq, - qp[qidx].nvme_wq, - &phba->sli4_hba.hdwq[qidx].nvme_cq_map, - qidx, LPFC_NVME); - if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "6123 Failed to setup fastpath " - "NVME WQ/CQ (%d), rc = 0x%x\n", - qidx, (uint32_t)rc); - goto out_destroy; - } - } - } - for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) { cpu = lpfc_find_cpu_handle(phba, qidx, LPFC_FIND_BY_HDWQ); cpup = &phba->sli4_hba.cpu_map[cpu]; @@ -9630,14 +9519,15 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) /* Create the CQ/WQ corresponding to the Hardware Queue */ rc = lpfc_create_wq_cq(phba, phba->sli4_hba.hdwq[cpup->hdwq].hba_eq, - qp[qidx].fcp_cq, - qp[qidx].fcp_wq, - &phba->sli4_hba.hdwq[qidx].fcp_cq_map, - qidx, LPFC_FCP); + qp[qidx].io_cq, + qp[qidx].io_wq, + &phba->sli4_hba.hdwq[qidx].io_cq_map, + qidx, + LPFC_IO); if (rc) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0535 Failed to setup fastpath " - "FCP WQ/CQ (%d), rc = 0x%x\n", + "IO WQ/CQ (%d), rc = 0x%x\n", qidx, (uint32_t)rc); goto out_destroy; } @@ -9937,10 +9827,8 @@ lpfc_sli4_queue_unset(struct lpfc_hba *phba) for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) { /* Destroy the CQ/WQ corresponding to Hardware Queue */ qp = &phba->sli4_hba.hdwq[qidx]; - lpfc_wq_destroy(phba, qp->fcp_wq); - lpfc_wq_destroy(phba, qp->nvme_wq); - lpfc_cq_destroy(phba, qp->fcp_cq); - lpfc_cq_destroy(phba, qp->nvme_cq); + lpfc_wq_destroy(phba, qp->io_wq); + lpfc_cq_destroy(phba, qp->io_cq); } /* Loop thru all IRQ vectors */ for (qidx = 0; qidx < phba->cfg_irq_chann; qidx++) { @@ -11397,11 +11285,10 @@ static void lpfc_sli4_xri_exchange_busy_wait(struct lpfc_hba *phba) { struct lpfc_sli4_hdw_queue *qp; - int idx, ccnt, fcnt; + int idx, ccnt; int wait_time = 0; int io_xri_cmpl = 1; int nvmet_xri_cmpl = 1; - int fcp_xri_cmpl = 1; int els_xri_cmpl = list_empty(&phba->sli4_hba.lpfc_abts_els_sgl_list); /* Driver just aborted IOs during the hba_unset process. Pause @@ -11415,32 +11302,21 @@ lpfc_sli4_xri_exchange_busy_wait(struct lpfc_hba *phba) lpfc_nvme_wait_for_io_drain(phba); ccnt = 0; - fcnt = 0; for (idx = 0; idx < phba->cfg_hdw_queue; idx++) { qp = &phba->sli4_hba.hdwq[idx]; - fcp_xri_cmpl = list_empty( - &qp->lpfc_abts_scsi_buf_list); - if (!fcp_xri_cmpl) /* if list is NOT empty */ - fcnt++; - if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { - io_xri_cmpl = list_empty( - &qp->lpfc_abts_nvme_buf_list); - if (!io_xri_cmpl) /* if list is NOT empty */ - ccnt++; - } + io_xri_cmpl = list_empty(&qp->lpfc_abts_io_buf_list); + if (!io_xri_cmpl) /* if list is NOT empty */ + ccnt++; } if (ccnt) io_xri_cmpl = 0; - if (fcnt) - fcp_xri_cmpl = 0; if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { nvmet_xri_cmpl = list_empty(&phba->sli4_hba.lpfc_abts_nvmet_ctx_list); } - while (!fcp_xri_cmpl || !els_xri_cmpl || !io_xri_cmpl || - !nvmet_xri_cmpl) { + while (!els_xri_cmpl || !io_xri_cmpl || !nvmet_xri_cmpl) { if (wait_time > LPFC_XRI_EXCH_BUSY_WAIT_TMO) { if (!nvmet_xri_cmpl) lpfc_printf_log(phba, KERN_ERR, LOG_INIT, @@ -11449,12 +11325,7 @@ lpfc_sli4_xri_exchange_busy_wait(struct lpfc_hba *phba) wait_time/1000); if (!io_xri_cmpl) lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "6100 NVME XRI exchange busy " - "wait time: %d seconds.\n", - wait_time/1000); - if (!fcp_xri_cmpl) - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "2877 FCP XRI exchange busy " + "6100 IO XRI exchange busy " "wait time: %d seconds.\n", wait_time/1000); if (!els_xri_cmpl) @@ -11470,24 +11341,15 @@ lpfc_sli4_xri_exchange_busy_wait(struct lpfc_hba *phba) } ccnt = 0; - fcnt = 0; for (idx = 0; idx < phba->cfg_hdw_queue; idx++) { qp = &phba->sli4_hba.hdwq[idx]; - fcp_xri_cmpl = list_empty( - &qp->lpfc_abts_scsi_buf_list); - if (!fcp_xri_cmpl) /* if list is NOT empty */ - fcnt++; - if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { - io_xri_cmpl = list_empty( - &qp->lpfc_abts_nvme_buf_list); - if (!io_xri_cmpl) /* if list is NOT empty */ - ccnt++; - } + io_xri_cmpl = list_empty( + &qp->lpfc_abts_io_buf_list); + if (!io_xri_cmpl) /* if list is NOT empty */ + ccnt++; } if (ccnt) io_xri_cmpl = 0; - if (fcnt) - fcp_xri_cmpl = 0; if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { nvmet_xri_cmpl = list_empty( @@ -12282,7 +12144,7 @@ lpfc_sli_prep_dev_for_reset(struct lpfc_hba *phba) lpfc_scsi_dev_block(phba); /* Flush all driver's outstanding SCSI I/Os as we are to reset */ - lpfc_sli_flush_fcp_rings(phba); + lpfc_sli_flush_io_rings(phba); /* stop all timers */ lpfc_stop_hba_timers(phba); @@ -12312,7 +12174,7 @@ lpfc_sli_prep_dev_for_perm_failure(struct lpfc_hba *phba) lpfc_stop_hba_timers(phba); /* Clean up all driver's outstanding SCSI I/Os */ - lpfc_sli_flush_fcp_rings(phba); + lpfc_sli_flush_io_rings(phba); } /** @@ -13084,12 +12946,8 @@ lpfc_sli4_prep_dev_for_reset(struct lpfc_hba *phba) /* Block all SCSI devices' I/Os on the host */ lpfc_scsi_dev_block(phba); - /* Flush all driver's outstanding SCSI I/Os as we are to reset */ - lpfc_sli_flush_fcp_rings(phba); - - /* Flush the outstanding NVME IOs if fc4 type enabled. */ - if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) - lpfc_sli_flush_nvme_rings(phba); + /* Flush all driver's outstanding I/Os as we are to reset */ + lpfc_sli_flush_io_rings(phba); /* stop all timers */ lpfc_stop_hba_timers(phba); @@ -13120,12 +12978,8 @@ lpfc_sli4_prep_dev_for_perm_failure(struct lpfc_hba *phba) /* stop all timers */ lpfc_stop_hba_timers(phba); - /* Clean up all driver's outstanding SCSI I/Os */ - lpfc_sli_flush_fcp_rings(phba); - - /* Flush the outstanding NVME IOs if fc4 type enabled. */ - if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) - lpfc_sli_flush_nvme_rings(phba); + /* Clean up all driver's outstanding I/Os */ + lpfc_sli_flush_io_rings(phba); } /** diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index f66859d928ac..a227e36cbdc2 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -1830,7 +1830,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, */ spin_lock_irqsave(&phba->hbalock, flags); /* driver queued commands are in process of being flushed */ - if (phba->hba_flag & HBA_NVME_IOQ_FLUSH) { + if (phba->hba_flag & HBA_IOQ_FLUSH) { spin_unlock_irqrestore(&phba->hbalock, flags); lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS, "6139 Driver in reset cleanup - flushing " @@ -2091,11 +2091,11 @@ lpfc_release_nvme_buf(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_ncmd) lpfc_ncmd->cur_iocbq.sli4_xritag, lpfc_ncmd->cur_iocbq.iotag); - spin_lock_irqsave(&qp->abts_nvme_buf_list_lock, iflag); + spin_lock_irqsave(&qp->abts_io_buf_list_lock, iflag); list_add_tail(&lpfc_ncmd->list, - &qp->lpfc_abts_nvme_buf_list); + &qp->lpfc_abts_io_buf_list); qp->abts_nvme_io_bufs++; - spin_unlock_irqrestore(&qp->abts_nvme_buf_list_lock, iflag); + spin_unlock_irqrestore(&qp->abts_io_buf_list_lock, iflag); } else lpfc_release_io_buf(phba, (struct lpfc_io_buf *)lpfc_ncmd, qp); } @@ -2220,7 +2220,7 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport, if (unlikely(!ret)) { pending = 0; for (i = 0; i < phba->cfg_hdw_queue; i++) { - pring = phba->sli4_hba.hdwq[i].nvme_wq->pring; + pring = phba->sli4_hba.hdwq[i].io_wq->pring; if (!pring) continue; if (pring->txcmplq_cnt) @@ -2624,6 +2624,7 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) * lpfc_sli4_nvme_xri_aborted - Fast-path process of NVME xri abort * @phba: pointer to lpfc hba data structure. * @axri: pointer to the fcp xri abort wcqe structure. + * @lpfc_ncmd: The nvme job structure for the request being aborted. * * This routine is invoked by the worker thread to process a SLI4 fast-path * NVME aborted xri. Aborted NVME IO commands are completed to the transport @@ -2631,59 +2632,33 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) **/ void lpfc_sli4_nvme_xri_aborted(struct lpfc_hba *phba, - struct sli4_wcqe_xri_aborted *axri, int idx) + struct sli4_wcqe_xri_aborted *axri, + struct lpfc_io_buf *lpfc_ncmd) { uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri); - struct lpfc_io_buf *lpfc_ncmd, *next_lpfc_ncmd; struct nvmefc_fcp_req *nvme_cmd = NULL; - struct lpfc_nodelist *ndlp; - struct lpfc_sli4_hdw_queue *qp; - unsigned long iflag = 0; + struct lpfc_nodelist *ndlp = lpfc_ncmd->ndlp; - if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME)) - return; - qp = &phba->sli4_hba.hdwq[idx]; - spin_lock_irqsave(&phba->hbalock, iflag); - spin_lock(&qp->abts_nvme_buf_list_lock); - list_for_each_entry_safe(lpfc_ncmd, next_lpfc_ncmd, - &qp->lpfc_abts_nvme_buf_list, list) { - if (lpfc_ncmd->cur_iocbq.sli4_xritag == xri) { - list_del_init(&lpfc_ncmd->list); - qp->abts_nvme_io_bufs--; - lpfc_ncmd->flags &= ~LPFC_SBUF_XBUSY; - lpfc_ncmd->status = IOSTAT_SUCCESS; - spin_unlock(&qp->abts_nvme_buf_list_lock); - - spin_unlock_irqrestore(&phba->hbalock, iflag); - ndlp = lpfc_ncmd->ndlp; - if (ndlp) - lpfc_sli4_abts_err_handler(phba, ndlp, axri); - - lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS, - "6311 nvme_cmd x%px xri x%x tag x%x " - "abort complete and xri released\n", - lpfc_ncmd->nvmeCmd, xri, - lpfc_ncmd->cur_iocbq.iotag); - - /* Aborted NVME commands are required to not complete - * before the abort exchange command fully completes. - * Once completed, it is available via the put list. - */ - if (lpfc_ncmd->nvmeCmd) { - nvme_cmd = lpfc_ncmd->nvmeCmd; - nvme_cmd->done(nvme_cmd); - lpfc_ncmd->nvmeCmd = NULL; - } - lpfc_release_nvme_buf(phba, lpfc_ncmd); - return; - } - } - spin_unlock(&qp->abts_nvme_buf_list_lock); - spin_unlock_irqrestore(&phba->hbalock, iflag); - lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS, - "6312 XRI Aborted xri x%x not found\n", xri); + if (ndlp) + lpfc_sli4_abts_err_handler(phba, ndlp, axri); + lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS, + "6311 nvme_cmd %p xri x%x tag x%x abort complete and " + "xri released\n", + lpfc_ncmd->nvmeCmd, xri, + lpfc_ncmd->cur_iocbq.iotag); + + /* Aborted NVME commands are required to not complete + * before the abort exchange command fully completes. + * Once completed, it is available via the put list. + */ + if (lpfc_ncmd->nvmeCmd) { + nvme_cmd = lpfc_ncmd->nvmeCmd; + nvme_cmd->done(nvme_cmd); + lpfc_ncmd->nvmeCmd = NULL; + } + lpfc_release_nvme_buf(phba, lpfc_ncmd); } /** @@ -2705,13 +2680,13 @@ lpfc_nvme_wait_for_io_drain(struct lpfc_hba *phba) if (phba->sli_rev < LPFC_SLI_REV4 || !phba->sli4_hba.hdwq) return; - /* Cycle through all NVME rings and make sure all outstanding + /* Cycle through all IO rings and make sure all outstanding * WQEs have been removed from the txcmplqs. */ for (i = 0; i < phba->cfg_hdw_queue; i++) { - if (!phba->sli4_hba.hdwq[i].nvme_wq) + if (!phba->sli4_hba.hdwq[i].io_wq) continue; - pring = phba->sli4_hba.hdwq[i].nvme_wq->pring; + pring = phba->sli4_hba.hdwq[i].io_wq->pring; if (!pring) continue; diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 253a9fdd245e..9884228800a5 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -1026,7 +1026,7 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport, * WQE release CQE */ ctxp->flag |= LPFC_NVMET_DEFER_WQFULL; - wq = ctxp->hdwq->nvme_wq; + wq = ctxp->hdwq->io_wq; pring = wq->pring; spin_lock_irqsave(&pring->ring_lock, iflags); list_add_tail(&nvmewqeq->list, &wq->wqfull_list); @@ -1104,7 +1104,7 @@ lpfc_nvmet_xmt_fcp_abort(struct nvmet_fc_target_port *tgtport, spin_unlock_irqrestore(&ctxp->ctxlock, flags); lpfc_nvmet_unsol_fcp_issue_abort(phba, ctxp, ctxp->sid, ctxp->oxid); - wq = ctxp->hdwq->nvme_wq; + wq = ctxp->hdwq->io_wq; lpfc_nvmet_wqfull_flush(phba, wq, ctxp); return; } @@ -1918,7 +1918,7 @@ lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba) if (phba->targetport) { tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private; for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) { - wq = phba->sli4_hba.hdwq[qidx].nvme_wq; + wq = phba->sli4_hba.hdwq[qidx].io_wq; lpfc_nvmet_wqfull_flush(phba, wq, NULL); } tgtp->tport_unreg_cmp = &tport_unreg_cmp; @@ -3295,7 +3295,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba, */ spin_lock_irqsave(&phba->hbalock, flags); /* driver queued commands are in process of being flushed */ - if (phba->hba_flag & HBA_NVME_IOQ_FLUSH) { + if (phba->hba_flag & HBA_IOQ_FLUSH) { spin_unlock_irqrestore(&phba->hbalock, flags); atomic_inc(&tgtp->xmt_abort_rsp_error); lpfc_printf_log(phba, KERN_ERR, LOG_NVME, diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index fb7df209c0aa..7c65bd652c4d 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -537,29 +537,32 @@ lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *vport) for (idx = 0; idx < phba->cfg_hdw_queue; idx++) { qp = &phba->sli4_hba.hdwq[idx]; - spin_lock(&qp->abts_scsi_buf_list_lock); + spin_lock(&qp->abts_io_buf_list_lock); list_for_each_entry_safe(psb, next_psb, - &qp->lpfc_abts_scsi_buf_list, list) { + &qp->lpfc_abts_io_buf_list, list) { + if (psb->cur_iocbq.iocb_flag == LPFC_IO_NVME) + continue; + if (psb->rdata && psb->rdata->pnode && psb->rdata->pnode->vport == vport) psb->rdata = NULL; } - spin_unlock(&qp->abts_scsi_buf_list_lock); + spin_unlock(&qp->abts_io_buf_list_lock); } spin_unlock_irqrestore(&phba->hbalock, iflag); } /** - * lpfc_sli4_fcp_xri_aborted - Fast-path process of fcp xri abort + * lpfc_sli4_io_xri_aborted - Fast-path process of fcp xri abort * @phba: pointer to lpfc hba data structure. * @axri: pointer to the fcp xri abort wcqe structure. * * This routine is invoked by the worker thread to process a SLI4 fast-path - * FCP aborted xri. + * FCP or NVME aborted xri. **/ void -lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba, - struct sli4_wcqe_xri_aborted *axri, int idx) +lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba, + struct sli4_wcqe_xri_aborted *axri, int idx) { uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri); uint16_t rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri); @@ -577,16 +580,25 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba, qp = &phba->sli4_hba.hdwq[idx]; spin_lock_irqsave(&phba->hbalock, iflag); - spin_lock(&qp->abts_scsi_buf_list_lock); + spin_lock(&qp->abts_io_buf_list_lock); list_for_each_entry_safe(psb, next_psb, - &qp->lpfc_abts_scsi_buf_list, list) { + &qp->lpfc_abts_io_buf_list, list) { if (psb->cur_iocbq.sli4_xritag == xri) { - list_del(&psb->list); - qp->abts_scsi_io_bufs--; + list_del_init(&psb->list); psb->exch_busy = 0; psb->status = IOSTAT_SUCCESS; - spin_unlock( - &qp->abts_scsi_buf_list_lock); +#ifdef BUILD_NVME + if (psb->cur_iocbq.iocb_flag == LPFC_IO_NVME) { + qp->abts_nvme_io_bufs--; + spin_unlock(&qp->abts_io_buf_list_lock); + spin_unlock_irqrestore(&phba->hbalock, iflag); + lpfc_sli4_nvme_xri_aborted(phba, axri, psb); + return; + } +#endif + qp->abts_scsi_io_bufs--; + spin_unlock(&qp->abts_io_buf_list_lock); + if (psb->rdata && psb->rdata->pnode) ndlp = psb->rdata->pnode; else @@ -605,12 +617,12 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba, return; } } - spin_unlock(&qp->abts_scsi_buf_list_lock); + spin_unlock(&qp->abts_io_buf_list_lock); for (i = 1; i <= phba->sli.last_iotag; i++) { iocbq = phba->sli.iocbq_lookup[i]; - if (!(iocbq->iocb_flag & LPFC_IO_FCP) || - (iocbq->iocb_flag & LPFC_IO_LIBDFC)) + if (!(iocbq->iocb_flag & LPFC_IO_FCP) || + (iocbq->iocb_flag & LPFC_IO_LIBDFC)) continue; if (iocbq->sli4_xritag != xri) continue; @@ -836,11 +848,11 @@ lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *psb) qp = psb->hdwq; if (psb->exch_busy) { - spin_lock_irqsave(&qp->abts_scsi_buf_list_lock, iflag); + spin_lock_irqsave(&qp->abts_io_buf_list_lock, iflag); psb->pCmd = NULL; - list_add_tail(&psb->list, &qp->lpfc_abts_scsi_buf_list); + list_add_tail(&psb->list, &qp->lpfc_abts_io_buf_list); qp->abts_scsi_io_bufs++; - spin_unlock_irqrestore(&qp->abts_scsi_buf_list_lock, iflag); + spin_unlock_irqrestore(&qp->abts_io_buf_list_lock, iflag); } else { lpfc_release_io_buf(phba, (struct lpfc_io_buf *)psb, qp); } @@ -4800,7 +4812,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) spin_lock_irqsave(&phba->hbalock, flags); /* driver queued commands are in process of being flushed */ - if (phba->hba_flag & HBA_FCP_IOQ_FLUSH) { + if (phba->hba_flag & HBA_IOQ_FLUSH) { lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, "3168 SCSI Layer abort requested I/O has been " "flushed by LLD.\n"); @@ -4821,7 +4833,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) iocb = &lpfc_cmd->cur_iocbq; if (phba->sli_rev == LPFC_SLI_REV4) { - pring_s4 = phba->sli4_hba.hdwq[iocb->hba_wqidx].fcp_wq->pring; + pring_s4 = phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq->pring; if (!pring_s4) { ret = FAILED; goto out_unlock_buf; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index f4beb9104d3a..0dfd30aa4d99 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -3978,7 +3978,7 @@ lpfc_sli_abort_fcp_rings(struct lpfc_hba *phba) /* Look on all the FCP Rings for the iotag */ if (phba->sli_rev >= LPFC_SLI_REV4) { for (i = 0; i < phba->cfg_hdw_queue; i++) { - pring = phba->sli4_hba.hdwq[i].fcp_wq->pring; + pring = phba->sli4_hba.hdwq[i].io_wq->pring; lpfc_sli_abort_iocb_ring(phba, pring); } } else { @@ -3988,17 +3988,17 @@ lpfc_sli_abort_fcp_rings(struct lpfc_hba *phba) } /** - * lpfc_sli_flush_fcp_rings - flush all iocbs in the fcp ring + * lpfc_sli_flush_io_rings - flush all iocbs in the IO ring * @phba: Pointer to HBA context object. * - * This function flushes all iocbs in the fcp ring and frees all the iocb + * This function flushes all iocbs in the IO ring and frees all the iocb * objects in txq and txcmplq. This function will not issue abort iocbs * for all the iocb commands in txcmplq, they will just be returned with * IOERR_SLI_DOWN. This function is invoked with EEH when device's PCI * slot has been permanently disabled. **/ void -lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba) +lpfc_sli_flush_io_rings(struct lpfc_hba *phba) { LIST_HEAD(txq); LIST_HEAD(txcmplq); @@ -4009,13 +4009,13 @@ lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba) spin_lock_irq(&phba->hbalock); /* Indicate the I/O queues are flushed */ - phba->hba_flag |= HBA_FCP_IOQ_FLUSH; + phba->hba_flag |= HBA_IOQ_FLUSH; spin_unlock_irq(&phba->hbalock); /* Look on all the FCP Rings for the iotag */ if (phba->sli_rev >= LPFC_SLI_REV4) { for (i = 0; i < phba->cfg_hdw_queue; i++) { - pring = phba->sli4_hba.hdwq[i].fcp_wq->pring; + pring = phba->sli4_hba.hdwq[i].io_wq->pring; spin_lock_irq(&pring->ring_lock); /* Retrieve everything on txq */ @@ -4062,56 +4062,6 @@ lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba) } } -/** - * lpfc_sli_flush_nvme_rings - flush all wqes in the nvme rings - * @phba: Pointer to HBA context object. - * - * This function flushes all wqes in the nvme rings and frees all resources - * in the txcmplq. This function does not issue abort wqes for the IO - * commands in txcmplq, they will just be returned with - * IOERR_SLI_DOWN. This function is invoked with EEH when device's PCI - * slot has been permanently disabled. - **/ -void -lpfc_sli_flush_nvme_rings(struct lpfc_hba *phba) -{ - LIST_HEAD(txcmplq); - struct lpfc_sli_ring *pring; - uint32_t i; - struct lpfc_iocbq *piocb, *next_iocb; - - if ((phba->sli_rev < LPFC_SLI_REV4) || - !(phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME)) - return; - - /* Hint to other driver operations that a flush is in progress. */ - spin_lock_irq(&phba->hbalock); - phba->hba_flag |= HBA_NVME_IOQ_FLUSH; - spin_unlock_irq(&phba->hbalock); - - /* Cycle through all NVME rings and complete each IO with - * a local driver reason code. This is a flush so no - * abort exchange to FW. - */ - for (i = 0; i < phba->cfg_hdw_queue; i++) { - pring = phba->sli4_hba.hdwq[i].nvme_wq->pring; - - spin_lock_irq(&pring->ring_lock); - list_for_each_entry_safe(piocb, next_iocb, - &pring->txcmplq, list) - piocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; - /* Retrieve everything on the txcmplq */ - list_splice_init(&pring->txcmplq, &txcmplq); - pring->txcmplq_cnt = 0; - spin_unlock_irq(&pring->ring_lock); - - /* Flush the txcmpq &&&PAE */ - lpfc_sli_cancel_iocbs(phba, &txcmplq, - IOSTAT_LOCAL_REJECT, - IOERR_SLI_DOWN); - } -} - /** * lpfc_sli_brdready_s3 - Check for sli3 host ready status * @phba: Pointer to HBA context object. @@ -5603,10 +5553,8 @@ lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba) for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) { qp = &sli4_hba->hdwq[qidx]; /* ARM the corresponding CQ */ - sli4_hba->sli4_write_cq_db(phba, qp->fcp_cq, 0, - LPFC_QUEUE_REARM); - sli4_hba->sli4_write_cq_db(phba, qp->nvme_cq, 0, - LPFC_QUEUE_REARM); + sli4_hba->sli4_write_cq_db(phba, qp[qidx].io_cq, 0, + LPFC_QUEUE_REARM); } /* Loop thru all IRQ vectors */ @@ -7262,7 +7210,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) else phba->hba_flag &= ~HBA_FIP_SUPPORT; - phba->hba_flag &= ~HBA_FCP_IOQ_FLUSH; + phba->hba_flag &= ~HBA_IOQ_FLUSH; if (phba->sli_rev != LPFC_SLI_REV4) { lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, @@ -9930,7 +9878,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, /* Get the WQ */ if ((piocb->iocb_flag & LPFC_IO_FCP) || (piocb->iocb_flag & LPFC_USE_FCPWQIDX)) { - wq = phba->sli4_hba.hdwq[piocb->hba_wqidx].fcp_wq; + wq = phba->sli4_hba.hdwq[piocb->hba_wqidx].io_wq; } else { wq = phba->sli4_hba.els_wq; } @@ -10077,7 +10025,7 @@ lpfc_sli4_calc_ring(struct lpfc_hba *phba, struct lpfc_iocbq *piocb) lpfc_cmd = (struct lpfc_io_buf *)piocb->context1; piocb->hba_wqidx = lpfc_cmd->hdwq_no; } - return phba->sli4_hba.hdwq[piocb->hba_wqidx].fcp_wq->pring; + return phba->sli4_hba.hdwq[piocb->hba_wqidx].io_wq->pring; } else { if (unlikely(!phba->sli4_hba.els_wq)) return NULL; @@ -10530,7 +10478,7 @@ lpfc_sli4_queue_init(struct lpfc_hba *phba) INIT_LIST_HEAD(&psli->mboxq_cmpl); /* Initialize list headers for txq and txcmplq as double linked lists */ for (i = 0; i < phba->cfg_hdw_queue; i++) { - pring = phba->sli4_hba.hdwq[i].fcp_wq->pring; + pring = phba->sli4_hba.hdwq[i].io_wq->pring; pring->flag = 0; pring->ringno = LPFC_FCP_RING; pring->txcmplq_cnt = 0; @@ -10549,16 +10497,6 @@ lpfc_sli4_queue_init(struct lpfc_hba *phba) spin_lock_init(&pring->ring_lock); if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { - for (i = 0; i < phba->cfg_hdw_queue; i++) { - pring = phba->sli4_hba.hdwq[i].nvme_wq->pring; - pring->flag = 0; - pring->ringno = LPFC_FCP_RING; - pring->txcmplq_cnt = 0; - INIT_LIST_HEAD(&pring->txq); - INIT_LIST_HEAD(&pring->txcmplq); - INIT_LIST_HEAD(&pring->iocb_continueq); - spin_lock_init(&pring->ring_lock); - } pring = phba->sli4_hba.nvmels_wq->pring; pring->flag = 0; pring->ringno = LPFC_ELS_RING; @@ -11522,7 +11460,7 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, int i; /* all I/Os are in process of being flushed */ - if (phba->hba_flag & HBA_FCP_IOQ_FLUSH) + if (phba->hba_flag & HBA_IOQ_FLUSH) return errcnt; for (i = 1; i <= phba->sli.last_iotag; i++) { @@ -11632,7 +11570,7 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, spin_lock_irqsave(&phba->hbalock, iflags); /* all I/Os are in process of being flushed */ - if (phba->hba_flag & HBA_FCP_IOQ_FLUSH) { + if (phba->hba_flag & HBA_IOQ_FLUSH) { spin_unlock_irqrestore(&phba->hbalock, iflags); return 0; } @@ -11656,7 +11594,7 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, if (phba->sli_rev == LPFC_SLI_REV4) { pring_s4 = - phba->sli4_hba.hdwq[iocbq->hba_wqidx].fcp_wq->pring; + phba->sli4_hba.hdwq[iocbq->hba_wqidx].io_wq->pring; if (!pring_s4) { spin_unlock(&lpfc_cmd->buf_lock); continue; @@ -13365,8 +13303,13 @@ lpfc_sli4_sp_handle_abort_xri_wcqe(struct lpfc_hba *phba, unsigned long iflags; switch (cq->subtype) { - case LPFC_FCP: - lpfc_sli4_fcp_xri_aborted(phba, wcqe, cq->hdwq); + case LPFC_IO: + lpfc_sli4_io_xri_aborted(phba, wcqe, cq->hdwq); + if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { + /* Notify aborted XRI for NVME work queue */ + if (phba->nvmet_support) + lpfc_sli4_nvmet_xri_aborted(phba, wcqe); + } workposted = false; break; case LPFC_NVME_LS: /* NVME LS uses ELS resources */ @@ -13384,15 +13327,6 @@ lpfc_sli4_sp_handle_abort_xri_wcqe(struct lpfc_hba *phba, spin_unlock_irqrestore(&phba->hbalock, iflags); workposted = true; break; - case LPFC_NVME: - /* Notify aborted XRI for NVME work queue */ - if (phba->nvmet_support) - lpfc_sli4_nvmet_xri_aborted(phba, wcqe); - else - lpfc_sli4_nvme_xri_aborted(phba, wcqe, cq->hdwq); - - workposted = false; - break; default: lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "0603 Invalid CQ subtype %d: " @@ -13720,7 +13654,7 @@ __lpfc_sli4_sp_process_cq(struct lpfc_queue *cq) &delay); break; case LPFC_WCQ: - if (cq->subtype == LPFC_FCP || cq->subtype == LPFC_NVME) + if (cq->subtype == LPFC_IO) workposted |= __lpfc_sli4_process_cq(phba, cq, lpfc_sli4_fp_handle_cqe, &delay); @@ -14037,10 +13971,7 @@ lpfc_sli4_fp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, cq->CQ_wq++; /* Process the WQ complete event */ phba->last_completion_time = jiffies; - if ((cq->subtype == LPFC_FCP) || (cq->subtype == LPFC_NVME)) - lpfc_sli4_fp_handle_fcp_wcqe(phba, cq, - (struct lpfc_wcqe_complete *)&wcqe); - if (cq->subtype == LPFC_NVME_LS) + if (cq->subtype == LPFC_IO || cq->subtype == LPFC_NVME_LS) lpfc_sli4_fp_handle_fcp_wcqe(phba, cq, (struct lpfc_wcqe_complete *)&wcqe); break; @@ -19506,7 +19437,7 @@ lpfc_drain_txq(struct lpfc_hba *phba) if (phba->link_flag & LS_MDS_LOOPBACK) { /* MDS WQE are posted only to first WQ*/ - wq = phba->sli4_hba.hdwq[0].fcp_wq; + wq = phba->sli4_hba.hdwq[0].io_wq; if (unlikely(!wq)) return 0; pring = wq->pring; @@ -19757,10 +19688,10 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp, /* NVME_FCREQ and NVME_ABTS requests */ if (pwqe->iocb_flag & LPFC_IO_NVME) { /* Get the IO distribution (hba_wqidx) for WQ assignment. */ - wq = qp->nvme_wq; + wq = qp->io_wq; pring = wq->pring; - bf_set(wqe_cqid, &wqe->generic.wqe_com, qp->nvme_cq_map); + bf_set(wqe_cqid, &wqe->generic.wqe_com, qp->io_cq_map); lpfc_qp_spin_lock_irqsave(&pring->ring_lock, iflags, qp, wq_access); @@ -19777,7 +19708,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp, /* NVMET requests */ if (pwqe->iocb_flag & LPFC_IO_NVMET) { /* Get the IO distribution (hba_wqidx) for WQ assignment. */ - wq = qp->nvme_wq; + wq = qp->io_wq; pring = wq->pring; ctxp = pwqe->context2; @@ -19788,7 +19719,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp, } bf_set(wqe_xri_tag, &pwqe->wqe.xmit_bls_rsp.wqe_com, pwqe->sli4_xritag); - bf_set(wqe_cqid, &wqe->generic.wqe_com, qp->nvme_cq_map); + bf_set(wqe_cqid, &wqe->generic.wqe_com, qp->io_cq_map); lpfc_qp_spin_lock_irqsave(&pring->ring_lock, iflags, qp, wq_access); @@ -19835,9 +19766,7 @@ void lpfc_snapshot_mxp(struct lpfc_hba *phba, u32 hwqid) if (multixri_pool->stat_snapshot_taken == LPFC_MXP_SNAPSHOT_TAKEN) { pvt_pool = &qp->p_multixri_pool->pvt_pool; pbl_pool = &qp->p_multixri_pool->pbl_pool; - txcmplq_cnt = qp->fcp_wq->pring->txcmplq_cnt; - if (qp->nvme_wq) - txcmplq_cnt += qp->nvme_wq->pring->txcmplq_cnt; + txcmplq_cnt = qp->io_wq->pring->txcmplq_cnt; multixri_pool->stat_pbl_count = pbl_pool->count; multixri_pool->stat_pvt_count = pvt_pool->count; @@ -19907,12 +19836,9 @@ void lpfc_adjust_high_watermark(struct lpfc_hba *phba, u32 hwqid) watermark_max = xri_limit; watermark_min = xri_limit / 2; - txcmplq_cnt = qp->fcp_wq->pring->txcmplq_cnt; + txcmplq_cnt = qp->io_wq->pring->txcmplq_cnt; abts_io_bufs = qp->abts_scsi_io_bufs; - if (qp->nvme_wq) { - txcmplq_cnt += qp->nvme_wq->pring->txcmplq_cnt; - abts_io_bufs += qp->abts_nvme_io_bufs; - } + abts_io_bufs += qp->abts_nvme_io_bufs; new_watermark = txcmplq_cnt + abts_io_bufs; new_watermark = min(watermark_max, new_watermark); @@ -20187,12 +20113,9 @@ void lpfc_release_io_buf(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_ncmd, pbl_pool = &qp->p_multixri_pool->pbl_pool; pvt_pool = &qp->p_multixri_pool->pvt_pool; - txcmplq_cnt = qp->fcp_wq->pring->txcmplq_cnt; + txcmplq_cnt = qp->io_wq->pring->txcmplq_cnt; abts_io_bufs = qp->abts_scsi_io_bufs; - if (qp->nvme_wq) { - txcmplq_cnt += qp->nvme_wq->pring->txcmplq_cnt; - abts_io_bufs += qp->abts_nvme_io_bufs; - } + abts_io_bufs += qp->abts_nvme_io_bufs; xri_owned = pvt_pool->count + txcmplq_cnt + abts_io_bufs; xri_limit = qp->p_multixri_pool->xri_limit; diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 3ec9cf4c6427..11a72bbef8f7 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -109,9 +109,8 @@ enum lpfc_sli4_queue_type { enum lpfc_sli4_queue_subtype { LPFC_NONE, LPFC_MBOX, - LPFC_FCP, + LPFC_IO, LPFC_ELS, - LPFC_NVME, LPFC_NVMET, LPFC_NVME_LS, LPFC_USOL @@ -641,22 +640,17 @@ struct lpfc_eq_intr_info { struct lpfc_sli4_hdw_queue { /* Pointers to the constructed SLI4 queues */ struct lpfc_queue *hba_eq; /* Event queues for HBA */ - struct lpfc_queue *fcp_cq; /* Fast-path FCP compl queue */ - struct lpfc_queue *nvme_cq; /* Fast-path NVME compl queue */ - struct lpfc_queue *fcp_wq; /* Fast-path FCP work queue */ - struct lpfc_queue *nvme_wq; /* Fast-path NVME work queue */ - uint16_t fcp_cq_map; - uint16_t nvme_cq_map; + struct lpfc_queue *io_cq; /* Fast-path FCP & NVME compl queue */ + struct lpfc_queue *io_wq; /* Fast-path FCP & NVME work queue */ + uint16_t io_cq_map; /* Keep track of IO buffers for this hardware queue */ spinlock_t io_buf_list_get_lock; /* Common buf alloc list lock */ struct list_head lpfc_io_buf_list_get; spinlock_t io_buf_list_put_lock; /* Common buf free list lock */ struct list_head lpfc_io_buf_list_put; - spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */ - struct list_head lpfc_abts_scsi_buf_list; - spinlock_t abts_nvme_buf_list_lock; /* list of aborted NVME IOs */ - struct list_head lpfc_abts_nvme_buf_list; + spinlock_t abts_io_buf_list_lock; /* list of aborted IOs */ + struct list_head lpfc_abts_io_buf_list; uint32_t total_io_bufs; uint32_t get_io_bufs; uint32_t put_io_bufs; @@ -852,8 +846,8 @@ struct lpfc_sli4_hba { struct lpfc_queue **cq_lookup; struct list_head lpfc_els_sgl_list; struct list_head lpfc_abts_els_sgl_list; - spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */ - struct list_head lpfc_abts_scsi_buf_list; + spinlock_t abts_io_buf_list_lock; /* list of aborted SCSI IOs */ + struct list_head lpfc_abts_io_buf_list; struct list_head lpfc_nvmet_sgl_list; spinlock_t abts_nvmet_buf_list_lock; /* list of aborted NVMET IOs */ struct list_head lpfc_abts_nvmet_ctx_list; @@ -1058,10 +1052,11 @@ int lpfc_sli4_resume_rpi(struct lpfc_nodelist *, void (*)(struct lpfc_hba *, LPFC_MBOXQ_t *), void *); void lpfc_sli4_fcp_xri_abort_event_proc(struct lpfc_hba *); void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *); -void lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *, - struct sli4_wcqe_xri_aborted *, int); void lpfc_sli4_nvme_xri_aborted(struct lpfc_hba *phba, - struct sli4_wcqe_xri_aborted *axri, int idx); + struct sli4_wcqe_xri_aborted *axri, + struct lpfc_io_buf *lpfc_ncmd); +void lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba, + struct sli4_wcqe_xri_aborted *axri, int idx); void lpfc_sli4_nvmet_xri_aborted(struct lpfc_hba *phba, struct sli4_wcqe_xri_aborted *axri); void lpfc_sli4_els_xri_aborted(struct lpfc_hba *, -- cgit v1.2.3-59-g8ed1b From 10541f037bd925c6752250e0b37b1ea43de27068 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Aug 2019 16:57:12 -0700 Subject: scsi: lpfc: Update lpfc version to 12.4.0.0 Update lpfc version to 12.4.0.0 Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index f7e93aaf1e00..b8aae31ffda3 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -20,7 +20,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "12.2.0.3" +#define LPFC_DRIVER_VERSION "12.4.0.0" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ -- cgit v1.2.3-59-g8ed1b From 5f6b4e1e09331938a818cf8f371025ae03dee069 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 31 Jul 2019 23:11:52 +0100 Subject: scsi: bfa: remove redundant assignment to variable error Variable error is being initialized with a value that is never read and error is being re-assigned a little later on. The assignment is redundant and hence can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen --- drivers/scsi/bfa/bfad_im.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index b2014cb96f58..22f06be2606f 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -536,7 +536,7 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port, struct device *dev) { struct bfad_im_port_pointer *im_portp; - int error = 1; + int error; mutex_lock(&bfad_mutex); error = idr_alloc(&bfad_im_port_index, im_port, 0, 0, GFP_KERNEL); -- cgit v1.2.3-59-g8ed1b From e55f24ffa936e09673905a9176a8a9d22cf68d40 Mon Sep 17 00:00:00 2001 From: Anil Varughese Date: Tue, 13 Aug 2019 08:42:50 +0100 Subject: scsi: ufs: Disable local LCC in .link_startup_notify() in Cadence UFS Some UFS devices have issues if LCC is enabled. So we are setting PA_LOCAL_TX_LCC_Enable to 0 before link startup which will make sure that both host and device TX LCC are disabled once link startup is completed. Signed-off-by: Anil Varughese Reviewed-by: Vignesh Raghavendra Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/cdns-pltfrm.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c index 993519080a84..b2af04c57a39 100644 --- a/drivers/scsi/ufs/cdns-pltfrm.c +++ b/drivers/scsi/ufs/cdns-pltfrm.c @@ -77,6 +77,31 @@ static int cdns_ufs_hce_enable_notify(struct ufs_hba *hba, return cdns_ufs_set_hclkdiv(hba); } +/** + * Called before and after Link startup is carried out. + * @hba: host controller instance + * @status: notify stage (pre, post change) + * + * Return zero for success and non-zero for failure + */ +static int cdns_ufs_link_startup_notify(struct ufs_hba *hba, + enum ufs_notify_change_status status) +{ + if (status != PRE_CHANGE) + return 0; + + /* + * Some UFS devices have issues if LCC is enabled. + * So we are setting PA_Local_TX_LCC_Enable to 0 + * before link startup which will make sure that both host + * and device TX LCC are disabled once link startup is + * completed. + */ + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0); + + return 0; +} + /** * cdns_ufs_init - performs additional ufs initialization * @hba: host controller instance @@ -114,12 +139,14 @@ static int cdns_ufs_m31_16nm_phy_initialization(struct ufs_hba *hba) static const struct ufs_hba_variant_ops cdns_ufs_pltfm_hba_vops = { .name = "cdns-ufs-pltfm", .hce_enable_notify = cdns_ufs_hce_enable_notify, + .link_startup_notify = cdns_ufs_link_startup_notify, }; static const struct ufs_hba_variant_ops cdns_ufs_m31_16nm_pltfm_hba_vops = { .name = "cdns-ufs-pltfm", .init = cdns_ufs_init, .hce_enable_notify = cdns_ufs_hce_enable_notify, + .link_startup_notify = cdns_ufs_link_startup_notify, .phy_initialization = cdns_ufs_m31_16nm_phy_initialization, }; -- cgit v1.2.3-59-g8ed1b From e8fd0b9f6f487820a05a46ce3ac4b5df11ad6799 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 15 Aug 2019 10:14:54 +0100 Subject: scsi: fcoe: remove redundant call to skb_transport_header Pointer fh is being assigned a return value from the call to skb_transport_header however this value is never read and fh is being re-assigned immediately afterwards with a new value. Since there are side-effects from calling skb_transport_header the call is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 00dd47bcbb1e..8e217ab7646e 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -1618,7 +1618,6 @@ static inline int fcoe_filter_frames(struct fc_lport *lport, else fr_flags(fp) |= FCPHF_CRC_UNCHECKED; - fh = (struct fc_frame_header *) skb_transport_header(skb); fh = fc_frame_header_get(fp); if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && fh->fh_type == FC_TYPE_FCP) return 0; -- cgit v1.2.3-59-g8ed1b From b557217c8475f40bc765ee20ff6b3b9124c8a4fe Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Mon, 19 Aug 2019 21:43:28 +0800 Subject: scsi: ufs: fix broken hba->outstanding_tasks Currently bits in hba->outstanding_tasks are cleared only after their corresponding task management commands are successfully done by __ufshcd_issue_tm_cmd(). If timeout happens in a task management command, its corresponding bit in hba->outstanding_tasks will not be cleared until next task management command with the same tag used successfully finishes. This is wrong and can lead to some issues, like power issue. For example, ufshcd_release() and ufshcd_gate_work() will do nothing if hba->outstanding_tasks is not zero even if both UFS host and devices are actually idle. Solution is referred from error handling of device commands: bits in hba->outstanding_tasks shall be cleared regardless of their execution results. Signed-off-by: Stanley Chu Signed-off-by: Chun-Hung Wu Reviewed-by: Avri Altman Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 507fd51e8039..ff6a440dc1c2 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5696,13 +5696,12 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba, memcpy(treq, hba->utmrdl_base_addr + free_slot, sizeof(*treq)); ufshcd_add_tm_upiu_trace(hba, task_tag, "tm_complete"); - - spin_lock_irqsave(hba->host->host_lock, flags); - __clear_bit(free_slot, &hba->outstanding_tasks); - spin_unlock_irqrestore(hba->host->host_lock, flags); - } + spin_lock_irqsave(hba->host->host_lock, flags); + __clear_bit(free_slot, &hba->outstanding_tasks); + spin_unlock_irqrestore(hba->host->host_lock, flags); + clear_bit(free_slot, &hba->tm_condition); ufshcd_put_tm_slot(hba, free_slot); wake_up(&hba->tm_tag_wq); -- cgit v1.2.3-59-g8ed1b From dd93b143706c636d3dfefe6cf355065d748b2473 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 19 Aug 2019 19:18:36 -0700 Subject: scsi: qla2xxx: Fix a recently introduced kernel warning According to the firmware documentation a status type 0 IOCB can be followed by one or more status continuation type 0 IOCBs. Hence do not complain if the completion function is not called from inside the status type 0 IOCB handler. WARNING: CPU: 10 PID: 425 at drivers/scsi/qla2xxx/qla_isr.c:2784 qla2x00_status_entry.isra.7+0x484/0x17b0 [qla2xxx] CPU: 10 PID: 425 Comm: kworker/10:1 Tainted: G E 5.3.0-rc4-next-20190813-autotest-autotest #1 Workqueue: qla2xxx_wq qla25xx_free_rsp_que [qla2xxx] Call Trace: qla2x00_status_entry.isra.7+0x1484/0x17b0 [qla2xxx] (unreliable) qla24xx_process_response_queue+0x7d8/0xbd0 [qla2xxx] qla25xx_free_rsp_que+0x1a0/0x220 [qla2xxx] process_one_work+0x25c/0x520 worker_thread+0x8c/0x5e0 kthread+0x154/0x1a0 ret_from_kernel_thread+0x5c/0x7c Cc: Himanshu Madhani Cc: Abdul Haleem Reported-by: Abdul Haleem Signed-off-by: Bart Van Assche Tested-by: Abdul Haleem Reviewed-by: Lee Duncan Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_isr.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index cd39ac18c5fd..d81b5ecce24b 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -2780,8 +2780,6 @@ out: if (rsp->status_srb == NULL) sp->done(sp, res); - else - WARN_ON_ONCE(true); } /** -- cgit v1.2.3-59-g8ed1b From 8dc8d29a00e29c679f027102fb9c6709347ca8ca Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Thu, 22 Aug 2019 02:19:01 -0400 Subject: scsi: mpt3sas: Introduce module parameter to override queue depth This patch provides a module parameter and sysfs interface to select whether the queue depth for each device should be based on the protocol-specific value set by the driver (the default) or the maximum supported by the controller (can_queue). Although we have a sysfs interface per sdev to change the queue depth of individual scsi devices, this implementation provides a single sysfs entry per shost to switch between the controller max and the driver default. [mkp: tweaked commit desc] Signed-off-by: Sreekanth Reddy Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 2 + drivers/scsi/mpt3sas/mpt3sas_ctl.c | 102 +++++++++++++++++++++++++++++++++++ drivers/scsi/mpt3sas/mpt3sas_scsih.c | 40 ++++++++++++-- 3 files changed, 140 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 745e0e13b7ab..faca0a5e71f8 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1232,6 +1232,7 @@ struct MPT3SAS_ADAPTER { u16 thresh_hold; u8 high_iops_queues; u32 drv_support_bitmap; + bool enable_sdev_max_qd; /* internal commands, callback index */ u8 scsi_io_cb_idx; @@ -1587,6 +1588,7 @@ struct _pcie_device *mpt3sas_get_pdev_by_handle(struct MPT3SAS_ADAPTER *ioc, void mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc); struct _raid_device * mpt3sas_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle); +void mpt3sas_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth); /* config shared API */ u8 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index da29005d72bd..7d696952b376 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -3400,6 +3400,107 @@ drv_support_bitmap_show(struct device *cdev, } static DEVICE_ATTR_RO(drv_support_bitmap); +/** + * enable_sdev_max_qd_show - display whether sdev max qd is enabled/disabled + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * A sysfs read/write shost attribute. This attribute is used to set the + * targets queue depth to HBA IO queue depth if this attribute is enabled. + */ +static ssize_t +enable_sdev_max_qd_show(struct device *cdev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); + + return snprintf(buf, PAGE_SIZE, "%d\n", ioc->enable_sdev_max_qd); +} + +/** + * enable_sdev_max_qd_store - Enable/disable sdev max qd + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * A sysfs read/write shost attribute. This attribute is used to set the + * targets queue depth to HBA IO queue depth if this attribute is enabled. + * If this attribute is disabled then targets will have corresponding default + * queue depth. + */ +static ssize_t +enable_sdev_max_qd_store(struct device *cdev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); + struct MPT3SAS_DEVICE *sas_device_priv_data; + struct MPT3SAS_TARGET *sas_target_priv_data; + int val = 0; + struct scsi_device *sdev; + struct _raid_device *raid_device; + int qdepth; + + if (kstrtoint(buf, 0, &val) != 0) + return -EINVAL; + + switch (val) { + case 0: + ioc->enable_sdev_max_qd = 0; + shost_for_each_device(sdev, ioc->shost) { + sas_device_priv_data = sdev->hostdata; + if (!sas_device_priv_data) + continue; + sas_target_priv_data = sas_device_priv_data->sas_target; + if (!sas_target_priv_data) + continue; + + if (sas_target_priv_data->flags & + MPT_TARGET_FLAGS_VOLUME) { + raid_device = + mpt3sas_raid_device_find_by_handle(ioc, + sas_target_priv_data->handle); + + switch (raid_device->volume_type) { + case MPI2_RAID_VOL_TYPE_RAID0: + if (raid_device->device_info & + MPI2_SAS_DEVICE_INFO_SSP_TARGET) + qdepth = + MPT3SAS_SAS_QUEUE_DEPTH; + else + qdepth = + MPT3SAS_SATA_QUEUE_DEPTH; + break; + case MPI2_RAID_VOL_TYPE_RAID1E: + case MPI2_RAID_VOL_TYPE_RAID1: + case MPI2_RAID_VOL_TYPE_RAID10: + case MPI2_RAID_VOL_TYPE_UNKNOWN: + default: + qdepth = MPT3SAS_RAID_QUEUE_DEPTH; + } + } else if (sas_target_priv_data->flags & + MPT_TARGET_FLAGS_PCIE_DEVICE) + qdepth = MPT3SAS_NVME_QUEUE_DEPTH; + else + qdepth = MPT3SAS_SAS_QUEUE_DEPTH; + + mpt3sas_scsih_change_queue_depth(sdev, qdepth); + } + break; + case 1: + ioc->enable_sdev_max_qd = 1; + shost_for_each_device(sdev, ioc->shost) + mpt3sas_scsih_change_queue_depth(sdev, + shost->can_queue); + break; + default: + return -EINVAL; + } + + return strlen(buf); +} +static DEVICE_ATTR_RW(enable_sdev_max_qd); + struct device_attribute *mpt3sas_host_attrs[] = { &dev_attr_version_fw, &dev_attr_version_bios, @@ -3427,6 +3528,7 @@ struct device_attribute *mpt3sas_host_attrs[] = { &dev_attr_diag_trigger_mpi, &dev_attr_drv_support_bitmap, &dev_attr_BRM_status, + &dev_attr_enable_sdev_max_qd, NULL, }; diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 9904775493d0..d0c2f8d6f2a2 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -155,6 +155,10 @@ static int prot_mask = -1; module_param(prot_mask, int, 0444); MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=7 "); +static bool enable_sdev_max_qd; +module_param(enable_sdev_max_qd, bool, 0444); +MODULE_PARM_DESC(enable_sdev_max_qd, + "Enable sdev max qd as can_queue, def=disabled(0)"); /* raid transport support */ static struct raid_template *mpt3sas_raid_template; @@ -1519,7 +1523,13 @@ scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) max_depth = shost->can_queue; - /* limit max device queue for SATA to 32 */ + /* + * limit max device queue for SATA to 32 if enable_sdev_max_qd + * is disabled. + */ + if (ioc->enable_sdev_max_qd) + goto not_sata; + sas_device_priv_data = sdev->hostdata; if (!sas_device_priv_data) goto not_sata; @@ -1548,6 +1558,25 @@ scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) return scsi_change_queue_depth(sdev, qdepth); } +/** + * mpt3sas_scsih_change_queue_depth - setting device queue depth + * @sdev: scsi device struct + * @qdepth: requested queue depth + * + * Returns nothing. + */ +void +mpt3sas_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) +{ + struct Scsi_Host *shost = sdev->host; + struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); + + if (ioc->enable_sdev_max_qd) + qdepth = shost->can_queue; + + scsih_change_queue_depth(sdev, qdepth); +} + /** * scsih_target_alloc - target add routine * @starget: scsi target struct @@ -2306,7 +2335,7 @@ scsih_slave_configure(struct scsi_device *sdev) MPT3SAS_RAID_MAX_SECTORS); } - scsih_change_queue_depth(sdev, qdepth); + mpt3sas_scsih_change_queue_depth(sdev, qdepth); /* raid transport support */ if (!ioc->is_warpdrive) @@ -2370,7 +2399,7 @@ scsih_slave_configure(struct scsi_device *sdev) pcie_device_put(pcie_device); spin_unlock_irqrestore(&ioc->pcie_device_lock, flags); - scsih_change_queue_depth(sdev, qdepth); + mpt3sas_scsih_change_queue_depth(sdev, qdepth); /* Enable QUEUE_FLAG_NOMERGES flag, so that IOs won't be ** merged and can eliminate holes created during merging ** operation. @@ -2430,7 +2459,7 @@ scsih_slave_configure(struct scsi_device *sdev) _scsih_display_sata_capabilities(ioc, handle, sdev); - scsih_change_queue_depth(sdev, qdepth); + mpt3sas_scsih_change_queue_depth(sdev, qdepth); if (ssp_target) { sas_read_port_mode_page(sdev); @@ -10507,6 +10536,9 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) * Enable MEMORY MOVE support flag. */ ioc->drv_support_bitmap |= MPT_DRV_SUPPORT_BITMAP_MEMMOVE; + + ioc->enable_sdev_max_qd = enable_sdev_max_qd; + /* misc semaphores and spin locks */ mutex_init(&ioc->reset_in_progress_mutex); /* initializing pci_access_mutex lock */ -- cgit v1.2.3-59-g8ed1b From 328bc6debf3dcaf8859dd1323882e8e24ec6e3f8 Mon Sep 17 00:00:00 2001 From: zhengbin Date: Thu, 22 Aug 2019 22:20:47 +0800 Subject: scsi: hisi_sas: remove set but not used variable 'irq_value' Fixes gcc '-Wunused-but-set-variable' warning: drivers/scsi/hisi_sas/hisi_sas_v1_hw.c: In function cq_interrupt_v1_hw: drivers/scsi/hisi_sas/hisi_sas_v1_hw.c:1542:6: warning: variable irq_value set but not used [-Wunused-but-set-variable] Reported-by: Hulk Robot Signed-off-by: zhengbin Acked-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 16974421cb31..3a584feca843 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1497,11 +1497,9 @@ static irqreturn_t cq_interrupt_v1_hw(int irq, void *p) struct hisi_sas_complete_v1_hdr *complete_queue = (struct hisi_sas_complete_v1_hdr *) hisi_hba->complete_hdr[queue]; - u32 irq_value, rd_point = cq->rd_point, wr_point; + u32 rd_point = cq->rd_point, wr_point; spin_lock(&hisi_hba->lock); - irq_value = hisi_sas_read32(hisi_hba, OQ_INT_SRC); - hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue); wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR + (0x14 * queue)); -- cgit v1.2.3-59-g8ed1b From 401fe8e99c71a51b61d24f237cb7c54842b9c662 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 22 Aug 2019 22:56:51 +0100 Subject: scsi: qla2xxx: fix spelling mistake "initializatin" -> "initialization" There is a spelling mistake in a ql_log message. Fix it. Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_nx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 372355bfcbb6..65a675906188 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -1977,7 +1977,7 @@ qla82xx_check_rcvpeg_state(struct qla_hw_data *ha) } while (--retries); ql_log(ql_log_fatal, vha, 0x00ac, - "Rcv Peg initializatin failed: 0x%x.\n", val); + "Rcv Peg initialization failed: 0x%x.\n", val); read_lock(&ha->hw_lock); qla82xx_wr_32(ha, CRB_RCVPEG_STATE, PHAN_INITIALIZE_FAILED); read_unlock(&ha->hw_lock); -- cgit v1.2.3-59-g8ed1b From 844b17d7438bc6e8acbd85163b7c6b9bce0a6ea2 Mon Sep 17 00:00:00 2001 From: zhengbin Date: Mon, 26 Aug 2019 09:15:49 +0800 Subject: scsi: ufs: remove set but not used variable 'val' Fixes gcc '-Wunused-but-set-variable' warning: drivers/scsi/ufs/ufs-qcom.c: In function ufs_qcom_pwr_change_notify: drivers/scsi/ufs/ufs-qcom.c:808:6: warning: variable val set but not used [-Wunused-but-set-variable] Fixes: 1e1e465c6d23 ("scsi/ufs: qcom: Remove ufs_qcom_phy_*() calls from host") Reported-by: Hulk Robot Signed-off-by: zhengbin Acked-by: Avri Altman Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-qcom.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 4473f339cbc0..02cdcefb81ac 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -800,7 +800,6 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba, struct ufs_pa_layer_attr *dev_max_params, struct ufs_pa_layer_attr *dev_req_params) { - u32 val; struct ufs_qcom_host *host = ufshcd_get_variant(hba); struct ufs_dev_params ufs_qcom_cap; int ret = 0; @@ -869,8 +868,6 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba, ret = -EINVAL; } - val = ~(MAX_U32 << dev_req_params->lane_tx); - /* cache the power mode parameters to use internally */ memcpy(&host->dev_req_params, dev_req_params, sizeof(*dev_req_params)); -- cgit v1.2.3-59-g8ed1b From 7f9989bace91a7a36051d64cbf46f7760c52bbf0 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 27 Aug 2019 14:27:46 -0700 Subject: scsi: lpfc: Resolve checker warning for lpfc_new_io_buf() Per Dan Carpenter: The patch d79c9e9d4b3d: "scsi: lpfc: Support dynamic unbounded SGL lists on G7 hardware." from Aug 14, 2019, leads to the following static checker warning: drivers/scsi/lpfc/lpfc_init.c:4107 lpfc_new_io_buf() error: not allocating enough data 784 vs 768 There was no need to compare sizes nor to allocate size based on a define. Change allocation to use actual structure length Signed-off-by: Dick Kennedy Signed-off-by: James Smart CC: Dan Carpenter Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 11 +---------- drivers/scsi/lpfc/lpfc_sli4.h | 3 --- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 0bc04af1d2fb..de92eb86579a 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -4093,18 +4093,9 @@ lpfc_new_io_buf(struct lpfc_hba *phba, int num_to_alloc) LIST_HEAD(post_nblist); LIST_HEAD(nvme_nblist); - /* Sanity check to ensure our sizing is right for both SCSI and NVME */ - if (sizeof(struct lpfc_io_buf) > LPFC_COMMON_IO_BUF_SZ) { - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, - "6426 Common buffer size %zd exceeds %d\n", - sizeof(struct lpfc_io_buf), - LPFC_COMMON_IO_BUF_SZ); - return 0; - } - phba->sli4_hba.io_xri_cnt = 0; for (bcnt = 0; bcnt < num_to_alloc; bcnt++) { - lpfc_ncmd = kzalloc(LPFC_COMMON_IO_BUF_SZ, GFP_KERNEL); + lpfc_ncmd = kzalloc(sizeof(*lpfc_ncmd), GFP_KERNEL); if (!lpfc_ncmd) break; /* diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 11a72bbef8f7..4bdd58de4692 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -44,9 +44,6 @@ #define LPFC_HBA_HDWQ_MAX 128 #define LPFC_HBA_HDWQ_DEF 0 -/* Common buffer size to accomidate SCSI and NVME IO buffers */ -#define LPFC_COMMON_IO_BUF_SZ 768 - /* * Provide the default FCF Record attributes used by the driver * when nonFIP mode is configured and there is no other default -- cgit v1.2.3-59-g8ed1b From 9db6c14c36fc8f7824ade95f53bcdad43df678b4 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 27 Aug 2019 14:28:05 -0700 Subject: scsi: lpfc: Remove bg debugfs buffers Capturing and downloading dif command data and dif data was done a dozen years ago and no longer being used. Also creates a potential security hole. Remove the debugfs buffer for dif debugging. Signed-off-by: Dick Kennedy Signed-off-by: James Smart CC: KyleMahlkuch CC: Hannes Reinecke Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 2 - drivers/scsi/lpfc/lpfc_crtn.h | 10 --- drivers/scsi/lpfc/lpfc_debugfs.c | 134 --------------------------------------- drivers/scsi/lpfc/lpfc_init.c | 70 -------------------- drivers/scsi/lpfc/lpfc_scsi.c | 79 ----------------------- 5 files changed, 295 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 11873f0d521c..d890564f00cc 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -1038,8 +1038,6 @@ struct lpfc_hba { struct dentry *debug_hbqinfo; struct dentry *debug_dumpHostSlim; struct dentry *debug_dumpHBASlim; - struct dentry *debug_dumpData; /* BlockGuard BPL */ - struct dentry *debug_dumpDif; /* BlockGuard BPL */ struct dentry *debug_InjErrLBA; /* LBA to inject errors at */ struct dentry *debug_InjErrNPortID; /* NPortID to inject errors at */ struct dentry *debug_InjErrWWPN; /* WWPN to inject errors at */ diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 8b84acc95a07..b2ad8c750486 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -433,16 +433,6 @@ int lpfc_sli4_get_allocated_extnts(struct lpfc_hba *, uint16_t, int lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *, uint16_t, uint16_t *, uint16_t *); -/* externs BlockGuard */ -extern char *_dump_buf_data; -extern unsigned long _dump_buf_data_order; -extern char *_dump_buf_dif; -extern unsigned long _dump_buf_dif_order; -extern spinlock_t _dump_buf_lock; -extern int _dump_buf_done; -extern spinlock_t pgcnt_lock; -extern unsigned int pgcnt; - /* Interface exported by fabric iocb scheduler */ void lpfc_fabric_abort_nport(struct lpfc_nodelist *); void lpfc_fabric_abort_hba(struct lpfc_hba *); diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 45f431fbe0d2..8d34be60d379 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -2162,89 +2162,6 @@ out: return rc; } -static int -lpfc_debugfs_dumpData_open(struct inode *inode, struct file *file) -{ - struct lpfc_debug *debug; - int rc = -ENOMEM; - - if (!_dump_buf_data) - return -EBUSY; - - debug = kmalloc(sizeof(*debug), GFP_KERNEL); - if (!debug) - goto out; - - /* Round to page boundary */ - pr_err("9059 BLKGRD: %s: _dump_buf_data=0x%p\n", - __func__, _dump_buf_data); - debug->buffer = _dump_buf_data; - if (!debug->buffer) { - kfree(debug); - goto out; - } - - debug->len = (1 << _dump_buf_data_order) << PAGE_SHIFT; - file->private_data = debug; - - rc = 0; -out: - return rc; -} - -static int -lpfc_debugfs_dumpDif_open(struct inode *inode, struct file *file) -{ - struct lpfc_debug *debug; - int rc = -ENOMEM; - - if (!_dump_buf_dif) - return -EBUSY; - - debug = kmalloc(sizeof(*debug), GFP_KERNEL); - if (!debug) - goto out; - - /* Round to page boundary */ - pr_err("9060 BLKGRD: %s: _dump_buf_dif=x%px file=%pD\n", - __func__, _dump_buf_dif, file); - debug->buffer = _dump_buf_dif; - if (!debug->buffer) { - kfree(debug); - goto out; - } - - debug->len = (1 << _dump_buf_dif_order) << PAGE_SHIFT; - file->private_data = debug; - - rc = 0; -out: - return rc; -} - -static ssize_t -lpfc_debugfs_dumpDataDif_write(struct file *file, const char __user *buf, - size_t nbytes, loff_t *ppos) -{ - /* - * The Data/DIF buffers only save one failing IO - * The write op is used as a reset mechanism after an IO has - * already been saved to the next one can be saved - */ - spin_lock(&_dump_buf_lock); - - memset((void *)_dump_buf_data, 0, - ((1 << PAGE_SHIFT) << _dump_buf_data_order)); - memset((void *)_dump_buf_dif, 0, - ((1 << PAGE_SHIFT) << _dump_buf_dif_order)); - - _dump_buf_done = 0; - - spin_unlock(&_dump_buf_lock); - - return nbytes; -} - static ssize_t lpfc_debugfs_dif_err_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) @@ -2457,17 +2374,6 @@ lpfc_debugfs_release(struct inode *inode, struct file *file) return 0; } -static int -lpfc_debugfs_dumpDataDif_release(struct inode *inode, struct file *file) -{ - struct lpfc_debug *debug = file->private_data; - - debug->buffer = NULL; - kfree(debug); - - return 0; -} - /** * lpfc_debugfs_multixripools_write - Clear multi-XRI pools statistics * @file: The file pointer to read from. @@ -5448,26 +5354,6 @@ static const struct file_operations lpfc_debugfs_op_cpucheck = { .release = lpfc_debugfs_release, }; -#undef lpfc_debugfs_op_dumpData -static const struct file_operations lpfc_debugfs_op_dumpData = { - .owner = THIS_MODULE, - .open = lpfc_debugfs_dumpData_open, - .llseek = lpfc_debugfs_lseek, - .read = lpfc_debugfs_read, - .write = lpfc_debugfs_dumpDataDif_write, - .release = lpfc_debugfs_dumpDataDif_release, -}; - -#undef lpfc_debugfs_op_dumpDif -static const struct file_operations lpfc_debugfs_op_dumpDif = { - .owner = THIS_MODULE, - .open = lpfc_debugfs_dumpDif_open, - .llseek = lpfc_debugfs_lseek, - .read = lpfc_debugfs_read, - .write = lpfc_debugfs_dumpDataDif_write, - .release = lpfc_debugfs_dumpDataDif_release, -}; - #undef lpfc_debugfs_op_dif_err static const struct file_operations lpfc_debugfs_op_dif_err = { .owner = THIS_MODULE, @@ -5864,20 +5750,6 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) } else phba->debug_dumpHostSlim = NULL; - /* Setup dumpData */ - snprintf(name, sizeof(name), "dumpData"); - phba->debug_dumpData = - debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, - phba->hba_debugfs_root, - phba, &lpfc_debugfs_op_dumpData); - - /* Setup dumpDif */ - snprintf(name, sizeof(name), "dumpDif"); - phba->debug_dumpDif = - debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, - phba->hba_debugfs_root, - phba, &lpfc_debugfs_op_dumpDif); - /* Setup DIF Error Injections */ snprintf(name, sizeof(name), "InjErrLBA"); phba->debug_InjErrLBA = @@ -6255,12 +6127,6 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport) debugfs_remove(phba->debug_dumpHostSlim); /* HostSlim */ phba->debug_dumpHostSlim = NULL; - debugfs_remove(phba->debug_dumpData); /* dumpData */ - phba->debug_dumpData = NULL; - - debugfs_remove(phba->debug_dumpDif); /* dumpDif */ - phba->debug_dumpDif = NULL; - debugfs_remove(phba->debug_InjErrLBA); /* InjErrLBA */ phba->debug_InjErrLBA = NULL; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index de92eb86579a..de64880c6c60 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -66,12 +66,6 @@ #include "lpfc_version.h" #include "lpfc_ids.h" -char *_dump_buf_data; -unsigned long _dump_buf_data_order; -char *_dump_buf_dif; -unsigned long _dump_buf_dif_order; -spinlock_t _dump_buf_lock; - /* Used when mapping IRQ vectors in a driver centric manner */ static uint32_t lpfc_present_cpu; @@ -7617,7 +7611,6 @@ lpfc_setup_bg(struct lpfc_hba *phba, struct Scsi_Host *shost) uint32_t old_mask; uint32_t old_guard; - int pagecnt = 10; if (phba->cfg_prot_mask && phba->cfg_prot_guard) { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "1478 Registering BlockGuard with the " @@ -7654,56 +7647,6 @@ lpfc_setup_bg(struct lpfc_hba *phba, struct Scsi_Host *shost) "layer, Bad protection parameters: %d %d\n", old_mask, old_guard); } - - if (!_dump_buf_data) { - while (pagecnt) { - spin_lock_init(&_dump_buf_lock); - _dump_buf_data = - (char *) __get_free_pages(GFP_KERNEL, pagecnt); - if (_dump_buf_data) { - lpfc_printf_log(phba, KERN_ERR, LOG_BG, - "9043 BLKGRD: allocated %d pages for " - "_dump_buf_data at x%px\n", - (1 << pagecnt), _dump_buf_data); - _dump_buf_data_order = pagecnt; - memset(_dump_buf_data, 0, - ((1 << PAGE_SHIFT) << pagecnt)); - break; - } else - --pagecnt; - } - if (!_dump_buf_data_order) - lpfc_printf_log(phba, KERN_ERR, LOG_BG, - "9044 BLKGRD: ERROR unable to allocate " - "memory for hexdump\n"); - } else - lpfc_printf_log(phba, KERN_ERR, LOG_BG, - "9045 BLKGRD: already allocated _dump_buf_data=x%px" - "\n", _dump_buf_data); - if (!_dump_buf_dif) { - while (pagecnt) { - _dump_buf_dif = - (char *) __get_free_pages(GFP_KERNEL, pagecnt); - if (_dump_buf_dif) { - lpfc_printf_log(phba, KERN_ERR, LOG_BG, - "9046 BLKGRD: allocated %d pages for " - "_dump_buf_dif at x%px\n", - (1 << pagecnt), _dump_buf_dif); - _dump_buf_dif_order = pagecnt; - memset(_dump_buf_dif, 0, - ((1 << PAGE_SHIFT) << pagecnt)); - break; - } else - --pagecnt; - } - if (!_dump_buf_dif_order) - lpfc_printf_log(phba, KERN_ERR, LOG_BG, - "9047 BLKGRD: ERROR unable to allocate " - "memory for hexdump\n"); - } else - lpfc_printf_log(phba, KERN_ERR, LOG_BG, - "9048 BLKGRD: already allocated _dump_buf_dif=x%px\n", - _dump_buf_dif); } /** @@ -13511,19 +13454,6 @@ lpfc_exit(void) pci_unregister_driver(&lpfc_driver); fc_release_transport(lpfc_transport_template); fc_release_transport(lpfc_vport_transport_template); - if (_dump_buf_data) { - printk(KERN_ERR "9062 BLKGRD: freeing %lu pages for " - "_dump_buf_data at x%px\n", - (1L << _dump_buf_data_order), _dump_buf_data); - free_pages((unsigned long)_dump_buf_data, _dump_buf_data_order); - } - - if (_dump_buf_dif) { - printk(KERN_ERR "9049 BLKGRD: freeing %lu pages for " - "_dump_buf_dif at x%px\n", - (1L << _dump_buf_dif_order), _dump_buf_dif); - free_pages((unsigned long)_dump_buf_dif, _dump_buf_dif_order); - } idr_destroy(&lpfc_hba_index); } diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 7c65bd652c4d..fe1097666de4 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -53,8 +53,6 @@ #define LPFC_RESET_WAIT 2 #define LPFC_ABORT_WAIT 2 -int _dump_buf_done = 1; - static char *dif_op_str[] = { "PROT_NORMAL", "PROT_READ_INSERT", @@ -89,63 +87,6 @@ lpfc_release_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *psb); static int lpfc_prot_group_type(struct lpfc_hba *phba, struct scsi_cmnd *sc); -static void -lpfc_debug_save_data(struct lpfc_hba *phba, struct scsi_cmnd *cmnd) -{ - void *src, *dst; - struct scatterlist *sgde = scsi_sglist(cmnd); - - if (!_dump_buf_data) { - lpfc_printf_log(phba, KERN_ERR, LOG_BG, - "9050 BLKGRD: ERROR %s _dump_buf_data is NULL\n", - __func__); - return; - } - - - if (!sgde) { - lpfc_printf_log(phba, KERN_ERR, LOG_BG, - "9051 BLKGRD: ERROR: data scatterlist is null\n"); - return; - } - - dst = (void *) _dump_buf_data; - while (sgde) { - src = sg_virt(sgde); - memcpy(dst, src, sgde->length); - dst += sgde->length; - sgde = sg_next(sgde); - } -} - -static void -lpfc_debug_save_dif(struct lpfc_hba *phba, struct scsi_cmnd *cmnd) -{ - void *src, *dst; - struct scatterlist *sgde = scsi_prot_sglist(cmnd); - - if (!_dump_buf_dif) { - lpfc_printf_log(phba, KERN_ERR, LOG_BG, - "9052 BLKGRD: ERROR %s _dump_buf_data is NULL\n", - __func__); - return; - } - - if (!sgde) { - lpfc_printf_log(phba, KERN_ERR, LOG_BG, - "9053 BLKGRD: ERROR: prot scatterlist is null\n"); - return; - } - - dst = _dump_buf_dif; - while (sgde) { - src = sg_virt(sgde); - memcpy(dst, src, sgde->length); - dst += sgde->length; - sgde = sg_next(sgde); - } -} - static inline unsigned lpfc_cmd_blksize(struct scsi_cmnd *sc) { @@ -2962,26 +2903,6 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, uint32_t bgstat = bgf->bgstat; uint64_t failing_sector = 0; - spin_lock(&_dump_buf_lock); - if (!_dump_buf_done) { - lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9070 BLKGRD: Saving" - " Data for %u blocks to debugfs\n", - (cmd->cmnd[7] << 8 | cmd->cmnd[8])); - lpfc_debug_save_data(phba, cmd); - - /* If we have a prot sgl, save the DIF buffer */ - if (lpfc_prot_group_type(phba, cmd) == - LPFC_PG_TYPE_DIF_BUF) { - lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9071 BLKGRD: " - "Saving DIF for %u blocks to debugfs\n", - (cmd->cmnd[7] << 8 | cmd->cmnd[8])); - lpfc_debug_save_dif(phba, cmd); - } - - _dump_buf_done = 1; - } - spin_unlock(&_dump_buf_lock); - if (lpfc_bgs_get_invalid_prof(bgstat)) { cmd->result = DID_ERROR << 16; lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, -- cgit v1.2.3-59-g8ed1b From 01f2ef6d18e70c92bbf3743be4b908f52a059263 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 28 Aug 2019 16:19:11 -0700 Subject: scsi: lpfc: fix 12.4.0.0 GPF at boot The 12.4.0.0 patch that merged WQ/CQ pairs into single per-cpu pair contained a bug: a local variable was set to the queue pair by index. This should have allowed the local variable to be natively used. Instead, the code reused the index relative to the local variable, obtaining a random pointer value that when used eventually faulted the system Convert offending code to use local variable. Fixes: c00f62e6c546 ("scsi: lpfc: Merge per-protocol WQ/CQ pairs into single per-cpu pair") Signed-off-by: Dick Kennedy Signed-off-by: James Smart Tested-by: Abdul Haleem Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_sli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 0dfd30aa4d99..bb5705267c39 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -5553,7 +5553,7 @@ lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba) for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) { qp = &sli4_hba->hdwq[qidx]; /* ARM the corresponding CQ */ - sli4_hba->sli4_write_cq_db(phba, qp[qidx].io_cq, 0, + sli4_hba->sli4_write_cq_db(phba, qp->io_cq, 0, LPFC_QUEUE_REARM); } -- cgit v1.2.3-59-g8ed1b From 5e6a9760f7da4dd86cca43ac6423695d6cb0dff4 Mon Sep 17 00:00:00 2001 From: Gilbert Wu Date: Thu, 22 Aug 2019 15:38:58 -0500 Subject: scsi: smartpqi: add module param for exposure order Expose physical devices before logical devices. Reviewed-by: Scott Benesh Reviewed-by: Kevin Barnett Signed-off-by: Gilbert Wu Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/smartpqi/smartpqi_init.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index 8fd5ffc55792..4324234aa26c 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -145,6 +145,12 @@ MODULE_PARM_DESC(lockup_action, "Action to take when controller locked up.\n" "\t\tSupported: none, reboot, panic\n" "\t\tDefault: none"); +static int pqi_expose_ld_first; +module_param_named(expose_ld_first, + pqi_expose_ld_first, int, 0644); +MODULE_PARM_DESC(expose_ld_first, + "Expose logical drives before physical drives."); + static char *raid_levels[] = { "RAID-0", "RAID-4", @@ -1988,6 +1994,8 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info) unsigned int num_valid_devices; bool is_physical_device; u8 *scsi3addr; + unsigned int physical_index; + unsigned int logical_index; static char *out_of_memory_msg = "failed to allocate memory, device discovery stopped"; @@ -2050,19 +2058,23 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info) device = NULL; num_valid_devices = 0; + physical_index = 0; + logical_index = 0; for (i = 0; i < num_new_devices; i++) { - if (i < num_physicals) { + if ((!pqi_expose_ld_first && i < num_physicals) || + (pqi_expose_ld_first && i >= num_logicals)) { is_physical_device = true; - phys_lun_ext_entry = &physdev_list->lun_entries[i]; + phys_lun_ext_entry = + &physdev_list->lun_entries[physical_index++]; log_lun_ext_entry = NULL; scsi3addr = phys_lun_ext_entry->lunid; } else { is_physical_device = false; phys_lun_ext_entry = NULL; log_lun_ext_entry = - &logdev_list->lun_entries[i - num_physicals]; + &logdev_list->lun_entries[logical_index++]; scsi3addr = log_lun_ext_entry->lunid; } -- cgit v1.2.3-59-g8ed1b From 8bdb3b9c67c53eaeac2b97a6f0d2f86ccd3e5ba8 Mon Sep 17 00:00:00 2001 From: Gilbert Wu Date: Thu, 22 Aug 2019 15:39:04 -0500 Subject: scsi: smartpqi: add pci ids for fiberhome controller Reviewed-by: Scott Benesh Reviewed-by: Kevin Barnett Signed-off-by: Gilbert Wu Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/smartpqi/smartpqi_init.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index 4324234aa26c..fa6403b2741c 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -8254,6 +8254,22 @@ static const struct pci_device_id pqi_pci_id_table[] = { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_VENDOR_ID_HP, 0x1101) }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1d8d, 0x0800) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1d8d, 0x0908) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1d8d, 0x0806) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1d8d, 0x0916) + }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_ANY_ID, PCI_ANY_ID) -- cgit v1.2.3-59-g8ed1b From 522bc026f01381a91e65ed343781b1656f5e659a Mon Sep 17 00:00:00 2001 From: Dave Carroll Date: Thu, 22 Aug 2019 15:39:11 -0500 Subject: scsi: smartpqi: add module param to hide vsep Reviewed-by: Scott Benesh Reviewed-by: Kevin Barnett Signed-off-by: Dave Carroll Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/smartpqi/smartpqi.h | 1 + drivers/scsi/smartpqi/smartpqi_init.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h index e8e768849c70..0a629f2f447a 100644 --- a/drivers/scsi/smartpqi/smartpqi.h +++ b/drivers/scsi/smartpqi/smartpqi.h @@ -822,6 +822,7 @@ union pqi_reset_register { #define PQI_HBA_BUS 2 #define PQI_EXTERNAL_RAID_VOLUME_BUS 3 #define PQI_MAX_BUS PQI_EXTERNAL_RAID_VOLUME_BUS +#define PQI_VSEP_CISS_BTL 379 struct report_lun_header { __be32 list_length; diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index fa6403b2741c..f289fbd4220d 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -151,6 +151,12 @@ module_param_named(expose_ld_first, MODULE_PARM_DESC(expose_ld_first, "Expose logical drives before physical drives."); +static int pqi_hide_vsep; +module_param_named(hide_vsep, + pqi_hide_vsep, int, 0644); +MODULE_PARM_DESC(hide_vsep, + "Hide the virtual SEP for direct attached drives."); + static char *raid_levels[] = { "RAID-0", "RAID-4", @@ -1951,6 +1957,11 @@ static inline bool pqi_skip_device(u8 *scsi3addr) return false; } +static inline void pqi_mask_device(u8 *scsi3addr) +{ + scsi3addr[3] |= 0xc0; +} + static inline bool pqi_is_device_with_sas_address(struct pqi_scsi_dev *device) { if (!device->is_physical_device) @@ -2031,6 +2042,21 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info) rc = -ENOMEM; goto out; } + if (pqi_hide_vsep) { + int i; + + for (i = num_physicals - 1; i >= 0; i--) { + phys_lun_ext_entry = + &physdev_list->lun_entries[i]; + if (CISS_GET_DRIVE_NUMBER( + phys_lun_ext_entry->lunid) == + PQI_VSEP_CISS_BTL) { + pqi_mask_device( + phys_lun_ext_entry->lunid); + break; + } + } + } } num_new_devices = num_physicals + num_logicals; -- cgit v1.2.3-59-g8ed1b From 6d90615f1346aed3674ebf825d1a6eda722e2e29 Mon Sep 17 00:00:00 2001 From: Murthy Bhat Date: Thu, 22 Aug 2019 15:39:18 -0500 Subject: scsi: smartpqi: add sysfs entries - serial number - model - vendor Reviewed-by: Scott Benesh Reviewed-by: Kevin Barnett Signed-off-by: Murthy Bhat Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/smartpqi/smartpqi.h | 15 +++- drivers/scsi/smartpqi/smartpqi_init.c | 125 ++++++++++++++++++++++++++++++---- 2 files changed, 124 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h index 0a629f2f447a..2b21c4ebc491 100644 --- a/drivers/scsi/smartpqi/smartpqi.h +++ b/drivers/scsi/smartpqi/smartpqi.h @@ -1074,6 +1074,9 @@ struct pqi_ctrl_info { unsigned int ctrl_id; struct pci_dev *pci_dev; char firmware_version[11]; + char serial_number[17]; + char model[17]; + char vendor[9]; void __iomem *iomem_base; struct pqi_ctrl_registers __iomem *registers; struct pqi_device_registers __iomem *pqi_registers; @@ -1225,9 +1228,17 @@ struct bmic_identify_controller { __le16 extended_logical_unit_count; u8 reserved1[34]; __le16 firmware_build_number; - u8 reserved2[100]; + u8 reserved2[8]; + u8 vendor_id[8]; + u8 product_id[16]; + u8 reserved3[68]; u8 controller_mode; - u8 reserved3[32]; + u8 reserved4[32]; +}; + +struct bmic_sense_subsystem_info { + u8 reserved[44]; + u8 ctrl_serial_number[16]; }; #define SA_EXPANDER_SMP_DEVICE 0x05 diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index f289fbd4220d..7d09998db1b1 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -484,6 +484,7 @@ static int pqi_build_raid_path_request(struct pqi_ctrl_info *ctrl_info, /* fall through */ case BMIC_IDENTIFY_CONTROLLER: case BMIC_IDENTIFY_PHYSICAL_DEVICE: + case BMIC_SENSE_SUBSYSTEM_INFORMATION: request->data_direction = SOP_READ_FLAG; cdb[0] = BMIC_READ; cdb[6] = cmd; @@ -612,6 +613,14 @@ static inline int pqi_identify_controller(struct pqi_ctrl_info *ctrl_info, buffer, sizeof(*buffer)); } +static inline int pqi_sense_subsystem_info(struct pqi_ctrl_info *ctrl_info, + struct bmic_sense_subsystem_info *sense_info) +{ + return pqi_send_ctrl_raid_request(ctrl_info, + BMIC_SENSE_SUBSYSTEM_INFORMATION, + sense_info, sizeof(*sense_info)); +} + static inline int pqi_scsi_inquiry(struct pqi_ctrl_info *ctrl_info, u8 *scsi3addr, u16 vpd_page, void *buffer, size_t buffer_length) { @@ -6129,23 +6138,65 @@ static int pqi_ioctl(struct scsi_device *sdev, unsigned int cmd, return rc; } -static ssize_t pqi_version_show(struct device *dev, +static ssize_t pqi_firmware_version_show(struct device *dev, struct device_attribute *attr, char *buffer) { - ssize_t count = 0; struct Scsi_Host *shost; struct pqi_ctrl_info *ctrl_info; shost = class_to_shost(dev); ctrl_info = shost_to_hba(shost); - count += snprintf(buffer + count, PAGE_SIZE - count, - " driver: %s\n", DRIVER_VERSION BUILD_TIMESTAMP); + return snprintf(buffer, PAGE_SIZE, "%s\n", ctrl_info->firmware_version); +} + +static ssize_t pqi_driver_version_show(struct device *dev, + struct device_attribute *attr, char *buffer) +{ + struct Scsi_Host *shost; + struct pqi_ctrl_info *ctrl_info; + + shost = class_to_shost(dev); + ctrl_info = shost_to_hba(shost); - count += snprintf(buffer + count, PAGE_SIZE - count, - "firmware: %s\n", ctrl_info->firmware_version); + return snprintf(buffer, PAGE_SIZE, + "%s\n", DRIVER_VERSION BUILD_TIMESTAMP); +} - return count; +static ssize_t pqi_serial_number_show(struct device *dev, + struct device_attribute *attr, char *buffer) +{ + struct Scsi_Host *shost; + struct pqi_ctrl_info *ctrl_info; + + shost = class_to_shost(dev); + ctrl_info = shost_to_hba(shost); + + return snprintf(buffer, PAGE_SIZE, "%s\n", ctrl_info->serial_number); +} + +static ssize_t pqi_model_show(struct device *dev, + struct device_attribute *attr, char *buffer) +{ + struct Scsi_Host *shost; + struct pqi_ctrl_info *ctrl_info; + + shost = class_to_shost(dev); + ctrl_info = shost_to_hba(shost); + + return snprintf(buffer, PAGE_SIZE, "%s\n", ctrl_info->model); +} + +static ssize_t pqi_vendor_show(struct device *dev, + struct device_attribute *attr, char *buffer) +{ + struct Scsi_Host *shost; + struct pqi_ctrl_info *ctrl_info; + + shost = class_to_shost(dev); + ctrl_info = shost_to_hba(shost); + + return snprintf(buffer, PAGE_SIZE, "%s\n", ctrl_info->vendor); } static ssize_t pqi_host_rescan_store(struct device *dev, @@ -6198,13 +6249,21 @@ static ssize_t pqi_lockup_action_store(struct device *dev, return -EINVAL; } -static DEVICE_ATTR(version, 0444, pqi_version_show, NULL); +static DEVICE_ATTR(driver_version, 0444, pqi_driver_version_show, NULL); +static DEVICE_ATTR(firmware_version, 0444, pqi_firmware_version_show, NULL); +static DEVICE_ATTR(model, 0444, pqi_model_show, NULL); +static DEVICE_ATTR(serial_number, 0444, pqi_serial_number_show, NULL); +static DEVICE_ATTR(vendor, 0444, pqi_vendor_show, NULL); static DEVICE_ATTR(rescan, 0200, NULL, pqi_host_rescan_store); static DEVICE_ATTR(lockup_action, 0644, pqi_lockup_action_show, pqi_lockup_action_store); static struct device_attribute *pqi_shost_attrs[] = { - &dev_attr_version, + &dev_attr_driver_version, + &dev_attr_firmware_version, + &dev_attr_model, + &dev_attr_serial_number, + &dev_attr_vendor, &dev_attr_rescan, &dev_attr_lockup_action, NULL @@ -6596,7 +6655,30 @@ static int pqi_reset(struct pqi_ctrl_info *ctrl_info) return rc; } -static int pqi_get_ctrl_firmware_version(struct pqi_ctrl_info *ctrl_info) +static int pqi_get_ctrl_serial_number(struct pqi_ctrl_info *ctrl_info) +{ + int rc; + struct bmic_sense_subsystem_info *sense_info; + + sense_info = kzalloc(sizeof(*sense_info), GFP_KERNEL); + if (!sense_info) + return -ENOMEM; + + rc = pqi_sense_subsystem_info(ctrl_info, sense_info); + if (rc) + goto out; + + memcpy(ctrl_info->serial_number, sense_info->ctrl_serial_number, + sizeof(sense_info->ctrl_serial_number)); + ctrl_info->serial_number[sizeof(sense_info->ctrl_serial_number)] = '\0'; + +out: + kfree(sense_info); + + return rc; +} + +static int pqi_get_ctrl_product_details(struct pqi_ctrl_info *ctrl_info) { int rc; struct bmic_identify_controller *identify; @@ -6617,6 +6699,14 @@ static int pqi_get_ctrl_firmware_version(struct pqi_ctrl_info *ctrl_info) sizeof(ctrl_info->firmware_version), "-%u", get_unaligned_le16(&identify->firmware_build_number)); + memcpy(ctrl_info->model, identify->product_id, + sizeof(identify->product_id)); + ctrl_info->model[sizeof(identify->product_id)] = '\0'; + + memcpy(ctrl_info->vendor, identify->vendor_id, + sizeof(identify->vendor_id)); + ctrl_info->vendor[sizeof(identify->vendor_id)] = '\0'; + out: kfree(identify); @@ -7136,10 +7226,17 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info) if (rc) return rc; - rc = pqi_get_ctrl_firmware_version(ctrl_info); + rc = pqi_get_ctrl_product_details(ctrl_info); + if (rc) { + dev_err(&ctrl_info->pci_dev->dev, + "error obtaining product details\n"); + return rc; + } + + rc = pqi_get_ctrl_serial_number(ctrl_info); if (rc) { dev_err(&ctrl_info->pci_dev->dev, - "error obtaining firmware version\n"); + "error obtaining ctrl serial number\n"); return rc; } @@ -7279,10 +7376,10 @@ static int pqi_ctrl_init_resume(struct pqi_ctrl_info *ctrl_info) return rc; } - rc = pqi_get_ctrl_firmware_version(ctrl_info); + rc = pqi_get_ctrl_product_details(ctrl_info); if (rc) { dev_err(&ctrl_info->pci_dev->dev, - "error obtaining firmware version\n"); + "error obtaining product detail\n"); return rc; } -- cgit v1.2.3-59-g8ed1b From 2d2ad4bc724e35459a19bbf77432facb9ac23f80 Mon Sep 17 00:00:00 2001 From: Gilbert Wu Date: Thu, 22 Aug 2019 15:39:25 -0500 Subject: scsi: smartpqi: add bay identifier Return identify physical device "Phys_Bay_in_Box" as bay_identifier. Reviewed-by: Scott Benesh Reviewed-by: Kevin Barnett Signed-off-by: Gilbert Wu Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/smartpqi/smartpqi.h | 4 + drivers/scsi/smartpqi/smartpqi_init.c | 13 +++- drivers/scsi/smartpqi/smartpqi_sas_transport.c | 102 ++++++++++++++++++++++++- 3 files changed, 113 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h index 2b21c4ebc491..79d2af36f655 100644 --- a/drivers/scsi/smartpqi/smartpqi.h +++ b/drivers/scsi/smartpqi/smartpqi.h @@ -931,6 +931,9 @@ struct pqi_scsi_dev { u8 active_path_index; u8 path_map; u8 bay; + u8 box_index; + u8 phys_box_on_bus; + u8 phy_connected_dev_type; u8 box[8]; u16 phys_connector[8]; bool raid_bypass_configured; /* RAID bypass configured */ @@ -1242,6 +1245,7 @@ struct bmic_sense_subsystem_info { }; #define SA_EXPANDER_SMP_DEVICE 0x05 +#define SA_CONTROLLER_DEVICE 0x07 /*SCSI Invalid Device Type for SAS devices*/ #define PQI_SAS_SCSI_INVALID_DEVTYPE 0xff diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index 7d09998db1b1..a6cb49b8e5d0 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -1413,7 +1413,9 @@ static void pqi_get_physical_disk_info(struct pqi_ctrl_info *ctrl_info, device->queue_depth = PQI_PHYSICAL_DISK_DEFAULT_MAX_QUEUE_DEPTH; return; } - + device->box_index = id_phys->box_index; + device->phys_box_on_bus = id_phys->phys_box_on_bus; + device->phy_connected_dev_type = id_phys->phy_connected_dev_type[0]; device->queue_depth = get_unaligned_le16(&id_phys->current_queue_depth_limit); device->device_type = id_phys->device_type; @@ -1740,6 +1742,10 @@ static void pqi_scsi_update_device(struct pqi_scsi_dev *existing_device, existing_device->active_path_index = new_device->active_path_index; existing_device->path_map = new_device->path_map; existing_device->bay = new_device->bay; + existing_device->box_index = new_device->box_index; + existing_device->phys_box_on_bus = new_device->phys_box_on_bus; + existing_device->phy_connected_dev_type = + new_device->phy_connected_dev_type; memcpy(existing_device->box, new_device->box, sizeof(existing_device->box)); memcpy(existing_device->phys_connector, new_device->phys_connector, @@ -2169,11 +2175,10 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info) device->aio_handle = phys_lun_ext_entry->aio_handle; } - if (device->devtype == TYPE_DISK || - device->devtype == TYPE_ZBC) { + pqi_get_physical_disk_info(ctrl_info, device, id_phys); - } + } else { memcpy(device->volume_id, log_lun_ext_entry->volume_id, sizeof(device->volume_id)); diff --git a/drivers/scsi/smartpqi/smartpqi_sas_transport.c b/drivers/scsi/smartpqi/smartpqi_sas_transport.c index 5cca1b9ef1f1..6776dfc1d317 100644 --- a/drivers/scsi/smartpqi/smartpqi_sas_transport.c +++ b/drivers/scsi/smartpqi/smartpqi_sas_transport.c @@ -312,12 +312,110 @@ static int pqi_sas_get_linkerrors(struct sas_phy *phy) static int pqi_sas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) { - return 0; + + int rc; + unsigned long flags; + struct Scsi_Host *shost; + struct pqi_ctrl_info *ctrl_info; + struct pqi_scsi_dev *found_device; + struct pqi_scsi_dev *device; + + if (!rphy) + return -ENODEV; + + shost = rphy_to_shost(rphy); + ctrl_info = shost_to_hba(shost); + spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); + found_device = pqi_find_device_by_sas_rphy(ctrl_info, rphy); + + if (!found_device) { + rc = -ENODEV; + goto out; + } + + if (found_device->devtype == TYPE_ENCLOSURE) { + *identifier = get_unaligned_be64(&found_device->wwid); + rc = 0; + goto out; + } + + if (found_device->box_index == 0xff || + found_device->phys_box_on_bus == 0 || + found_device->bay == 0xff) { + rc = -EINVAL; + goto out; + } + + list_for_each_entry(device, &ctrl_info->scsi_device_list, + scsi_device_list_entry) { + if (device->devtype == TYPE_ENCLOSURE && + device->box_index == found_device->box_index && + device->phys_box_on_bus == + found_device->phys_box_on_bus && + memcmp(device->phys_connector, + found_device->phys_connector, 2) == 0) { + *identifier = + get_unaligned_be64(&device->wwid); + rc = 0; + goto out; + } + } + + if (found_device->phy_connected_dev_type != SA_CONTROLLER_DEVICE) { + rc = -EINVAL; + goto out; + } + + list_for_each_entry(device, &ctrl_info->scsi_device_list, + scsi_device_list_entry) { + if (device->devtype == TYPE_ENCLOSURE && + CISS_GET_DRIVE_NUMBER(device->scsi3addr) == + PQI_VSEP_CISS_BTL) { + *identifier = get_unaligned_be64(&device->wwid); + rc = 0; + goto out; + } + } + + rc = -EINVAL; +out: + spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); + + return rc; + } static int pqi_sas_get_bay_identifier(struct sas_rphy *rphy) { - return -ENXIO; + + int rc; + unsigned long flags; + struct pqi_ctrl_info *ctrl_info; + struct pqi_scsi_dev *device; + struct Scsi_Host *shost; + + if (!rphy) + return -ENODEV; + + shost = rphy_to_shost(rphy); + ctrl_info = shost_to_hba(shost); + spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); + device = pqi_find_device_by_sas_rphy(ctrl_info, rphy); + + if (!device) { + rc = -ENODEV; + goto out; + } + + if (device->bay == 0xff) + rc = -EINVAL; + else + rc = device->bay; + +out: + spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); + + return rc; } static int pqi_sas_phy_reset(struct sas_phy *phy, int hard_reset) -- cgit v1.2.3-59-g8ed1b From 530dd8a7a2b1ff2ee6c862ba250ca54ccc8c8c3e Mon Sep 17 00:00:00 2001 From: Mahesh Rajashekhara Date: Thu, 22 Aug 2019 15:39:31 -0500 Subject: scsi: smartpqi: correct hang when deleting 32 lds When each ld is deleted, a rescan event is triggered in the driver. These can stack up waiting on mutex_lock. Change to mutex_try_lock and schedule a rescan for later. Reviewed-by: Scott Benesh Reviewed-by: Kevin Barnett Signed-off-by: Mahesh Rajashekhara Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/smartpqi/smartpqi_init.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index a6cb49b8e5d0..9801606dadfa 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -2236,18 +2236,20 @@ static void pqi_remove_all_scsi_devices(struct pqi_ctrl_info *ctrl_info) static int pqi_scan_scsi_devices(struct pqi_ctrl_info *ctrl_info) { - int rc; + int rc = 0; if (pqi_ctrl_offline(ctrl_info)) return -ENXIO; - mutex_lock(&ctrl_info->scan_mutex); - - rc = pqi_update_scsi_devices(ctrl_info); - if (rc) + if (!mutex_trylock(&ctrl_info->scan_mutex)) { pqi_schedule_rescan_worker_delayed(ctrl_info); - mutex_unlock(&ctrl_info->scan_mutex); + } else { + rc = pqi_update_scsi_devices(ctrl_info); + if (rc) + pqi_schedule_rescan_worker_delayed(ctrl_info); + mutex_unlock(&ctrl_info->scan_mutex); + } return rc; } -- cgit v1.2.3-59-g8ed1b From 71ecc60d9ba47ee5af5a1d0f33cc92755995fb78 Mon Sep 17 00:00:00 2001 From: Gilbert Wu Date: Thu, 22 Aug 2019 15:39:38 -0500 Subject: scsi: smartpqi: add gigabyte controller Reviewed-by: Scott Benesh Reviewed-by: Kevin Barnett Signed-off-by: Gilbert Wu Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/smartpqi/smartpqi_init.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index 9801606dadfa..159e9cfc2996 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -8400,6 +8400,10 @@ static const struct pci_device_id pqi_pci_id_table[] = { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x1d8d, 0x0916) }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_GIGABYTE, 0x1000) + }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_ANY_ID, PCI_ANY_ID) -- cgit v1.2.3-59-g8ed1b From 9946a3987248353c32c94f3b5b13070aee0a1a6b Mon Sep 17 00:00:00 2001 From: Murthy Bhat Date: Thu, 22 Aug 2019 15:39:44 -0500 Subject: scsi: smartpqi: correct REGNEWD return status Return -EINPROGRESS when a rescan worker is queued. Reviewed-by: Scott Benesh Reviewed-by: Kevin Barnett Signed-off-by: Murthy Bhat Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/smartpqi/smartpqi_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index 159e9cfc2996..61371ea35bb3 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -2243,7 +2243,7 @@ static int pqi_scan_scsi_devices(struct pqi_ctrl_info *ctrl_info) if (!mutex_trylock(&ctrl_info->scan_mutex)) { pqi_schedule_rescan_worker_delayed(ctrl_info); - + rc = -EINPROGRESS; } else { rc = pqi_update_scsi_devices(ctrl_info); if (rc) -- cgit v1.2.3-59-g8ed1b From 63a7956ae1e8cdb7bd026b584aef7d505cb393ee Mon Sep 17 00:00:00 2001 From: Gilbert Wu Date: Thu, 22 Aug 2019 15:39:51 -0500 Subject: scsi: smartpqi: add new pci ids Add: PM8222 VID_9005, DID_028F, SVID_1BD4 and SDID_004F 3101E-4i (1G, no GB) VID_9005, DID_028F, SVID_9005 and SDID_0808 3102E-8i (2G, no GB) VID_9005, DID_028F, SVID_9005 and SDID_0809 Reviewed-by: Scott Benesh Reviewed-by: Kevin Barnett Signed-off-by: Gilbert Wu Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/smartpqi/smartpqi_init.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index 61371ea35bb3..c9da65117120 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -8164,6 +8164,10 @@ static const struct pci_device_id pqi_pci_id_table[] = { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x1bd4, 0x004c) }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x004f) + }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x19e5, 0xd227) @@ -8228,6 +8232,14 @@ static const struct pci_device_id pqi_pci_id_table[] = { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_VENDOR_ID_ADAPTEC2, 0x0807) }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_ADAPTEC2, 0x0808) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_ADAPTEC2, 0x0809) + }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_VENDOR_ID_ADAPTEC2, 0x0900) -- cgit v1.2.3-59-g8ed1b From 48edb87801004f2b93420701ad253a058dd48d49 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Thu, 22 Aug 2019 15:39:58 -0500 Subject: scsi: smartpqi: update copyright Reviewed-by: Scott Benesh Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/smartpqi/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/smartpqi/Kconfig b/drivers/scsi/smartpqi/Kconfig index 97e159c2cecd..bc6506884e3b 100644 --- a/drivers/scsi/smartpqi/Kconfig +++ b/drivers/scsi/smartpqi/Kconfig @@ -1,6 +1,8 @@ # # Kernel configuration file for the SMARTPQI # +# Copyright (c) 2019 Microchip Technology Inc. and its subsidiaries +# Copyright (c) 2017-2018 Microsemi Corporation # Copyright (c) 2016 Microsemi Corporation # Copyright (c) 2016 PMC-Sierra, Inc. # (mailto:esc.storagedev@microsemi.com) -- cgit v1.2.3-59-g8ed1b From 391a2417942358de4c794846a4a7dde095010258 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Thu, 22 Aug 2019 15:40:05 -0500 Subject: scsi: smartpqi: bump version Reviewed-by: Scott Benesh Reviewed-by: Gerry Morong Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/smartpqi/smartpqi_init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index c9da65117120..ea5409bebf57 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -33,11 +33,11 @@ #define BUILD_TIMESTAMP #endif -#define DRIVER_VERSION "1.2.6-015" +#define DRIVER_VERSION "1.2.8-026" #define DRIVER_MAJOR 1 #define DRIVER_MINOR 2 -#define DRIVER_RELEASE 6 -#define DRIVER_REVISION 15 +#define DRIVER_RELEASE 8 +#define DRIVER_REVISION 26 #define DRIVER_NAME "Microsemi PQI Driver (v" \ DRIVER_VERSION BUILD_TIMESTAMP ")" -- cgit v1.2.3-59-g8ed1b From e82e6ff7779a76ea9b2161ee5fe2cdd9387cf263 Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Fri, 23 Aug 2019 02:52:31 -0700 Subject: scsi: qedf: Print message during bailout conditions Print messages during exiting condition to help debugging. Signed-off-by: Saurav Kashyap Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf_debugfs.c | 16 +++++------ drivers/scsi/qedf/qedf_els.c | 38 ++++++++++++++++++++------ drivers/scsi/qedf/qedf_fip.c | 5 +++- drivers/scsi/qedf/qedf_io.c | 58 +++++++++++++++++++++++++++++++++------- drivers/scsi/qedf/qedf_main.c | 53 ++++++++++++++++++++++++++---------- 5 files changed, 130 insertions(+), 40 deletions(-) diff --git a/drivers/scsi/qedf/qedf_debugfs.c b/drivers/scsi/qedf/qedf_debugfs.c index d905a307302d..b88bed9bb133 100644 --- a/drivers/scsi/qedf/qedf_debugfs.c +++ b/drivers/scsi/qedf/qedf_debugfs.c @@ -47,13 +47,13 @@ qedf_dbg_host_init(struct qedf_dbg_ctx *qedf, * @pf: the pf that is stopping **/ void -qedf_dbg_host_exit(struct qedf_dbg_ctx *qedf) +qedf_dbg_host_exit(struct qedf_dbg_ctx *qedf_dbg) { - QEDF_INFO(qedf, QEDF_LOG_DEBUGFS, "Destroying debugfs host " + QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "Destroying debugfs host " "entry\n"); /* remove debugfs entries of this PF */ - debugfs_remove_recursive(qedf->bdf_dentry); - qedf->bdf_dentry = NULL; + debugfs_remove_recursive(qedf_dbg->bdf_dentry); + qedf_dbg->bdf_dentry = NULL; } /** @@ -140,10 +140,10 @@ qedf_dbg_debug_cmd_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos) { int cnt; - struct qedf_dbg_ctx *qedf = + struct qedf_dbg_ctx *qedf_dbg = (struct qedf_dbg_ctx *)filp->private_data; - QEDF_INFO(qedf, QEDF_LOG_DEBUGFS, "entered\n"); + QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "debug mask=0x%x\n", qedf_debug); cnt = sprintf(buffer, "debug mask = 0x%x\n", qedf_debug); cnt = min_t(int, count, cnt - *ppos); @@ -158,7 +158,7 @@ qedf_dbg_debug_cmd_write(struct file *filp, const char __user *buffer, uint32_t val; void *kern_buf; int rval; - struct qedf_dbg_ctx *qedf = + struct qedf_dbg_ctx *qedf_dbg = (struct qedf_dbg_ctx *)filp->private_data; if (!count || *ppos) @@ -178,7 +178,7 @@ qedf_dbg_debug_cmd_write(struct file *filp, const char __user *buffer, else qedf_debug = val; - QEDF_INFO(qedf, QEDF_LOG_DEBUGFS, "Setting debug=0x%x.\n", val); + QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "Setting debug=0x%x.\n", val); return count; } diff --git a/drivers/scsi/qedf/qedf_els.c b/drivers/scsi/qedf/qedf_els.c index 5996f68fbf2b..87e169dcebdb 100644 --- a/drivers/scsi/qedf/qedf_els.c +++ b/drivers/scsi/qedf/qedf_els.c @@ -179,8 +179,11 @@ static void qedf_rrq_compl(struct qedf_els_cb_arg *cb_arg) orig_io_req = cb_arg->aborted_io_req; - if (!orig_io_req) + if (!orig_io_req) { + QEDF_ERR(&qedf->dbg_ctx, + "Original io_req is NULL, rrq_req = %p.\n", rrq_req); goto out_free; + } if (rrq_req->event != QEDF_IOREQ_EV_ELS_TMO && rrq_req->event != QEDF_IOREQ_EV_ELS_ERR_DETECT) @@ -350,8 +353,10 @@ void qedf_restart_rport(struct qedf_rport *fcport) u32 port_id; unsigned long flags; - if (!fcport) + if (!fcport) { + QEDF_ERR(NULL, "fcport is NULL.\n"); return; + } spin_lock_irqsave(&fcport->rport_lock, flags); if (test_bit(QEDF_RPORT_IN_RESET, &fcport->flags) || @@ -418,8 +423,11 @@ static void qedf_l2_els_compl(struct qedf_els_cb_arg *cb_arg) * If we are flushing the command just free the cb_arg as none of the * response data will be valid. */ - if (els_req->event == QEDF_IOREQ_EV_ELS_FLUSH) + if (els_req->event == QEDF_IOREQ_EV_ELS_FLUSH) { + QEDF_ERR(NULL, "els_req xid=0x%x event is flush.\n", + els_req->xid); goto free_arg; + } fcport = els_req->fcport; mp_req = &(els_req->mp_req); @@ -532,8 +540,10 @@ static void qedf_srr_compl(struct qedf_els_cb_arg *cb_arg) orig_io_req = cb_arg->aborted_io_req; - if (!orig_io_req) + if (!orig_io_req) { + QEDF_ERR(NULL, "orig_io_req is NULL.\n"); goto out_free; + } clear_bit(QEDF_CMD_SRR_SENT, &orig_io_req->flags); @@ -547,8 +557,11 @@ static void qedf_srr_compl(struct qedf_els_cb_arg *cb_arg) orig_io_req, orig_io_req->xid, srr_req->xid, refcount); /* If a SRR times out, simply free resources */ - if (srr_req->event == QEDF_IOREQ_EV_ELS_TMO) + if (srr_req->event == QEDF_IOREQ_EV_ELS_TMO) { + QEDF_ERR(&qedf->dbg_ctx, + "ELS timeout rec_xid=0x%x.\n", srr_req->xid); goto out_put; + } /* Normalize response data into struct fc_frame */ mp_req = &(srr_req->mp_req); @@ -721,8 +734,11 @@ void qedf_process_seq_cleanup_compl(struct qedf_ctx *qedf, cb_arg = io_req->cb_arg; /* If we timed out just free resources */ - if (io_req->event == QEDF_IOREQ_EV_ELS_TMO || !cqe) + if (io_req->event == QEDF_IOREQ_EV_ELS_TMO || !cqe) { + QEDF_ERR(&qedf->dbg_ctx, + "cqe is NULL or timeout event (0x%x)", io_req->event); goto free; + } /* Kill the timer we put on the request */ cancel_delayed_work_sync(&io_req->timeout_work); @@ -825,8 +841,10 @@ static void qedf_rec_compl(struct qedf_els_cb_arg *cb_arg) orig_io_req = cb_arg->aborted_io_req; - if (!orig_io_req) + if (!orig_io_req) { + QEDF_ERR(NULL, "orig_io_req is NULL.\n"); goto out_free; + } if (rec_req->event != QEDF_IOREQ_EV_ELS_TMO && rec_req->event != QEDF_IOREQ_EV_ELS_ERR_DETECT) @@ -838,8 +856,12 @@ static void qedf_rec_compl(struct qedf_els_cb_arg *cb_arg) orig_io_req, orig_io_req->xid, rec_req->xid, refcount); /* If a REC times out, free resources */ - if (rec_req->event == QEDF_IOREQ_EV_ELS_TMO) + if (rec_req->event == QEDF_IOREQ_EV_ELS_TMO) { + QEDF_ERR(&qedf->dbg_ctx, + "Got TMO event, orig_io_req %p orig_io_xid=0x%x.\n", + orig_io_req, orig_io_req->xid); goto out_put; + } /* Normalize response data into struct fc_frame */ mp_req = &(rec_req->mp_req); diff --git a/drivers/scsi/qedf/qedf_fip.c b/drivers/scsi/qedf/qedf_fip.c index 362d2bed72fb..5143d93bcc38 100644 --- a/drivers/scsi/qedf/qedf_fip.c +++ b/drivers/scsi/qedf/qedf_fip.c @@ -23,8 +23,11 @@ void qedf_fcoe_send_vlan_req(struct qedf_ctx *qedf) int rc = -1; skb = dev_alloc_skb(sizeof(struct fip_vlan)); - if (!skb) + if (!skb) { + QEDF_ERR(&qedf->dbg_ctx, + "Failed to allocate skb.\n"); return; + } eth_fr = (char *)skb->data; vlan = (struct fip_vlan *)eth_fr; diff --git a/drivers/scsi/qedf/qedf_io.c b/drivers/scsi/qedf/qedf_io.c index d881e822f92c..5b428922b83e 100644 --- a/drivers/scsi/qedf/qedf_io.c +++ b/drivers/scsi/qedf/qedf_io.c @@ -104,6 +104,8 @@ static void qedf_cmd_timeout(struct work_struct *work) qedf_process_seq_cleanup_compl(qedf, NULL, io_req); break; default: + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO, + "Hit default case, xid=0x%x.\n", io_req->xid); break; } } @@ -122,8 +124,10 @@ void qedf_cmd_mgr_free(struct qedf_cmd_mgr *cmgr) num_ios = max_xid - min_xid + 1; /* Free fcoe_bdt_ctx structures */ - if (!cmgr->io_bdt_pool) + if (!cmgr->io_bdt_pool) { + QEDF_ERR(&qedf->dbg_ctx, "io_bdt_pool is NULL.\n"); goto free_cmd_pool; + } bd_tbl_sz = QEDF_MAX_BDS_PER_CMD * sizeof(struct scsi_sge); for (i = 0; i < num_ios; i++) { @@ -226,8 +230,11 @@ struct qedf_cmd_mgr *qedf_cmd_mgr_alloc(struct qedf_ctx *qedf) io_req->sense_buffer = dma_alloc_coherent(&qedf->pdev->dev, QEDF_SCSI_SENSE_BUFFERSIZE, &io_req->sense_buffer_dma, GFP_KERNEL); - if (!io_req->sense_buffer) + if (!io_req->sense_buffer) { + QEDF_ERR(&qedf->dbg_ctx, + "Failed to alloc sense buffer.\n"); goto mem_err; + } /* Allocate task parameters to pass to f/w init funcions */ io_req->task_params = kzalloc(sizeof(*io_req->task_params), @@ -437,8 +444,12 @@ void qedf_release_cmd(struct kref *ref) struct qedf_rport *fcport = io_req->fcport; unsigned long flags; - if (io_req->cmd_type == QEDF_SCSI_CMD) + if (io_req->cmd_type == QEDF_SCSI_CMD) { + QEDF_WARN(&fcport->qedf->dbg_ctx, + "Cmd released called without scsi_done called, io_req %p xid=0x%x.\n", + io_req, io_req->xid); WARN_ON(io_req->sc_cmd); + } if (io_req->cmd_type == QEDF_ELS || io_req->cmd_type == QEDF_TASK_MGMT_CMD) @@ -447,8 +458,10 @@ void qedf_release_cmd(struct kref *ref) atomic_inc(&cmd_mgr->free_list_cnt); atomic_dec(&fcport->num_active_ios); atomic_set(&io_req->state, QEDF_CMD_ST_INACTIVE); - if (atomic_read(&fcport->num_active_ios) < 0) + if (atomic_read(&fcport->num_active_ios) < 0) { QEDF_WARN(&(fcport->qedf->dbg_ctx), "active_ios < 0.\n"); + WARN_ON(1); + } /* Increment task retry identifier now that the request is released */ io_req->task_retry_identifier++; @@ -951,6 +964,9 @@ qedf_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc_cmd) if (test_bit(QEDF_UNLOADING, &qedf->flags) || test_bit(QEDF_DBG_STOP_IO, &qedf->flags)) { + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO, + "Returning DNC as unloading or stop io, flags 0x%lx.\n", + qedf->flags); sc_cmd->result = DID_NO_CONNECT << 16; sc_cmd->scsi_done(sc_cmd); return 0; @@ -967,6 +983,9 @@ qedf_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc_cmd) rval = fc_remote_port_chkready(rport); if (rval) { + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO, + "fc_remote_port_chkready failed=0x%x for port_id=0x%06x.\n", + rval, rport->port_id); sc_cmd->result = rval; sc_cmd->scsi_done(sc_cmd); return 0; @@ -974,12 +993,14 @@ qedf_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc_cmd) /* Retry command if we are doing a qed drain operation */ if (test_bit(QEDF_DRAIN_ACTIVE, &qedf->flags)) { + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO, "Drain active.\n"); rc = SCSI_MLQUEUE_HOST_BUSY; goto exit_qcmd; } if (lport->state != LPORT_ST_READY || atomic_read(&qedf->link_state) != QEDF_LINK_UP) { + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO, "Link down.\n"); rc = SCSI_MLQUEUE_HOST_BUSY; goto exit_qcmd; } @@ -1297,8 +1318,10 @@ void qedf_scsi_done(struct qedf_ctx *qedf, struct qedf_ioreq *io_req, struct scsi_cmnd *sc_cmd; int refcount; - if (!io_req) + if (!io_req) { + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO, "io_req is NULL\n"); return; + } if (test_and_set_bit(QEDF_CMD_ERR_SCSI_DONE, &io_req->flags)) { QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO, @@ -1414,8 +1437,12 @@ void qedf_process_warning_compl(struct qedf_ctx *qedf, struct fcoe_cqe *cqe, u64 err_warn_bit_map; u8 err_warn = 0xff; - if (!cqe) + if (!cqe) { + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO, + "cqe is NULL for io_req %p xid=0x%x\n", + io_req, io_req->xid); return; + } QEDF_ERR(&(io_req->fcport->qedf->dbg_ctx), "Warning CQE, " "xid=0x%x\n", io_req->xid); @@ -1477,8 +1504,11 @@ void qedf_process_error_detect(struct qedf_ctx *qedf, struct fcoe_cqe *cqe, { int rval; - if (!cqe) + if (!cqe) { + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO, + "cqe is NULL for io_req %p\n", io_req); return; + } QEDF_ERR(&(io_req->fcport->qedf->dbg_ctx), "Error detection CQE, " "xid=0x%x\n", io_req->xid); @@ -1543,8 +1573,10 @@ void qedf_flush_active_ios(struct qedf_rport *fcport, int lun) int wait_cnt = 100; int refcount = 0; - if (!fcport) + if (!fcport) { + QEDF_ERR(NULL, "fcport is NULL\n"); return; + } /* Check that fcport is still offloaded */ if (!test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags)) { @@ -1976,6 +2008,10 @@ void qedf_process_abts_compl(struct qedf_ctx *qedf, struct fcoe_cqe *cqe, clear_bit(QEDF_CMD_IN_ABORT, &io_req->flags); if (io_req->sc_cmd) { + if (!io_req->return_scsi_cmd_on_abts) + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_SCSI_TM, + "Not call scsi_done for xid=0x%x.\n", + io_req->xid); if (io_req->return_scsi_cmd_on_abts) qedf_scsi_done(qedf, io_req, DID_ERROR); } @@ -2201,6 +2237,10 @@ int qedf_initiate_cleanup(struct qedf_ioreq *io_req, } if (io_req->sc_cmd) { + if (!io_req->return_scsi_cmd_on_abts) + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_SCSI_TM, + "Not call scsi_done for xid=0x%x.\n", + io_req->xid); if (io_req->return_scsi_cmd_on_abts) qedf_scsi_done(qedf, io_req, DID_ERROR); } @@ -2241,7 +2281,7 @@ static int qedf_execute_tmf(struct qedf_rport *fcport, struct scsi_cmnd *sc_cmd, u16 sqe_idx; if (!sc_cmd) { - QEDF_ERR(&(qedf->dbg_ctx), "invalid arg\n"); + QEDF_ERR(&qedf->dbg_ctx, "sc_cmd is NULL\n"); return FAILED; } diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index a42babde036d..3e245b08fb10 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -128,8 +128,11 @@ static bool qedf_initiate_fipvlan_req(struct qedf_ctx *qedf) return false; } - if (qedf->vlan_id > 0) + if (qedf->vlan_id > 0) { + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC, + "vlan = 0x%x already set.\n", qedf->vlan_id); return true; + } QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, "Retry %d.\n", qedf->fipvlan_retries); @@ -162,6 +165,8 @@ static void qedf_handle_link_update(struct work_struct *work) return; if (atomic_read(&qedf->link_state) != QEDF_LINK_UP) { + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC, + "Link is down, resetting vlan_id.\n"); qedf->vlan_id = 0; return; } @@ -311,8 +316,10 @@ int qedf_send_flogi(struct qedf_ctx *qedf) lport = qedf->lport; - if (!lport->tt.elsct_send) + if (!lport->tt.elsct_send) { + QEDF_ERR(&qedf->dbg_ctx, "tt.elsct_send not set.\n"); return -EINVAL; + } fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi)); if (!fp) { @@ -2340,12 +2347,14 @@ static void qedf_recv_frame(struct qedf_ctx *qedf, fr_dev(fp) = lport; fr_sof(fp) = hp->fcoe_sof; if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) { + QEDF_INFO(NULL, QEDF_LOG_LL2, "skb_copy_bits failed.\n"); kfree_skb(skb); return; } fr_eof(fp) = crc_eof.fcoe_eof; fr_crc(fp) = crc_eof.fcoe_crc32; if (pskb_trim(skb, fr_len)) { + QEDF_INFO(NULL, QEDF_LOG_LL2, "pskb_trim failed.\n"); kfree_skb(skb); return; } @@ -2406,9 +2415,9 @@ static void qedf_recv_frame(struct qedf_ctx *qedf, * empty then this is not addressed to our port so simply drop it. */ if (lport->port_id != ntoh24(fh->fh_d_id) && !vn_port) { - QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2, - "Dropping frame due to destination mismatch: lport->port_id=%x fh->d_id=%x.\n", - lport->port_id, ntoh24(fh->fh_d_id)); + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_LL2, + "Dropping frame due to destination mismatch: lport->port_id=0x%x fh->d_id=0x%x.\n", + lport->port_id, ntoh24(fh->fh_d_id)); kfree_skb(skb); return; } @@ -2417,6 +2426,8 @@ static void qedf_recv_frame(struct qedf_ctx *qedf, if ((fh->fh_type == FC_TYPE_BLS) && (f_ctl & FC_FC_SEQ_CTX) && (f_ctl & FC_FC_EX_CTX)) { /* Drop incoming ABTS response that has both SEQ/EX CTX set */ + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_LL2, + "Dropping ABTS response as both SEQ/EX CTX set.\n"); kfree_skb(skb); return; } @@ -2560,8 +2571,9 @@ static int qedf_alloc_and_init_sb(struct qedf_ctx *qedf, sizeof(struct status_block_e4), &sb_phys, GFP_KERNEL); if (!sb_virt) { - QEDF_ERR(&(qedf->dbg_ctx), "Status block allocation failed " - "for id = %d.\n", sb_id); + QEDF_ERR(&qedf->dbg_ctx, + "Status block allocation failed for id = %d.\n", + sb_id); return -ENOMEM; } @@ -2569,8 +2581,9 @@ static int qedf_alloc_and_init_sb(struct qedf_ctx *qedf, sb_id, QED_SB_TYPE_STORAGE); if (ret) { - QEDF_ERR(&(qedf->dbg_ctx), "Status block initialization " - "failed for id = %d.\n", sb_id); + QEDF_ERR(&qedf->dbg_ctx, + "Status block initialization failed (0x%x) for id = %d.\n", + ret, sb_id); return ret; } @@ -2654,13 +2667,18 @@ void qedf_process_cqe(struct qedf_ctx *qedf, struct fcoe_cqe *cqe) io_req = &qedf->cmd_mgr->cmds[xid]; /* Completion not for a valid I/O anymore so just return */ - if (!io_req) + if (!io_req) { + QEDF_ERR(&qedf->dbg_ctx, + "io_req is NULL for xid=0x%x.\n", xid); return; + } fcport = io_req->fcport; if (fcport == NULL) { - QEDF_ERR(&(qedf->dbg_ctx), "fcport is NULL.\n"); + QEDF_ERR(&qedf->dbg_ctx, + "fcport is NULL for xid=0x%x io_req=%p.\n", + xid, io_req); return; } @@ -2669,7 +2687,8 @@ void qedf_process_cqe(struct qedf_ctx *qedf, struct fcoe_cqe *cqe) * isn't valid and shouldn't be taken. We should just return. */ if (!test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags)) { - QEDF_ERR(&(qedf->dbg_ctx), "Session not offloaded yet.\n"); + QEDF_ERR(&qedf->dbg_ctx, + "Session not offloaded yet, fcport = %p.\n", fcport); return; } @@ -2881,6 +2900,7 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf) */ if (!qedf->p_cpuq) { status = 1; + QEDF_ERR(&qedf->dbg_ctx, "p_cpuq is NULL.\n"); goto mem_alloc_failure; } @@ -2896,8 +2916,10 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf) /* Allocate DMA coherent buffers for BDQ */ rc = qedf_alloc_bdq(qedf); - if (rc) + if (rc) { + QEDF_ERR(&qedf->dbg_ctx, "Unable to allocate bdq.\n"); goto mem_alloc_failure; + } /* Allocate a CQ and an associated PBL for each MSI-X vector */ for (i = 0; i < qedf->num_queues; i++) { @@ -3209,6 +3231,7 @@ static int __qedf_probe(struct pci_dev *pdev, int mode) qed_params.is_vf = is_vf; qedf->cdev = qed_ops->common->probe(pdev, &qed_params); if (!qedf->cdev) { + QEDF_ERR(&qedf->dbg_ctx, "common probe failed.\n"); rc = -ENODEV; goto err1; } @@ -3277,8 +3300,10 @@ static int __qedf_probe(struct pci_dev *pdev, int mode) /* Setup interrupts */ rc = qedf_setup_int(qedf); - if (rc) + if (rc) { + QEDF_ERR(&qedf->dbg_ctx, "Setup interrupts failed.\n"); goto err3; + } rc = qed_ops->start(qedf->cdev, &qedf->tasks); if (rc) { -- cgit v1.2.3-59-g8ed1b From 4909e153e608360702ad34f76f72190bfaec3d9d Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Fri, 23 Aug 2019 02:52:32 -0700 Subject: scsi: qedf: Stop sending fipvlan request on unload - On some setups fipvlan can be retried for long duration and the connection to switch was not there so it was not getting any reply. - During unload this thread was hanging. Problem Resolution: Check if unload is in progress, then quit from fipvlan thread. Signed-off-by: Saurav Kashyap Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf_main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index 3e245b08fb10..2d69860d1f06 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -128,6 +128,11 @@ static bool qedf_initiate_fipvlan_req(struct qedf_ctx *qedf) return false; } + if (test_bit(QEDF_UNLOADING, &qedf->flags)) { + QEDF_ERR(&qedf->dbg_ctx, "Driver unloading.\n"); + return false; + } + if (qedf->vlan_id > 0) { QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC, "vlan = 0x%x already set.\n", qedf->vlan_id); -- cgit v1.2.3-59-g8ed1b From 47aeee5549cf9326656a8f9190960dfd35c101e2 Mon Sep 17 00:00:00 2001 From: Arun Easi Date: Fri, 23 Aug 2019 02:52:33 -0700 Subject: scsi: qedf: Fix crash during sg_reset Driver was attempting to print cdb[0], which is not set for resets coming from SCSI ioctls. Check for cmd_len before accessing cmnd. Crash info: [84790.864747] BUG: unable to handle kernel NULL pointer dereference at (null) [84790.864783] IP: qedf_initiate_tmf+0x7a/0x6e0 [qedf] [84790.865204] Call Trace: [84790.865246] scsi_try_target_reset+0x2b/0x90 [scsi_mod] [84790.865266] scsi_ioctl_reset+0x20f/0x2a0 [scsi_mod] [84790.865284] scsi_ioctl+0x131/0x3a0 [scsi_mod] Signed-off-by: Arun Easi Signed-off-by: Saurav Kashyap Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf_io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qedf/qedf_io.c b/drivers/scsi/qedf/qedf_io.c index 5b428922b83e..7377a534ff0e 100644 --- a/drivers/scsi/qedf/qedf_io.c +++ b/drivers/scsi/qedf/qedf_io.c @@ -2403,8 +2403,8 @@ int qedf_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags) QEDF_ERR(NULL, "tm_flags 0x%x sc_cmd %p op = 0x%02x target_id = 0x%x lun=%d\n", - tm_flags, sc_cmd, sc_cmd->cmnd[0], rport->scsi_target_id, - (int)sc_cmd->device->lun); + tm_flags, sc_cmd, sc_cmd->cmd_len ? sc_cmd->cmnd[0] : 0xff, + rport->scsi_target_id, (int)sc_cmd->device->lun); if (!rdata || !kref_get_unless_zero(&rdata->kref)) { QEDF_ERR(NULL, "stale rport\n"); -- cgit v1.2.3-59-g8ed1b From ec6350b800072db227585ee830672dc357f3983d Mon Sep 17 00:00:00 2001 From: Nilesh Javali Date: Fri, 23 Aug 2019 02:52:34 -0700 Subject: scsi: qedf: Update module description string Update module description. Signed-off-by: Nilesh Javali Signed-off-by: Saurav Kashyap Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index 2d69860d1f06..6959f7c68ddf 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -3875,7 +3875,7 @@ static void __exit qedf_cleanup(void) } MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("QLogic QEDF 25/40/50/100Gb FCoE Driver"); +MODULE_DESCRIPTION("QLogic FastLinQ 4xxxx FCoE Module"); MODULE_AUTHOR("QLogic Corporation"); MODULE_VERSION(QEDF_VERSION); module_init(qedf_init); -- cgit v1.2.3-59-g8ed1b From 31696204c44ced38ca0a4b97069b4d8558c1483a Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Fri, 23 Aug 2019 02:52:35 -0700 Subject: scsi: qedf: Add shutdown callback handler Add shutdown callback handler. Signed-off-by: Saurav Kashyap Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf_main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index 6959f7c68ddf..a824bbb8e835 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -27,6 +27,7 @@ const struct qed_fcoe_ops *qed_ops; static int qedf_probe(struct pci_dev *pdev, const struct pci_device_id *id); static void qedf_remove(struct pci_dev *pdev); +static void qedf_shutdown(struct pci_dev *pdev); /* * Driver module parameters. @@ -3134,6 +3135,7 @@ static struct pci_driver qedf_pci_driver = { .id_table = qedf_pci_tbl, .probe = qedf_probe, .remove = qedf_remove, + .shutdown = qedf_shutdown, }; static int __qedf_probe(struct pci_dev *pdev, int mode) @@ -3749,6 +3751,11 @@ void qedf_get_protocol_tlv_data(void *dev, void *data) fcoe->scsi_tsk_full = qedf->task_set_fulls; } +static void qedf_shutdown(struct pci_dev *pdev) +{ + __qedf_remove(pdev, QEDF_MODE_NORMAL); +} + /* Generic TLV data callback */ void qedf_get_generic_tlv_data(void *dev, struct qed_generic_tlvs *data) { -- cgit v1.2.3-59-g8ed1b From fa74f5e380b6d671735d72ab36646b781af3f876 Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Fri, 23 Aug 2019 02:52:36 -0700 Subject: scsi: qedf: Interpret supported caps value correctly Driver was wrongly interpreting the supported cap value returned by qed. Solution: Use QED define macros instead of OS defined for interpreting supporting speeds. Signed-off-by: Saurav Kashyap Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf_main.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index a824bbb8e835..995fd32c7335 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -489,16 +489,38 @@ static void qedf_update_link_speed(struct qedf_ctx *qedf, * Set supported link speed by querying the supported * capabilities of the link. */ - if (link->supported_caps & SUPPORTED_10000baseKR_Full) + if ((link->supported_caps & QED_LM_10000baseT_Full_BIT) || + (link->supported_caps & QED_LM_10000baseKX4_Full_BIT) || + (link->supported_caps & QED_LM_10000baseR_FEC_BIT) || + (link->supported_caps & QED_LM_10000baseCR_Full_BIT) || + (link->supported_caps & QED_LM_10000baseSR_Full_BIT) || + (link->supported_caps & QED_LM_10000baseLR_Full_BIT) || + (link->supported_caps & QED_LM_10000baseLRM_Full_BIT) || + (link->supported_caps & QED_LM_10000baseKR_Full_BIT)) { lport->link_supported_speeds |= FC_PORTSPEED_10GBIT; - if (link->supported_caps & SUPPORTED_25000baseKR_Full) + } + if ((link->supported_caps & QED_LM_25000baseKR_Full_BIT) || + (link->supported_caps & QED_LM_25000baseCR_Full_BIT) || + (link->supported_caps & QED_LM_25000baseSR_Full_BIT)) { lport->link_supported_speeds |= FC_PORTSPEED_25GBIT; - if (link->supported_caps & SUPPORTED_40000baseLR4_Full) + } + if ((link->supported_caps & QED_LM_40000baseLR4_Full_BIT) || + (link->supported_caps & QED_LM_40000baseKR4_Full_BIT) || + (link->supported_caps & QED_LM_40000baseCR4_Full_BIT) || + (link->supported_caps & QED_LM_40000baseSR4_Full_BIT)) { lport->link_supported_speeds |= FC_PORTSPEED_40GBIT; - if (link->supported_caps & SUPPORTED_50000baseKR2_Full) + } + if ((link->supported_caps & QED_LM_50000baseKR2_Full_BIT) || + (link->supported_caps & QED_LM_50000baseCR2_Full_BIT) || + (link->supported_caps & QED_LM_50000baseSR2_Full_BIT)) { lport->link_supported_speeds |= FC_PORTSPEED_50GBIT; - if (link->supported_caps & SUPPORTED_100000baseKR4_Full) + } + if ((link->supported_caps & QED_LM_100000baseKR4_Full_BIT) || + (link->supported_caps & QED_LM_100000baseSR4_Full_BIT) || + (link->supported_caps & QED_LM_100000baseCR4_Full_BIT) || + (link->supported_caps & QED_LM_100000baseLR4_ER4_Full_BIT)) { lport->link_supported_speeds |= FC_PORTSPEED_100GBIT; + } fc_host_supported_speeds(lport->host) = lport->link_supported_speeds; } -- cgit v1.2.3-59-g8ed1b From 931285e0123c4f380a9e2ff06434c8307b92b726 Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Fri, 23 Aug 2019 02:52:37 -0700 Subject: scsi: qedf: Add support for 20 Gbps speed The current code doeesn't support 20Gbps speed for current and supported speed. Add support for it. Signed-off-by: Saurav Kashyap Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf_main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index 995fd32c7335..50b1fa8740da 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -480,6 +480,9 @@ static void qedf_update_link_speed(struct qedf_ctx *qedf, case 100000: lport->link_speed = FC_PORTSPEED_100GBIT; break; + case 20000: + lport->link_speed = FC_PORTSPEED_20GBIT; + break; default: lport->link_speed = FC_PORTSPEED_UNKNOWN; break; @@ -521,6 +524,8 @@ static void qedf_update_link_speed(struct qedf_ctx *qedf, (link->supported_caps & QED_LM_100000baseLR4_ER4_Full_BIT)) { lport->link_supported_speeds |= FC_PORTSPEED_100GBIT; } + if (link->supported_caps & QED_LM_20000baseKR2_Full_BIT) + lport->link_supported_speeds |= FC_PORTSPEED_20GBIT; fc_host_supported_speeds(lport->host) = lport->link_supported_speeds; } -- cgit v1.2.3-59-g8ed1b From aa5175a88cbb7eeab2aec874694e28a479d32bfe Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Fri, 23 Aug 2019 02:52:38 -0700 Subject: scsi: qedf: Add debug information for unsolicited processing Log s_id, d_id, type and command to the log message. [mkp: fixed warning] Signed-off-by: Saurav Kashyap Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf_io.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/qedf/qedf_io.c b/drivers/scsi/qedf/qedf_io.c index 7377a534ff0e..e749a2dcaad7 100644 --- a/drivers/scsi/qedf/qedf_io.c +++ b/drivers/scsi/qedf/qedf_io.c @@ -2555,6 +2555,11 @@ void qedf_process_unsol_compl(struct qedf_ctx *qedf, uint16_t que_idx, fh = (struct fc_frame_header *)fc_frame_header_get(fp); memcpy(fh, (void *)bdq_addr, pktlen); + QEDF_WARN(&qedf->dbg_ctx, + "Processing Unsolicated frame, src=%06x dest=%06x r_ctl=0x%x type=0x%x cmd=%02x\n", + ntoh24(fh->fh_s_id), ntoh24(fh->fh_d_id), fh->fh_r_ctl, + fh->fh_type, fc_frame_payload_op(fp)); + /* Initialize the frame so libfc sees it as a valid frame */ crc = fcoe_fc_crc(fp); fc_frame_init(fp); -- cgit v1.2.3-59-g8ed1b From b29a907f105cc659a303bb2657959c7d0d188620 Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Fri, 23 Aug 2019 02:52:39 -0700 Subject: scsi: qedf: Initiator fails to re-login to switch after link down Problem Statement: - Driver has fc_id of 0xcc0200 - Driver gets link down (due to test) and calls fcoe_ctlr_link_down(). - At this point, the fc_id of the initiator port is zeroed out. - Driver gets a link up 14 seconds later. - Driver performs FIP VLAN request, gets a response from the switch. - No change in VLAN is detected. - Driver then notifies libfcoe via fcoe_ctlr_link_up(). - Libfcoe then issues a multicast discovery solicitation as expected. - Cisco FCF responds to that correctly. - Libfcoe at this point starts a 3 sec count-down to allow any other FCFs to be discovered. However, at this point, it has been 20 seconds since the last FKA from the driver (which would have been sent prior to backlink toggle), which causes the CVL to be issued from Cisco CVL from the switch is dropped by the driver as the vx_port identification descriptor is present and has value of 0xcc0200, which does not match the driver's value of 0. Libfcoe completes the 3 sec count down and proceeds to issue FLOGI as per protocol. Switch rejects FLogi request. All subsequent FLOGI requests from libfc are rejected by the switch (possibly because it is now expecting a new solicitation). This situation will continue until the next link toggle. Solution: The Vx_port descriptor in the CVL has three fields: MAC address Fabric ID Port Name Today, the code checks for both #1 and #2 above. In the case where we went through a link down, both these will be zero until FLOGI succeeds. We should change our code to check if any one of these 3 is valid and if so, handle the CVL (basically switching from AND to OR). The port name field is definitely expected to be valid always. Signed-off-by: Saurav Kashyap Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf_fip.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/qedf/qedf_fip.c b/drivers/scsi/qedf/qedf_fip.c index 5143d93bcc38..bb82f0875eca 100644 --- a/drivers/scsi/qedf/qedf_fip.c +++ b/drivers/scsi/qedf/qedf_fip.c @@ -253,18 +253,24 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb) fc_wwpn_valid = true; break; case FIP_DT_VN_ID: + fabric_id_valid = false; vp = (struct fip_vn_desc *)desc; - QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC, - "vx_port fd_fc_id=%x fd_mac=%pM.\n", - ntoh24(vp->fd_fc_id), vp->fd_mac); - /* Check vx_port fabric ID */ - if (ntoh24(vp->fd_fc_id) != - qedf->lport->port_id) - fabric_id_valid = false; - /* Check vx_port MAC */ - if (!ether_addr_equal(vp->fd_mac, - qedf->data_src_addr)) - fabric_id_valid = false; + + QEDF_ERR(&qedf->dbg_ctx, + "CVL vx_port fd_fc_id=0x%x fd_mac=%pM fd_wwpn=%016llx.\n", + ntoh24(vp->fd_fc_id), vp->fd_mac, + get_unaligned_be64(&vp->fd_wwpn)); + /* Check for vx_port wwpn OR Check vx_port + * fabric ID OR Check vx_port MAC + */ + if ((get_unaligned_be64(&vp->fd_wwpn) == + qedf->wwpn) || + (ntoh24(vp->fd_fc_id) == + qedf->lport->port_id) || + (ether_addr_equal(vp->fd_mac, + qedf->data_src_addr))) { + fabric_id_valid = true; + } break; default: /* Ignore anything else */ -- cgit v1.2.3-59-g8ed1b From 0482262646e4e9e089c4e75f336244c5eaf360e1 Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Fri, 23 Aug 2019 02:52:40 -0700 Subject: scsi: qedf: Check for module unloading bit before processing link update AEN Prevent race where we're removing the module and we get link update Signed-off-by: Saurav Kashyap Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf_main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index 50b1fa8740da..ab9a932089ae 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -533,6 +533,16 @@ static void qedf_link_update(void *dev, struct qed_link_output *link) { struct qedf_ctx *qedf = (struct qedf_ctx *)dev; + /* + * Prevent race where we're removing the module and we get link update + * for qed. + */ + if (test_bit(QEDF_UNLOADING, &qedf->flags)) { + QEDF_ERR(&qedf->dbg_ctx, + "Ignore link update, driver getting unload.\n"); + return; + } + if (link->link_up) { if (atomic_read(&qedf->link_state) == QEDF_LINK_UP) { QEDF_INFO((&qedf->dbg_ctx), QEDF_LOG_DISC, -- cgit v1.2.3-59-g8ed1b From f6d63678b07f935fefd7cfefe7b43f56bad274b6 Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Fri, 23 Aug 2019 02:52:41 -0700 Subject: scsi: qedf: Decrease the LL2 MTU size to 2500 Decrease the LL2 MTU size to 2500. Signed-off-by: Saurav Kashyap Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf.h | 1 + drivers/scsi/qedf/qedf_main.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qedf/qedf.h b/drivers/scsi/qedf/qedf.h index 5a021217bfc9..f3f399fe10c8 100644 --- a/drivers/scsi/qedf/qedf.h +++ b/drivers/scsi/qedf/qedf.h @@ -49,6 +49,7 @@ #define QEDF_ABORT_TIMEOUT (10 * 1000) #define QEDF_CLEANUP_TIMEOUT 1 #define QEDF_MAX_CDB_LEN 16 +#define QEDF_LL2_BUF_SIZE 2500 /* Buffer size required for LL2 Rx */ #define UPSTREAM_REMOVE 1 #define UPSTREAM_KEEP 1 diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index ab9a932089ae..884587351df8 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -3429,7 +3429,7 @@ static int __qedf_probe(struct pci_dev *pdev, int mode) } memset(¶ms, 0, sizeof(params)); - params.mtu = 9000; + params.mtu = QEDF_LL2_BUF_SIZE; ether_addr_copy(params.ll2_mac_address, qedf->mac); /* Start LL2 processing thread */ -- cgit v1.2.3-59-g8ed1b From 5797bcc897c363a775ac3d929b62d2579bdf8573 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 23 Aug 2019 02:52:42 -0700 Subject: scsi: qedf: Use discovery list to traverse rports The list of rports might become stale so we should rather traverse the discovery list when trying relogin. Signed-off-by: Hannes Reinecke Signed-off-by: Saurav Kashyap Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf_main.c | 39 +++++++-------------------------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index 884587351df8..0856d136bab6 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -343,11 +343,6 @@ int qedf_send_flogi(struct qedf_ctx *qedf) return 0; } -struct qedf_tmp_rdata_item { - struct fc_rport_priv *rdata; - struct list_head list; -}; - /* * This function is called if link_down_tmo is in use. If we get a link up and * link_down_tmo has not expired then use just FLOGI/ADISC to recover our @@ -357,9 +352,8 @@ static void qedf_link_recovery(struct work_struct *work) { struct qedf_ctx *qedf = container_of(work, struct qedf_ctx, link_recovery.work); - struct qedf_rport *fcport; + struct fc_lport *lport = qedf->lport; struct fc_rport_priv *rdata; - struct qedf_tmp_rdata_item *rdata_item, *tmp_rdata_item; bool rc; int retries = 30; int rval, i; @@ -426,33 +420,14 @@ static void qedf_link_recovery(struct work_struct *work) * Call lport->tt.rport_login which will cause libfc to send an * ADISC since the rport is in state ready. */ - rcu_read_lock(); - list_for_each_entry_rcu(fcport, &qedf->fcports, peers) { - rdata = fcport->rdata; - if (rdata == NULL) - continue; - rdata_item = kzalloc(sizeof(struct qedf_tmp_rdata_item), - GFP_ATOMIC); - if (!rdata_item) - continue; + mutex_lock(&lport->disc.disc_mutex); + list_for_each_entry_rcu(rdata, &lport->disc.rports, peers) { if (kref_get_unless_zero(&rdata->kref)) { - rdata_item->rdata = rdata; - list_add(&rdata_item->list, &rdata_login_list); - } else - kfree(rdata_item); - } - rcu_read_unlock(); - /* - * Do the fc_rport_login outside of the rcu lock so we don't take a - * mutex in an atomic context. - */ - list_for_each_entry_safe(rdata_item, tmp_rdata_item, &rdata_login_list, - list) { - list_del(&rdata_item->list); - fc_rport_login(rdata_item->rdata); - kref_put(&rdata_item->rdata->kref, fc_rport_destroy); - kfree(rdata_item); + fc_rport_login(rdata); + kref_put(&rdata->kref, fc_rport_destroy); + } } + mutex_unlock(&lport->disc.disc_mutex); } static void qedf_update_link_speed(struct qedf_ctx *qedf, -- cgit v1.2.3-59-g8ed1b From 3480e7a8c8e47a6ee101ab722c58d61761b67e4a Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Fri, 23 Aug 2019 02:52:43 -0700 Subject: scsi: qedf: Fix race betwen fipvlan request and response path There is a race b/w fipvlan request and response path: ===== qedf_fcoe_process_vlan_resp:113]:2: VLAN response, vid=0xffd. qedf_initiate_fipvlan_req:165]:2: vlan = 0x6ffd already set. qedf_set_vlan_id:139]:2: Setting vlan_id=0ffd prio=3. ====== The request thread sees that vlan is already set and fails to call ctrl_link_up. Fix: - While setting vlan_id use local variable and before setting vlan_id. - Call fcoe_ctlr_link_up in next iteration of fipvlan request. Signed-off-by: Saurav Kashyap Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf_main.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index 0856d136bab6..9c24f3834d70 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -111,16 +111,18 @@ static struct kmem_cache *qedf_io_work_cache; void qedf_set_vlan_id(struct qedf_ctx *qedf, int vlan_id) { - qedf->vlan_id = vlan_id; - qedf->vlan_id |= qedf->prio << VLAN_PRIO_SHIFT; - QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, "Setting vlan_id=%04x " - "prio=%d.\n", vlan_id, qedf->prio); + int vlan_id_tmp = 0; + + vlan_id_tmp = vlan_id | (qedf->prio << VLAN_PRIO_SHIFT); + qedf->vlan_id = vlan_id_tmp; + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC, + "Setting vlan_id=0x%04x prio=%d.\n", + vlan_id_tmp, qedf->prio); } /* Returns true if we have a valid vlan, false otherwise */ static bool qedf_initiate_fipvlan_req(struct qedf_ctx *qedf) { - int rc; while (qedf->fipvlan_retries--) { /* This is to catch if link goes down during fipvlan retries */ @@ -136,7 +138,10 @@ static bool qedf_initiate_fipvlan_req(struct qedf_ctx *qedf) if (qedf->vlan_id > 0) { QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC, - "vlan = 0x%x already set.\n", qedf->vlan_id); + "vlan = 0x%x already set, calling ctlr_link_up.\n", + qedf->vlan_id); + if (atomic_read(&qedf->link_state) == QEDF_LINK_UP) + fcoe_ctlr_link_up(&qedf->ctlr); return true; } @@ -144,13 +149,7 @@ static bool qedf_initiate_fipvlan_req(struct qedf_ctx *qedf) "Retry %d.\n", qedf->fipvlan_retries); init_completion(&qedf->fipvlan_compl); qedf_fcoe_send_vlan_req(qedf); - rc = wait_for_completion_timeout(&qedf->fipvlan_compl, - 1 * HZ); - if (rc > 0 && - (atomic_read(&qedf->link_state) == QEDF_LINK_UP)) { - fcoe_ctlr_link_up(&qedf->ctlr); - return true; - } + wait_for_completion_timeout(&qedf->fipvlan_compl, 1 * HZ); } return false; -- cgit v1.2.3-59-g8ed1b From 32dce48c054d345c8bce6ffe94aa39349fbf2147 Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Fri, 23 Aug 2019 02:52:44 -0700 Subject: scsi: qedf: Update the version to 8.42.3.0 Update the driver version to 8.42.3.0. Signed-off-by: Saurav Kashyap Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf_version.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qedf/qedf_version.h b/drivers/scsi/qedf/qedf_version.h index e57533de7e96..b0e37afe5bbb 100644 --- a/drivers/scsi/qedf/qedf_version.h +++ b/drivers/scsi/qedf/qedf_version.h @@ -4,9 +4,9 @@ * Copyright (c) 2016-2018 Cavium Inc. */ -#define QEDF_VERSION "8.37.25.20" +#define QEDF_VERSION "8.42.3.0" #define QEDF_DRIVER_MAJOR_VER 8 -#define QEDF_DRIVER_MINOR_VER 37 -#define QEDF_DRIVER_REV_VER 25 -#define QEDF_DRIVER_ENG_VER 20 +#define QEDF_DRIVER_MINOR_VER 42 +#define QEDF_DRIVER_REV_VER 3 +#define QEDF_DRIVER_ENG_VER 0 -- cgit v1.2.3-59-g8ed1b From 7444ad400bfd8c85a28678a7b68accc6c41041fd Mon Sep 17 00:00:00 2001 From: zhengbin Date: Fri, 23 Aug 2019 21:22:51 +0800 Subject: scsi: bnx2fc: remove set but not used variable 'fh' Fixes gcc '-Wunused-but-set-variable' warning: drivers/scsi/bnx2fc/bnx2fc_fcoe.c: In function bnx2fc_rcv: drivers/scsi/bnx2fc/bnx2fc_fcoe.c:431:26: warning: variable fh set but not used [-Wunused-but-set-variable] Reported-by: Hulk Robot Signed-off-by: zhengbin Acked-by: Saurav Kashyap Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 7796799bf04a..ab721ab9ee9c 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -428,7 +428,6 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev, struct fc_lport *lport; struct bnx2fc_interface *interface; struct fcoe_ctlr *ctlr; - struct fc_frame_header *fh; struct fcoe_rcv_info *fr; struct fcoe_percpu_s *bg; struct sk_buff *tmp_skb; @@ -463,7 +462,6 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev, goto err; skb_set_transport_header(skb, sizeof(struct fcoe_hdr)); - fh = (struct fc_frame_header *) skb_transport_header(skb); fr = fcoe_dev_from_skb(skb); fr->fr_dev = lport; -- cgit v1.2.3-59-g8ed1b From 2f8eeaa258a9e8ac922f72957a5b0643c0d1b7f0 Mon Sep 17 00:00:00 2001 From: zhengbin Date: Fri, 23 Aug 2019 21:22:52 +0800 Subject: scsi: bnx2fc: remove set but not used variables 'lport','host' Fixes gcc '-Wunused-but-set-variable' warning: drivers/scsi/bnx2fc/bnx2fc_io.c: In function bnx2fc_initiate_seq_cleanup: drivers/scsi/bnx2fc/bnx2fc_io.c:932:19: warning: variable lport set but not used [-Wunused-but-set-variable] drivers/scsi/bnx2fc/bnx2fc_io.c: In function bnx2fc_initiate_cleanup: drivers/scsi/bnx2fc/bnx2fc_io.c:1001:19: warning: variable lport set but not used [-Wunused-but-set-variable] drivers/scsi/bnx2fc/bnx2fc_io.c: In function bnx2fc_process_scsi_cmd_compl: drivers/scsi/bnx2fc/bnx2fc_io.c:1882:20: warning: variable host set but not used [-Wunused-but-set-variable] Reported-by: Hulk Robot Signed-off-by: zhengbin Acked-by: Saurav Kashyap Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc_io.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c index 9e50e5b53763..da00ca5fa5dc 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_io.c +++ b/drivers/scsi/bnx2fc/bnx2fc_io.c @@ -930,7 +930,6 @@ abts_err: int bnx2fc_initiate_seq_cleanup(struct bnx2fc_cmd *orig_io_req, u32 offset, enum fc_rctl r_ctl) { - struct fc_lport *lport; struct bnx2fc_rport *tgt = orig_io_req->tgt; struct bnx2fc_interface *interface; struct fcoe_port *port; @@ -948,7 +947,6 @@ int bnx2fc_initiate_seq_cleanup(struct bnx2fc_cmd *orig_io_req, u32 offset, port = orig_io_req->port; interface = port->priv; - lport = port->lport; cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC); if (!cb_arg) { @@ -999,7 +997,6 @@ cleanup_err: int bnx2fc_initiate_cleanup(struct bnx2fc_cmd *io_req) { - struct fc_lport *lport; struct bnx2fc_rport *tgt = io_req->tgt; struct bnx2fc_interface *interface; struct fcoe_port *port; @@ -1015,7 +1012,6 @@ int bnx2fc_initiate_cleanup(struct bnx2fc_cmd *io_req) port = io_req->port; interface = port->priv; - lport = port->lport; cleanup_io_req = bnx2fc_elstm_alloc(tgt, BNX2FC_CLEANUP); if (!cleanup_io_req) { @@ -1927,8 +1923,6 @@ void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req, struct fcoe_fcp_rsp_payload *fcp_rsp; struct bnx2fc_rport *tgt = io_req->tgt; struct scsi_cmnd *sc_cmd; - struct Scsi_Host *host; - /* scsi_cmd_cmpl is called with tgt lock held */ @@ -1957,7 +1951,6 @@ void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req, /* parse fcp_rsp and obtain sense data from RQ if available */ bnx2fc_parse_fcp_rsp(io_req, fcp_rsp, num_rq); - host = sc_cmd->device->host; if (!sc_cmd->SCp.ptr) { printk(KERN_ERR PFX "SCp.ptr is NULL\n"); return; -- cgit v1.2.3-59-g8ed1b From 84769706dde5881b8da0dc3da666f7443be95a8a Mon Sep 17 00:00:00 2001 From: zhengbin Date: Fri, 23 Aug 2019 21:22:53 +0800 Subject: scsi: bnx2fc: remove set but not used variables 'task','port','orig_task' Fixes gcc '-Wunused-but-set-variable' warning: drivers/scsi/bnx2fc/bnx2fc_hwi.c: In function bnx2fc_process_unsol_compl: drivers/scsi/bnx2fc/bnx2fc_hwi.c:636:30: warning: variable task set but not used [-Wunused-but-set-variable] drivers/scsi/bnx2fc/bnx2fc_hwi.c: In function bnx2fc_process_ofld_cmpl: drivers/scsi/bnx2fc/bnx2fc_hwi.c:1125:21: warning: variable port set but not used [-Wunused-but-set-variable] drivers/scsi/bnx2fc/bnx2fc_hwi.c: In function bnx2fc_init_seq_cleanup_task: drivers/scsi/bnx2fc/bnx2fc_hwi.c:1468:30: warning: variable orig_task set but not used [-Wunused-but-set-variable] Reported-by: Hulk Robot Signed-off-by: zhengbin Acked-by: Saurav Kashyap Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc_hwi.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c index 747f019fb393..f069e09beb10 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c +++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c @@ -633,7 +633,6 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe) u16 xid; u32 frame_len, len; struct bnx2fc_cmd *io_req = NULL; - struct fcoe_task_ctx_entry *task, *task_page; struct bnx2fc_interface *interface = tgt->port->priv; struct bnx2fc_hba *hba = interface->hba; int task_idx, index; @@ -711,9 +710,6 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe) task_idx = xid / BNX2FC_TASKS_PER_PAGE; index = xid % BNX2FC_TASKS_PER_PAGE; - task_page = (struct fcoe_task_ctx_entry *) - hba->task_ctx[task_idx]; - task = &(task_page[index]); io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid]; if (!io_req) @@ -839,9 +835,6 @@ ret_err_rqe: task_idx = xid / BNX2FC_TASKS_PER_PAGE; index = xid % BNX2FC_TASKS_PER_PAGE; - task_page = (struct fcoe_task_ctx_entry *) - interface->hba->task_ctx[task_idx]; - task = &(task_page[index]); io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid]; if (!io_req) goto ret_warn_rqe; @@ -1122,7 +1115,6 @@ static void bnx2fc_process_ofld_cmpl(struct bnx2fc_hba *hba, struct fcoe_kcqe *ofld_kcqe) { struct bnx2fc_rport *tgt; - struct fcoe_port *port; struct bnx2fc_interface *interface; u32 conn_id; u32 context_id; @@ -1136,7 +1128,6 @@ static void bnx2fc_process_ofld_cmpl(struct bnx2fc_hba *hba, } BNX2FC_TGT_DBG(tgt, "Entered ofld compl - context_id = 0x%x\n", ofld_kcqe->fcoe_conn_context_id); - port = tgt->port; interface = tgt->port->priv; if (hba != interface->hba) { printk(KERN_ERR PFX "ERROR:ofld_cmpl: HBA mis-match\n"); @@ -1463,10 +1454,7 @@ void bnx2fc_init_seq_cleanup_task(struct bnx2fc_cmd *seq_clnp_req, { struct scsi_cmnd *sc_cmd = orig_io_req->sc_cmd; struct bnx2fc_rport *tgt = seq_clnp_req->tgt; - struct bnx2fc_interface *interface = tgt->port->priv; struct fcoe_bd_ctx *bd = orig_io_req->bd_tbl->bd_tbl; - struct fcoe_task_ctx_entry *orig_task; - struct fcoe_task_ctx_entry *task_page; struct fcoe_ext_mul_sges_ctx *sgl; u8 task_type = FCOE_TASK_TYPE_SEQUENCE_CLEANUP; u8 orig_task_type; @@ -1528,10 +1516,6 @@ void bnx2fc_init_seq_cleanup_task(struct bnx2fc_cmd *seq_clnp_req, orig_task_idx = orig_xid / BNX2FC_TASKS_PER_PAGE; index = orig_xid % BNX2FC_TASKS_PER_PAGE; - task_page = (struct fcoe_task_ctx_entry *) - interface->hba->task_ctx[orig_task_idx]; - orig_task = &(task_page[index]); - /* Multiple SGEs were used for this IO */ sgl = &task->rxwr_only.union_ctx.read_info.sgl_ctx.sgl; sgl->mul_sgl.cur_sge_addr.lo = (u32)phys_addr; -- cgit v1.2.3-59-g8ed1b From 90302e95a4e185ee0ef5c2e78cf6112149c74908 Mon Sep 17 00:00:00 2001 From: John Pittman Date: Fri, 23 Aug 2019 10:08:52 -0400 Subject: scsi: fnic: print port speed only at driver init or speed change Port speed printing was added by commit d948e6383ec3 ("scsi: fnic: Add port speed stat to fnic debug stats"). As currently configured, this will cause the port speed to be printed to syslog every 2 seconds. To prevent log spamming, only print the vnic port speed at driver initialization and if the speed changes. Also clean up a small typo in fnic_trace.c. Fixes: d948e6383ec3 ("scsi: fnic: Add port speed stat to fnic debug stats") Signed-off-by: John Pittman Reviewed-by: Satish Kharat Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic_fcs.c | 14 ++++++++++---- drivers/scsi/fnic/fnic_trace.c | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c index 911a5adc289c..673887e383cc 100644 --- a/drivers/scsi/fnic/fnic_fcs.c +++ b/drivers/scsi/fnic/fnic_fcs.c @@ -52,6 +52,7 @@ void fnic_handle_link(struct work_struct *work) unsigned long flags; int old_link_status; u32 old_link_down_cnt; + u64 old_port_speed, new_port_speed; spin_lock_irqsave(&fnic->fnic_lock, flags); @@ -62,14 +63,19 @@ void fnic_handle_link(struct work_struct *work) old_link_down_cnt = fnic->link_down_cnt; old_link_status = fnic->link_status; + old_port_speed = atomic64_read( + &fnic->fnic_stats.misc_stats.current_port_speed); + fnic->link_status = vnic_dev_link_status(fnic->vdev); fnic->link_down_cnt = vnic_dev_link_down_cnt(fnic->vdev); + new_port_speed = vnic_dev_port_speed(fnic->vdev); atomic64_set(&fnic->fnic_stats.misc_stats.current_port_speed, - vnic_dev_port_speed(fnic->vdev)); - shost_printk(KERN_INFO, fnic->lport->host, "Current vnic speed set to : %llu\n", - (u64)atomic64_read( - &fnic->fnic_stats.misc_stats.current_port_speed)); + new_port_speed); + if (old_port_speed != new_port_speed) + shost_printk(KERN_INFO, fnic->lport->host, + "Current vnic speed set to : %llu\n", + new_port_speed); switch (vnic_dev_port_speed(fnic->vdev)) { case DCEM_PORTSPEED_10G: diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c index 9621831e17ba..a0d01aea28f7 100644 --- a/drivers/scsi/fnic/fnic_trace.c +++ b/drivers/scsi/fnic/fnic_trace.c @@ -453,7 +453,7 @@ int fnic_get_stats_data(struct stats_debug_info *debug, (u64)atomic64_read(&stats->misc_stats.frame_errors)); len += snprintf(debug->debug_buffer + len, buf_size - len, - "Firmware reported port seed: %llu\n", + "Firmware reported port speed: %llu\n", (u64)atomic64_read( &stats->misc_stats.current_port_speed)); -- cgit v1.2.3-59-g8ed1b From 3ec24fb4c035e9cbb2f02a48640a09aa913442a2 Mon Sep 17 00:00:00 2001 From: Govindarajulu Varadarajan Date: Tue, 27 Aug 2019 14:13:40 -0700 Subject: scsi: fnic: fix msix interrupt allocation pci_alloc_irq_vectors() returns number of vectors allocated. Fix the check for error condition. Fixes: cca678dfbad49 ("scsi: fnic: switch to pci_alloc_irq_vectors") Link: https://lore.kernel.org/r/20190827211340.1095-1-gvaradar@cisco.com Signed-off-by: Govindarajulu Varadarajan Acked-by: Satish Kharat Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic_isr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/fnic/fnic_isr.c b/drivers/scsi/fnic/fnic_isr.c index da4602b63495..2fb2731f50fb 100644 --- a/drivers/scsi/fnic/fnic_isr.c +++ b/drivers/scsi/fnic/fnic_isr.c @@ -254,7 +254,7 @@ int fnic_set_intr_mode(struct fnic *fnic) int vecs = n + m + o + 1; if (pci_alloc_irq_vectors(fnic->pdev, vecs, vecs, - PCI_IRQ_MSIX) < 0) { + PCI_IRQ_MSIX) == vecs) { fnic->rq_count = n; fnic->raw_wq_count = m; fnic->wq_copy_count = o; @@ -280,7 +280,7 @@ int fnic_set_intr_mode(struct fnic *fnic) fnic->wq_copy_count >= 1 && fnic->cq_count >= 3 && fnic->intr_count >= 1 && - pci_alloc_irq_vectors(fnic->pdev, 1, 1, PCI_IRQ_MSI) < 0) { + pci_alloc_irq_vectors(fnic->pdev, 1, 1, PCI_IRQ_MSI) == 1) { fnic->rq_count = 1; fnic->raw_wq_count = 1; fnic->wq_copy_count = 1; -- cgit v1.2.3-59-g8ed1b From 670d8be28e72f984a61ccad3e9e98247c0d31e1c Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Wed, 28 Aug 2019 14:35:11 +0900 Subject: scsi: sd: Improve unaligned completion resid message For commands completing with a resid not aligned on the device logical sector size, also print the command CDB in addition to the current message to help debug hardware generating such incorrect command completion information. Link: https://lore.kernel.org/r/20190828053511.14818-1-damien.lemoal@wdc.com Signed-off-by: Damien Le Moal Signed-off-by: Martin K. Petersen --- drivers/scsi/sd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 149d406aacc9..91af598f2f53 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1978,6 +1978,7 @@ static int sd_done(struct scsi_cmnd *SCpnt) sd_printk(KERN_INFO, sdkp, "Unaligned partial completion (resid=%u, sector_sz=%u)\n", resid, sector_size); + scsi_print_command(SCpnt); resid = min(scsi_bufflen(SCpnt), round_up(resid, sector_size)); scsi_set_resid(SCpnt, resid); -- cgit v1.2.3-59-g8ed1b From da48b82425b8bf999fb9f7c220e967c4d661b5f8 Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Fri, 30 Aug 2019 15:23:57 -0700 Subject: scsi: qla2xxx: Fix message indicating vectors used by driver This patch updates log message which indicates number of vectors used by the driver instead of displaying failure to get maximum requested vectors. Driver will always request maximum vectors during initialization. In the event driver is not able to get maximum requested vectors, it will adjust the allocated vectors. This is normal and does not imply failure in driver. Signed-off-by: Himanshu Madhani Reviewed-by: Ewan D. Milne Reviewed-by: Lee Duncan Link: https://lore.kernel.org/r/20190830222402.23688-2-hmadhani@marvell.com Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_isr.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index d81b5ecce24b..4c26630c1c3e 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -3466,10 +3466,8 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp) ha->msix_count, ret); goto msix_out; } else if (ret < ha->msix_count) { - ql_log(ql_log_warn, vha, 0x00c6, - "MSI-X: Failed to enable support " - "with %d vectors, using %d vectors.\n", - ha->msix_count, ret); + ql_log(ql_log_info, vha, 0x00c6, + "MSI-X: Using %d vectors\n", ret); ha->msix_count = ret; /* Recalculate queue values */ if (ha->mqiobase && (ql2xmqsupport || ql2xnvmeenable)) { -- cgit v1.2.3-59-g8ed1b From cb92cb1657c438efe7c88c9759f40c0a9d46c353 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Fri, 30 Aug 2019 15:23:58 -0700 Subject: scsi: qla2xxx: Fix flash read for Qlogic ISPs Use adapter specific callback to read flash instead of ISP adapter specific. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Reviewed-by: Ewan D. Milne Link: https://lore.kernel.org/r/20190830222402.23688-3-hmadhani@marvell.com Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 4 ++-- drivers/scsi/qla2xxx/qla_nx.c | 1 + drivers/scsi/qla2xxx/qla_sup.c | 8 ++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 4a89ec58fb41..d9e8b808bb59 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -8229,7 +8229,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) active_regions.aux.vpd_nvram == QLA27XX_PRIMARY_IMAGE ? "primary" : "secondary"); } - qla24xx_read_flash_data(vha, ha->vpd, faddr, ha->vpd_size >> 2); + ha->isp_ops->read_optrom(vha, ha->vpd, faddr << 2, ha->vpd_size); /* Get NVRAM data into cache and calculate checksum. */ faddr = ha->flt_region_nvram; @@ -8241,7 +8241,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) "Loading %s nvram image.\n", active_regions.aux.vpd_nvram == QLA27XX_PRIMARY_IMAGE ? "primary" : "secondary"); - qla24xx_read_flash_data(vha, ha->nvram, faddr, ha->nvram_size >> 2); + ha->isp_ops->read_optrom(vha, ha->nvram, faddr << 2, ha->nvram_size); dptr = (uint32_t *)nv; for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++) diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 65a675906188..a79f8da38abe 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -2288,6 +2288,7 @@ qla82xx_disable_intrs(struct qla_hw_data *ha) scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); qla82xx_mbx_intr_disable(vha); + spin_lock_irq(&ha->hardware_lock); if (IS_QLA8044(ha)) qla8044_wr_reg(ha, LEG_INTR_MASK_OFFSET, 1); diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 764e1bb0f695..f2d5115b2d8d 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -682,8 +682,8 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) ha->flt_region_flt = flt_addr; wptr = (uint16_t *)ha->flt; - qla24xx_read_flash_data(vha, (void *)flt, flt_addr, - (sizeof(struct qla_flt_header) + FLT_REGIONS_SIZE) >> 2); + ha->isp_ops->read_optrom(vha, (void *)flt, flt_addr << 2, + (sizeof(struct qla_flt_header) + FLT_REGIONS_SIZE)); if (le16_to_cpu(*wptr) == 0xffff) goto no_flash_data; @@ -950,11 +950,11 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha) struct req_que *req = ha->req_q_map[0]; uint16_t cnt, chksum; uint16_t *wptr = (void *)req->ring; - struct qla_fdt_layout *fdt = (void *)req->ring; + struct qla_fdt_layout *fdt = (struct qla_fdt_layout *)req->ring; uint8_t man_id, flash_id; uint16_t mid = 0, fid = 0; - qla24xx_read_flash_data(vha, (void *)fdt, ha->flt_region_fdt, + ha->isp_ops->read_optrom(vha, fdt, ha->flt_region_fdt << 2, OPTROM_BURST_DWORDS); if (le16_to_cpu(*wptr) == 0xffff) goto no_flash_data; -- cgit v1.2.3-59-g8ed1b From 32a13df21668b92f70f0673387f29251e0f285ec Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Fri, 30 Aug 2019 15:23:59 -0700 Subject: scsi: qla2xxx: Fix driver reload for ISP82xx HINT_MBX_INT_PENDING is not guaranteed to be cleared by firmware. Remove check that prevent driver load with ISP82XX. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Reviewed-by: Ewan D. Milne Link: https://lore.kernel.org/r/20190830222402.23688-4-hmadhani@marvell.com Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_mbx.c | 16 ++-------------- drivers/scsi/qla2xxx/qla_nx.c | 3 ++- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index a82b6db2fa9d..4c858e2d0ea8 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -253,21 +253,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) if ((!abort_active && io_lock_on) || IS_NOPOLLING_TYPE(ha)) { set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); - if (IS_P3P_TYPE(ha)) { - if (RD_REG_DWORD(®->isp82.hint) & - HINT_MBX_INT_PENDING) { - ha->flags.mbox_busy = 0; - spin_unlock_irqrestore(&ha->hardware_lock, - flags); - - atomic_dec(&ha->num_pend_mbx_stage2); - ql_dbg(ql_dbg_mbx, vha, 0x1010, - "Pending mailbox timeout, exiting.\n"); - rval = QLA_FUNCTION_TIMEOUT; - goto premature_exit; - } + if (IS_P3P_TYPE(ha)) WRT_REG_DWORD(®->isp82.hint, HINT_MBX_INT_PENDING); - } else if (IS_FWI2_CAPABLE(ha)) + else if (IS_FWI2_CAPABLE(ha)) WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT); else WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index a79f8da38abe..2b2028f2383e 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -2287,7 +2287,8 @@ qla82xx_disable_intrs(struct qla_hw_data *ha) { scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); - qla82xx_mbx_intr_disable(vha); + if (ha->interrupts_on) + qla82xx_mbx_intr_disable(vha); spin_lock_irq(&ha->hardware_lock); if (IS_QLA8044(ha)) -- cgit v1.2.3-59-g8ed1b From ce0ba496dccfc15d3a8866b845864585b5d316ff Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Fri, 30 Aug 2019 15:24:00 -0700 Subject: scsi: qla2xxx: Fix stuck login session Login session was stucked on cable pull. When FW is in the middle PRLI PENDING + driver is in Initiator mode, driver fails to check back with FW to see if the PRLI has completed. This patch would re-check with FW again to make sure PRLI would complete before pushing forward with relogin. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Reviewed-by: Ewan D. Milne Link: https://lore.kernel.org/r/20190830222402.23688-5-hmadhani@marvell.com Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index d9e8b808bb59..b6cdf108994c 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -808,6 +808,15 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, fcport->fw_login_state = current_login_state; fcport->d_id = id; switch (current_login_state) { + case DSC_LS_PRLI_PEND: + /* + * In the middle of PRLI. Let it finish. + * Allow relogin code to recheck state again + * with GNL. Push disc_state back to DELETED + * so GNL can go out again + */ + fcport->disc_state = DSC_DELETED; + break; case DSC_LS_PRLI_COMP: if ((e->prli_svc_param_word_3[0] & BIT_4) == 0) fcport->port_type = FCT_INITIATOR; @@ -1474,7 +1483,7 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport) u64 wwn; u16 sec; - ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x20d8, + ql_dbg(ql_dbg_disc, vha, 0x20d8, "%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d lid %d scan %d\n", __func__, fcport->port_name, fcport->disc_state, fcport->fw_login_state, fcport->login_pause, fcport->flags, @@ -1485,6 +1494,7 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport) return 0; if ((fcport->loop_id != FC_NO_LOOP_ID) && + qla_dual_mode_enabled(vha) && ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) || (fcport->fw_login_state == DSC_LS_PRLI_PEND))) return 0; @@ -1674,17 +1684,6 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha, fcport->last_login_gen, fcport->login_gen, fcport->flags); - if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) || - (fcport->fw_login_state == DSC_LS_PRLI_PEND)) - return; - - if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) { - if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline)) { - set_bit(RELOGIN_NEEDED, &vha->dpc_flags); - return; - } - } - if (fcport->last_rscn_gen != fcport->rscn_gen) { ql_dbg(ql_dbg_disc, vha, 0x20e9, "%s %d %8phC post gnl\n", __func__, __LINE__, fcport->port_name); -- cgit v1.2.3-59-g8ed1b From 2037ce49d30a0d07348df406ef78f6664f4bc899 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Fri, 30 Aug 2019 15:24:01 -0700 Subject: scsi: qla2xxx: Fix stale session On fast cable pull, where driver is unable to detect device has disappeared and came back based on switch info, qla2xxx would not re-login while remote port has already invalidated the session. This causes IO timeout. This patch would relogin to remote device for RSCN affected port. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Reviewed-by: Ewan D. Milne Link: https://lore.kernel.org/r/20190830222402.23688-6-hmadhani@marvell.com Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_gs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 03f94eb372b6..dc0e36676313 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3628,7 +3628,6 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) list_for_each_entry(fcport, &vha->vp_fcports, list) { if (memcmp(rp->port_name, fcport->port_name, WWN_SIZE)) continue; - fcport->scan_needed = 0; fcport->scan_state = QLA_FCPORT_FOUND; found = true; /* @@ -3637,10 +3636,12 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) { qla2x00_clear_loop_id(fcport); fcport->flags |= FCF_FABRIC_DEVICE; - } else if (fcport->d_id.b24 != rp->id.b24) { + } else if (fcport->d_id.b24 != rp->id.b24 || + fcport->scan_needed) { qlt_schedule_sess_for_deletion(fcport); } fcport->d_id.b24 = rp->id.b24; + fcport->scan_needed = 0; break; } -- cgit v1.2.3-59-g8ed1b From fd807dc4719cbc081f647300a76af49a35c7b28e Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Fri, 30 Aug 2019 15:24:02 -0700 Subject: scsi: qla2xxx: Update driver version to 10.01.00.19-k Signed-off-by: Himanshu Madhani Reviewed-by: Ewan D. Milne Link: https://lore.kernel.org/r/20190830222402.23688-7-hmadhani@marvell.com Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 0833546a1b43..a8f2a953ceff 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.01.00.18-k" +#define QLA2XXX_VERSION "10.01.00.19-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 1 -- cgit v1.2.3-59-g8ed1b From 2d44d165e93975c5f209f49fdd8e3d682ef255dd Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 4 Sep 2019 19:04:23 +0300 Subject: scsi: lpfc: Convert existing %pf users to %ps Convert the remaining %pf users to %ps to prepare for the removal of the old %pf conversion specifier support. Fixes: 323506644972 ("scsi: lpfc: Migrate to %px and %pf in kernel print calls") Link: https://lore.kernel.org/r/20190904160423.3865-1-sakari.ailus@linux.intel.com Signed-off-by: Sakari Ailus Reviewed-by: Andy Shevchenko Reviewed-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hbadisc.c | 4 ++-- drivers/scsi/lpfc/lpfc_sli.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index e7463d561f30..749286acdc17 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -6051,7 +6051,7 @@ __lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param) list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { if (filter(ndlp, param)) { lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, - "3185 FIND node filter %pf DID " + "3185 FIND node filter %ps DID " "ndlp x%px did x%x flg x%x st x%x " "xri x%x type x%x rpi x%x\n", filter, ndlp, ndlp->nlp_DID, @@ -6062,7 +6062,7 @@ __lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param) } } lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, - "3186 FIND node filter %pf NOT FOUND.\n", filter); + "3186 FIND node filter %ps NOT FOUND.\n", filter); return NULL; } diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index bb5705267c39..2ff0879a9512 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2712,7 +2712,7 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba) /* Mailbox cmd Cmpl */ lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "(%d):0307 Mailbox cmd x%x (x%x/x%x) Cmpl %pf " + "(%d):0307 Mailbox cmd x%x (x%x/x%x) Cmpl %ps " "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x " "x%x x%x x%x\n", pmb->vport ? pmb->vport->vpi : 0, -- cgit v1.2.3-59-g8ed1b From 4fb86a6bc549fc482bdb21086aa272668ed955d2 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 3 Sep 2019 14:54:41 -0700 Subject: scsi: lpfc: Fix reset recovery paths that are not recovering A recent patch unconditionally marks the hba as in error as part of resetting the adapter. The driver flow that called the adapter reset was a recovery path, which expects the adapter to not be in an error state in order to finish the recovery. Given the new error state being set, the recovery fails and the adapter is left in limbo. Revise the adapter reset routine so that it will only mark the adapter in error if it was unable to reset the adapter. Fixes: 8c24a4f643ed ("scsi: lpfc: Fix crash due to port reset racing vs adapter error handling") Link: https://lore.kernel.org/r/20190903215441.10490-1-jsmart2021@gmail.com Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_sli.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 2ff0879a9512..a0c6945b8139 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -4619,8 +4619,10 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba) hba_aer_enabled = phba->hba_flag & HBA_AER_ENABLED; rc = lpfc_sli4_brdreset(phba); - if (rc) - goto error; + if (rc) { + phba->link_state = LPFC_HBA_ERROR; + goto hba_down_queue; + } spin_lock_irq(&phba->hbalock); phba->pport->stopped = 0; @@ -4635,8 +4637,7 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba) if (hba_aer_enabled) pci_disable_pcie_error_reporting(phba->pcidev); -error: - phba->link_state = LPFC_HBA_ERROR; +hba_down_queue: lpfc_hba_down_post(phba); lpfc_sli4_queue_destroy(phba); -- cgit v1.2.3-59-g8ed1b From d8d9f7931ac2698fc2b37d2db748c47122ee2a6f Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Wed, 28 Aug 2019 12:17:54 -0700 Subject: scsi: ufs: Introduce vops for resetting device Some UFS memory devices needs their reset line toggled in order to get them into a good state for initialization. Provide a new vops to allow the platform driver to implement this operation. Link: https://lore.kernel.org/r/20190828191756.24312-2-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson Reviewed-by: Alim Akhtar Reviewed-by: Bean Huo Reviewed-by: Stanley Chu Acked-by: Avri Altman Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 6 ++++++ drivers/scsi/ufs/ufshcd.h | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index ff6a440dc1c2..5c2eb4866044 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6234,6 +6234,9 @@ static int ufshcd_reset_and_restore(struct ufs_hba *hba) int retries = MAX_HOST_RESET_RETRIES; do { + /* Reset the attached device */ + ufshcd_vops_device_reset(hba); + err = ufshcd_host_reset_and_restore(hba); } while (err && --retries); @@ -8367,6 +8370,9 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) goto exit_gating; } + /* Reset the attached device */ + ufshcd_vops_device_reset(hba); + /* Host controller enable */ err = ufshcd_hba_enable(hba); if (err) { diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 9f61550abc7f..c94cfda52829 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -298,6 +298,7 @@ struct ufs_pwr_mode_info { * @resume: called during host controller PM callback * @dbg_register_dump: used to dump controller debug information * @phy_initialization: used to initialize phys + * @device_reset: called to issue a reset pulse on the UFS device */ struct ufs_hba_variant_ops { const char *name; @@ -326,6 +327,7 @@ struct ufs_hba_variant_ops { int (*resume)(struct ufs_hba *, enum ufs_pm_op); void (*dbg_register_dump)(struct ufs_hba *hba); int (*phy_initialization)(struct ufs_hba *); + void (*device_reset)(struct ufs_hba *hba); }; /* clock gating state */ @@ -1070,6 +1072,12 @@ static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba) hba->vops->dbg_register_dump(hba); } +static inline void ufshcd_vops_device_reset(struct ufs_hba *hba) +{ + if (hba->vops && hba->vops->device_reset) + hba->vops->device_reset(hba); +} + extern struct ufs_pm_lvl_states ufs_pm_lvl_states[]; /* -- cgit v1.2.3-59-g8ed1b From b8416b2fedbf1cfe1c3645c627b2341d253880bd Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Wed, 28 Aug 2019 12:17:55 -0700 Subject: scsi: ufs-qcom: Implement device_reset vops The UFS_RESET pin on Qualcomm SoCs are controlled by TLMM and exposed through the GPIO framework. Acquire the device-reset GPIO and use this to implement the device_reset vops, to allow resetting the attached memory. Based on downstream support implemented by Subhash Jadavani . Link: https://lore.kernel.org/r/20190828191756.24312-3-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson Acked-by: Rob Herring Acked-by: Avri Altman Signed-off-by: Martin K. Petersen --- .../devicetree/bindings/ufs/ufshcd-pltfrm.txt | 2 ++ drivers/scsi/ufs/ufs-qcom.c | 36 ++++++++++++++++++++++ drivers/scsi/ufs/ufs-qcom.h | 4 +++ 3 files changed, 42 insertions(+) diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt index a74720486ee2..d78ef63935f9 100644 --- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt +++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt @@ -54,6 +54,8 @@ Optional properties: PHY reset from the UFS controller. - resets : reset node register - reset-names : describe reset node register, the "rst" corresponds to reset the whole UFS IP. +- reset-gpios : A phandle and gpio specifier denoting the GPIO connected + to the RESET pin of the UFS memory device. Note: If above properties are not defined it can be assumed that the supply regulators or clocks are always on. diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 02cdcefb81ac..a5b71487a206 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "ufshcd.h" @@ -1137,6 +1138,15 @@ static int ufs_qcom_init(struct ufs_hba *hba) } } + host->device_reset = devm_gpiod_get_optional(dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(host->device_reset)) { + err = PTR_ERR(host->device_reset); + if (err != -EPROBE_DEFER) + dev_err(dev, "failed to acquire reset gpio: %d\n", err); + goto out_variant_clear; + } + err = ufs_qcom_bus_register(host); if (err) goto out_variant_clear; @@ -1542,6 +1552,31 @@ static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba) usleep_range(1000, 1100); } +/** + * ufs_qcom_device_reset() - toggle the (optional) device reset line + * @hba: per-adapter instance + * + * Toggles the (optional) reset line to reset the attached device. + */ +static void ufs_qcom_device_reset(struct ufs_hba *hba) +{ + struct ufs_qcom_host *host = ufshcd_get_variant(hba); + + /* reset gpio is optional */ + if (!host->device_reset) + return; + + /* + * The UFS device shall detect reset pulses of 1us, sleep for 10us to + * be on the safe side. + */ + gpiod_set_value_cansleep(host->device_reset, 1); + usleep_range(10, 15); + + gpiod_set_value_cansleep(host->device_reset, 0); + usleep_range(10, 15); +} + /** * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations * @@ -1562,6 +1597,7 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = { .suspend = ufs_qcom_suspend, .resume = ufs_qcom_resume, .dbg_register_dump = ufs_qcom_dump_dbg_regs, + .device_reset = ufs_qcom_device_reset, }; /** diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h index 001915d1e0e4..d401f174bb70 100644 --- a/drivers/scsi/ufs/ufs-qcom.h +++ b/drivers/scsi/ufs/ufs-qcom.h @@ -195,6 +195,8 @@ struct ufs_qcom_testbus { u8 select_minor; }; +struct gpio_desc; + struct ufs_qcom_host { /* * Set this capability if host controller supports the QUniPro mode @@ -232,6 +234,8 @@ struct ufs_qcom_host { struct ufs_qcom_testbus testbus; struct reset_controller_dev rcdev; + + struct gpio_desc *device_reset; }; static inline u32 -- cgit v1.2.3-59-g8ed1b From 3e303a42a3a8710a64a19fffff5af218403bc8a8 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Wed, 28 Aug 2019 12:17:56 -0700 Subject: scsi: arm64: dts: qcom: sdm845: Specify UFS device-reset GPIO Specify the UFS device-reset gpio for db845c and mtp, so that the controller will issue a reset of the UFS device. Link: https://lore.kernel.org/r/20190828191756.24312-4-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson Reviewed-by: Linus Walleij Acked-by: Avri Altman Signed-off-by: Martin K. Petersen --- arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 2 ++ arch/arm64/boot/dts/qcom/sdm845-mtp.dts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts index 71bd717a4251..f5a85caff1a3 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts +++ b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts @@ -497,6 +497,8 @@ &ufs_mem_hc { status = "okay"; + reset-gpios = <&tlmm 150 GPIO_ACTIVE_LOW>; + vcc-supply = <&vreg_l20a_2p95>; vcc-max-microamp = <800000>; }; diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts index 2e78638eb73b..c57548b7b250 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts +++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts @@ -388,6 +388,8 @@ &ufs_mem_hc { status = "okay"; + reset-gpios = <&tlmm 150 GPIO_ACTIVE_LOW>; + vcc-supply = <&vreg_l20a_2p95>; vcc-max-microamp = <600000>; }; -- cgit v1.2.3-59-g8ed1b From 5f57704dbcfe8ed718fc7cef0b1699c3aad7739c Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 31 Aug 2019 12:44:24 +0000 Subject: scsi: ufs: Use kmemdup in ufshcd_read_string_desc() Use kmemdup rather than duplicating its implementation Link: https://lore.kernel.org/r/20190831124424.18642-1-yuehaibing@huawei.com Signed-off-by: YueHaibing Acked-by: Tomas Winkler Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 5c2eb4866044..c4a015e42045 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -3309,12 +3309,11 @@ int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index, str[ret++] = '\0'; } else { - str = kzalloc(uc_str->len, GFP_KERNEL); + str = kmemdup(uc_str, uc_str->len, GFP_KERNEL); if (!str) { ret = -ENOMEM; goto out; } - memcpy(str, uc_str, uc_str->len); ret = uc_str->len; } out: -- cgit v1.2.3-59-g8ed1b From c0c1a71e9542e6b0b58642332eb86fd32c9b2ed8 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:02:56 +0800 Subject: scsi: hisi_sas: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Link: https://lore.kernel.org/r/20190904130256.24704-1-yuehaibing@huawei.com Reported-by: Hulk Robot Signed-off-by: YueHaibing Acked-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index d60eaaa4c5e8..d34e398d4a5d 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -2579,8 +2579,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev, goto err_out; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hisi_hba->regs = devm_ioremap_resource(dev, res); + hisi_hba->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hisi_hba->regs)) goto err_out; -- cgit v1.2.3-59-g8ed1b From 0b27555166241cb54e203f82bb98ebea2286fe9e Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:03:48 +0800 Subject: scsi: ufshcd: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Link: https://lore.kernel.org/r/20190904130348.24772-1-yuehaibing@huawei.com Reported-by: Hulk Robot Signed-off-by: YueHaibing Reviewed-by: Avri Altman Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd-pltfrm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index d7d521b394c3..8d40dc918f4e 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -391,12 +391,10 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, { struct ufs_hba *hba; void __iomem *mmio_base; - struct resource *mem_res; int irq, err; struct device *dev = &pdev->dev; - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mmio_base = devm_ioremap_resource(dev, mem_res); + mmio_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mmio_base)) { err = PTR_ERR(mmio_base); goto out; -- cgit v1.2.3-59-g8ed1b From 7ce5eed0998c0b2884329a06f29d0251079fca62 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:04:57 +0800 Subject: scsi: ufs-hisi: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Link: https://lore.kernel.org/r/20190904130457.24744-1-yuehaibing@huawei.com Reported-by: Hulk Robot Signed-off-by: YueHaibing Reviewed-by: Avri Altman Acked-by: Manivannan Sadhasivam Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-hisi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/scsi/ufs/ufs-hisi.c b/drivers/scsi/ufs/ufs-hisi.c index f4d1dca962c4..6bbb1679bb91 100644 --- a/drivers/scsi/ufs/ufs-hisi.c +++ b/drivers/scsi/ufs/ufs-hisi.c @@ -447,13 +447,11 @@ static int ufs_hisi_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) static int ufs_hisi_get_resource(struct ufs_hisi_host *host) { - struct resource *mem_res; struct device *dev = host->hba->dev; struct platform_device *pdev = to_platform_device(dev); /* get resource of ufs sys ctrl */ - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - host->ufs_sys_ctrl = devm_ioremap_resource(dev, mem_res); + host->ufs_sys_ctrl = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(host->ufs_sys_ctrl)) return PTR_ERR(host->ufs_sys_ctrl); -- cgit v1.2.3-59-g8ed1b From f96d279f0a5e53f4b96b16a5c08e2c75e139ba0b Mon Sep 17 00:00:00 2001 From: zhengbin Date: Tue, 20 Aug 2019 13:43:09 +0800 Subject: scsi: fcoe: fix null-ptr-deref Read in fc_release_transport In fcoe_if_init, if fc_attach_transport(&fcoe_vport_fc_functions) fails, need to free the previously memory and return fail, otherwise will trigger null-ptr-deref Read in fc_release_transport. fcoe_exit fcoe_if_exit fc_release_transport(fcoe_vport_scsi_transport) Link: https://lore.kernel.org/r/1566279789-58207-1-git-send-email-zhengbin13@huawei.com Reported-by: Hulk Robot Reviewed-by: Hannes Reinecke Signed-off-by: zhengbin Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 8e217ab7646e..813f26d8b417 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -1250,15 +1250,21 @@ static int __init fcoe_if_init(void) /* attach to scsi transport */ fcoe_nport_scsi_transport = fc_attach_transport(&fcoe_nport_fc_functions); + if (!fcoe_nport_scsi_transport) + goto err; + fcoe_vport_scsi_transport = fc_attach_transport(&fcoe_vport_fc_functions); - - if (!fcoe_nport_scsi_transport) { - printk(KERN_ERR "fcoe: Failed to attach to the FC transport\n"); - return -ENODEV; - } + if (!fcoe_vport_scsi_transport) + goto err_vport; return 0; + +err_vport: + fc_release_transport(fcoe_nport_scsi_transport); +err: + printk(KERN_ERR "fcoe: Failed to attach to the FC transport\n"); + return -ENODEV; } /** -- cgit v1.2.3-59-g8ed1b From 57adf5d4cfd3198aa480e7c94a101fc8c4e6109d Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Wed, 4 Sep 2019 15:52:29 +0000 Subject: scsi: scsi_dh_rdac: zero cdb in send_mode_select() cdb in send_mode_select() is not zeroed and is only partially filled in rdac_failover_get(), which leads to some random data getting to the device. Users have reported storage responding to such commands with INVALID FIELD IN CDB. Code before commit 327825574132 was not affected, as it called blk_rq_set_block_pc(). Fix this by zeroing out the cdb first. Identified & fix proposed by HPE. Fixes: 327825574132 ("scsi_dh_rdac: switch to scsi_execute_req_flags()") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20190904155205.1666-1-martin.wilck@suse.com Signed-off-by: Martin Wilck Acked-by: Ales Novak Reviewed-by: Shane Seymour Signed-off-by: Martin K. Petersen --- drivers/scsi/device_handler/scsi_dh_rdac.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 65f1fe343c64..5efc959493ec 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -546,6 +546,8 @@ static void send_mode_select(struct work_struct *work) spin_unlock(&ctlr->ms_lock); retry: + memset(cdb, 0, sizeof(cdb)); + data_size = rdac_failover_get(ctlr, &list, cdb); RDAC_LOG(RDAC_LOG_FAILOVER, sdev, "array %s, ctlr %d, " -- cgit v1.2.3-59-g8ed1b From 5ff843721467b4ef8d857b4724e3da7f515cf242 Mon Sep 17 00:00:00 2001 From: Matt Lupfer Date: Thu, 5 Sep 2019 18:19:28 +0000 Subject: scsi: virtio_scsi: unplug LUNs when events missed The event handler calls scsi_scan_host() when events are missed, which will hotplug new LUNs. However, this function won't remove any unplugged LUNs. The result is that hotunplug doesn't work properly when the number of unplugged LUNs exceeds the event queue size (currently 8). Scan existing LUNs when events are missed to check if they are still present. If not, remove them. Link: https://lore.kernel.org/r/20190905181903.29756-1-mlupfer@ddn.com Signed-off-by: Matt Lupfer Reviewed-by: Stefan Hajnoczi Acked-by: Paolo Bonzini Signed-off-by: Martin K. Petersen --- drivers/scsi/virtio_scsi.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index cff083049d5c..bfec84aacd90 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -30,6 +30,8 @@ #include #include +#include "sd.h" + #define VIRTIO_SCSI_MEMPOOL_SZ 64 #define VIRTIO_SCSI_EVENT_LEN 8 #define VIRTIO_SCSI_VQ_BASE 2 @@ -324,6 +326,36 @@ static void virtscsi_handle_param_change(struct virtio_scsi *vscsi, scsi_device_put(sdev); } +static void virtscsi_rescan_hotunplug(struct virtio_scsi *vscsi) +{ + struct scsi_device *sdev; + struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); + unsigned char scsi_cmd[MAX_COMMAND_SIZE]; + int result, inquiry_len, inq_result_len = 256; + char *inq_result = kmalloc(inq_result_len, GFP_KERNEL); + + shost_for_each_device(sdev, shost) { + inquiry_len = sdev->inquiry_len ? sdev->inquiry_len : 36; + + memset(scsi_cmd, 0, sizeof(scsi_cmd)); + scsi_cmd[0] = INQUIRY; + scsi_cmd[4] = (unsigned char) inquiry_len; + + memset(inq_result, 0, inq_result_len); + + result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, + inq_result, inquiry_len, NULL, + SD_TIMEOUT, SD_MAX_RETRIES, NULL); + + if (result == 0 && inq_result[0] >> 5) { + /* PQ indicates the LUN is not attached */ + scsi_remove_device(sdev); + } + } + + kfree(inq_result); +} + static void virtscsi_handle_event(struct work_struct *work) { struct virtio_scsi_event_node *event_node = @@ -335,6 +367,7 @@ static void virtscsi_handle_event(struct work_struct *work) cpu_to_virtio32(vscsi->vdev, VIRTIO_SCSI_T_EVENTS_MISSED)) { event->event &= ~cpu_to_virtio32(vscsi->vdev, VIRTIO_SCSI_T_EVENTS_MISSED); + virtscsi_rescan_hotunplug(vscsi); scsi_scan_host(virtio_scsi_host(vscsi->vdev)); } -- cgit v1.2.3-59-g8ed1b From 7105e68afaec062c0329910a491e57c9f3a82bef Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Fri, 6 Sep 2019 20:55:25 +0800 Subject: scsi: hisi_sas: add debugfs auto-trigger for internal abort time out This trigger is add at _hisi_sas_internal_task_abort() Link: https://lore.kernel.org/r/1567774537-20003-2-git-send-email-john.garry@huawei.com Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index d34e398d4a5d..1731764e951c 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -2060,6 +2060,9 @@ _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, /* Internal abort timed out */ if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { + if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct) + queue_work(hisi_hba->wq, &hisi_hba->debugfs_work); + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { struct hisi_sas_slot *slot = task->lldd_task; -- cgit v1.2.3-59-g8ed1b From af01b2b92454c0f9aa71f8f57d8e85dd68b774db Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Fri, 6 Sep 2019 20:55:26 +0800 Subject: scsi: hisi_sas: Use true/false as input parameter of sas_phy_reset() When calling sas_phy_reset(), we need to specify whether the reset type is hard reset or link reset - use true/false for clarity. Link: https://lore.kernel.org/r/1567774537-20003-3-git-send-email-john.garry@huawei.com Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 1731764e951c..59c11f4fcc23 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1762,7 +1762,7 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) } reset_type = (sas_dev->dev_status == HISI_SAS_DEV_INIT || - !dev_is_sata(device)) ? 1 : 0; + !dev_is_sata(device)) ? true : false; rc = sas_phy_reset(local_phy, reset_type); sas_put_local_phy(local_phy); @@ -1843,7 +1843,7 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun) phy = sas_get_local_phy(device); - rc = sas_phy_reset(phy, 1); + rc = sas_phy_reset(phy, true); if (rc == 0) hisi_sas_release_task(hisi_hba, device); -- cgit v1.2.3-59-g8ed1b From c2bae4f7d721e06e6bb8d1174ec7f8ff7604892c Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Fri, 6 Sep 2019 20:55:27 +0800 Subject: scsi: hisi_sas: Directly return when running I_T_nexus reset if phy disabled At hisi_sas_debug_I_T_nexus_reset(), we call sas_phy_reset() to reset a phy. But if the phy is disabled, sas_phy_reset() will directly return -ENODEV without issue a phy reset request. If so, We can directly return -ENODEV to libsas before issue a phy reset. Link: https://lore.kernel.org/r/1567774537-20003-4-git-send-email-john.garry@huawei.com Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 59c11f4fcc23..ffe02f9cf49a 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1752,6 +1752,11 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) DECLARE_COMPLETION_ONSTACK(phyreset); int rc, reset_type; + if (!local_phy->enabled) { + sas_put_local_phy(local_phy); + return -ENODEV; + } + if (scsi_is_sas_phy_local(local_phy)) { struct asd_sas_phy *sas_phy = sas_ha->sas_phy[local_phy->number]; -- cgit v1.2.3-59-g8ed1b From 76dd768b4471848672b4689aa926e9910c52a158 Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Fri, 6 Sep 2019 20:55:28 +0800 Subject: scsi: hisi_sas: Remove sleep after issue phy reset if sas_smp_phy_control() fails At expander environment, we delay after issue phy reset to wait for hardware to handle phy reset. But if sas_smp_phy_control() fails, the delay is unnecessary so remove it. Link: https://lore.kernel.org/r/1567774537-20003-5-git-send-email-john.garry@huawei.com Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index ffe02f9cf49a..a3691154e13c 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1791,9 +1791,10 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) } else if (sas_dev->dev_status != HISI_SAS_DEV_INIT) { /* * If in init state, we rely on caller to wait for link to be - * ready; otherwise, delay. + * ready; otherwise, except phy reset is fail, delay. */ - msleep(2000); + if (!rc) + msleep(2000); } return rc; -- cgit v1.2.3-59-g8ed1b From b45e05aa5d29264e2b7905cba6ff0626beda3637 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Fri, 6 Sep 2019 20:55:29 +0800 Subject: scsi: hisi_sas: Retry 3 times TMF IO for SAS disks when init device When init device for SAS disks, it will send TMF IO to clear disks. At that time TMF IO is broken by some operations such as injecting controller reset from HW RAs event, the TMF IO will be timeout, and at last device will be gone. Print is as followed: hisi_sas_v3_hw 0000:74:02.0: dev[240:1] found ... hisi_sas_v3_hw 0000:74:02.0: controller resetting... hisi_sas_v3_hw 0000:74:02.0: phyup: phy7 link_rate=10(sata) hisi_sas_v3_hw 0000:74:02.0: phyup: phy0 link_rate=9(sata) hisi_sas_v3_hw 0000:74:02.0: phyup: phy1 link_rate=9(sata) hisi_sas_v3_hw 0000:74:02.0: phyup: phy2 link_rate=9(sata) hisi_sas_v3_hw 0000:74:02.0: phyup: phy3 link_rate=9(sata) hisi_sas_v3_hw 0000:74:02.0: phyup: phy6 link_rate=10(sata) hisi_sas_v3_hw 0000:74:02.0: phyup: phy5 link_rate=11 hisi_sas_v3_hw 0000:74:02.0: phyup: phy4 link_rate=11 hisi_sas_v3_hw 0000:74:02.0: controller reset complete hisi_sas_v3_hw 0000:74:02.0: abort tmf: TMF task timeout and not done hisi_sas_v3_hw 0000:74:02.0: dev[240:1] is gone sas: driver on host 0000:74:02.0 cannot handle device 5000c500a75a860d, error:5 To improve the reliability, retry TMF IO max of 3 times for SAS disks which is the same as softreset does. Link: https://lore.kernel.org/r/1567774537-20003-6-git-send-email-john.garry@huawei.com Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index a3691154e13c..6392869a4e41 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -698,13 +698,13 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device) return sas_dev; } -#define HISI_SAS_SRST_ATA_DISK_CNT 3 +#define HISI_SAS_DISK_RECOVER_CNT 3 static int hisi_sas_init_device(struct domain_device *device) { int rc = TMF_RESP_FUNC_COMPLETE; struct scsi_lun lun; struct hisi_sas_tmf_task tmf_task; - int retry = HISI_SAS_SRST_ATA_DISK_CNT; + int retry = HISI_SAS_DISK_RECOVER_CNT; struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); struct device *dev = hisi_hba->dev; struct sas_phy *local_phy; @@ -714,10 +714,14 @@ static int hisi_sas_init_device(struct domain_device *device) int_to_scsilun(0, &lun); tmf_task.tmf = TMF_CLEAR_TASK_SET; - rc = hisi_sas_debug_issue_ssp_tmf(device, lun.scsi_lun, - &tmf_task); - if (rc == TMF_RESP_FUNC_COMPLETE) - hisi_sas_release_task(hisi_hba, device); + while (retry-- > 0) { + rc = hisi_sas_debug_issue_ssp_tmf(device, lun.scsi_lun, + &tmf_task); + if (rc == TMF_RESP_FUNC_COMPLETE) { + hisi_sas_release_task(hisi_hba, device); + break; + } + } break; case SAS_SATA_DEV: case SAS_SATA_PM: -- cgit v1.2.3-59-g8ed1b From 73a4925d154cbd3c73e6643033e7167cb2353d9a Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Fri, 6 Sep 2019 20:55:30 +0800 Subject: scsi: hisi_sas: Update all the registers after suspend and resume After suspend and resume, the HW registers will be set back to their initial value. We use init_reg_v3_hw() to set some registers, but some registers are set via firmware in ACPI "_RST" method, so add reset handler before init_reg_v3_hw(). Link: https://lore.kernel.org/r/1567774537-20003-7-git-send-email-john.garry@huawei.com Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 2adb5c93bd81..4c32088b9199 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -3283,15 +3283,21 @@ static int hisi_sas_v3_resume(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D0, 0); pci_restore_state(pdev); rc = pci_enable_device(pdev); - if (rc) + if (rc) { dev_err(dev, "enable device failed during resume (%d)\n", rc); + return rc; + } pci_set_master(pdev); scsi_unblock_requests(shost); clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); sas_prep_resume_ha(sha); - init_reg_v3_hw(hisi_hba); + rc = hw_init_v3_hw(hisi_hba); + if (rc) { + scsi_remove_host(shost); + pci_disable_device(pdev); + } hisi_hba->hw->phys_init(hisi_hba); sas_resume_ha(sha); clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags); -- cgit v1.2.3-59-g8ed1b From 435a05cf8c003221fd945229e2b61b5ecca9070d Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Fri, 6 Sep 2019 20:55:31 +0800 Subject: scsi: hisi_sas: Assign NCQ tag for all NCQ commands Currently the NCQ tag is only assigned for FPDMA READ and FPDMA WRITE commands, and for other NCQ commands (such as FPDMA SEND), their NCQ tags are set in the delivery command to 0. So for all the NCQ commands, we also need to assign normal NCQ tag for them, so drop the command type check in hisi_sas_get_ncq_tag() [drop hisi_sas_get_ncq_tag() altogether actually], and always use the ATA command NCQ tag when appropriate. Link: https://lore.kernel.org/r/1567774537-20003-8-git-send-email-john.garry@huawei.com Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 1 - drivers/scsi/hisi_sas/hisi_sas_main.c | 15 --------------- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 5 ++++- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 5 ++++- 4 files changed, 8 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index fd998d07ffcd..a72d06d973ff 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -559,7 +559,6 @@ extern u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, extern struct hisi_sas_port *to_hisi_sas_port(struct asd_sas_port *sas_port); extern void hisi_sas_sata_done(struct sas_task *task, struct hisi_sas_slot *slot); -extern int hisi_sas_get_ncq_tag(struct sas_task *task, u32 *tag); extern int hisi_sas_get_fw_info(struct hisi_hba *hisi_hba); extern int hisi_sas_probe(struct platform_device *pdev, const struct hisi_sas_hw *ops); diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 6392869a4e41..751db9588a1e 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -118,21 +118,6 @@ void hisi_sas_sata_done(struct sas_task *task, } EXPORT_SYMBOL_GPL(hisi_sas_sata_done); -int hisi_sas_get_ncq_tag(struct sas_task *task, u32 *tag) -{ - struct ata_queued_cmd *qc = task->uldd_task; - - if (qc) { - if (qc->tf.command == ATA_CMD_FPDMA_WRITE || - qc->tf.command == ATA_CMD_FPDMA_READ) { - *tag = qc->tag; - return 1; - } - } - return 0; -} -EXPORT_SYMBOL_GPL(hisi_sas_get_ncq_tag); - /* * This function assumes linkrate mask fits in 8 bits, which it * does for all HW versions supported. diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index fba4fcad4735..9d316f28c74c 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2534,7 +2534,10 @@ static void prep_ata_v2_hw(struct hisi_hba *hisi_hba, hdr->dw1 = cpu_to_le32(dw1); /* dw2 */ - if (task->ata_task.use_ncq && hisi_sas_get_ncq_tag(task, &hdr_tag)) { + if (task->ata_task.use_ncq) { + struct ata_queued_cmd *qc = task->uldd_task; + + hdr_tag = qc->tag; task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3); dw2 |= hdr_tag << CMD_HDR_NCQ_TAG_OFF; } diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 4c32088b9199..cd901213a59b 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -1356,7 +1356,10 @@ static void prep_ata_v3_hw(struct hisi_hba *hisi_hba, hdr->dw1 = cpu_to_le32(dw1); /* dw2 */ - if (task->ata_task.use_ncq && hisi_sas_get_ncq_tag(task, &hdr_tag)) { + if (task->ata_task.use_ncq) { + struct ata_queued_cmd *qc = task->uldd_task; + + hdr_tag = qc->tag; task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3); dw2 |= hdr_tag << CMD_HDR_NCQ_TAG_OFF; } -- cgit v1.2.3-59-g8ed1b From 971b59443f213d8085d122fae65aa96087b269bc Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Fri, 6 Sep 2019 20:55:32 +0800 Subject: scsi: hisi_sas: Remove hisi_sas_hw.slot_complete We never call hisi_sas_hw.slot_complete, so remove it. Link: https://lore.kernel.org/r/1567774537-20003-9-git-send-email-john.garry@huawei.com Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 2 -- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 1 - drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 1 - drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 1 - 4 files changed, 5 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index a72d06d973ff..a6b53d29a8a1 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -289,8 +289,6 @@ struct hisi_sas_hw { void (*prep_abort)(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot, int device_id, int abort_flag, int tag_to_abort); - int (*slot_complete)(struct hisi_hba *hisi_hba, - struct hisi_sas_slot *slot); void (*phys_init)(struct hisi_hba *hisi_hba); void (*phy_start)(struct hisi_hba *hisi_hba, int phy_no); void (*phy_disable)(struct hisi_hba *hisi_hba, int phy_no); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 3a584feca843..b861a0f14c9d 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1782,7 +1782,6 @@ static const struct hisi_sas_hw hisi_sas_v1_hw = { .prep_smp = prep_smp_v1_hw, .prep_ssp = prep_ssp_v1_hw, .start_delivery = start_delivery_v1_hw, - .slot_complete = slot_complete_v1_hw, .phys_init = phys_init_v1_hw, .phy_start = start_phy_v1_hw, .phy_disable = disable_phy_v1_hw, diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 9d316f28c74c..b01ccb38b00a 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -3561,7 +3561,6 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = { .prep_stp = prep_ata_v2_hw, .prep_abort = prep_abort_v2_hw, .start_delivery = start_delivery_v2_hw, - .slot_complete = slot_complete_v2_hw, .phys_init = phys_init_v2_hw, .phy_start = start_phy_v2_hw, .phy_disable = disable_phy_v2_hw, diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index cd901213a59b..0a159df87d7b 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2961,7 +2961,6 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = { .prep_stp = prep_ata_v3_hw, .prep_abort = prep_abort_v3_hw, .start_delivery = start_delivery_v3_hw, - .slot_complete = slot_complete_v3_hw, .phys_init = phys_init_v3_hw, .phy_start = start_phy_v3_hw, .phy_disable = disable_phy_v3_hw, -- cgit v1.2.3-59-g8ed1b From 27f22723c3f4a1a3e66642b3da7a3d16ee602972 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Fri, 6 Sep 2019 20:55:33 +0800 Subject: scsi: hisi_sas: Remove redundant work declaration Remove redundant work declaration in HISI_SAS_DECLARE_RST_WORK_ON_STACK Link: https://lore.kernel.org/r/1567774537-20003-10-git-send-email-john.garry@huawei.com Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index a6b53d29a8a1..d02ab2699b9b 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -134,7 +134,6 @@ struct hisi_sas_rst { #define HISI_SAS_DECLARE_RST_WORK_ON_STACK(r) \ DECLARE_COMPLETION_ONSTACK(c); \ - DECLARE_WORK(w, hisi_sas_sync_rst_work_handler); \ struct hisi_sas_rst r = HISI_SAS_RST_WORK_INIT(r, c) enum hisi_sas_bit_err_type { -- cgit v1.2.3-59-g8ed1b From 4bc058097aa8b1af046fa000fbc6bf5408ace9bf Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Fri, 6 Sep 2019 20:55:34 +0800 Subject: scsi: hisi_sas: Remove some unused function arguments Some function arguments are unused, so remove them. Also move the timeout print in for wait_cmds_complete_timeout_vX_hw() callsites into that same function. Link: https://lore.kernel.org/r/1567774537-20003-11-git-send-email-john.garry@huawei.com Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 4 ++-- drivers/scsi/hisi_sas/hisi_sas_main.c | 5 ++--- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 11 ++++++----- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 17 +++++++---------- 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index d02ab2699b9b..ccbe4563402a 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -306,8 +306,8 @@ struct hisi_sas_hw { u32 (*get_phys_state)(struct hisi_hba *hisi_hba); int (*write_gpio)(struct hisi_hba *hisi_hba, u8 reg_type, u8 reg_index, u8 reg_count, u8 *write_data); - int (*wait_cmds_complete_timeout)(struct hisi_hba *hisi_hba, - int delay_ms, int timeout_ms); + void (*wait_cmds_complete_timeout)(struct hisi_hba *hisi_hba, + int delay_ms, int timeout_ms); void (*snapshot_prepare)(struct hisi_hba *hisi_hba); void (*snapshot_restore)(struct hisi_hba *hisi_hba); void (*read_iost_itct_cache)(struct hisi_hba *hisi_hba, diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 751db9588a1e..dcbb1aa005b5 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1391,8 +1391,7 @@ static void hisi_sas_refresh_port_id(struct hisi_hba *hisi_hba) } } -static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 old_state, - u32 state) +static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state) { struct sas_ha_struct *sas_ha = &hisi_hba->sha; struct asd_sas_port *_sas_port = NULL; @@ -1553,7 +1552,7 @@ void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba) clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags); state = hisi_hba->hw->get_phys_state(hisi_hba); - hisi_sas_rescan_topology(hisi_hba, hisi_hba->phy_state, state); + hisi_sas_rescan_topology(hisi_hba, state); } EXPORT_SYMBOL_GPL(hisi_sas_controller_reset_done); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index b01ccb38b00a..8e96a257e439 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -3498,8 +3498,8 @@ static int write_gpio_v2_hw(struct hisi_hba *hisi_hba, u8 reg_type, return 0; } -static int wait_cmds_complete_timeout_v2_hw(struct hisi_hba *hisi_hba, - int delay_ms, int timeout_ms) +static void wait_cmds_complete_timeout_v2_hw(struct hisi_hba *hisi_hba, + int delay_ms, int timeout_ms) { struct device *dev = hisi_hba->dev; int entries, entries_old = 0, time; @@ -3513,12 +3513,13 @@ static int wait_cmds_complete_timeout_v2_hw(struct hisi_hba *hisi_hba, msleep(delay_ms); } - if (time >= timeout_ms) - return -ETIMEDOUT; + if (time >= timeout_ms) { + dev_dbg(dev, "Wait commands complete timeout!\n"); + return; + } dev_dbg(dev, "wait commands complete %dms\n", time); - return 0; } static struct device_attribute *host_attrs_v2_hw[] = { diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 0a159df87d7b..e4db85b8af3e 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2576,8 +2576,8 @@ static int write_gpio_v3_hw(struct hisi_hba *hisi_hba, u8 reg_type, return 0; } -static int wait_cmds_complete_timeout_v3_hw(struct hisi_hba *hisi_hba, - int delay_ms, int timeout_ms) +static void wait_cmds_complete_timeout_v3_hw(struct hisi_hba *hisi_hba, + int delay_ms, int timeout_ms) { struct device *dev = hisi_hba->dev; int entries, entries_old = 0, time; @@ -2591,12 +2591,12 @@ static int wait_cmds_complete_timeout_v3_hw(struct hisi_hba *hisi_hba, msleep(delay_ms); } - if (time >= timeout_ms) - return -ETIMEDOUT; + if (time >= timeout_ms) { + dev_dbg(dev, "Wait commands complete timeout!\n"); + return; + } dev_dbg(dev, "wait commands complete %dms\n", time); - - return 0; } static ssize_t intr_conv_v3_hw_show(struct device *dev, @@ -2877,14 +2877,11 @@ static const struct hisi_sas_debugfs_reg debugfs_ras_reg = { static void debugfs_snapshot_prepare_v3_hw(struct hisi_hba *hisi_hba) { - struct device *dev = hisi_hba->dev; - set_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0); - if (wait_cmds_complete_timeout_v3_hw(hisi_hba, 100, 5000) == -ETIMEDOUT) - dev_dbg(dev, "Wait commands complete timeout!\n"); + wait_cmds_complete_timeout_v3_hw(hisi_hba, 100, 5000); hisi_sas_kill_tasklets(hisi_hba); } -- cgit v1.2.3-59-g8ed1b From 7ec7082c57ecdd8d37040d31203951f7e2e8e218 Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Fri, 6 Sep 2019 20:55:35 +0800 Subject: scsi: hisi_sas: Add hisi_sas_debugfs_alloc() to centralise allocation We extract the code of memory allocate and construct an new function for it. We think it's convenient for subsequent optimization. Link: https://lore.kernel.org/r/1567774537-20003-12-git-send-email-john.garry@huawei.com Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 102 +++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 44 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index dcbb1aa005b5..9a135f8cf14e 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -3306,27 +3306,44 @@ void hisi_sas_debugfs_work_handler(struct work_struct *work) } EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler); -void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) +void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba) +{ + struct device *dev = hisi_hba->dev; + int i; + + devm_kfree(dev, hisi_hba->debugfs_iost_cache); + devm_kfree(dev, hisi_hba->debugfs_itct_cache); + devm_kfree(dev, hisi_hba->debugfs_iost); + + for (i = 0; i < hisi_hba->queue_count; i++) + devm_kfree(dev, hisi_hba->debugfs_cmd_hdr[i]); + + for (i = 0; i < hisi_hba->queue_count; i++) + devm_kfree(dev, hisi_hba->debugfs_complete_hdr[i]); + + for (i = 0; i < DEBUGFS_REGS_NUM; i++) + devm_kfree(dev, hisi_hba->debugfs_regs[i]); + + for (i = 0; i < hisi_hba->n_phy; i++) + devm_kfree(dev, hisi_hba->debugfs_port_reg[i]); +} + +int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba) { - int max_command_entries = HISI_SAS_MAX_COMMANDS; const struct hisi_sas_hw *hw = hisi_hba->hw; struct device *dev = hisi_hba->dev; - int p, i, c, d; + int p, c, d; size_t sz; - hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev), - hisi_sas_debugfs_dir); - debugfs_create_file("trigger_dump", 0600, - hisi_hba->debugfs_dir, - hisi_hba, - &hisi_sas_debugfs_trigger_dump_fops); + hisi_hba->debugfs_dump_dentry = + debugfs_create_dir("dump", hisi_hba->debugfs_dir); sz = hw->debugfs_reg_array[DEBUGFS_GLOBAL]->count * 4; hisi_hba->debugfs_regs[DEBUGFS_GLOBAL] = devm_kmalloc(dev, sz, GFP_KERNEL); if (!hisi_hba->debugfs_regs[DEBUGFS_GLOBAL]) - goto fail_global; + goto fail; sz = hw->debugfs_reg_port->count * 4; for (p = 0; p < hisi_hba->n_phy; p++) { @@ -3334,7 +3351,7 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) devm_kmalloc(dev, sz, GFP_KERNEL); if (!hisi_hba->debugfs_port_reg[p]) - goto fail_port; + goto fail; } sz = hw->debugfs_reg_array[DEBUGFS_AXI]->count * 4; @@ -3342,14 +3359,14 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) devm_kmalloc(dev, sz, GFP_KERNEL); if (!hisi_hba->debugfs_regs[DEBUGFS_AXI]) - goto fail_axi; + goto fail; sz = hw->debugfs_reg_array[DEBUGFS_RAS]->count * 4; hisi_hba->debugfs_regs[DEBUGFS_RAS] = devm_kmalloc(dev, sz, GFP_KERNEL); if (!hisi_hba->debugfs_regs[DEBUGFS_RAS]) - goto fail_ras; + goto fail; sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS; for (c = 0; c < hisi_hba->queue_count; c++) { @@ -3357,7 +3374,7 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) devm_kmalloc(dev, sz, GFP_KERNEL); if (!hisi_hba->debugfs_complete_hdr[c]) - goto fail_cq; + goto fail; } sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS; @@ -3366,60 +3383,57 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) devm_kmalloc(dev, sz, GFP_KERNEL); if (!hisi_hba->debugfs_cmd_hdr[d]) - goto fail_iost_dq; + goto fail; } - sz = max_command_entries * sizeof(struct hisi_sas_iost); + sz = HISI_SAS_MAX_COMMANDS * sizeof(struct hisi_sas_iost); hisi_hba->debugfs_iost = devm_kmalloc(dev, sz, GFP_KERNEL); if (!hisi_hba->debugfs_iost) - goto fail_iost_dq; + goto fail; sz = HISI_SAS_IOST_ITCT_CACHE_NUM * sizeof(struct hisi_sas_iost_itct_cache); hisi_hba->debugfs_iost_cache = devm_kmalloc(dev, sz, GFP_KERNEL); if (!hisi_hba->debugfs_iost_cache) - goto fail_iost_cache; + goto fail; sz = HISI_SAS_IOST_ITCT_CACHE_NUM * sizeof(struct hisi_sas_iost_itct_cache); hisi_hba->debugfs_itct_cache = devm_kmalloc(dev, sz, GFP_KERNEL); if (!hisi_hba->debugfs_itct_cache) - goto fail_itct_cache; + goto fail; /* New memory allocation must be locate before itct */ sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct); hisi_hba->debugfs_itct = devm_kmalloc(dev, sz, GFP_KERNEL); if (!hisi_hba->debugfs_itct) - goto fail_itct; + goto fail; - return; -fail_itct: - devm_kfree(dev, hisi_hba->debugfs_iost_cache); -fail_itct_cache: - devm_kfree(dev, hisi_hba->debugfs_iost_cache); -fail_iost_cache: - devm_kfree(dev, hisi_hba->debugfs_iost); -fail_iost_dq: - for (i = 0; i < d; i++) - devm_kfree(dev, hisi_hba->debugfs_cmd_hdr[i]); -fail_cq: - for (i = 0; i < c; i++) - devm_kfree(dev, hisi_hba->debugfs_complete_hdr[i]); - devm_kfree(dev, hisi_hba->debugfs_regs[DEBUGFS_RAS]); -fail_ras: - devm_kfree(dev, hisi_hba->debugfs_regs[DEBUGFS_AXI]); -fail_axi: -fail_port: - for (i = 0; i < p; i++) - devm_kfree(dev, hisi_hba->debugfs_port_reg[i]); - devm_kfree(dev, hisi_hba->debugfs_regs[DEBUGFS_GLOBAL]); -fail_global: - debugfs_remove_recursive(hisi_hba->debugfs_dir); - dev_dbg(dev, "failed to init debugfs!\n"); + return 0; +fail: + hisi_sas_debugfs_release(hisi_hba); + return -ENOMEM; +} + +void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) +{ + struct device *dev = hisi_hba->dev; + + hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev), + hisi_sas_debugfs_dir); + debugfs_create_file("trigger_dump", 0600, + hisi_hba->debugfs_dir, + hisi_hba, + &hisi_sas_debugfs_trigger_dump_fops); + + if (hisi_sas_debugfs_alloc(hisi_hba)) { + debugfs_remove_recursive(hisi_hba->debugfs_dir); + dev_dbg(dev, "failed to init debugfs!\n"); + } } EXPORT_SYMBOL_GPL(hisi_sas_debugfs_init); -- cgit v1.2.3-59-g8ed1b From 97b151e75861674a176ff8fb5e243dc2aa066af4 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Fri, 6 Sep 2019 20:55:36 +0800 Subject: scsi: hisi_sas: Add BIST support for phy loopback Add BIST (built in self test) support for phy loopback. Through the new debugfs interface, the user can configure loopback mode/linkrate/phy id/code mode before enabling it. And also user can enable/disable BIST function. Link: https://lore.kernel.org/r/1567774537-20003-13-git-send-email-john.garry@huawei.com Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 10 + drivers/scsi/hisi_sas/hisi_sas_main.c | 407 +++++++++++++++++++++++++++++++++ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 126 ++++++++++ 3 files changed, 543 insertions(+) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index ccbe4563402a..720c4d6be939 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -310,6 +310,7 @@ struct hisi_sas_hw { int delay_ms, int timeout_ms); void (*snapshot_prepare)(struct hisi_hba *hisi_hba); void (*snapshot_restore)(struct hisi_hba *hisi_hba); + int (*set_bist)(struct hisi_hba *hisi_hba, bool enable); void (*read_iost_itct_cache)(struct hisi_hba *hisi_hba, enum hisi_sas_debugfs_cache_type type, u32 *cache); @@ -391,6 +392,14 @@ struct hisi_hba { int cq_nvecs; unsigned int *reply_map; + /* bist */ + enum sas_linkrate debugfs_bist_linkrate; + int debugfs_bist_code_mode; + int debugfs_bist_phy_no; + int debugfs_bist_mode; + u32 debugfs_bist_cnt; + int debugfs_bist_enable; + /* debugfs memories */ /* Put Global AXI and RAS Register into register array */ u32 *debugfs_regs[DEBUGFS_REGS_NUM]; @@ -404,6 +413,7 @@ struct hisi_hba { struct dentry *debugfs_dir; struct dentry *debugfs_dump_dentry; + struct dentry *debugfs_bist_dentry; bool debugfs_snapshot; }; diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 9a135f8cf14e..fdf6bb10c556 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -3293,6 +3293,382 @@ static const struct file_operations hisi_sas_debugfs_trigger_dump_fops = { .owner = THIS_MODULE, }; +enum { + HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL = 0, + HISI_SAS_BIST_LOOPBACK_MODE_SERDES, + HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, +}; + +enum { + HISI_SAS_BIST_CODE_MODE_PRBS7 = 0, + HISI_SAS_BIST_CODE_MODE_PRBS23, + HISI_SAS_BIST_CODE_MODE_PRBS31, + HISI_SAS_BIST_CODE_MODE_JTPAT, + HISI_SAS_BIST_CODE_MODE_CJTPAT, + HISI_SAS_BIST_CODE_MODE_SCRAMBED_0, + HISI_SAS_BIST_CODE_MODE_TRAIN, + HISI_SAS_BIST_CODE_MODE_TRAIN_DONE, + HISI_SAS_BIST_CODE_MODE_HFTP, + HISI_SAS_BIST_CODE_MODE_MFTP, + HISI_SAS_BIST_CODE_MODE_LFTP, + HISI_SAS_BIST_CODE_MODE_FIXED_DATA, +}; + +static const struct { + int value; + char *name; +} hisi_sas_debugfs_loop_linkrate[] = { + { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" }, + { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" }, + { SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" }, + { SAS_LINK_RATE_12_0_GBPS, "12.0 Gbit" }, +}; + +static int hisi_sas_debugfs_bist_linkrate_show(struct seq_file *s, void *p) +{ + struct hisi_hba *hisi_hba = s->private; + int i; + + for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_linkrate); i++) { + int match = (hisi_hba->debugfs_bist_linkrate == + hisi_sas_debugfs_loop_linkrate[i].value); + + seq_printf(s, "%s%s%s ", match ? "[" : "", + hisi_sas_debugfs_loop_linkrate[i].name, + match ? "]" : ""); + } + seq_puts(s, "\n"); + + return 0; +} + +static ssize_t hisi_sas_debugfs_bist_linkrate_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + struct seq_file *m = filp->private_data; + struct hisi_hba *hisi_hba = m->private; + char kbuf[16] = {}, *pkbuf; + bool found = false; + int i; + + if (hisi_hba->debugfs_bist_enable) + return -EPERM; + + if (count >= sizeof(kbuf)) + return -EOVERFLOW; + + if (copy_from_user(kbuf, buf, count)) + return -EINVAL; + + pkbuf = strstrip(kbuf); + + for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_linkrate); i++) { + if (!strncmp(hisi_sas_debugfs_loop_linkrate[i].name, + pkbuf, 16)) { + hisi_hba->debugfs_bist_linkrate = + hisi_sas_debugfs_loop_linkrate[i].value; + found = true; + break; + } + } + + if (!found) + return -EINVAL; + + return count; +} + +static int hisi_sas_debugfs_bist_linkrate_open(struct inode *inode, + struct file *filp) +{ + return single_open(filp, hisi_sas_debugfs_bist_linkrate_show, + inode->i_private); +} + +static const struct file_operations hisi_sas_debugfs_bist_linkrate_ops = { + .open = hisi_sas_debugfs_bist_linkrate_open, + .read = seq_read, + .write = hisi_sas_debugfs_bist_linkrate_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static const struct { + int value; + char *name; +} hisi_sas_debugfs_loop_code_mode[] = { + { HISI_SAS_BIST_CODE_MODE_PRBS7, "PRBS7" }, + { HISI_SAS_BIST_CODE_MODE_PRBS23, "PRBS23" }, + { HISI_SAS_BIST_CODE_MODE_PRBS31, "PRBS31" }, + { HISI_SAS_BIST_CODE_MODE_JTPAT, "JTPAT" }, + { HISI_SAS_BIST_CODE_MODE_CJTPAT, "CJTPAT" }, + { HISI_SAS_BIST_CODE_MODE_SCRAMBED_0, "SCRAMBED_0" }, + { HISI_SAS_BIST_CODE_MODE_TRAIN, "TRAIN" }, + { HISI_SAS_BIST_CODE_MODE_TRAIN_DONE, "TRAIN_DONE" }, + { HISI_SAS_BIST_CODE_MODE_HFTP, "HFTP" }, + { HISI_SAS_BIST_CODE_MODE_MFTP, "MFTP" }, + { HISI_SAS_BIST_CODE_MODE_LFTP, "LFTP" }, + { HISI_SAS_BIST_CODE_MODE_FIXED_DATA, "FIXED_DATA" }, +}; + +static int hisi_sas_debugfs_bist_code_mode_show(struct seq_file *s, void *p) +{ + struct hisi_hba *hisi_hba = s->private; + int i; + + for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_code_mode); i++) { + int match = (hisi_hba->debugfs_bist_code_mode == + hisi_sas_debugfs_loop_code_mode[i].value); + + seq_printf(s, "%s%s%s ", match ? "[" : "", + hisi_sas_debugfs_loop_code_mode[i].name, + match ? "]" : ""); + } + seq_puts(s, "\n"); + + return 0; +} + +static ssize_t hisi_sas_debugfs_bist_code_mode_write(struct file *filp, + const char __user *buf, + size_t count, + loff_t *ppos) +{ + struct seq_file *m = filp->private_data; + struct hisi_hba *hisi_hba = m->private; + char kbuf[16] = {}, *pkbuf; + bool found = false; + int i; + + if (hisi_hba->debugfs_bist_enable) + return -EPERM; + + if (count >= sizeof(kbuf)) + return -EINVAL; + + if (copy_from_user(kbuf, buf, count)) + return -EOVERFLOW; + + pkbuf = strstrip(kbuf); + + for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_code_mode); i++) { + if (!strncmp(hisi_sas_debugfs_loop_code_mode[i].name, + pkbuf, 16)) { + hisi_hba->debugfs_bist_code_mode = + hisi_sas_debugfs_loop_code_mode[i].value; + found = true; + break; + } + } + + if (!found) + return -EINVAL; + + return count; +} + +static int hisi_sas_debugfs_bist_code_mode_open(struct inode *inode, + struct file *filp) +{ + return single_open(filp, hisi_sas_debugfs_bist_code_mode_show, + inode->i_private); +} + +static const struct file_operations hisi_sas_debugfs_bist_code_mode_ops = { + .open = hisi_sas_debugfs_bist_code_mode_open, + .read = seq_read, + .write = hisi_sas_debugfs_bist_code_mode_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static ssize_t hisi_sas_debugfs_bist_phy_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + struct seq_file *m = filp->private_data; + struct hisi_hba *hisi_hba = m->private; + unsigned int phy_no; + int val; + + if (hisi_hba->debugfs_bist_enable) + return -EPERM; + + val = kstrtouint_from_user(buf, count, 0, &phy_no); + if (val) + return val; + + if (phy_no >= hisi_hba->n_phy) + return -EINVAL; + + hisi_hba->debugfs_bist_phy_no = phy_no; + + return count; +} + +static int hisi_sas_debugfs_bist_phy_show(struct seq_file *s, void *p) +{ + struct hisi_hba *hisi_hba = s->private; + + seq_printf(s, "%d\n", hisi_hba->debugfs_bist_phy_no); + + return 0; +} + +static int hisi_sas_debugfs_bist_phy_open(struct inode *inode, + struct file *filp) +{ + return single_open(filp, hisi_sas_debugfs_bist_phy_show, + inode->i_private); +} + +static const struct file_operations hisi_sas_debugfs_bist_phy_ops = { + .open = hisi_sas_debugfs_bist_phy_open, + .read = seq_read, + .write = hisi_sas_debugfs_bist_phy_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static const struct { + int value; + char *name; +} hisi_sas_debugfs_loop_modes[] = { + { HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL, "digial" }, + { HISI_SAS_BIST_LOOPBACK_MODE_SERDES, "serdes" }, + { HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, "remote" }, +}; + +static int hisi_sas_debugfs_bist_mode_show(struct seq_file *s, void *p) +{ + struct hisi_hba *hisi_hba = s->private; + int i; + + for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_modes); i++) { + int match = (hisi_hba->debugfs_bist_mode == + hisi_sas_debugfs_loop_modes[i].value); + + seq_printf(s, "%s%s%s ", match ? "[" : "", + hisi_sas_debugfs_loop_modes[i].name, + match ? "]" : ""); + } + seq_puts(s, "\n"); + + return 0; +} + +static ssize_t hisi_sas_debugfs_bist_mode_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + struct seq_file *m = filp->private_data; + struct hisi_hba *hisi_hba = m->private; + char kbuf[16] = {}, *pkbuf; + bool found = false; + int i; + + if (hisi_hba->debugfs_bist_enable) + return -EPERM; + + if (count >= sizeof(kbuf)) + return -EINVAL; + + if (copy_from_user(kbuf, buf, count)) + return -EOVERFLOW; + + pkbuf = strstrip(kbuf); + + for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_modes); i++) { + if (!strncmp(hisi_sas_debugfs_loop_modes[i].name, pkbuf, 16)) { + hisi_hba->debugfs_bist_mode = + hisi_sas_debugfs_loop_modes[i].value; + found = true; + break; + } + } + + if (!found) + return -EINVAL; + + return count; +} + +static int hisi_sas_debugfs_bist_mode_open(struct inode *inode, + struct file *filp) +{ + return single_open(filp, hisi_sas_debugfs_bist_mode_show, + inode->i_private); +} + +static const struct file_operations hisi_sas_debugfs_bist_mode_ops = { + .open = hisi_sas_debugfs_bist_mode_open, + .read = seq_read, + .write = hisi_sas_debugfs_bist_mode_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static ssize_t hisi_sas_debugfs_bist_enable_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + struct seq_file *m = filp->private_data; + struct hisi_hba *hisi_hba = m->private; + unsigned int enable; + int val; + + val = kstrtouint_from_user(buf, count, 0, &enable); + if (val) + return val; + + if (enable > 1) + return -EINVAL; + + if (enable == hisi_hba->debugfs_bist_enable) + return count; + + if (!hisi_hba->hw->set_bist) + return -EPERM; + + val = hisi_hba->hw->set_bist(hisi_hba, enable); + if (val < 0) + return val; + + hisi_hba->debugfs_bist_enable = enable; + + return count; +} + +static int hisi_sas_debugfs_bist_enable_show(struct seq_file *s, void *p) +{ + struct hisi_hba *hisi_hba = s->private; + + seq_printf(s, "%d\n", hisi_hba->debugfs_bist_enable); + + return 0; +} + +static int hisi_sas_debugfs_bist_enable_open(struct inode *inode, + struct file *filp) +{ + return single_open(filp, hisi_sas_debugfs_bist_enable_show, + inode->i_private); +} + +static const struct file_operations hisi_sas_debugfs_bist_enable_ops = { + .open = hisi_sas_debugfs_bist_enable_open, + .read = seq_read, + .write = hisi_sas_debugfs_bist_enable_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + void hisi_sas_debugfs_work_handler(struct work_struct *work) { struct hisi_hba *hisi_hba = @@ -3419,6 +3795,34 @@ fail: return -ENOMEM; } +void hisi_sas_debugfs_bist_init(struct hisi_hba *hisi_hba) +{ + hisi_hba->debugfs_bist_dentry = + debugfs_create_dir("bist", hisi_hba->debugfs_dir); + debugfs_create_file("link_rate", 0600, + hisi_hba->debugfs_bist_dentry, hisi_hba, + &hisi_sas_debugfs_bist_linkrate_ops); + + debugfs_create_file("code_mode", 0600, + hisi_hba->debugfs_bist_dentry, hisi_hba, + &hisi_sas_debugfs_bist_code_mode_ops); + + debugfs_create_file("phy_id", 0600, hisi_hba->debugfs_bist_dentry, + hisi_hba, &hisi_sas_debugfs_bist_phy_ops); + + debugfs_create_u32("cnt", 0600, hisi_hba->debugfs_bist_dentry, + &hisi_hba->debugfs_bist_cnt); + + debugfs_create_file("loopback_mode", 0600, + hisi_hba->debugfs_bist_dentry, + hisi_hba, &hisi_sas_debugfs_bist_mode_ops); + + debugfs_create_file("enable", 0600, hisi_hba->debugfs_bist_dentry, + hisi_hba, &hisi_sas_debugfs_bist_enable_ops); + + hisi_hba->debugfs_bist_linkrate = SAS_LINK_RATE_1_5_GBPS; +} + void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) { struct device *dev = hisi_hba->dev; @@ -3430,6 +3834,9 @@ void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) hisi_hba, &hisi_sas_debugfs_trigger_dump_fops); + /* create bist structures */ + hisi_sas_debugfs_bist_init(hisi_hba); + if (hisi_sas_debugfs_alloc(hisi_hba)) { debugfs_remove_recursive(hisi_hba->debugfs_dir); dev_dbg(dev, "failed to init debugfs!\n"); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index e4db85b8af3e..cb8d087762db 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -191,12 +191,30 @@ #define PHY_CFG_PHY_RST_OFF 3 #define PHY_CFG_PHY_RST_MSK (0x1 << PHY_CFG_PHY_RST_OFF) #define PROG_PHY_LINK_RATE (PORT_BASE + 0x8) +#define CFG_PROG_PHY_LINK_RATE_OFF 8 +#define CFG_PROG_PHY_LINK_RATE_MSK (0xf << CFG_PROG_PHY_LINK_RATE_OFF) #define PHY_CTRL (PORT_BASE + 0x14) #define PHY_CTRL_RESET_OFF 0 #define PHY_CTRL_RESET_MSK (0x1 << PHY_CTRL_RESET_OFF) #define CMD_HDR_PIR_OFF 8 #define CMD_HDR_PIR_MSK (0x1 << CMD_HDR_PIR_OFF) #define SERDES_CFG (PORT_BASE + 0x1c) +#define CFG_ALOS_CHK_DISABLE_OFF 9 +#define CFG_ALOS_CHK_DISABLE_MSK (0x1 << CFG_ALOS_CHK_DISABLE_OFF) +#define SAS_PHY_BIST_CTRL (PORT_BASE + 0x2c) +#define CFG_BIST_MODE_SEL_OFF 0 +#define CFG_BIST_MODE_SEL_MSK (0xf << CFG_BIST_MODE_SEL_OFF) +#define CFG_LOOP_TEST_MODE_OFF 14 +#define CFG_LOOP_TEST_MODE_MSK (0x3 << CFG_LOOP_TEST_MODE_OFF) +#define CFG_RX_BIST_EN_OFF 16 +#define CFG_RX_BIST_EN_MSK (0x1 << CFG_RX_BIST_EN_OFF) +#define CFG_TX_BIST_EN_OFF 17 +#define CFG_TX_BIST_EN_MSK (0x1 << CFG_TX_BIST_EN_OFF) +#define CFG_BIST_TEST_OFF 18 +#define CFG_BIST_TEST_MSK (0x1 << CFG_BIST_TEST_OFF) +#define SAS_PHY_BIST_CODE (PORT_BASE + 0x30) +#define SAS_PHY_BIST_CODE1 (PORT_BASE + 0x34) +#define SAS_BIST_ERR_CNT (PORT_BASE + 0x38) #define SL_CFG (PORT_BASE + 0x84) #define AIP_LIMIT (PORT_BASE + 0x90) #define SL_CONTROL (PORT_BASE + 0x94) @@ -2923,6 +2941,113 @@ static void read_iost_itct_cache_v3_hw(struct hisi_hba *hisi_hba, buf[i] = hisi_sas_read32(hisi_hba, TAB_DFX); } +static void hisi_sas_bist_test_prep_v3_hw(struct hisi_hba *hisi_hba) +{ + u32 reg_val; + int phy_id = hisi_hba->debugfs_bist_phy_no; + + /* disable PHY */ + hisi_sas_phy_enable(hisi_hba, phy_id, 0); + + /* disable ALOS */ + reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, SERDES_CFG); + reg_val |= CFG_ALOS_CHK_DISABLE_MSK; + hisi_sas_phy_write32(hisi_hba, phy_id, SERDES_CFG, reg_val); +} + +static void hisi_sas_bist_test_restore_v3_hw(struct hisi_hba *hisi_hba) +{ + u32 reg_val; + int phy_id = hisi_hba->debugfs_bist_phy_no; + + /* disable loopback */ + reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, SAS_PHY_BIST_CTRL); + reg_val &= ~(CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK | + CFG_BIST_TEST_MSK); + hisi_sas_phy_write32(hisi_hba, phy_id, SAS_PHY_BIST_CTRL, reg_val); + + /* enable ALOS */ + reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, SERDES_CFG); + reg_val &= ~CFG_ALOS_CHK_DISABLE_MSK; + hisi_sas_phy_write32(hisi_hba, phy_id, SERDES_CFG, reg_val); + + /* restore the linkrate */ + reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, PROG_PHY_LINK_RATE); + /* init OOB link rate as 1.5 Gbits */ + reg_val &= ~CFG_PROG_PHY_LINK_RATE_MSK; + reg_val |= (0x8 << CFG_PROG_PHY_LINK_RATE_OFF); + hisi_sas_phy_write32(hisi_hba, phy_id, PROG_PHY_LINK_RATE, reg_val); + + /* enable PHY */ + hisi_sas_phy_enable(hisi_hba, phy_id, 1); +} + +#define SAS_PHY_BIST_CODE_INIT 0x1 +#define SAS_PHY_BIST_CODE1_INIT 0X80 +static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable) +{ + u32 reg_val, mode_tmp; + u32 linkrate = hisi_hba->debugfs_bist_linkrate; + u32 phy_id = hisi_hba->debugfs_bist_phy_no; + u32 code_mode = hisi_hba->debugfs_bist_code_mode; + u32 path_mode = hisi_hba->debugfs_bist_mode; + struct device *dev = hisi_hba->dev; + + dev_info(dev, "BIST info:linkrate=%d phy_id=%d code_mode=%d path_mode=%d\n", + linkrate, phy_id, code_mode, path_mode); + mode_tmp = path_mode ? 2 : 1; + if (enable) { + /* some preparations before bist test */ + hisi_sas_bist_test_prep_v3_hw(hisi_hba); + + /* set linkrate of bit test*/ + reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, + PROG_PHY_LINK_RATE); + reg_val &= ~CFG_PROG_PHY_LINK_RATE_MSK; + reg_val |= (linkrate << CFG_PROG_PHY_LINK_RATE_OFF); + hisi_sas_phy_write32(hisi_hba, phy_id, + PROG_PHY_LINK_RATE, reg_val); + + /* set code mode of bit test */ + reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, + SAS_PHY_BIST_CTRL); + reg_val &= ~(CFG_BIST_MODE_SEL_MSK | + CFG_LOOP_TEST_MODE_MSK | + CFG_RX_BIST_EN_MSK | + CFG_TX_BIST_EN_MSK | + CFG_BIST_TEST_MSK); + reg_val |= ((code_mode << CFG_BIST_MODE_SEL_OFF) | + (mode_tmp << CFG_LOOP_TEST_MODE_OFF) | + CFG_BIST_TEST_MSK); + hisi_sas_phy_write32(hisi_hba, phy_id, + SAS_PHY_BIST_CTRL, reg_val); + + mdelay(100); + reg_val |= (CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK); + hisi_sas_phy_write32(hisi_hba, phy_id, + SAS_PHY_BIST_CTRL, reg_val); + + /* set the bist init value */ + hisi_sas_phy_write32(hisi_hba, phy_id, + SAS_PHY_BIST_CODE, + SAS_PHY_BIST_CODE_INIT); + hisi_sas_phy_write32(hisi_hba, phy_id, + SAS_PHY_BIST_CODE1, + SAS_PHY_BIST_CODE1_INIT); + + /* clear error bit */ + mdelay(100); + hisi_sas_phy_read32(hisi_hba, phy_id, SAS_BIST_ERR_CNT); + } else { + /* disable bist test and recover it */ + hisi_hba->debugfs_bist_cnt += hisi_sas_phy_read32(hisi_hba, + phy_id, SAS_BIST_ERR_CNT); + hisi_sas_bist_test_restore_v3_hw(hisi_hba); + } + + return 0; +} + static struct scsi_host_template sht_v3_hw = { .name = DRV_NAME, .module = THIS_MODULE, @@ -2977,6 +3102,7 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = { .snapshot_prepare = debugfs_snapshot_prepare_v3_hw, .snapshot_restore = debugfs_snapshot_restore_v3_hw, .read_iost_itct_cache = read_iost_itct_cache_v3_hw, + .set_bist = debugfs_set_bist_v3_hw, }; static struct Scsi_Host * -- cgit v1.2.3-59-g8ed1b From e74006edd0d42b45ff37ae4ae13c614cfa30056b Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Fri, 6 Sep 2019 20:55:37 +0800 Subject: scsi: hisi_sas: Fix the conflict between device gone and host reset When device gone, it will check whether it is during reset, if not, it will send internal task abort. Before internal task abort returned, reset begins, and it will check whether SAS_PHY_UNUSED is set, if not, it will call hisi_sas_init_device(), but at that time domain_device may already be freed or part of it is freed, so it may referenece null pointer in hisi_sas_init_device(). It may occur as follows: thread0 thread1 hisi_sas_dev_gone() check whether in RESET(no) internal task abort reset prep soft_reset ... (part of reset_done) internal task abort failed release resource anyway clear_itct device->lldd_dev=NULL hisi_sas_reset_init_all_device check sas_dev->dev_type is SAS_PHY_UNUSED and !device set dev_type SAS_PHY_UNUSED sas_free_device hisi_sas_init_device ... Semaphore hisi_hba.sema is used to sync the processes of device gone and host reset. To solve the issue, expand the scope that semaphore protects and let them never occur together. And also some places will check whether domain_device is NULL to judge whether the device is gone. So when device gone, need to clear sas_dev->sas_device. Link: https://lore.kernel.org/r/1567774537-20003-14-git-send-email-john.garry@huawei.com Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index fdf6bb10c556..d1513fdf1e00 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1049,21 +1049,22 @@ static void hisi_sas_dev_gone(struct domain_device *device) dev_info(dev, "dev[%d:%x] is gone\n", sas_dev->device_id, sas_dev->dev_type); + down(&hisi_hba->sem); if (!test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) { hisi_sas_internal_task_abort(hisi_hba, device, HISI_SAS_INT_ABT_DEV, 0); hisi_sas_dereg_device(hisi_hba, device); - down(&hisi_hba->sem); hisi_hba->hw->clear_itct(hisi_hba, sas_dev); - up(&hisi_hba->sem); device->lldd_dev = NULL; } if (hisi_hba->hw->free_device) hisi_hba->hw->free_device(sas_dev); sas_dev->dev_type = SAS_PHY_UNUSED; + sas_dev->sas_device = NULL; + up(&hisi_hba->sem); } static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags) @@ -1543,11 +1544,11 @@ void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba) msleep(1000); hisi_sas_refresh_port_id(hisi_hba); clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); - up(&hisi_hba->sem); if (hisi_hba->reject_stp_links_msk) hisi_sas_terminate_stp_reject(hisi_hba); hisi_sas_reset_init_all_devices(hisi_hba); + up(&hisi_hba->sem); scsi_unblock_requests(shost); clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags); -- cgit v1.2.3-59-g8ed1b