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

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
...@@ -535,6 +535,7 @@ typedef struct srb { ...@@ -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 { ...@@ -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 { ...@@ -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,
}; };
......
...@@ -650,7 +650,6 @@ extern void qla2x00_free_fcport(fc_port_t *); ...@@ -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 *); ...@@ -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.
......
...@@ -14,6 +14,10 @@ static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *); ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
qlt_rff_id(vha, ct_req); 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;
}
ct_req->req.rff_id.fc4_type = type; /* SCSI - FCP */ 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;
/* Execute MS IOCB */ /* Prepare CT request */
rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, ct_req = qla2x00_prep_ct_req(ct_sns, RFF_ID_CMD, RFF_ID_RSP_SIZE);
sizeof(ms_iocb_entry_t));
/* 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;
rval = qla2x00_start_sp(sp);
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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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)
......
...@@ -4918,6 +4918,20 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) ...@@ -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) ...@@ -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) ...@@ -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);
......
...@@ -6619,18 +6619,21 @@ qlt_vport_create(struct scsi_qla_host *vha, struct qla_hw_data *ha) ...@@ -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;
} }
/* /*
......
...@@ -1072,7 +1072,7 @@ extern void qlt_free_cmd(struct qla_tgt_cmd *cmd); ...@@ -1072,7 +1072,7 @@ extern void qlt_free_cmd(struct qla_tgt_cmd *cmd);
extern void qlt_async_event(uint16_t, struct scsi_qla_host *, uint16_t *); extern void qlt_async_event(uint16_t, struct scsi_qla_host *, uint16_t *);
extern void qlt_enable_vha(struct scsi_qla_host *); extern void qlt_enable_vha(struct scsi_qla_host *);
extern void qlt_vport_create(struct scsi_qla_host *, struct qla_hw_data *); extern void qlt_vport_create(struct scsi_qla_host *, struct qla_hw_data *);
extern void qlt_rff_id(struct scsi_qla_host *, struct ct_sns_req *); extern u8 qlt_rff_id(struct scsi_qla_host *);
extern void qlt_init_atio_q_entries(struct scsi_qla_host *); extern void qlt_init_atio_q_entries(struct scsi_qla_host *);
extern void qlt_24xx_process_atio_queue(struct scsi_qla_host *, uint8_t); extern void qlt_24xx_process_atio_queue(struct scsi_qla_host *, uint8_t);
extern void qlt_24xx_config_rings(struct scsi_qla_host *); extern void qlt_24xx_config_rings(struct scsi_qla_host *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment