Commit 22b8d89b authored by Martin K. Petersen's avatar Martin K. Petersen
Browse files

Merge patch series "qla2xxx misc. bug fixes"

Nilesh Javali <njavali@marvell.com> says:

Martin,

Please apply the qla2xxx driver miscellaneous bug fixes to the scsi
tree at your earliest convenience.

Link: https://lore.kernel.org/r/20240710171057.35066-1-njavali@marvell.com


Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parents af8e69ef a1392b19
Loading
Loading
Loading
Loading
+58 −40
Original line number Diff line number Diff line
@@ -324,7 +324,7 @@ qla2x00_process_els(struct bsg_job *bsg_job)
		    "request_sg_cnt=%x reply_sg_cnt=%x.\n",
		    bsg_job->request_payload.sg_cnt,
		    bsg_job->reply_payload.sg_cnt);
		rval = -EPERM;
		rval = -ENOBUFS;
		goto done;
	}

@@ -3059,43 +3059,29 @@ qla24xx_bsg_request(struct bsg_job *bsg_job)
	return ret;
}

int
qla24xx_bsg_timeout(struct bsg_job *bsg_job)
static bool qla_bsg_found(struct qla_qpair *qpair, struct bsg_job *bsg_job)
{
	bool found = false;
	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
	scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
	struct qla_hw_data *ha = vha->hw;
	srb_t *sp;
	int cnt, que;
	srb_t *sp = NULL;
	int cnt;
	unsigned long flags;
	struct req_que *req;

	ql_log(ql_log_info, vha, 0x708b, "%s CMD timeout. bsg ptr %p.\n",
	    __func__, bsg_job);

	if (qla2x00_isp_reg_stat(ha)) {
		ql_log(ql_log_info, vha, 0x9007,
		    "PCI/Register disconnect.\n");
		qla_pci_set_eeh_busy(vha);
	}

	/* find the bsg job from the active list of commands */
	spin_lock_irqsave(&ha->hardware_lock, flags);
	for (que = 0; que < ha->max_req_queues; que++) {
		req = ha->req_q_map[que];
		if (!req)
			continue;
	spin_lock_irqsave(qpair->qp_lock_ptr, flags);
	req = qpair->req;

	for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
		sp = req->outstanding_cmds[cnt];
		if (sp &&
		    (sp->type == SRB_CT_CMD ||
		     sp->type == SRB_ELS_CMD_HST ||
			     sp->type == SRB_ELS_CMD_HST_NOLOGIN ||
			     sp->type == SRB_FXIOCB_BCMD) &&
		     sp->type == SRB_ELS_CMD_HST_NOLOGIN) &&
		    sp->u.bsg_job == bsg_job) {
			req->outstanding_cmds[cnt] = NULL;
				spin_unlock_irqrestore(&ha->hardware_lock, flags);
			spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);

			if (!ha->flags.eeh_busy && ha->isp_ops->abort_command(sp)) {
				ql_log(ql_log_warn, vha, 0x7089,
@@ -3106,21 +3092,53 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job)
						"mbx abort_command success.\n");
				bsg_reply->result = 0;
			}
				spin_lock_irqsave(&ha->hardware_lock, flags);
			/* ref: INIT */
			kref_put(&sp->cmd_kref, qla2x00_sp_release);

			found = true;
			goto done;
		}
	}
	spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);

done:
	return found;
}

int
qla24xx_bsg_timeout(struct bsg_job *bsg_job)
{
	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
	scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
	struct qla_hw_data *ha = vha->hw;
	int i;
	struct qla_qpair *qpair;

	ql_log(ql_log_info, vha, 0x708b, "%s CMD timeout. bsg ptr %p.\n",
	    __func__, bsg_job);

	if (qla2x00_isp_reg_stat(ha)) {
		ql_log(ql_log_info, vha, 0x9007,
		    "PCI/Register disconnect.\n");
		qla_pci_set_eeh_busy(vha);
	}

	if (qla_bsg_found(ha->base_qpair, bsg_job))
		goto done;

	/* find the bsg job from the active list of commands */
	for (i = 0; i < ha->max_qpairs; i++) {
		qpair = vha->hw->queue_pair_map[i];
		if (!qpair)
			continue;
		if (qla_bsg_found(qpair, bsg_job))
			goto done;
	}
	spin_unlock_irqrestore(&ha->hardware_lock, flags);

	ql_log(ql_log_info, vha, 0x708b, "SRB not found to abort.\n");
	bsg_reply->result = -ENXIO;
	return 0;

done:
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
	/* ref: INIT */
	kref_put(&sp->cmd_kref, qla2x00_sp_release);
	return 0;
}

+14 −3
Original line number Diff line number Diff line
@@ -3309,9 +3309,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;
@@ -3537,9 +3548,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,
@@ -5030,6 +5040,7 @@ typedef struct scsi_qla_host {

	/* Counter to detect races between ELS and RSCN events */
	atomic_t		generation_tick;
	atomic_t		rscn_gen;
	/* Time when global fcport update has been scheduled */
	int			total_fcport_update_gen;
	/* List of pending LOGOs, protected by tgt_mutex */
+3 −3
Original line number Diff line number Diff line
@@ -728,9 +728,9 @@ int qla24xx_async_gpsc(scsi_qla_host_t *, fc_port_t *);
void qla24xx_handle_gpsc_event(scsi_qla_host_t *, struct event_arg *);
int qla2x00_mgmt_svr_login(scsi_qla_host_t *);
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 *);
+212 −255
Original line number Diff line number Diff line
@@ -1710,7 +1710,7 @@ qla2x00_hba_attributes(scsi_qla_host_t *vha, void *entries,
	eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
	alen = scnprintf(
		eiter->a.orom_version, sizeof(eiter->a.orom_version),
		"%d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
		"%d.%02d", ha->efi_revision[1], ha->efi_revision[0]);
	alen += FDMI_ATTR_ALIGNMENT(alen);
	alen += FDMI_ATTR_TYPELEN(eiter);
	eiter->len = cpu_to_be16(alen);
@@ -3168,7 +3168,30 @@ static int qla2x00_is_a_vp(scsi_qla_host_t *vha, u64 wwn)
	return rc;
}

void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
static bool qla_ok_to_clear_rscn(scsi_qla_host_t *vha, fc_port_t *fcport)
{
	u32 rscn_gen;

	rscn_gen = atomic_read(&vha->rscn_gen);
	ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2017,
	    "%s %d %8phC rscn_gen %x start %x end %x current %x\n",
	    __func__, __LINE__, fcport->port_name, fcport->rscn_gen,
	    vha->scan.rscn_gen_start, vha->scan.rscn_gen_end, rscn_gen);

	if (val_is_in_range(fcport->rscn_gen, vha->scan.rscn_gen_start,
	    vha->scan.rscn_gen_end))
		/* rscn came in before fabric scan */
		return true;

	if (val_is_in_range(fcport->rscn_gen, vha->scan.rscn_gen_end, rscn_gen))
		/* rscn came in after fabric scan */
		return false;

	/* rare: fcport's scan_needed + rscn_gen must be stale */
	return true;
}

void qla_fab_scan_finish(scsi_qla_host_t *vha, srb_t *sp)
{
	fc_port_t *fcport;
	u32 i, rc;
@@ -3281,10 +3304,10 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
				   (fcport->scan_needed &&
				    fcport->port_type != FCT_INITIATOR &&
				    fcport->port_type != FCT_NVME_INITIATOR)) {
				fcport->scan_needed = 0;
				qlt_schedule_sess_for_deletion(fcport);
			}
			fcport->d_id.b24 = rp->id.b24;
			fcport->scan_needed = 0;
			break;
		}

@@ -3325,7 +3348,9 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
				do_delete = true;
			}

			if (qla_ok_to_clear_rscn(vha, fcport))
				fcport->scan_needed = 0;

			if (((qla_dual_mode_enabled(vha) ||
			      qla_ini_mode_enabled(vha)) &&
			    atomic_read(&fcport->state) == FCS_ONLINE) ||
@@ -3355,6 +3380,8 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
					    fcport->port_name, fcport->loop_id,
					    fcport->login_retry);
				}

				if (qla_ok_to_clear_rscn(vha, fcport))
					fcport->scan_needed = 0;
				qla24xx_fcport_handle_login(vha, fcport);
			}
@@ -3379,14 +3406,11 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
	}
}

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;
@@ -3396,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;
@@ -3445,14 +3447,19 @@ 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) {
		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;
			} else {
			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) {
@@ -3461,16 +3468,13 @@ static void qla2x00_find_free_fcp_nvme_slot(struct scsi_qla_host *vha,
					break;
				}
			}
			}
		} else {
			/* Search if the fibre device supports FC4_TYPE_NVME */
			if (cmd == GPN_FT_CMD) {
			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)) {
				if (!memcmp(rp->port_name, d->port_name, 8)) {
					/*
					 * Supports FC-NVMe & FCP
					 */
@@ -3488,42 +3492,38 @@ static void qla2x00_find_free_fcp_nvme_slot(struct scsi_qla_host *vha,
						continue;
					} else {
						rp->id = id;
							memcpy(rp->port_name,
							    d->port_name, 8);
							rp->fc4type =
							    FS_FC4TYPE_NVME;
						memcpy(rp->port_name, d->port_name, 8);
						rp->fc4type = FS_FC4TYPE_NVME;
						break;
					}
				}
			}
			} else {
			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);
					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) {
@@ -3547,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);
@@ -3573,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);

		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) {
@@ -3605,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)
@@ -3734,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) {
@@ -3765,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;
@@ -3773,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 *
@@ -3785,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;
@@ -3805,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");

		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  */
	switch (vha->scan.step) {
	case FAB_SCAN_GPNFT_FCP:
		sp->name = "gpnft";
		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_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) {
@@ -3864,7 +3812,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *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);
@@ -3875,6 +3823,15 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *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),
+70 −22

File changed.

Preview size limit exceeded, changes collapsed.

Loading