PLEASE CONFIRM PURCHASE ORDER
Could you please confirm if your recieved our purchase order last week. If no please confirm let me resend it to you. NARESH KUMAR Executive Purchase Saiapextrading Ltd Dubai, KSA. (T/F): +96-2667-264 777 / 778 (Mo): +96 94284 02803 Website - http://www.saiapexgeneraltrading.com
Re: [PATCH 2/3] scsi: qla2xxx: unset RCE/EFT fields in failure case
On Wed, 2019-08-14 at 08:24 +0200, Hannes Reinecke wrote: > On 8/13/19 10:31 PM, Martin Wilck wrote: > > From: Martin Wilck > > > > Reset ha->rce, ha->eft and the respective dma fields if > > the buffers aren't mapped for some reason. Also, treat > > both failure cases (allocation and initialization failure) > > equally. The next patch modifies the failure behavior > > slightly again. > > > > 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 > > --- > > drivers/scsi/qla2xxx/qla_init.c | 10 ++ > > 1 file changed, 10 insertions(+) > > > > diff --git a/drivers/scsi/qla2xxx/qla_init.c > > b/drivers/scsi/qla2xxx/qla_init.c > > index 6dd68be..ca9c3f3 100644 > > --- a/drivers/scsi/qla2xxx/qla_init.c > > +++ b/drivers/scsi/qla2xxx/qla_init.c > > @@ -3063,6 +3063,8 @@ qla2x00_alloc_offload_mem(scsi_qla_host_t > > *vha) > > ql_log(ql_log_warn, vha, 0x00be, > > "Unable to allocate (%d KB) for FCE.\n", > > FCE_SIZE / 1024); > > + ha->fce_dma = 0; > > + ha->fce = NULL; > > goto try_eft; > > } > > > Actually, I would set this earlier here: > > if (ha->fce) > dma_free_coherent(&ha->pdev->dev, > FCE_SIZE, ha->fce, ha->fce_dma); > > which is the logical place to clear 'ha->fce' and 'ha->fce_dma' IMO. Fine with me. > Alsoe there is this call later on: > > 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; > } > > which also needs to be protected. Right. > > @@ -3111,9 +3113,12 @@ qla2x00_alloc_offload_mem(scsi_qla_host_t > > *vha) > > > > ha->eft_dma = tc_dma; > > ha->eft = tc; > > + return; > > } > > > > eft_err: > > + ha->eft = NULL; > > + ha->eft_dma = 0; > > return; > > } > > > I wonder why this is even there. > > Right at the start we have: > if (ha->eft) { > ql_dbg(ql_dbg_init, vha, 0x00bd, > "%s: Offload Mem is already allocated.\n", > __func__); > return; > } > > IE the second half of this function really should be unreachable > code. This check is only in qla2x00_alloc_offload_mem(), not in qla2x00_alloc_fw_dump(), where EFT allocation is attempted again (and qla2x00_alloc_offload_mem() is called first). It looks like an oversight, indeed. IMO this part of the code needs cleanup; for now I tried to keep the patches small. > Himanshu? > Thanks, Martin
[PATCH v2 1/2] scsi: qla2xxx: qla2x00_alloc_fw_dump: set ha->eft
From: Martin Wilck 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 --- 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 535dc21..6dd68be 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3197,6 +3197,8 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) 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)) { -- 2.22.0
[PATCH v2 2/2] scsi: qla2xxx: cleanup trace buffer initialization
From: Martin Wilck 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 --- drivers/scsi/qla2xxx/qla_init.c | 220 +++- drivers/scsi/qla2xxx/qla_os.c | 1 + 2 files changed, 102 insertions(+), 119 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 6dd68be..4a89ec5 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 (!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: FCE Mem is already allocated.\n", + __func__); + 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); + return; + } + + 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; + } + + ql_dbg(ql_dbg_init, vha, 0x00c0, + "Allocated (%d KB) for FCE...\n", FCE_SIZE / 1024); + + ha->flags.fce_enabled = 1; + ha->fce_dma = tc_dma; + ha->fce = tc; +} + +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; + if (ha->eft) { ql_dbg(ql_dbg_init, vha, 0x00bd, - "%s: Offload Mem is already allocated.\n", + "%s: EFT 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; - - if (ha->fce) - dma_free_coherent(&ha->pdev->dev, - FCE_SIZE, ha->fce, ha->fce_dma); - - /* 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) -
[PATCH v2 0/2] scsi: qla2xxx: fixes for FW trace/dump buffers
From: Martin Wilck Hi Himanshu, hi Martin, Please consider this series for merging. The first patch of the series is a fix for a memory corruption we saw in a test where qla2xxx was loaded/unloaded repeatedly under memory pressure. The second one is a cleanup/consistency fix. Regards, Martin Changes in v2: rather then keeping the patches small, cleanup the buffer allocation code properly, following (and going beyond) Hannes' review suggestions for the v1 set. Martin Wilck (2): scsi: qla2xxx: qla2x00_alloc_fw_dump: set ha->eft scsi: qla2xxx: cleanup trace buffer initialization drivers/scsi/qla2xxx/qla_init.c | 218 +++- drivers/scsi/qla2xxx/qla_os.c | 1 + 2 files changed, 102 insertions(+), 117 deletions(-) -- 2.22.0
Re: [PATCH] qla2xxx: Fix gnl.l memory leak on adapter init failure
On 7/16/19, 1:57 PM, "linux-scsi-ow...@vger.kernel.org on behalf of Bill Kuzeja" wrote: If HBA initialization fails unexpectedly (exiting via probe_failed:), we may fail to free vha->gnl.l. So that we don't attempt to double free, set this pointer to NULL after a free and check for NULL at probe_failed: so we know whether or not to call dma_free_coherent. Signed-off-by: Bill Kuzeja --- drivers/scsi/qla2xxx/qla_attr.c | 2 ++ drivers/scsi/qla2xxx/qla_os.c | 11 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 8d560c5..6b7b390 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -2956,6 +2956,8 @@ void qla_insert_tgt_attrs(void) dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l, vha->gnl.ldma); + vha->gnl.l = NULL; + vfree(vha->scan.l); if (vha->qpair && vha->qpair->vp_idx == vha->vp_idx) { diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2e58cff..98e60a3 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -3440,6 +3440,12 @@ static void qla2x00_iocb_work_fn(struct work_struct *work) return 0; probe_failed: + if (base_vha->gnl.l) { + dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size, + base_vha->gnl.l, base_vha->gnl.ldma); + base_vha->gnl.l = NULL; + } + if (base_vha->timer_active) qla2x00_stop_timer(base_vha); base_vha->flags.online = 0; @@ -3673,7 +3679,7 @@ static void qla2x00_iocb_work_fn(struct work_struct *work) if (!atomic_read(&pdev->enable_cnt)) { dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma); - + base_vha->gnl.l = NULL; scsi_host_put(base_vha->host); kfree(ha); pci_set_drvdata(pdev, NULL); @@ -3713,6 +3719,8 @@ static void qla2x00_iocb_work_fn(struct work_struct *work) dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma); + base_vha->gnl.l = NULL; + vfree(base_vha->scan.l); if (IS_QLAFX00(ha)) @@ -4816,6 +4824,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); + vha->gnl.l = NULL; scsi_remove_host(vha->host); return NULL; } -- 1.8.3.1 Looks Good. Acked-by: Himanshu Madhani
Re: [PATCH] scsi: qla2xxx: replace snprintf with strscpy
On 7/25/19, 12:54 AM, "linux-scsi-ow...@vger.kernel.org on behalf of Wang Xiayang" wrote: As commit a86028f8e3ee ("staging: most: sound: replace snprintf with strscpy") suggested, using snprintf without a format specifier is potentially risky if a0->vendor_name or a0->vendor_pn mistakenly contain format specifiers. In addition, as compared in the implementation, strscpy looks more light-weight than snprintf. This patch does not incur any functional change. Signed-off-by: Wang Xiayang --- 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 4059655639d9..068b54218ff4 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3461,12 +3461,12 @@ static void qla2xxx_print_sfp_info(struct scsi_qla_host *vha) int leftover, len; memset(str, 0, STR_LEN); - snprintf(str, SFF_VEN_NAME_LEN+1, a0->vendor_name); + strscpy(str, a0->vendor_name, SFF_VEN_NAME_LEN+1); ql_dbg(ql_dbg_init, vha, 0x015a, "SFP MFG Name: %s\n", str); memset(str, 0, STR_LEN); - snprintf(str, SFF_PART_NAME_LEN+1, a0->vendor_pn); + strscpy(str, a0->vendor_pn, SFF_PART_NAME_LEN+1); ql_dbg(ql_dbg_init, vha, 0x015c, "SFP Part Name: %s\n", str); -- 2.11.0 Looks Good. Acked-by: Himanshu Madhani
Re: [PATCH 2/3] scsi: qla2xxx: unset RCE/EFT fields in failure case
On 8/14/19, 6:30 AM, "linux-scsi-ow...@vger.kernel.org on behalf of Martin Wilck" wrote: On Wed, 2019-08-14 at 08:24 +0200, Hannes Reinecke wrote: > On 8/13/19 10:31 PM, Martin Wilck wrote: > > From: Martin Wilck > > > > Reset ha->rce, ha->eft and the respective dma fields if > > the buffers aren't mapped for some reason. Also, treat > > both failure cases (allocation and initialization failure) > > equally. The next patch modifies the failure behavior > > slightly again. > > > > 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 > > --- > > drivers/scsi/qla2xxx/qla_init.c | 10 ++ > > 1 file changed, 10 insertions(+) > > > > diff --git a/drivers/scsi/qla2xxx/qla_init.c > > b/drivers/scsi/qla2xxx/qla_init.c > > index 6dd68be..ca9c3f3 100644 > > --- a/drivers/scsi/qla2xxx/qla_init.c > > +++ b/drivers/scsi/qla2xxx/qla_init.c > > @@ -3063,6 +3063,8 @@ qla2x00_alloc_offload_mem(scsi_qla_host_t > > *vha) > > ql_log(ql_log_warn, vha, 0x00be, > > "Unable to allocate (%d KB) for FCE.\n", > > FCE_SIZE / 1024); > > + ha->fce_dma = 0; > > + ha->fce = NULL; > > goto try_eft; > > } > > > Actually, I would set this earlier here: > > if (ha->fce) > dma_free_coherent(&ha->pdev->dev, > FCE_SIZE, ha->fce, ha->fce_dma); > > which is the logical place to clear 'ha->fce' and 'ha->fce_dma' IMO. Fine with me. > Alsoe there is this call later on: > > 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; > } > > which also needs to be protected. Right. > > @@ -3111,9 +3113,12 @@ qla2x00_alloc_offload_mem(scsi_qla_host_t > > *vha) > > > > ha->eft_dma = tc_dma; > > ha->eft = tc; > > + return; > > } > > > > eft_err: > > + ha->eft = NULL; > > + ha->eft_dma = 0; > > return; > > } > > > I wonder why this is even there. > > Right at the start we have: > if (ha->eft) { > ql_dbg(ql_dbg_init, vha, 0x00bd, > "%s: Offload Mem is already allocated.\n", > __func__); > return; > } > > IE the second half of this function really should be unreachable > code. I do agree that second half of the function was unreachable code. This check is only in qla2x00_alloc_offload_mem(), not in qla2x00_alloc_fw_dump(), where EFT allocation is attempted again (and qla2x00_alloc_offload_mem() is called first). It looks like an oversight, indeed. IMO this part of the code needs cleanup; for now I tried to keep the patches small. > Himanshu? > I see you sent out v2 already of this series with cleanups suggested by Hannes. I'll review your v2 on the list. Thanks, Himanshu Thanks, Martin
[PATCH RESEND] qla2xxx: Fix gnl.l memory leak on adapter init failure
If HBA initialization fails unexpectedly (exiting via probe_failed:), we may fail to free vha->gnl.l. So that we don't attempt to double free, set this pointer to NULL after a free and check for NULL at probe_failed: so we know whether or not to call dma_free_coherent. Signed-off-by: Bill Kuzeja --- drivers/scsi/qla2xxx/qla_attr.c | 2 ++ drivers/scsi/qla2xxx/qla_os.c | 11 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 8d560c5..6b7b390 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -2956,6 +2956,8 @@ void qla_insert_tgt_attrs(void) dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l, vha->gnl.ldma); + vha->gnl.l = NULL; + vfree(vha->scan.l); if (vha->qpair && vha->qpair->vp_idx == vha->vp_idx) { diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2e58cff..98e60a3 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -3440,6 +3440,12 @@ static void qla2x00_iocb_work_fn(struct work_struct *work) return 0; probe_failed: + if (base_vha->gnl.l) { + dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size, + base_vha->gnl.l, base_vha->gnl.ldma); + base_vha->gnl.l = NULL; + } + if (base_vha->timer_active) qla2x00_stop_timer(base_vha); base_vha->flags.online = 0; @@ -3673,7 +3679,7 @@ static void qla2x00_iocb_work_fn(struct work_struct *work) if (!atomic_read(&pdev->enable_cnt)) { dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma); - + base_vha->gnl.l = NULL; scsi_host_put(base_vha->host); kfree(ha); pci_set_drvdata(pdev, NULL); @@ -3713,6 +3719,8 @@ static void qla2x00_iocb_work_fn(struct work_struct *work) dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma); + base_vha->gnl.l = NULL; + vfree(base_vha->scan.l); if (IS_QLAFX00(ha)) @@ -4816,6 +4824,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); + vha->gnl.l = NULL; scsi_remove_host(vha->host); return NULL; } -- 1.8.3.1
Re: [PATCH] scsi: qla2xxx: replace snprintf with strscpy
On 7/24/19 10:46 PM, Wang Xiayang wrote: As commit a86028f8e3ee ("staging: most: sound: replace snprintf with strscpy") suggested, using snprintf without a format specifier is potentially risky if a0->vendor_name or a0->vendor_pn mistakenly contain format specifiers. In addition, as compared in the implementation, strscpy looks more light-weight than snprintf. This patch does not incur any functional change. Signed-off-by: Wang Xiayang --- 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 4059655639d9..068b54218ff4 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3461,12 +3461,12 @@ static void qla2xxx_print_sfp_info(struct scsi_qla_host *vha) int leftover, len; memset(str, 0, STR_LEN); - snprintf(str, SFF_VEN_NAME_LEN+1, a0->vendor_name); + strscpy(str, a0->vendor_name, SFF_VEN_NAME_LEN+1); ql_dbg(ql_dbg_init, vha, 0x015a, "SFP MFG Name: %s\n", str); memset(str, 0, STR_LEN); - snprintf(str, SFF_PART_NAME_LEN+1, a0->vendor_pn); + strscpy(str, a0->vendor_pn, SFF_PART_NAME_LEN+1); ql_dbg(ql_dbg_init, vha, 0x015c, "SFP Part Name: %s\n", str); From qla_def.h: /* Refer to SNIA SFF 8247 */ struct sff_8247_a0 { [ ... ] u8 vendor_name[SFF_VEN_NAME_LEN]; /* offset 20/14h */ u8 vendor_pn[SFF_PART_NAME_LEN];/* part number */ So I think that using SFF_PART_NAME_LEN+1 as length limit is wrong. Himanshu, do you perhaps know whether or not the vendor_name and vendor_pn arrays should be '\0'-terminated in struct sff_8247_a0? Thanks, Bart.
Re: [PATCH RESEND] qla2xxx: Fix gnl.l memory leak on adapter init failure
On 8/14/19, 9:25 AM, "linux-scsi-ow...@vger.kernel.org on behalf of Bill Kuzeja" wrote: If HBA initialization fails unexpectedly (exiting via probe_failed:), we may fail to free vha->gnl.l. So that we don't attempt to double free, set this pointer to NULL after a free and check for NULL at probe_failed: so we know whether or not to call dma_free_coherent. Signed-off-by: Bill Kuzeja --- drivers/scsi/qla2xxx/qla_attr.c | 2 ++ drivers/scsi/qla2xxx/qla_os.c | 11 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 8d560c5..6b7b390 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -2956,6 +2956,8 @@ void qla_insert_tgt_attrs(void) dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l, vha->gnl.ldma); + vha->gnl.l = NULL; + vfree(vha->scan.l); if (vha->qpair && vha->qpair->vp_idx == vha->vp_idx) { diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2e58cff..98e60a3 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -3440,6 +3440,12 @@ static void qla2x00_iocb_work_fn(struct work_struct *work) return 0; probe_failed: + if (base_vha->gnl.l) { + dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size, + base_vha->gnl.l, base_vha->gnl.ldma); + base_vha->gnl.l = NULL; + } + if (base_vha->timer_active) qla2x00_stop_timer(base_vha); base_vha->flags.online = 0; @@ -3673,7 +3679,7 @@ static void qla2x00_iocb_work_fn(struct work_struct *work) if (!atomic_read(&pdev->enable_cnt)) { dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma); - + base_vha->gnl.l = NULL; scsi_host_put(base_vha->host); kfree(ha); pci_set_drvdata(pdev, NULL); @@ -3713,6 +3719,8 @@ static void qla2x00_iocb_work_fn(struct work_struct *work) dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma); + base_vha->gnl.l = NULL; + vfree(base_vha->scan.l); if (IS_QLAFX00(ha)) @@ -4816,6 +4824,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); + vha->gnl.l = NULL; scsi_remove_host(vha->host); return NULL; } -- 1.8.3.1 Thanks for resend Bill Patch Looks Good. Acked-by: Himanshu Madhani
Re: [PATCH] scsi: qla2xxx: replace snprintf with strscpy
On 8/14/19, 10:25 AM, "linux-scsi-ow...@vger.kernel.org on behalf of Bart Van Assche" wrote: On 7/24/19 10:46 PM, Wang Xiayang wrote: > As commit a86028f8e3ee ("staging: most: sound: replace snprintf > with strscpy") suggested, using snprintf without a format specifier > is potentially risky if a0->vendor_name or a0->vendor_pn mistakenly > contain format specifiers. In addition, as compared in the > implementation, strscpy looks more light-weight than snprintf. > > This patch does not incur any functional change. > > Signed-off-by: Wang Xiayang > --- > 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 4059655639d9..068b54218ff4 100644 > --- a/drivers/scsi/qla2xxx/qla_init.c > +++ b/drivers/scsi/qla2xxx/qla_init.c > @@ -3461,12 +3461,12 @@ static void qla2xxx_print_sfp_info(struct scsi_qla_host *vha) > int leftover, len; > > memset(str, 0, STR_LEN); > - snprintf(str, SFF_VEN_NAME_LEN+1, a0->vendor_name); > + strscpy(str, a0->vendor_name, SFF_VEN_NAME_LEN+1); > ql_dbg(ql_dbg_init, vha, 0x015a, > "SFP MFG Name: %s\n", str); > > memset(str, 0, STR_LEN); > - snprintf(str, SFF_PART_NAME_LEN+1, a0->vendor_pn); > + strscpy(str, a0->vendor_pn, SFF_PART_NAME_LEN+1); > ql_dbg(ql_dbg_init, vha, 0x015c, > "SFP Part Name: %s\n", str); From qla_def.h: /* Refer to SNIA SFF 8247 */ struct sff_8247_a0 { [ ... ] u8 vendor_name[SFF_VEN_NAME_LEN]; /* offset 20/14h */ u8 vendor_pn[SFF_PART_NAME_LEN];/* part number */ So I think that using SFF_PART_NAME_LEN+1 as length limit is wrong. Himanshu, do you perhaps know whether or not the vendor_name and vendor_pn arrays should be '\0'-terminated in struct sff_8247_a0? Hi Bart, Since the data is coming from firmware itself so it's not \0 terminated. So yes the array should be terminated with \0. Thanks, Himanshu Thanks, Bart.
[Bug 204119] scsi_mod: Could not allocate 4104 bytes percpu data
https://bugzilla.kernel.org/show_bug.cgi?id=204119 --- Comment #10 from Bart Van Assche (bvanass...@acm.org) --- This patch has been accepted in Martin's tree as commit dccc96abfb21 ("scsi: core: Reduce memory required for SCSI logging") and is on its way to kernel v5.4. If you need that patch in kernel v5.2 soon and if you cannot compile the kernel yourself then only your Linux distributor can help you. -- You are receiving this mail because: You are the assignee for the bug.
TODAY, Wed, Aug 14, 2019 I AM READY FOR COMING TO YOUR ADDRESS WITH THIS ATM CARD
ATTN DEAR PARCEL BENEFICIARY. I AM CATHY JONES,DIPLOMATIC AGENT ASIGNED ON THE DELIVERY OF YOUR ATM CARD THROUGH MS. MARYANNA B. THOMASON, DHL MANAGEMENT DIRECTOR NEW YORK. TODAY, Wed, Aug 14, 2019 I AM READY FOR COMING TO YOUR ADDRESS WITH THIS ATM CARD, So before i deliver I want you to send me. official diplomatic agent delivery fee sum of $150.00 us only. I am here at JFK Airport,Florida. USA SEND THIS FEE BY WESTERN UNION OR MONEY WITH RECEIVER'S NAME AND ADDRESS BELOW. RECEIVER'S NAME-ERROL PRINGLE ADDRESS3500 OLD DENTON RD APT 208; CARROLLTON, TEXAS 75007 COUNTRYUSA AMOUNT$150.00 ONLY TEST QUESTIONWHO IS THE CREATOR ANSWER--GOD meanwhile this $150.00 is required by the Custom Service,USA Homeland Security,for protection of your delivery, it will make the ATM CARD and funds worth $15.8MILLION US DOLLARS secure, Beleiev me, this is my word, remark my word,you will receive your delivery from me, Mrs. Cathy Jones once you send this only $150.00 today. I WAIT ON YOUR PAYMENT CONFIRMATION, ONCE I GOT YOUR PAYMENT, I WILL FINALLY ARRIVE TO YOUR NEAREST ADDRESS. today THANKS AND MAY GOD BLESS YOU CATHY JONES,DIPLOMATIC AGENT EMAIL; katerinejone...@gmail.com CALL OR TEXT ME, DIPLOMATIC AGENT MS. CATHY JONES Phone Number; (408) 650-6103,
Re: [EXT] [PATCH v2 0/2] scsi: qla2xxx: fixes for FW trace/dump buffers
Hi Martin W, On 8/14/19, 8:52 AM, "Martin Wilck" wrote: External Email -- From: Martin Wilck Hi Himanshu, hi Martin, Please consider this series for merging. The first patch of the series is a fix for a memory corruption we saw in a test where qla2xxx was loaded/unloaded repeatedly under memory pressure. The second one is a cleanup/consistency fix. Regards, Martin Changes in v2: rather then keeping the patches small, cleanup the buffer allocation code properly, following (and going beyond) Hannes' review suggestions for the v1 set. Martin Wilck (2): scsi: qla2xxx: qla2x00_alloc_fw_dump: set ha->eft scsi: qla2xxx: cleanup trace buffer initialization drivers/scsi/qla2xxx/qla_init.c | 218 +++- drivers/scsi/qla2xxx/qla_os.c | 1 + 2 files changed, 102 insertions(+), 117 deletions(-) -- 2.22.0 Thanks for the series. We recently also observed similar issue on upstream kernel with load/unload script and I tested your series and did not see this issue. Tested-by: Himanshu Madhani Reviewed-by: Himanshu Madhani Thanks, Himanshu
[PATCH 20/42] 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 --- 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 } -- 2.13.7
[PATCH 03/42] 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 --- 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 { -- 2.13.7
[PATCH 19/42] 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 --- 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 90181afe0e28..7ac6508b7ed8 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -7196,16 +7196,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 fcc1c45f2d35..84a77faed114 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -11702,6 +11702,15 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) } } + /* 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))) -- 2.13.7
[PATCH 01/42] 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 64MBs. Totals are well over 100MBs for a single shost. Given kdump memory auto-sizing utilities don't accommodate this amount of memory well, its 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 --- 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 1ac98becb5ba..02231370428a 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 @@ -8309,6 +8310,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 = -- 2.13.7
[PATCH 17/42] 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 --- 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 6360683417b8..a47db99784ab 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
[PATCH 14/42] 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 --- 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 @@ -1207,6 +1207,39 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *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. * @ndlp: pointer to a node-list 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, &pri
[PATCH 16/42] 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 --- 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)) { -- 2.13.7
[PATCH 11/42] 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 --- 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); -- 2.13.7
[PATCH 04/42] 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 --- 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 02231370428a..50d641f65af9 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -6415,6 +6415,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 */ @@ -6998,12 +7003,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; } -- 2.13.7
[PATCH 22/42] 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 --- 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 a47db99784ab..44e779e4c885 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, ifla
[PATCH 25/42] 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 --- 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 c580d512a3db..98db1f7e536e 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-
[PATCH 18/42] 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 --- 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 33c8bae49821..90181afe0e28 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -6859,10 +6859,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 } /** -- 2.13.7
[PATCH 24/42] 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 dm1 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 --- 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;
[PATCH 10/42] lpfc: Fix issuing init_vpi mbox on SLI-3 card
The driver is inadvertantly 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 --- 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, -- 2.13.7
[PATCH 21/42] 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 --- 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, -- 2.13.7
[PATCH 09/42] 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 --- 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", -- 2.13.7
[PATCH 42/42] 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 --- 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 */ -- 2.13.7
[PATCH 39/42] 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 --- 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 bade2e025ecf..856a468d9b7d 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_SIZE256 +#define LPFC_MAX_SG_TABLESIZE 0x #define LPFC_MIN_SG_SLI4_BUF_SZ0x800 /* 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; @@ -905,6 +908,7 @@ struct lpfc_hba { wait_queue_head_twork_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 */ @@ -987,6 +991,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
[PATCH 06/42] 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 --- 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 504f56a99b20..3e128ea01dc0 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); -- 2.13.7
[PATCH 13/42] 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 --- 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 72353c9c0fa9..fcc1c45f2d35 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -8878,7 +8878,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 */ @@ -10725,7 +10725,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; @@ -10767,8 +10767,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; @@ -10826,17 +10826,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); } } @@ -10950,69 +10950,103 @@ lpfc_cpu_affinity_check(struct lpfc_hba *phba, int vectors) } } + /* 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, + " 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 wi
[PATCH 00/42] lpfc: Update lpfc to revision 12.4.0.0
Update lpfc to revision 12.4.0.0 This patch set contains a laundry list of fixes for lpfc. Most are small. There are a couple of cleanup patches and several functional additions at the tail of the patch set. The patches were cut against Martin's 5.4/scsi-queue tree James Smart (42): lpfc: Limit xri count for kdump environment lpfc: Fix PLOGI failure with high remoteport count lpfc: Fix ELS field alignments lpfc: Fix crash on driver unload in wq free lpfc: Fix failure to clear non-zero eq_delay after io rate reduction lpfc: Fix leak of ELS completions on adapter reset lpfc: Fix port relogin failure due to GID_FT interaction lpfc: Fix discovery when target has no GID_FT information lpfc: Fix ADISC reception terminating login state if a NVME target lpfc: Fix issuing init_vpi mbox on SLI-3 card lpfc: Fix Oops in nvme_register with target logout/login lpfc: Fix irq raising in lpfc_sli_hba_down lpfc: Fix oops when fewer hdwqs than cpus lpfc: Fix FLOGI handling across multiple link up/down conditions lpfc: Fix null ptr oops updating lpfc_devloss_tmo via sysfs attribute lpfc: Fix devices that don't return after devloss followed by rediscovery lpfc: Fix loss of remote port after devloss due to lack of RPIs lpfc: Fix propagation of devloss_tmo setting to nvme transport lpfc: Fix sg_seg_cnt for HBAs that don't support NVME lpfc: Fix driver nvme rescan logging lpfc: Fix error in remote port address change lpfc: Fix deadlock on host_lock during cable pulls lpfc: Fix crash due to port reset racing vs adapter error handling lpfc: Fix too many sg segments spamming in kernel log lpfc: Fix hang when downloading fw on port enabled for nvme lpfc: Fix nvme target mode ABTSing a received ABTS lpfc: Fix nvme sg_seg_cnt display if HBA does not support NVME lpfc: Fix sli4 adapter initialization with MSI lpfc: Fix upcall to bsg done in non-success cases lpfc: Fix Max Frame Size value shown in fdmishow output lpfc: Fix reported physical link speed on a disabled trunked link lpfc: Fix BlockGuard enablement on FCoE adapters lpfc: Fix nvme first burst module parameter description lpfc: Fix coverity warnings lpfc: Add simple unlikely optimizations to reduce NVME latency lpfc: Migrate to %px and %pf in kernel print calls lpfc: Add first and second level hardware revisions to sysfs reporting lpfc: Add MDS driver loopback diagnostics support lpfc: Support dynamic unbounded SGL lists on G7 hardware. lpfc: Add NVMe sequence level error recovery support lpfc: Merge per-protocol WQ/CQ pairs into single per-cpu pair lpfc: Update lpfc version to 12.4.0.0 drivers/scsi/lpfc/lpfc.h | 9 +- drivers/scsi/lpfc/lpfc_attr.c | 76 +++- drivers/scsi/lpfc/lpfc_bsg.c | 24 +- drivers/scsi/lpfc/lpfc_crtn.h | 3 +- drivers/scsi/lpfc/lpfc_ct.c| 68 ++- drivers/scsi/lpfc/lpfc_debugfs.c | 96 + drivers/scsi/lpfc/lpfc_debugfs.h | 61 +-- drivers/scsi/lpfc/lpfc_disc.h | 3 + drivers/scsi/lpfc/lpfc_els.c | 116 - drivers/scsi/lpfc/lpfc_hbadisc.c | 176 +--- drivers/scsi/lpfc/lpfc_hw.h| 6 +- drivers/scsi/lpfc/lpfc_hw4.h | 34 ++ drivers/scsi/lpfc/lpfc_init.c | 857 +++-- drivers/scsi/lpfc/lpfc_mem.c | 44 +- drivers/scsi/lpfc/lpfc_nportdisc.c | 43 +- drivers/scsi/lpfc/lpfc_nvme.c | 389 ++--- drivers/scsi/lpfc/lpfc_nvmet.c | 28 +- drivers/scsi/lpfc/lpfc_scsi.c | 512 -- drivers/scsi/lpfc/lpfc_sli.c | 529 +-- drivers/scsi/lpfc/lpfc_sli.h | 11 +- drivers/scsi/lpfc/lpfc_sli4.h | 47 +- drivers/scsi/lpfc/lpfc_version.h | 2 +- drivers/scsi/lpfc/lpfc_vport.c | 8 +- 23 files changed, 1965 insertions(+), 1177 deletions(-) -- 2.13.7
[PATCH 15/42] 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 --- 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 8d8c495b5b60..33c8bae49821 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 } -- 2.13.7
[PATCH 40/42] 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 --- 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 856a468d9b7d..8fb43169a445 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_tnlp_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 0x0001 #define cfg_bv1s_WORD word19 +#define cfg_nsler_SHIFT 12 +#define cfg_nsler_MASK 0x0001 +#define cfg_nsler_WORD word19 + uint32_t word20; #define cfg_max_tow_xri_SHIFT 0 #define cfg_max_tow_xri_MASK 0x @@ -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 0x0001 @@ -4637,6 +4642,9 @@ struct lpfc_nvme_prli { #define prli_conf_SHIFT 7 #define prli_conf_MASK 0x0001 #define prli_conf_WORD word4 +#define prli_nsler_SHIFT 8 +#define prli_nsler_MASK0x0001 +#define prli_nsler_WORDword4 uint32_t word5; #define prli_fb_sz_SHIFT0 #define prli_fb_sz_MASK 0x diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 35faaf915c6a..7e620c0b5b4a 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -11867,6 +11867,14 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) 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/lp
[PATCH 26/42] 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 --- 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; -- 2.13.7
[PATCH 28/42] 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 --- 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 1e43890f9ae1..7227bd46244d 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -11140,10 +11140,10 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba) * @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 @@ -11154,20 +11154,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; -- 2.13.7
[PATCH 23/42] 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 --- 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 84a77faed114..c580d512a3db 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 058c092bda73..ca6988ae8924 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); -- 2.13.7
[PATCH 07/42] 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 --- 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; } -- 2.13.7
[PATCH 33/42] 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 --- 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 63e631f116e4..a851bf557dba 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 -- 2.13.7
[PATCH 05/42] 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 --- 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 50d641f65af9..72353c9c0fa9 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; -- 2.13.7
[PATCH 31/42] 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 --- 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 44e779e4c885..95db23adc96d 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; -- 2.13.7
[PATCH 30/42] 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 --- 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); -- 2.13.7
[PATCH 12/42] 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 --- 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 3e128ea01dc0..52704e709925 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 */ -- 2.13.7
[PATCH 32/42] 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 --- 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 7ac6508b7ed8..63e631f116e4 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -7080,6 +7080,21 @@ struct fc_function_template lpfc_vport_transport_functions = { }; /** + * 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. **/ @@ -7135,8 +7150,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); -- 2.13.7
[PATCH 27/42] 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 --- 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 98db1f7e536e..1e43890f9ae1 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -11697,6 +11697,7 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) 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)) -- 2.13.7
[PATCH 29/42] 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 --- 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 c7f66239ca70..9b9858078076 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -5449,7 +5449,9 @@ lpfc_bsg_get_ras_config(struct bsg_job *job) 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; } @@ -5528,8 +5530,9 @@ lpfc_bsg_set_ras_config(struct bsg_job *job) 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; } @@ -5589,7 +5592,9 @@ lpfc_bsg_get_ras_lwpd(struct bsg_job *job) 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; } @@ -5671,7 +5676,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; } @@ -5742,8 +5749,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; } -- 2.13.7
[PATCH 36/42] 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 --- 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 9b9858078076..9966588ef3b2 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 & 0x); 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
[PATCH 08/42] 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 --- 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; -- 2.13.7
[PATCH 38/42] 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 --- 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 f4f1291ec1ba..491a999056aa 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -5925,7 +5925,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 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, 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 0x #define wqe_rcvoxid_WORD word9 +#define wqe_sof_SHIFT 24 +#define wqe_sof_MASK 0x00FF +#define wqe_sof_WORD word9 +#define wqe_eof_SHIFT 16 +#define wqe_eof_MASK 0x00FF +#define wqe_eof_WORD word9 uint32_t word10; #define wqe_ebde_cnt_SHIFT0 #define wqe_ebde_cnt_MASK 0x000f diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index efa602592728..6e8b03f38fac 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_
[PATCH 35/42] 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 --- 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 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, 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); -- 2.13.7
[PATCH 02/42] 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 --- 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 0x0001 /* Rcvd rscn before we cmpl reg login */ #define NLP_REG_LOGIN_SEND 0x0002 /* sent reglogin to adapter */ +#define NLP_RELEASE_RPI0x0004 /* Release RPI to free pool */ #define NLP_SUPPRESS_RSP 0x0010 /* Remote NPort supports suppress rsp */ #define NLP_PLOGI_SND 0x0020 /* sent PLOGI request for this entry */ #define NLP_PRLI_SND 0x0040 /* sent PRLI request for this entry */ diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 28ecaa7fc715..6360683417b8 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; @@ -6200,8 +6206,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 f9e6a135d656..504f56a99b20 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; } } -- 2.13.7
[PATCH 37/42] 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 --- 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 a851bf557dba..f4f1291ec1ba 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); } /** -- 2.13.7
[PATCH 34/42] 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 --- 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 6ac6620aab00..0142545873a5 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)); -- 2.13.7
[PATCH 41/42] 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 --- 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 8fb43169a445..73540bb13b3e 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -734,14 +734,13 @@ struct lpfc_hba { #define HBA_AER_ENABLED0x1000 /* 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 0x1 /* Skips fn reset before FW dump */ #define HBA_RECOVERABLE_UE 0x2 /* Firmware supports recoverable UE */ #define HBA_FORCED_LINK_SPEED 0x4 /* * Firmware supports Forced Link Speed * capability */ -#define HBA_NVME_IOQ_FLUSH 0x8 /* NVME IO queues flushed. */ #define HBA_FLOGI_ISSUED 0x10 /* 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
Re: [PATCH RESEND] qla2xxx: Fix gnl.l memory leak on adapter init failure
Bill, > If HBA initialization fails unexpectedly (exiting via probe_failed:), > we may fail to free vha->gnl.l. So that we don't attempt to double > free, set this pointer to NULL after a free and check for NULL at > probe_failed: so we know whether or not to call dma_free_coherent. Applied to 5.3/scsi-fixes, thanks! -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH v2] tcmu: avoid use-after-free after command timeout
Dmitry, > In tcmu_handle_completion() function, the variable called read_len is > always initialized with a value taken from se_cmd structure. If this > function is called to complete an expired (timed out) out command, the > session command pointed by se_cmd is likely to be already deallocated > by the target core at that moment. As the result, this access triggers > a use-after-free warning from KASAN. Applied to 5.3/scsi-fixes, thanks! -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH v2 0/2] scsi: qla2xxx: fixes for FW trace/dump buffers
Martin, > The first patch of the series is a fix for a memory corruption we > saw in a test where qla2xxx was loaded/unloaded repeatedly under > memory pressure. The second one is a cleanup/consistency fix. Applied to 5.4/scsi-queue, thanks! -- Martin K. Petersen Oracle Linux Engineering
[PATCH v5 00/18] compat_ioctl.c removal, part 2/3
This is a follow-up to part 1/3 that I posted after -rc2. I hope these are still largely uncontroversial changes, and I would like to get them into linux-5.4. Part 1 was in https://lore.kernel.org/lkml/capcyv4i_nhzv155rcgnaq189aq2lfd2g8pa1d5nbzqo9e_u...@mail.gmail.com/ Part 3 will be one kernel release after part 2 is merged, as that still needs a little extra work. The entire series is available at git://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground.git compat_ioctl Arnd Al Viro (2): compat_ioctl: unify copy-in of ppp filters compat_ioctl: move PPPIOCSCOMPRESS to ppp_generic Arnd Bergmann (16): xfs: compat_ioctl: use compat_ptr() xfs: compat_ioctl: add missing conversions gfs2: add compat_ioctl support fs: compat_ioctl: move FITRIM emulation into file systems watchdog: cpwd: use generic compat_ptr_ioctl compat_ioctl: move WDIOC handling into wdt drivers compat_ioctl: reimplement SG_IO handling af_unix: add compat_ioctl support compat_ioctl: handle SIOCOUTQNSD compat_ioctl: move SIOCOUTQ out of compat_ioctl.c tty: handle compat PPP ioctls compat_ioctl: handle PPPIOCGIDLE for 64-bit time_t compat_ioctl: ppp: move simple commands into ppp_generic.c compat_ioctl: move SG_GET_REQUEST_TABLE handling pktcdvd: add compat_ioctl handler scsi: sd: enable compat ioctls for sed-opal Documentation/networking/ppp_generic.txt | 2 + arch/powerpc/platforms/52xx/mpc52xx_gpt.c | 1 + arch/um/drivers/harddog_kern.c| 1 + block/scsi_ioctl.c| 132 - drivers/block/pktcdvd.c | 25 ++ drivers/char/ipmi/ipmi_watchdog.c | 1 + drivers/hwmon/fschmd.c| 1 + drivers/net/ppp/ppp_generic.c | 245 ++- drivers/rtc/rtc-ds1374.c | 1 + drivers/scsi/sd.c | 14 +- drivers/scsi/sg.c | 59 +++- drivers/tty/tty_io.c | 5 + drivers/watchdog/acquirewdt.c | 1 + drivers/watchdog/advantechwdt.c | 1 + drivers/watchdog/alim1535_wdt.c | 1 + drivers/watchdog/alim7101_wdt.c | 1 + drivers/watchdog/ar7_wdt.c| 1 + drivers/watchdog/at91rm9200_wdt.c | 1 + drivers/watchdog/ath79_wdt.c | 1 + drivers/watchdog/bcm63xx_wdt.c| 1 + drivers/watchdog/cpu5wdt.c| 1 + drivers/watchdog/cpwd.c | 25 +- drivers/watchdog/eurotechwdt.c| 1 + drivers/watchdog/f71808e_wdt.c| 1 + drivers/watchdog/gef_wdt.c| 1 + drivers/watchdog/geodewdt.c | 1 + drivers/watchdog/ib700wdt.c | 1 + drivers/watchdog/ibmasr.c | 1 + drivers/watchdog/indydog.c| 1 + drivers/watchdog/intel_scu_watchdog.c | 1 + drivers/watchdog/iop_wdt.c| 1 + drivers/watchdog/it8712f_wdt.c| 1 + drivers/watchdog/ixp4xx_wdt.c | 1 + drivers/watchdog/ks8695_wdt.c | 1 + drivers/watchdog/m54xx_wdt.c | 1 + drivers/watchdog/machzwd.c| 1 + drivers/watchdog/mixcomwd.c | 1 + drivers/watchdog/mtx-1_wdt.c | 1 + drivers/watchdog/mv64x60_wdt.c| 1 + drivers/watchdog/nuc900_wdt.c | 1 + drivers/watchdog/nv_tco.c | 1 + drivers/watchdog/pc87413_wdt.c| 1 + drivers/watchdog/pcwd.c | 1 + drivers/watchdog/pcwd_pci.c | 1 + drivers/watchdog/pcwd_usb.c | 1 + drivers/watchdog/pika_wdt.c | 1 + drivers/watchdog/pnx833x_wdt.c| 1 + drivers/watchdog/rc32434_wdt.c| 1 + drivers/watchdog/rdc321x_wdt.c| 1 + drivers/watchdog/riowd.c | 1 + drivers/watchdog/sa1100_wdt.c | 1 + drivers/watchdog/sb_wdog.c| 1 + drivers/watchdog/sbc60xxwdt.c | 1 + drivers/watchdog/sbc7240_wdt.c| 1 + drivers/watchdog/sbc_epx_c3.c | 1 + drivers/watchdog/sbc_fitpc2_wdt.c | 1 + drivers/watchdog/sc1200wdt.c | 1 + drivers/watchdog/sc520_wdt.c | 1 + drivers/watchdog/sch311x_wdt.c| 1 + drivers/watchdog/scx200_wdt.c | 1 + drivers/watchdog/smsc37b787_wdt.c | 1 + drivers/watchdog/w83877f_wdt.c| 1 + drivers/watchdog/w83977f_wdt.c| 1 + drivers/watchdog/wafer5823wdt.c | 1 + drivers/watchdog/watchdog_dev.c | 1 + drivers/watchdog/wdrtas.c | 1 + drivers/watchdog/wdt.c| 1 + drivers/watchdog/wdt285.c | 1 + drivers/watchdog/wdt977.c | 1 + drivers/watchdog/wdt_pci.c| 1 + fs/compat_ioctl.c | 346