Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e374f9f5 authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen
Browse files

scsi: qla2xxx: Migrate switch registration commands away from mailbox interface



Migrate switch registration commands: RFTID, RFFID, RNNID and RSNN_NN
out of mailbox interface to reduce fabric scan bottle neck.

Signed-off-by: default avatarQuinn Tran <quinn.tran@cavium.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 2dee5521
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -535,6 +535,7 @@ typedef struct srb {
	u32 gen1;	/* scratch */
	u32 gen1;	/* scratch */
	u32 gen2;	/* scratch */
	u32 gen2;	/* scratch */
	int rc;
	int rc;
	int retry_count;
	struct completion comp;
	struct completion comp;
	union {
	union {
		struct srb_iocb iocb_cmd;
		struct srb_iocb iocb_cmd;
@@ -3187,7 +3188,7 @@ enum qla_work_type {
	QLA_EVT_AENFX,
	QLA_EVT_AENFX,
	QLA_EVT_GIDPN,
	QLA_EVT_GIDPN,
	QLA_EVT_GPNID,
	QLA_EVT_GPNID,
	QLA_EVT_GPNID_DONE,
	QLA_EVT_UNMAP,
	QLA_EVT_NEW_SESS,
	QLA_EVT_NEW_SESS,
	QLA_EVT_GPDB,
	QLA_EVT_GPDB,
	QLA_EVT_PRLI,
	QLA_EVT_PRLI,
@@ -3203,6 +3204,7 @@ enum qla_work_type {
	QLA_EVT_GNNFT_DONE,
	QLA_EVT_GNNFT_DONE,
	QLA_EVT_GNNID,
	QLA_EVT_GNNID,
	QLA_EVT_GFPNID,
	QLA_EVT_GFPNID,
	QLA_EVT_SP_RETRY,
};
};




+1 −1
Original line number Original line Diff line number Diff line
@@ -650,7 +650,6 @@ extern void qla2x00_free_fcport(fc_port_t *);


extern int qla24xx_post_gpnid_work(struct scsi_qla_host *, port_id_t *);
extern int qla24xx_post_gpnid_work(struct scsi_qla_host *, port_id_t *);
extern int qla24xx_async_gpnid(scsi_qla_host_t *, port_id_t *);
extern int qla24xx_async_gpnid(scsi_qla_host_t *, port_id_t *);
void qla24xx_async_gpnid_done(scsi_qla_host_t *, srb_t*);
void qla24xx_handle_gpnid_event(scsi_qla_host_t *, struct event_arg *);
void qla24xx_handle_gpnid_event(scsi_qla_host_t *, struct event_arg *);


int qla24xx_post_gpsc_work(struct scsi_qla_host *, fc_port_t *);
int qla24xx_post_gpsc_work(struct scsi_qla_host *, fc_port_t *);
@@ -668,6 +667,7 @@ int qla24xx_post_gnnid_work(struct scsi_qla_host *, fc_port_t *);
int qla24xx_post_gfpnid_work(struct scsi_qla_host *, fc_port_t *);
int qla24xx_post_gfpnid_work(struct scsi_qla_host *, fc_port_t *);
int qla24xx_async_gfpnid(scsi_qla_host_t *, 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 *);
void qla24xx_handle_gfpnid_event(scsi_qla_host_t *, struct event_arg *);
void qla24xx_sp_unmap(scsi_qla_host_t *, srb_t *);


/*
/*
 * Global Function Prototypes in qla_attr.c source file.
 * Global Function Prototypes in qla_attr.c source file.
+316 −134
Original line number Original line Diff line number Diff line
@@ -14,6 +14,10 @@ static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *);
static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *);
static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *);
static int qla2x00_sns_rft_id(scsi_qla_host_t *);
static int qla2x00_sns_rft_id(scsi_qla_host_t *);
static int qla2x00_sns_rnn_id(scsi_qla_host_t *);
static int qla2x00_sns_rnn_id(scsi_qla_host_t *);
static int qla_async_rftid(scsi_qla_host_t *, port_id_t *);
static int qla_async_rffid(scsi_qla_host_t *, port_id_t *, u8, u8);
static int qla_async_rnnid(scsi_qla_host_t *, port_id_t *, u8*);
static int qla_async_rsnn_nn(scsi_qla_host_t *);


/**
/**
 * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query.
 * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query.
@@ -511,6 +515,72 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
	return (rval);
	return (rval);
}
}


static void qla2x00_async_sns_sp_done(void *s, int rc)
{
	struct srb *sp = s;
	struct scsi_qla_host *vha = sp->vha;
	struct ct_sns_pkt *ct_sns;
	struct qla_work_evt *e;

	sp->rc = rc;
	if (rc == QLA_SUCCESS) {
		ql_dbg(ql_dbg_disc, vha, 0x204f,
		    "Async done-%s exiting normally.\n",
		    sp->name);
	} else if (rc == QLA_FUNCTION_TIMEOUT) {
		ql_dbg(ql_dbg_disc, vha, 0x204f,
		    "Async done-%s timeout\n", sp->name);
	} else {
		ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
		memset(ct_sns, 0, sizeof(*ct_sns));
		sp->retry_count++;
		if (sp->retry_count > 3)
			goto err;

		ql_dbg(ql_dbg_disc, vha, 0x204f,
		    "Async done-%s fail rc %x.  Retry count %d\n",
		    sp->name, rc, sp->retry_count);

		e = qla2x00_alloc_work(vha, QLA_EVT_SP_RETRY);
		if (!e)
			goto err2;

		del_timer(&sp->u.iocb_cmd.timer);
		e->u.iosb.sp = sp;
		qla2x00_post_work(vha, e);
		return;
	}

err:
	e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP);
err2:
	if (!e) {
		/* please ignore kernel warning. otherwise, we have mem leak. */
		if (sp->u.iocb_cmd.u.ctarg.req) {
			dma_free_coherent(&vha->hw->pdev->dev,
			    sizeof(struct ct_sns_pkt),
			    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,
			    sizeof(struct ct_sns_pkt),
			    sp->u.iocb_cmd.u.ctarg.rsp,
			    sp->u.iocb_cmd.u.ctarg.rsp_dma);
			sp->u.iocb_cmd.u.ctarg.rsp = NULL;
		}

		sp->free(sp);

		return;
	}

	e->u.iosb.sp = sp;
	qla2x00_post_work(vha, e);
}

/**
/**
 * qla2x00_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
 * qla2x00_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
 * @ha: HA context
 * @ha: HA context
@@ -520,57 +590,87 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
int
int
qla2x00_rft_id(scsi_qla_host_t *vha)
qla2x00_rft_id(scsi_qla_host_t *vha)
{
{
	int		rval;
	struct qla_hw_data *ha = vha->hw;
	struct qla_hw_data *ha = vha->hw;
	ms_iocb_entry_t	*ms_pkt;
	struct ct_sns_req	*ct_req;
	struct ct_sns_rsp	*ct_rsp;
	struct ct_arg arg;


	if (IS_QLA2100(ha) || IS_QLA2200(ha))
	if (IS_QLA2100(ha) || IS_QLA2200(ha))
		return qla2x00_sns_rft_id(vha);
		return qla2x00_sns_rft_id(vha);


	arg.iocb = ha->ms_iocb;
	return qla_async_rftid(vha, &vha->d_id);
	arg.req_dma = ha->ct_sns_dma;
}
	arg.rsp_dma = ha->ct_sns_dma;
	arg.req_size = RFT_ID_REQ_SIZE;
	arg.rsp_size = RFT_ID_RSP_SIZE;
	arg.nport_handle = NPH_SNS;


	/* Issue RFT_ID */
static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id)
	/* Prepare common MS IOCB */
{
	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
	int rval = QLA_MEMORY_ALLOC_FAILED;
	struct ct_sns_req *ct_req;
	srb_t *sp;
	struct ct_sns_pkt *ct_sns;

	if (!vha->flags.online)
		goto done;

	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
	if (!sp)
		goto done;

	sp->type = SRB_CT_PTHRU_CMD;
	sp->name = "rft_id";
	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);

	sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
	    GFP_KERNEL);
	if (!sp->u.iocb_cmd.u.ctarg.req) {
		ql_log(ql_log_warn, vha, 0xd041,
		    "%s: Failed to allocate ct_sns request.\n",
		    __func__);
		goto done_free_sp;
	}

	sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
	    GFP_KERNEL);
	if (!sp->u.iocb_cmd.u.ctarg.rsp) {
		ql_log(ql_log_warn, vha, 0xd042,
		    "%s: Failed to allocate ct_sns request.\n",
		    __func__);
		goto done_free_sp;
	}
	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
	memset(ct_sns, 0, sizeof(*ct_sns));
	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;


	/* Prepare CT request */
	/* Prepare CT request */
	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFT_ID_CMD,
	ct_req = qla2x00_prep_ct_req(ct_sns, RFT_ID_CMD, RFT_ID_RSP_SIZE);
	    RFT_ID_RSP_SIZE);
	ct_rsp = &ha->ct_sns->p.rsp;


	/* Prepare CT arguments -- port_id, FC-4 types */
	/* Prepare CT arguments -- port_id, FC-4 types */
	ct_req->req.rft_id.port_id[0] = vha->d_id.b.domain;
	ct_req->req.rft_id.port_id[0] = vha->d_id.b.domain;
	ct_req->req.rft_id.port_id[1] = vha->d_id.b.area;
	ct_req->req.rft_id.port_id[1] = vha->d_id.b.area;
	ct_req->req.rft_id.port_id[2] = vha->d_id.b.al_pa;
	ct_req->req.rft_id.port_id[2] = vha->d_id.b.al_pa;

	ct_req->req.rft_id.fc4_types[2] = 0x01;		/* FCP-3 */
	ct_req->req.rft_id.fc4_types[2] = 0x01;		/* FCP-3 */


	if (vha->flags.nvme_enabled)
	if (vha->flags.nvme_enabled)
		ct_req->req.rft_id.fc4_types[6] = 1;    /* NVMe type 28h */
		ct_req->req.rft_id.fc4_types[6] = 1;    /* NVMe type 28h */
	/* Execute MS IOCB */

	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
	sp->u.iocb_cmd.u.ctarg.req_size = RFT_ID_REQ_SIZE;
	    sizeof(ms_iocb_entry_t));
	sp->u.iocb_cmd.u.ctarg.rsp_size = RFT_ID_RSP_SIZE;
	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
	sp->done = qla2x00_async_sns_sp_done;

	rval = qla2x00_start_sp(sp);
	if (rval != QLA_SUCCESS) {
	if (rval != QLA_SUCCESS) {
		/*EMPTY*/
		ql_dbg(ql_dbg_disc, vha, 0x2043,
		ql_dbg(ql_dbg_disc, vha, 0x2043,
		    "RFT_ID issue IOCB failed (%d).\n", rval);
		    "RFT_ID issue IOCB failed (%d).\n", rval);
	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFT_ID") !=
		goto done_free_sp;
	    QLA_SUCCESS) {
		rval = QLA_FUNCTION_FAILED;
	} else {
		ql_dbg(ql_dbg_disc, vha, 0x2044,
		    "RFT_ID exiting normally.\n");
	}
	}

	ql_dbg(ql_dbg_disc, vha, 0xffff,
	return (rval);
	    "Async-%s - hdl=%x portid %06x.\n",
	    sp->name, sp->handle, d_id->b24);
	return rval;
done_free_sp:
	sp->free(sp);
done:
	return rval;
}
}


/**
/**
@@ -582,12 +682,7 @@ qla2x00_rft_id(scsi_qla_host_t *vha)
int
int
qla2x00_rff_id(scsi_qla_host_t *vha, u8 type)
qla2x00_rff_id(scsi_qla_host_t *vha, u8 type)
{
{
	int		rval;
	struct qla_hw_data *ha = vha->hw;
	struct qla_hw_data *ha = vha->hw;
	ms_iocb_entry_t	*ms_pkt;
	struct ct_sns_req	*ct_req;
	struct ct_sns_rsp	*ct_rsp;
	struct ct_arg arg;


	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
		ql_dbg(ql_dbg_disc, vha, 0x2046,
		ql_dbg(ql_dbg_disc, vha, 0x2046,
@@ -595,47 +690,81 @@ qla2x00_rff_id(scsi_qla_host_t *vha, u8 type)
		return (QLA_SUCCESS);
		return (QLA_SUCCESS);
	}
	}


	arg.iocb = ha->ms_iocb;
	return qla_async_rffid(vha, &vha->d_id, qlt_rff_id(vha),
	arg.req_dma = ha->ct_sns_dma;
	    FC4_TYPE_FCP_SCSI);
	arg.rsp_dma = ha->ct_sns_dma;
}
	arg.req_size = RFF_ID_REQ_SIZE;
	arg.rsp_size = RFF_ID_RSP_SIZE;
	arg.nport_handle = NPH_SNS;


	/* Issue RFF_ID */
static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id,
	/* Prepare common MS IOCB */
    u8 fc4feature, u8 fc4type)
	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
{
	int rval = QLA_MEMORY_ALLOC_FAILED;
	struct ct_sns_req *ct_req;
	srb_t *sp;
	struct ct_sns_pkt *ct_sns;


	/* Prepare CT request */
	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFF_ID_CMD,
	if (!sp)
	    RFF_ID_RSP_SIZE);
		goto done;
	ct_rsp = &ha->ct_sns->p.rsp;


	/* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */
	sp->type = SRB_CT_PTHRU_CMD;
	ct_req->req.rff_id.port_id[0] = vha->d_id.b.domain;
	sp->name = "rff_id";
	ct_req->req.rff_id.port_id[1] = vha->d_id.b.area;
	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
	ct_req->req.rff_id.port_id[2] = vha->d_id.b.al_pa;

	sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
	    GFP_KERNEL);
	if (!sp->u.iocb_cmd.u.ctarg.req) {
		ql_log(ql_log_warn, vha, 0xd041,
		    "%s: Failed to allocate ct_sns request.\n",
		    __func__);
		goto done_free_sp;
	}

	sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
	    GFP_KERNEL);
	if (!sp->u.iocb_cmd.u.ctarg.rsp) {
		ql_log(ql_log_warn, vha, 0xd042,
		    "%s: Failed to allocate ct_sns request.\n",
		    __func__);
		goto done_free_sp;
	}
	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
	memset(ct_sns, 0, sizeof(*ct_sns));
	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;


	qlt_rff_id(vha, ct_req);
	/* Prepare CT request */
	ct_req = qla2x00_prep_ct_req(ct_sns, RFF_ID_CMD, RFF_ID_RSP_SIZE);


	ct_req->req.rff_id.fc4_type = type;		/* SCSI - FCP */
	/* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */
	ct_req->req.rff_id.port_id[0] = d_id->b.domain;
	ct_req->req.rff_id.port_id[1] = d_id->b.area;
	ct_req->req.rff_id.port_id[2] = d_id->b.al_pa;
	ct_req->req.rff_id.fc4_feature = fc4feature;
	ct_req->req.rff_id.fc4_type = fc4type;		/* SCSI - FCP */

	sp->u.iocb_cmd.u.ctarg.req_size = RFF_ID_REQ_SIZE;
	sp->u.iocb_cmd.u.ctarg.rsp_size = RFF_ID_RSP_SIZE;
	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
	sp->done = qla2x00_async_sns_sp_done;


	/* Execute MS IOCB */
	rval = qla2x00_start_sp(sp);
	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
	    sizeof(ms_iocb_entry_t));
	if (rval != QLA_SUCCESS) {
	if (rval != QLA_SUCCESS) {
		/*EMPTY*/
		ql_dbg(ql_dbg_disc, vha, 0x2047,
		ql_dbg(ql_dbg_disc, vha, 0x2047,
		    "RFF_ID issue IOCB failed (%d).\n", rval);
		    "RFF_ID issue IOCB failed (%d).\n", rval);
	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFF_ID") !=
		goto done_free_sp;
	    QLA_SUCCESS) {
		rval = QLA_FUNCTION_FAILED;
	} else {
		ql_dbg(ql_dbg_disc, vha, 0x2048,
		    "RFF_ID exiting normally.\n");
	}
	}


	return (rval);
	ql_dbg(ql_dbg_disc, vha, 0xffff,
	    "Async-%s - hdl=%x portid %06x feature %x type %x.\n",
	    sp->name, sp->handle, d_id->b24, fc4feature, fc4type);
	return rval;

done_free_sp:
	sp->free(sp);
done:
	return rval;
}
}


/**
/**
@@ -647,54 +776,85 @@ qla2x00_rff_id(scsi_qla_host_t *vha, u8 type)
int
int
qla2x00_rnn_id(scsi_qla_host_t *vha)
qla2x00_rnn_id(scsi_qla_host_t *vha)
{
{
	int		rval;
	struct qla_hw_data *ha = vha->hw;
	struct qla_hw_data *ha = vha->hw;
	ms_iocb_entry_t	*ms_pkt;
	struct ct_sns_req	*ct_req;
	struct ct_sns_rsp	*ct_rsp;
	struct ct_arg arg;


	if (IS_QLA2100(ha) || IS_QLA2200(ha))
	if (IS_QLA2100(ha) || IS_QLA2200(ha))
		return qla2x00_sns_rnn_id(vha);
		return qla2x00_sns_rnn_id(vha);


	arg.iocb = ha->ms_iocb;
	return  qla_async_rnnid(vha, &vha->d_id, vha->node_name);
	arg.req_dma = ha->ct_sns_dma;
}
	arg.rsp_dma = ha->ct_sns_dma;
	arg.req_size = RNN_ID_REQ_SIZE;
	arg.rsp_size = RNN_ID_RSP_SIZE;
	arg.nport_handle = NPH_SNS;


	/* Issue RNN_ID */
static int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t *d_id,
	/* Prepare common MS IOCB */
	u8 *node_name)
	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
{
	int rval = QLA_MEMORY_ALLOC_FAILED;
	struct ct_sns_req *ct_req;
	srb_t *sp;
	struct ct_sns_pkt *ct_sns;

	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
	if (!sp)
		goto done;

	sp->type = SRB_CT_PTHRU_CMD;
	sp->name = "rnid";
	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);

	sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
	    GFP_KERNEL);
	if (!sp->u.iocb_cmd.u.ctarg.req) {
		ql_log(ql_log_warn, vha, 0xd041,
		    "%s: Failed to allocate ct_sns request.\n",
		    __func__);
		goto done_free_sp;
	}

	sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
	    GFP_KERNEL);
	if (!sp->u.iocb_cmd.u.ctarg.rsp) {
		ql_log(ql_log_warn, vha, 0xd042,
		    "%s: Failed to allocate ct_sns request.\n",
		    __func__);
		goto done_free_sp;
	}
	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
	memset(ct_sns, 0, sizeof(*ct_sns));
	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;


	/* Prepare CT request */
	/* Prepare CT request */
	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE);
	ct_req = qla2x00_prep_ct_req(ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE);
	ct_rsp = &ha->ct_sns->p.rsp;


	/* Prepare CT arguments -- port_id, node_name */
	/* Prepare CT arguments -- port_id, node_name */
	ct_req->req.rnn_id.port_id[0] = vha->d_id.b.domain;
	ct_req->req.rnn_id.port_id[0] = vha->d_id.b.domain;
	ct_req->req.rnn_id.port_id[1] = vha->d_id.b.area;
	ct_req->req.rnn_id.port_id[1] = vha->d_id.b.area;
	ct_req->req.rnn_id.port_id[2] = vha->d_id.b.al_pa;
	ct_req->req.rnn_id.port_id[2] = vha->d_id.b.al_pa;

	memcpy(ct_req->req.rnn_id.node_name, vha->node_name, WWN_SIZE);
	memcpy(ct_req->req.rnn_id.node_name, vha->node_name, WWN_SIZE);


	/* Execute MS IOCB */
	sp->u.iocb_cmd.u.ctarg.req_size = RNN_ID_REQ_SIZE;
	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
	sp->u.iocb_cmd.u.ctarg.rsp_size = RNN_ID_RSP_SIZE;
	    sizeof(ms_iocb_entry_t));
	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;

	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
	sp->done = qla2x00_async_sns_sp_done;

	rval = qla2x00_start_sp(sp);
	if (rval != QLA_SUCCESS) {
	if (rval != QLA_SUCCESS) {
		/*EMPTY*/
		ql_dbg(ql_dbg_disc, vha, 0x204d,
		ql_dbg(ql_dbg_disc, vha, 0x204d,
		    "RNN_ID issue IOCB failed (%d).\n", rval);
		    "RNN_ID issue IOCB failed (%d).\n", rval);
	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RNN_ID") !=
		goto done_free_sp;
	    QLA_SUCCESS) {
		rval = QLA_FUNCTION_FAILED;
	} else {
		ql_dbg(ql_dbg_disc, vha, 0x204e,
		    "RNN_ID exiting normally.\n");
	}
	}
	ql_dbg(ql_dbg_disc, vha, 0xffff,
	    "Async-%s - hdl=%x portid %06x\n",
	    sp->name, sp->handle, d_id->b24);


	return (rval);
	return rval;

done_free_sp:
	sp->free(sp);
done:
	return rval;
}
}


void
void
@@ -721,12 +881,7 @@ qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn, size_t size)
int
int
qla2x00_rsnn_nn(scsi_qla_host_t *vha)
qla2x00_rsnn_nn(scsi_qla_host_t *vha)
{
{
	int		rval;
	struct qla_hw_data *ha = vha->hw;
	struct qla_hw_data *ha = vha->hw;
	ms_iocb_entry_t	*ms_pkt;
	struct ct_sns_req	*ct_req;
	struct ct_sns_rsp	*ct_rsp;
	struct ct_arg arg;


	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
		ql_dbg(ql_dbg_disc, vha, 0x2050,
		ql_dbg(ql_dbg_disc, vha, 0x2050,
@@ -734,22 +889,49 @@ qla2x00_rsnn_nn(scsi_qla_host_t *vha)
		return (QLA_SUCCESS);
		return (QLA_SUCCESS);
	}
	}


	arg.iocb = ha->ms_iocb;
	return qla_async_rsnn_nn(vha);
	arg.req_dma = ha->ct_sns_dma;
}
	arg.rsp_dma = ha->ct_sns_dma;
	arg.req_size = 0;
	arg.rsp_size = RSNN_NN_RSP_SIZE;
	arg.nport_handle = NPH_SNS;


	/* Issue RSNN_NN */
static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
	/* Prepare common MS IOCB */
{
	/*   Request size adjusted after CT preparation */
	int rval = QLA_MEMORY_ALLOC_FAILED;
	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
	struct ct_sns_req *ct_req;
	srb_t *sp;
	struct ct_sns_pkt *ct_sns;

	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
	if (!sp)
		goto done;

	sp->type = SRB_CT_PTHRU_CMD;
	sp->name = "rsnn_nn";
	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);

	sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
	    GFP_KERNEL);
	if (!sp->u.iocb_cmd.u.ctarg.req) {
		ql_log(ql_log_warn, vha, 0xd041,
		    "%s: Failed to allocate ct_sns request.\n",
		    __func__);
		goto done_free_sp;
	}

	sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
	    GFP_KERNEL);
	if (!sp->u.iocb_cmd.u.ctarg.rsp) {
		ql_log(ql_log_warn, vha, 0xd042,
		    "%s: Failed to allocate ct_sns request.\n",
		    __func__);
		goto done_free_sp;
	}
	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
	memset(ct_sns, 0, sizeof(*ct_sns));
	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;


	/* Prepare CT request */
	/* Prepare CT request */
	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RSNN_NN_CMD,
	ct_req = qla2x00_prep_ct_req(ct_sns, RSNN_NN_CMD, RSNN_NN_RSP_SIZE);
	    RSNN_NN_RSP_SIZE);
	ct_rsp = &ha->ct_sns->p.rsp;


	/* Prepare CT arguments -- node_name, symbolic node_name, size */
	/* Prepare CT arguments -- node_name, symbolic node_name, size */
	memcpy(ct_req->req.rsnn_nn.node_name, vha->node_name, WWN_SIZE);
	memcpy(ct_req->req.rsnn_nn.node_name, vha->node_name, WWN_SIZE);
@@ -757,32 +939,33 @@ qla2x00_rsnn_nn(scsi_qla_host_t *vha)
	/* Prepare the Symbolic Node Name */
	/* Prepare the Symbolic Node Name */
	qla2x00_get_sym_node_name(vha, ct_req->req.rsnn_nn.sym_node_name,
	qla2x00_get_sym_node_name(vha, ct_req->req.rsnn_nn.sym_node_name,
	    sizeof(ct_req->req.rsnn_nn.sym_node_name));
	    sizeof(ct_req->req.rsnn_nn.sym_node_name));

	/* Calculate SNN length */
	ct_req->req.rsnn_nn.name_len =
	ct_req->req.rsnn_nn.name_len =
	    (uint8_t)strlen(ct_req->req.rsnn_nn.sym_node_name);
	    (uint8_t)strlen(ct_req->req.rsnn_nn.sym_node_name);


	/* Update MS IOCB request */
	ms_pkt->req_bytecount =
	    cpu_to_le32(24 + 1 + ct_req->req.rsnn_nn.name_len);
	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;


	/* Execute MS IOCB */
	sp->u.iocb_cmd.u.ctarg.req_size = 24 + 1 + ct_req->req.rsnn_nn.name_len;
	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
	sp->u.iocb_cmd.u.ctarg.rsp_size = RSNN_NN_RSP_SIZE;
	    sizeof(ms_iocb_entry_t));
	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;

	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
	sp->done = qla2x00_async_sns_sp_done;

	rval = qla2x00_start_sp(sp);
	if (rval != QLA_SUCCESS) {
	if (rval != QLA_SUCCESS) {
		/*EMPTY*/
		ql_dbg(ql_dbg_disc, vha, 0x2043,
		ql_dbg(ql_dbg_disc, vha, 0x2051,
		    "RFT_ID issue IOCB failed (%d).\n", rval);
		    "RSNN_NN issue IOCB failed (%d).\n", rval);
		goto done_free_sp;
	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RSNN_NN") !=
	    QLA_SUCCESS) {
		rval = QLA_FUNCTION_FAILED;
	} else {
		ql_dbg(ql_dbg_disc, vha, 0x2052,
		    "RSNN_NN exiting normally.\n");
	}
	}
	ql_dbg(ql_dbg_disc, vha, 0xffff,
	    "Async-%s - hdl=%x.\n",
	    sp->name, sp->handle);


	return (rval);
	return rval;

done_free_sp:
	sp->free(sp);
done:
	return rval;
}
}


/**
/**
@@ -3204,7 +3387,7 @@ int qla24xx_post_gpnid_work(struct scsi_qla_host *vha, port_id_t *id)
	return qla2x00_post_work(vha, e);
	return qla2x00_post_work(vha, e);
}
}


void qla24xx_async_gpnid_done(scsi_qla_host_t *vha, srb_t *sp)
void qla24xx_sp_unmap(scsi_qla_host_t *vha, srb_t *sp)
{
{
	if (sp->u.iocb_cmd.u.ctarg.req) {
	if (sp->u.iocb_cmd.u.ctarg.req) {
		dma_free_coherent(&vha->hw->pdev->dev,
		dma_free_coherent(&vha->hw->pdev->dev,
@@ -3412,7 +3595,7 @@ static void qla2x00_async_gpnid_sp_done(void *s, int res)


	qla2x00_fcport_event_handler(vha, &ea);
	qla2x00_fcport_event_handler(vha, &ea);


	e = qla2x00_alloc_work(vha, QLA_EVT_GPNID_DONE);
	e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP);
	if (!e) {
	if (!e) {
		/* please ignore kernel warning. otherwise, we have mem leak. */
		/* please ignore kernel warning. otherwise, we have mem leak. */
		if (sp->u.iocb_cmd.u.ctarg.req) {
		if (sp->u.iocb_cmd.u.ctarg.req) {
@@ -3782,8 +3965,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
	}
	}


out:
out:
	/* re-use gpnid_done to free resource */
	qla24xx_sp_unmap(vha, sp);
	qla24xx_async_gpnid_done(vha, sp);
}
}


static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)
static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)
+18 −2
Original line number Original line Diff line number Diff line
@@ -4918,6 +4918,20 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
	}
	}
}
}


static void qla_sp_retry(struct scsi_qla_host *vha, struct qla_work_evt *e)
{
	struct srb *sp = e->u.iosb.sp;
	int rval;

	rval = qla2x00_start_sp(sp);
	if (rval != QLA_SUCCESS) {
		ql_dbg(ql_dbg_disc, vha, 0x2043,
		    "%s: %s: Re-issue IOCB failed (%d).\n",
		    __func__, sp->name, rval);
		qla24xx_sp_unmap(vha, sp);
	}
}

void
void
qla2x00_do_work(struct scsi_qla_host *vha)
qla2x00_do_work(struct scsi_qla_host *vha)
{
{
@@ -4971,8 +4985,8 @@ qla2x00_do_work(struct scsi_qla_host *vha)
		case QLA_EVT_GPNID:
		case QLA_EVT_GPNID:
			qla24xx_async_gpnid(vha, &e->u.gpnid.id);
			qla24xx_async_gpnid(vha, &e->u.gpnid.id);
			break;
			break;
		case QLA_EVT_GPNID_DONE:
		case QLA_EVT_UNMAP:
			qla24xx_async_gpnid_done(vha, e->u.iosb.sp);
			qla24xx_sp_unmap(vha, e->u.iosb.sp);
			break;
			break;
		case QLA_EVT_RELOGIN:
		case QLA_EVT_RELOGIN:
			qla2x00_relogin(vha);
			qla2x00_relogin(vha);
@@ -5021,6 +5035,8 @@ qla2x00_do_work(struct scsi_qla_host *vha)
		case QLA_EVT_GFPNID:
		case QLA_EVT_GFPNID:
			qla24xx_async_gfpnid(vha, e->u.fcport.fcport);
			qla24xx_async_gfpnid(vha, e->u.fcport.fcport);
			break;
			break;
		case QLA_EVT_SP_RETRY:
			qla_sp_retry(vha, e);
		}
		}
		if (e->flags & QLA_EVT_FLAG_FREE)
		if (e->flags & QLA_EVT_FLAG_FREE)
			kfree(e);
			kfree(e);
+8 −5
Original line number Original line Diff line number Diff line
@@ -6619,18 +6619,21 @@ qlt_vport_create(struct scsi_qla_host *vha, struct qla_hw_data *ha)
	qlt_add_target(ha, vha);
	qlt_add_target(ha, vha);
}
}


void
u8
qlt_rff_id(struct scsi_qla_host *vha, struct ct_sns_req *ct_req)
qlt_rff_id(struct scsi_qla_host *vha)
{
{
	u8 fc4_feature = 0;
	/*
	/*
	 * FC-4 Feature bit 0 indicates target functionality to the name server.
	 * FC-4 Feature bit 0 indicates target functionality to the name server.
	 */
	 */
	if (qla_tgt_mode_enabled(vha)) {
	if (qla_tgt_mode_enabled(vha)) {
		ct_req->req.rff_id.fc4_feature = BIT_0;
		fc4_feature = BIT_0;
	} else if (qla_ini_mode_enabled(vha)) {
	} else if (qla_ini_mode_enabled(vha)) {
		ct_req->req.rff_id.fc4_feature = BIT_1;
		fc4_feature = BIT_1;
	} else if (qla_dual_mode_enabled(vha))
	} else if (qla_dual_mode_enabled(vha))
		ct_req->req.rff_id.fc4_feature = BIT_0 | BIT_1;
		fc4_feature = BIT_0 | BIT_1;

	return fc4_feature;
}
}


/*
/*
Loading