[PATCH 6.1 24/64] scsi: qla2xxx: Reduce fabric scan duplicate code

Greg Kroah-Hartman
2026-02-17T20:46:19Z

From: Quinn Tran <qutran@marvell.com>

[ Upstream commit beafd692461443e0fb1d61aa56886bf85ef6f5e4 ]

For fabric scan, current code uses switch scan opcode and flags as the
method to iterate through different commands to carry out the process.
This makes it hard to read. This patch convert those opcode and flags into
steps. In addition, this help reduce some duplicate code.

Consolidate routines that handle GPNFT & GNNFT.

Cc: stable@vger.kernel.org
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://lore.kernel.org/r/20240710171057.35066-10-njavali@marvell.com
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Stable-dep-of: 7adbd2b78090 ("scsi: qla2xxx: Free sp in error path to fix system crash")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/scsi/qla2xxx/qla_def.h | 14 +
drivers/scsi/qla2xxx/qla_gbl.h | 6
drivers/scsi/qla2xxx/qla_gs.c | 432 ++++++++++++++++------------------------
drivers/scsi/qla2xxx/qla_init.c | 5
drivers/scsi/qla2xxx/qla_os.c | 12 -
5 files changed, 200 insertions(+), 269 deletions(-)

--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3273,11 +3273,20 @@ struct fab_scan_rp {
u8 node_name[8];
};

+enum scan_step {
+ FAB_SCAN_START,
+ FAB_SCAN_GPNFT_FCP,
+ FAB_SCAN_GNNFT_FCP,
+ FAB_SCAN_GPNFT_NVME,
+ FAB_SCAN_GNNFT_NVME,
+};
+
struct fab_scan {
struct fab_scan_rp *l;
u32 size;
u32 rscn_gen_start;
u32 rscn_gen_end;
+ enum scan_step step;
u16 scan_retry;
#define MAX_SCAN_RETRIES 5
enum scan_flags_t scan_flags;
@@ -3503,9 +3512,8 @@ enum qla_work_type {
QLA_EVT_RELOGIN,
QLA_EVT_ASYNC_PRLO,
QLA_EVT_ASYNC_PRLO_DONE,
- QLA_EVT_GPNFT,
- QLA_EVT_GPNFT_DONE,
- QLA_EVT_GNNFT_DONE,
+ QLA_EVT_SCAN_CMD,
+ QLA_EVT_SCAN_FINISH,
QLA_EVT_GFPNID,
QLA_EVT_SP_RETRY,
QLA_EVT_IIDMA,
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -736,9 +736,9 @@ void qla24xx_handle_gpsc_event(scsi_qla_
int qla2x00_mgmt_svr_login(scsi_qla_host_t *);
void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea);
int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport, bool);
-int qla24xx_async_gpnft(scsi_qla_host_t *, u8, srb_t *);
-void qla24xx_async_gpnft_done(scsi_qla_host_t *, srb_t *);
-void qla24xx_async_gnnft_done(scsi_qla_host_t *, srb_t *);
+int qla_fab_async_scan(scsi_qla_host_t *, srb_t *);
+void qla_fab_scan_start(struct scsi_qla_host *);
+void qla_fab_scan_finish(scsi_qla_host_t *, srb_t *);
int qla24xx_post_gfpnid_work(struct scsi_qla_host *, fc_port_t *);
int qla24xx_async_gfpnid(scsi_qla_host_t *, fc_port_t *);
void qla24xx_handle_gfpnid_event(scsi_qla_host_t *, struct event_arg *);
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3488,7 +3488,7 @@ static bool qla_ok_to_clear_rscn(scsi_ql
return true;
}

-void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
+void qla_fab_scan_finish(scsi_qla_host_t *vha, srb_t *sp)
{
fc_port_t *fcport;
u32 i, rc;
@@ -3700,14 +3700,11 @@ out:
}
}

-static int qla2x00_post_gnnft_gpnft_done_work(struct scsi_qla_host *vha,
+static int qla2x00_post_next_scan_work(struct scsi_qla_host *vha,
srb_t *sp, int cmd)
{
struct qla_work_evt *e;

- if (cmd != QLA_EVT_GPNFT_DONE && cmd != QLA_EVT_GNNFT_DONE)
- return QLA_PARAMETER_ERROR;
-
e = qla2x00_alloc_work(vha, cmd);
if (!e)
return QLA_FUNCTION_FAILED;
@@ -3717,37 +3714,15 @@ static int qla2x00_post_gnnft_gpnft_done
return qla2x00_post_work(vha, e);
}

-static int qla2x00_post_nvme_gpnft_work(struct scsi_qla_host *vha,
- srb_t *sp, int cmd)
-{
- struct qla_work_evt *e;
-
- if (cmd != QLA_EVT_GPNFT)
- return QLA_PARAMETER_ERROR;
-
- e = qla2x00_alloc_work(vha, cmd);
- if (!e)
- return QLA_FUNCTION_FAILED;
-
- e->u.gpnft.fc4_type = FC4_TYPE_NVME;
- e->u.gpnft.sp = sp;
-
- return qla2x00_post_work(vha, e);
-}
-
static void qla2x00_find_free_fcp_nvme_slot(struct scsi_qla_host *vha,
struct srb *sp)
{
struct qla_hw_data *ha = vha->hw;
int num_fibre_dev = ha->max_fibre_devices;
- struct ct_sns_req *ct_req =
- (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
struct ct_sns_gpnft_rsp *ct_rsp =
(struct ct_sns_gpnft_rsp *)sp->u.iocb_cmd.u.ctarg.rsp;
struct ct_sns_gpn_ft_data *d;
struct fab_scan_rp *rp;
- u16 cmd = be16_to_cpu(ct_req->command);
- u8 fc4_type = sp->gen2;
int i, j, k;
port_id_t id;
u8 found;
@@ -3766,85 +3741,83 @@ static void qla2x00_find_free_fcp_nvme_s
if (id.b24 == 0 || wwn == 0)
continue;

- if (fc4_type == FC4_TYPE_FCP_SCSI) {
- if (cmd == GPN_FT_CMD) {
- rp = &vha->scan.l[j];
- rp->id = id;
- memcpy(rp->port_name, d->port_name, 8);
- j++;
- rp->fc4type = FS_FC4TYPE_FCP;
- } else {
- for (k = 0; k < num_fibre_dev; k++) {
- rp = &vha->scan.l[k];
- if (id.b24 == rp->id.b24) {
- memcpy(rp->node_name,
- d->port_name, 8);
- break;
- }
+ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2025,
+ "%s %06x %8ph \n",
+ __func__, id.b24, d->port_name);
+
+ switch (vha->scan.step) {
+ case FAB_SCAN_GPNFT_FCP:
+ rp = &vha->scan.l[j];
+ rp->id = id;
+ memcpy(rp->port_name, d->port_name, 8);
+ j++;
+ rp->fc4type = FS_FC4TYPE_FCP;
+ break;
+ case FAB_SCAN_GNNFT_FCP:
+ for (k = 0; k < num_fibre_dev; k++) {
+ rp = &vha->scan.l[k];
+ if (id.b24 == rp->id.b24) {
+ memcpy(rp->node_name,
+ d->port_name, 8);
+ break;
}
}
- } else {
- /* Search if the fibre device supports FC4_TYPE_NVME */
- if (cmd == GPN_FT_CMD) {
- found = 0;
+ break;
+ case FAB_SCAN_GPNFT_NVME:
+ found = 0;

- for (k = 0; k < num_fibre_dev; k++) {
- rp = &vha->scan.l[k];
- if (!memcmp(rp->port_name,
- d->port_name, 8)) {
- /*
- * Supports FC-NVMe & FCP
- */
- rp->fc4type |= FS_FC4TYPE_NVME;
- found = 1;
- break;
- }
+ for (k = 0; k < num_fibre_dev; k++) {
+ rp = &vha->scan.l[k];
+ if (!memcmp(rp->port_name, d->port_name, 8)) {
+ /*
+ * Supports FC-NVMe & FCP
+ */
+ rp->fc4type |= FS_FC4TYPE_NVME;
+ found = 1;
+ break;
}
+ }

- /* We found new FC-NVMe only port */
- if (!found) {
- for (k = 0; k < num_fibre_dev; k++) {
- rp = &vha->scan.l[k];
- if (wwn_to_u64(rp->port_name)) {
- continue;
- } else {
- rp->id = id;
- memcpy(rp->port_name,
- d->port_name, 8);
- rp->fc4type =
- FS_FC4TYPE_NVME;
- break;
- }
- }
- }
- } else {
+ /* We found new FC-NVMe only port */
+ if (!found) {
for (k = 0; k < num_fibre_dev; k++) {
rp = &vha->scan.l[k];
- if (id.b24 == rp->id.b24) {
- memcpy(rp->node_name,
- d->port_name, 8);
+ if (wwn_to_u64(rp->port_name)) {
+ continue;
+ } else {
+ rp->id = id;
+ memcpy(rp->port_name, d->port_name, 8);
+ rp->fc4type = FS_FC4TYPE_NVME;
break;
}
}
}
+ break;
+ case FAB_SCAN_GNNFT_NVME:
+ for (k = 0; k < num_fibre_dev; k++) {
+ rp = &vha->scan.l[k];
+ if (id.b24 == rp->id.b24) {
+ memcpy(rp->node_name, d->port_name, 8);
+ break;
+ }
+ }
+ break;
+ default:
+ break;
}
}
}

-static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res)
+static void qla_async_scan_sp_done(srb_t *sp, int res)
{
struct scsi_qla_host *vha = sp->vha;
- struct ct_sns_req *ct_req =
- (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
- u16 cmd = be16_to_cpu(ct_req->command);
- u8 fc4_type = sp->gen2;
unsigned long flags;
int rc;

/* gen2 field is holding the fc4type */
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Async done-%s res %x FC4Type %x\n",
- sp->name, res, sp->gen2);
+ ql_dbg(ql_dbg_disc, vha, 0x2026,
+ "Async done-%s res %x step %x\n",
+ sp->name, res, vha->scan.step);

sp->rc = res;
if (res) {
@@ -3868,8 +3841,7 @@ static void qla2x00_async_gpnft_gnnft_sp
* sp for GNNFT_DONE work. This will allow all
* the resource to get freed up.
*/
- rc = qla2x00_post_gnnft_gpnft_done_work(vha, sp,
- QLA_EVT_GNNFT_DONE);
+ rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_FINISH);
if (rc) {
/* Cleanup here to prevent memory leak */
qla24xx_sp_unmap(vha, sp);
@@ -3894,28 +3866,30 @@ static void qla2x00_async_gpnft_gnnft_sp

qla2x00_find_free_fcp_nvme_slot(vha, sp);

- if ((fc4_type == FC4_TYPE_FCP_SCSI) && vha->flags.nvme_enabled &&
- cmd == GNN_FT_CMD) {
- spin_lock_irqsave(&vha->work_lock, flags);
- vha->scan.scan_flags &= ~SF_SCANNING;
- spin_unlock_irqrestore(&vha->work_lock, flags);
-
- sp->rc = res;
- rc = qla2x00_post_nvme_gpnft_work(vha, sp, QLA_EVT_GPNFT);
- if (rc) {
- qla24xx_sp_unmap(vha, sp);
- set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
- set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
- }
- return;
- }
+ spin_lock_irqsave(&vha->work_lock, flags);
+ vha->scan.scan_flags &= ~SF_SCANNING;
+ spin_unlock_irqrestore(&vha->work_lock, flags);

- if (cmd == GPN_FT_CMD) {
- rc = qla2x00_post_gnnft_gpnft_done_work(vha, sp,
- QLA_EVT_GPNFT_DONE);
- } else {
- rc = qla2x00_post_gnnft_gpnft_done_work(vha, sp,
- QLA_EVT_GNNFT_DONE);
+ switch (vha->scan.step) {
+ case FAB_SCAN_GPNFT_FCP:
+ case FAB_SCAN_GPNFT_NVME:
+ rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_CMD);
+ break;
+ case FAB_SCAN_GNNFT_FCP:
+ if (vha->flags.nvme_enabled)
+ rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_CMD);
+ else
+ rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_FINISH);
+
+ break;
+ case FAB_SCAN_GNNFT_NVME:
+ rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_FINISH);
+ break;
+ default:
+ /* should not be here */
+ WARN_ON(1);
+ rc = QLA_FUNCTION_FAILED;
+ break;
}

if (rc) {
@@ -3926,127 +3900,16 @@ static void qla2x00_async_gpnft_gnnft_sp
}
}

-/*
- * Get WWNN list for fc4_type
- *
- * It is assumed the same SRB is re-used from GPNFT to avoid
- * mem free & re-alloc
- */
-static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
- u8 fc4_type)
-{
- int rval = QLA_FUNCTION_FAILED;
- struct ct_sns_req *ct_req;
- struct ct_sns_pkt *ct_sns;
- unsigned long flags;
-
- if (!vha->flags.online) {
- spin_lock_irqsave(&vha->work_lock, flags);
- vha->scan.scan_flags &= ~SF_SCANNING;
- spin_unlock_irqrestore(&vha->work_lock, flags);
- goto done_free_sp;
- }
-
- if (!sp->u.iocb_cmd.u.ctarg.req || !sp->u.iocb_cmd.u.ctarg.rsp) {
- ql_log(ql_log_warn, vha, 0xffff,
- "%s: req %p rsp %p are not setup\n",
- __func__, sp->u.iocb_cmd.u.ctarg.req,
- sp->u.iocb_cmd.u.ctarg.rsp);
- spin_lock_irqsave(&vha->work_lock, flags);
- vha->scan.scan_flags &= ~SF_SCANNING;
- spin_unlock_irqrestore(&vha->work_lock, flags);
- WARN_ON(1);
- set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
- set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
- goto done_free_sp;
- }
-
- ql_dbg(ql_dbg_disc, vha, 0xfffff,
- "%s: FC4Type %x, CT-PASSTHRU %s command ctarg rsp size %d, ctarg req size %d\n",
- __func__, fc4_type, sp->name, sp->u.iocb_cmd.u.ctarg.rsp_size,
- sp->u.iocb_cmd.u.ctarg.req_size);
-
- sp->type = SRB_CT_PTHRU_CMD;
- sp->name = "gnnft";
- sp->gen1 = vha->hw->base_qpair->chip_reset;
- sp->gen2 = fc4_type;
- qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
- qla2x00_async_gpnft_gnnft_sp_done);
-
- memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);
- memset(sp->u.iocb_cmd.u.ctarg.req, 0, sp->u.iocb_cmd.u.ctarg.req_size);
-
- ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
- /* CT_IU preamble */
- ct_req = qla2x00_prep_ct_req(ct_sns, GNN_FT_CMD,
- sp->u.iocb_cmd.u.ctarg.rsp_size);
-
- /* GPN_FT req */
- ct_req->req.gpn_ft.port_type = fc4_type;
-
- sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE;
- sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
-
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Async-%s hdl=%x FC4Type %x.\n", sp->name,
- sp->handle, ct_req->req.gpn_ft.port_type);
-
- rval = qla2x00_start_sp(sp);
- if (rval != QLA_SUCCESS) {
- goto done_free_sp;
- }
-
- return rval;
-
-done_free_sp:
- if (sp->u.iocb_cmd.u.ctarg.req) {
- dma_free_coherent(&vha->hw->pdev->dev,
- sp->u.iocb_cmd.u.ctarg.req_allocated_size,
- sp->u.iocb_cmd.u.ctarg.req,
- sp->u.iocb_cmd.u.ctarg.req_dma);
- sp->u.iocb_cmd.u.ctarg.req = NULL;
- }
- if (sp->u.iocb_cmd.u.ctarg.rsp) {
- dma_free_coherent(&vha->hw->pdev->dev,
- sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
- sp->u.iocb_cmd.u.ctarg.rsp,
- sp->u.iocb_cmd.u.ctarg.rsp_dma);
- sp->u.iocb_cmd.u.ctarg.rsp = NULL;
- }
- /* ref: INIT */
- kref_put(&sp->cmd_kref, qla2x00_sp_release);
-
- spin_lock_irqsave(&vha->work_lock, flags);
- vha->scan.scan_flags &= ~SF_SCANNING;
- if (vha->scan.scan_flags == 0) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s: schedule\n", __func__);
- vha->scan.scan_flags |= SF_QUEUED;
- schedule_delayed_work(&vha->scan.scan_work, 5);
- }
- spin_unlock_irqrestore(&vha->work_lock, flags);
-
-
- return rval;
-} /* GNNFT */
-
-void qla24xx_async_gpnft_done(scsi_qla_host_t *vha, srb_t *sp)
-{
- ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
- "%s enter\n", __func__);
- qla24xx_async_gnnft(vha, sp, sp->gen2);
-}
-
/* Get WWPN list for certain fc4_type */
-int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
+int qla_fab_async_scan(scsi_qla_host_t *vha, srb_t *sp)
{
int rval = QLA_FUNCTION_FAILED;
struct ct_sns_req *ct_req;
struct ct_sns_pkt *ct_sns;
- u32 rspsz;
+ u32 rspsz = 0;
unsigned long flags;

- ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
+ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x200c,
"%s enter\n", __func__);

if (!vha->flags.online)
@@ -4055,22 +3918,21 @@ int qla24xx_async_gpnft(scsi_qla_host_t
spin_lock_irqsave(&vha->work_lock, flags);
if (vha->scan.scan_flags & SF_SCANNING) {
spin_unlock_irqrestore(&vha->work_lock, flags);
- ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
+ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2012,
"%s: scan active\n", __func__);
return rval;
}
vha->scan.scan_flags |= SF_SCANNING;
+ if (!sp)
+ vha->scan.step = FAB_SCAN_START;
+
spin_unlock_irqrestore(&vha->work_lock, flags);

- if (fc4_type == FC4_TYPE_FCP_SCSI) {
- ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
+ switch (vha->scan.step) {
+ case FAB_SCAN_START:
+ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2018,
"%s: Performing FCP Scan\n", __func__);

- if (sp) {
- /* ref: INIT */
- kref_put(&sp->cmd_kref, qla2x00_sp_release);
- }
-
/* ref: INIT */
sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
if (!sp) {
@@ -4086,7 +3948,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t
GFP_KERNEL);
sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt);
if (!sp->u.iocb_cmd.u.ctarg.req) {
- ql_log(ql_log_warn, vha, 0xffff,
+ ql_log(ql_log_warn, vha, 0x201a,
"Failed to allocate ct_sns request.\n");
spin_lock_irqsave(&vha->work_lock, flags);
vha->scan.scan_flags &= ~SF_SCANNING;
@@ -4094,7 +3956,6 @@ int qla24xx_async_gpnft(scsi_qla_host_t
qla2x00_rel_sp(sp);
return rval;
}
- sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE;

rspsz = sizeof(struct ct_sns_gpnft_rsp) +
((vha->hw->max_fibre_devices - 1) *
@@ -4106,7 +3967,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t
GFP_KERNEL);
sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = rspsz;
if (!sp->u.iocb_cmd.u.ctarg.rsp) {
- ql_log(ql_log_warn, vha, 0xffff,
+ ql_log(ql_log_warn, vha, 0x201b,
"Failed to allocate ct_sns request.\n");
spin_lock_irqsave(&vha->work_lock, flags);
vha->scan.scan_flags &= ~SF_SCANNING;
@@ -4126,35 +3987,95 @@ int qla24xx_async_gpnft(scsi_qla_host_t
"%s scan list size %d\n", __func__, vha->scan.size);

memset(vha->scan.l, 0, vha->scan.size);
- } else if (!sp) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "NVME scan did not provide SP\n");
+
+ vha->scan.step = FAB_SCAN_GPNFT_FCP;
+ break;
+ case FAB_SCAN_GPNFT_FCP:
+ vha->scan.step = FAB_SCAN_GNNFT_FCP;
+ break;
+ case FAB_SCAN_GNNFT_FCP:
+ vha->scan.step = FAB_SCAN_GPNFT_NVME;
+ break;
+ case FAB_SCAN_GPNFT_NVME:
+ vha->scan.step = FAB_SCAN_GNNFT_NVME;
+ break;
+ case FAB_SCAN_GNNFT_NVME:
+ default:
+ /* should not be here */
+ WARN_ON(1);
+ goto done_free_sp;
+ }
+
+ if (!sp) {
+ ql_dbg(ql_dbg_disc, vha, 0x201c,
+ "scan did not provide SP\n");
return rval;
}
+ if (!sp->u.iocb_cmd.u.ctarg.req || !sp->u.iocb_cmd.u.ctarg.rsp) {
+ ql_log(ql_log_warn, vha, 0x201d,
+ "%s: req %p rsp %p are not setup\n",
+ __func__, sp->u.iocb_cmd.u.ctarg.req,
+ sp->u.iocb_cmd.u.ctarg.rsp);
+ spin_lock_irqsave(&vha->work_lock, flags);
+ vha->scan.scan_flags &= ~SF_SCANNING;
+ spin_unlock_irqrestore(&vha->work_lock, flags);
+ WARN_ON(1);
+ set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ goto done_free_sp;
+ }
+
+ rspsz = sp->u.iocb_cmd.u.ctarg.rsp_size;
+ memset(sp->u.iocb_cmd.u.ctarg.req, 0, sp->u.iocb_cmd.u.ctarg.req_size);
+ memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);
+

sp->type = SRB_CT_PTHRU_CMD;
- sp->name = "gpnft";
sp->gen1 = vha->hw->base_qpair->chip_reset;
- sp->gen2 = fc4_type;
qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
- qla2x00_async_gpnft_gnnft_sp_done);
-
- rspsz = sp->u.iocb_cmd.u.ctarg.rsp_size;
- memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);
- memset(sp->u.iocb_cmd.u.ctarg.req, 0, sp->u.iocb_cmd.u.ctarg.req_size);
+ qla_async_scan_sp_done);

ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
- /* CT_IU preamble */
- ct_req = qla2x00_prep_ct_req(ct_sns, GPN_FT_CMD, rspsz);

- /* GPN_FT req */
- ct_req->req.gpn_ft.port_type = fc4_type;
+ /* CT_IU preamble */
+ switch (vha->scan.step) {
+ case FAB_SCAN_GPNFT_FCP:
+ sp->name = "gpnft";
+ ct_req = qla2x00_prep_ct_req(ct_sns, GPN_FT_CMD, rspsz);
+ ct_req->req.gpn_ft.port_type = FC4_TYPE_FCP_SCSI;
+ sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE;
+ break;
+ case FAB_SCAN_GNNFT_FCP:
+ sp->name = "gnnft";
+ ct_req = qla2x00_prep_ct_req(ct_sns, GNN_FT_CMD, rspsz);
+ ct_req->req.gpn_ft.port_type = FC4_TYPE_FCP_SCSI;
+ sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE;
+ break;
+ case FAB_SCAN_GPNFT_NVME:
+ sp->name = "gpnft";
+ ct_req = qla2x00_prep_ct_req(ct_sns, GPN_FT_CMD, rspsz);
+ ct_req->req.gpn_ft.port_type = FC4_TYPE_NVME;
+ sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE;
+ break;
+ case FAB_SCAN_GNNFT_NVME:
+ sp->name = "gnnft";
+ ct_req = qla2x00_prep_ct_req(ct_sns, GNN_FT_CMD, rspsz);
+ ct_req->req.gpn_ft.port_type = FC4_TYPE_NVME;
+ sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE;
+ break;
+ default:
+ /* should not be here */
+ WARN_ON(1);
+ goto done_free_sp;
+ }

sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;

- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Async-%s hdl=%x FC4Type %x.\n", sp->name,
- sp->handle, ct_req->req.gpn_ft.port_type);
+ ql_dbg(ql_dbg_disc, vha, 0x2003,
+ "%s: step %d, rsp size %d, req size %d hdl %x %s FC4TYPE %x \n",
+ __func__, vha->scan.step, sp->u.iocb_cmd.u.ctarg.rsp_size,
+ sp->u.iocb_cmd.u.ctarg.req_size, sp->handle, sp->name,
+ ct_req->req.gpn_ft.port_type);

rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
@@ -4187,7 +4108,7 @@ done_free_sp:
spin_lock_irqsave(&vha->work_lock, flags);
vha->scan.scan_flags &= ~SF_SCANNING;
if (vha->scan.scan_flags == 0) {
- ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
+ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2007,
"%s: Scan scheduled.\n", __func__);
vha->scan.scan_flags |= SF_QUEUED;
schedule_delayed_work(&vha->scan.scan_work, 5);
@@ -4198,6 +4119,15 @@ done_free_sp:
return rval;
}

+void qla_fab_scan_start(struct scsi_qla_host *vha)
+{
+ int rval;
+
+ rval = qla_fab_async_scan(vha, NULL);
+ if (rval)
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+}
+
void qla_scan_work_fn(struct work_struct *work)
{
struct fab_scan *s = container_of(to_delayed_work(work),
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -6444,10 +6444,7 @@ qla2x00_configure_fabric(scsi_qla_host_t
if (USE_ASYNC_SCAN(ha)) {
/* start of scan begins here */
vha->scan.rscn_gen_end = atomic_read(&vha->rscn_gen);
- rval = qla24xx_async_gpnft(vha, FC4_TYPE_FCP_SCSI,
- NULL);
- if (rval)
- set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ qla_fab_scan_start(vha);
} else {
list_for_each_entry(fcport, &vha->vp_fcports, list)
fcport->scan_state = QLA_FCPORT_SCAN;
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -5522,15 +5522,11 @@ qla2x00_do_work(struct scsi_qla_host *vh
qla2x00_async_prlo_done(vha, e->u.logio.fcport,
e->u.logio.data);
break;
- case QLA_EVT_GPNFT:
- qla24xx_async_gpnft(vha, e->u.gpnft.fc4_type,
- e->u.gpnft.sp);
+ case QLA_EVT_SCAN_CMD:
+ qla_fab_async_scan(vha, e->u.iosb.sp);
break;
- case QLA_EVT_GPNFT_DONE:
- qla24xx_async_gpnft_done(vha, e->u.iosb.sp);
- break;
- case QLA_EVT_GNNFT_DONE:
- qla24xx_async_gnnft_done(vha, e->u.iosb.sp);
+ case QLA_EVT_SCAN_FINISH:
+ qla_fab_scan_finish(vha, e->u.iosb.sp);
break;
case QLA_EVT_GFPNID:
qla24xx_async_gfpnid(vha, e->u.fcport.fcport);