|
|
|
|
@@ -3191,7 +3191,7 @@ static bool qla_ok_to_clear_rscn(scsi_qla_host_t *vha, fc_port_t *fcport)
|
|
|
|
|
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;
|
|
|
|
|
@@ -3406,14 +3406,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;
|
|
|
|
|
@@ -3423,37 +3420,15 @@ static int qla2x00_post_gnnft_gpnft_done_work(struct scsi_qla_host *vha,
|
|
|
|
|
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;
|
|
|
|
|
@@ -3472,85 +3447,83 @@ static void qla2x00_find_free_fcp_nvme_slot(struct scsi_qla_host *vha,
|
|
|
|
|
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 {
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* Search if the fibre device supports FC4_TYPE_NVME */
|
|
|
|
|
if (cmd == GPN_FT_CMD) {
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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 {
|
|
|
|
|
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;
|
|
|
|
|
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) {
|
|
|
|
|
@@ -3574,8 +3547,7 @@ static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res)
|
|
|
|
|
* 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);
|
|
|
|
|
@@ -3600,28 +3572,30 @@ static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res)
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
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) {
|
|
|
|
|
@@ -3632,127 +3606,16 @@ static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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)
|
|
|
|
|
@@ -3761,22 +3624,21 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
|
|
|
|
|
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) {
|
|
|
|
|
@@ -3792,7 +3654,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
|
|
|
|
|
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;
|
|
|
|
|
@@ -3800,7 +3662,6 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
|
|
|
|
|
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 *
|
|
|
|
|
@@ -3812,7 +3673,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
|
|
|
|
|
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;
|
|
|
|
|
@@ -3832,35 +3693,95 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
|
|
|
|
|
"%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");
|
|
|
|
|
return rval;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
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.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);
|
|
|
|
|
memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sp->type = SRB_CT_PTHRU_CMD;
|
|
|
|
|
sp->gen1 = vha->hw->base_qpair->chip_reset;
|
|
|
|
|
qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
|
|
|
|
|
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) {
|
|
|
|
|
@@ -3891,7 +3812,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);
|
|
|
|
|
@@ -3902,6 +3823,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),
|
|
|
|
|
|