18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * QLogic Fibre Channel HBA Driver
48c2ecf20Sopenharmony_ci * Copyright (c)  2003-2014 QLogic Corporation
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci#include "qla_def.h"
78c2ecf20Sopenharmony_ci#include "qla_target.h"
88c2ecf20Sopenharmony_ci#include <linux/utsname.h>
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_cistatic int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *);
118c2ecf20Sopenharmony_cistatic int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *);
128c2ecf20Sopenharmony_cistatic int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *);
138c2ecf20Sopenharmony_cistatic int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *);
148c2ecf20Sopenharmony_cistatic int qla2x00_sns_rft_id(scsi_qla_host_t *);
158c2ecf20Sopenharmony_cistatic int qla2x00_sns_rnn_id(scsi_qla_host_t *);
168c2ecf20Sopenharmony_cistatic int qla_async_rftid(scsi_qla_host_t *, port_id_t *);
178c2ecf20Sopenharmony_cistatic int qla_async_rffid(scsi_qla_host_t *, port_id_t *, u8, u8);
188c2ecf20Sopenharmony_cistatic int qla_async_rnnid(scsi_qla_host_t *, port_id_t *, u8*);
198c2ecf20Sopenharmony_cistatic int qla_async_rsnn_nn(scsi_qla_host_t *);
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/**
248c2ecf20Sopenharmony_ci * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query.
258c2ecf20Sopenharmony_ci * @vha: HA context
268c2ecf20Sopenharmony_ci * @arg: CT arguments
278c2ecf20Sopenharmony_ci *
288c2ecf20Sopenharmony_ci * Returns a pointer to the @vha's ms_iocb.
298c2ecf20Sopenharmony_ci */
308c2ecf20Sopenharmony_civoid *
318c2ecf20Sopenharmony_ciqla2x00_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
348c2ecf20Sopenharmony_ci	ms_iocb_entry_t *ms_pkt;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	ms_pkt = (ms_iocb_entry_t *)arg->iocb;
378c2ecf20Sopenharmony_ci	memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	ms_pkt->entry_type = MS_IOCB_TYPE;
408c2ecf20Sopenharmony_ci	ms_pkt->entry_count = 1;
418c2ecf20Sopenharmony_ci	SET_TARGET_ID(ha, ms_pkt->loop_id, SIMPLE_NAME_SERVER);
428c2ecf20Sopenharmony_ci	ms_pkt->control_flags = cpu_to_le16(CF_READ | CF_HEAD_TAG);
438c2ecf20Sopenharmony_ci	ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
448c2ecf20Sopenharmony_ci	ms_pkt->cmd_dsd_count = cpu_to_le16(1);
458c2ecf20Sopenharmony_ci	ms_pkt->total_dsd_count = cpu_to_le16(2);
468c2ecf20Sopenharmony_ci	ms_pkt->rsp_bytecount = cpu_to_le32(arg->rsp_size);
478c2ecf20Sopenharmony_ci	ms_pkt->req_bytecount = cpu_to_le32(arg->req_size);
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	put_unaligned_le64(arg->req_dma, &ms_pkt->req_dsd.address);
508c2ecf20Sopenharmony_ci	ms_pkt->req_dsd.length = ms_pkt->req_bytecount;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	put_unaligned_le64(arg->rsp_dma, &ms_pkt->rsp_dsd.address);
538c2ecf20Sopenharmony_ci	ms_pkt->rsp_dsd.length = ms_pkt->rsp_bytecount;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	vha->qla_stats.control_requests++;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	return (ms_pkt);
588c2ecf20Sopenharmony_ci}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci/**
618c2ecf20Sopenharmony_ci * qla24xx_prep_ms_iocb() - Prepare common CT IOCB fields for SNS CT query.
628c2ecf20Sopenharmony_ci * @vha: HA context
638c2ecf20Sopenharmony_ci * @arg: CT arguments
648c2ecf20Sopenharmony_ci *
658c2ecf20Sopenharmony_ci * Returns a pointer to the @ha's ms_iocb.
668c2ecf20Sopenharmony_ci */
678c2ecf20Sopenharmony_civoid *
688c2ecf20Sopenharmony_ciqla24xx_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
718c2ecf20Sopenharmony_ci	struct ct_entry_24xx *ct_pkt;
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	ct_pkt = (struct ct_entry_24xx *)arg->iocb;
748c2ecf20Sopenharmony_ci	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	ct_pkt->entry_type = CT_IOCB_TYPE;
778c2ecf20Sopenharmony_ci	ct_pkt->entry_count = 1;
788c2ecf20Sopenharmony_ci	ct_pkt->nport_handle = cpu_to_le16(arg->nport_handle);
798c2ecf20Sopenharmony_ci	ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
808c2ecf20Sopenharmony_ci	ct_pkt->cmd_dsd_count = cpu_to_le16(1);
818c2ecf20Sopenharmony_ci	ct_pkt->rsp_dsd_count = cpu_to_le16(1);
828c2ecf20Sopenharmony_ci	ct_pkt->rsp_byte_count = cpu_to_le32(arg->rsp_size);
838c2ecf20Sopenharmony_ci	ct_pkt->cmd_byte_count = cpu_to_le32(arg->req_size);
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	put_unaligned_le64(arg->req_dma, &ct_pkt->dsd[0].address);
868c2ecf20Sopenharmony_ci	ct_pkt->dsd[0].length = ct_pkt->cmd_byte_count;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	put_unaligned_le64(arg->rsp_dma, &ct_pkt->dsd[1].address);
898c2ecf20Sopenharmony_ci	ct_pkt->dsd[1].length = ct_pkt->rsp_byte_count;
908c2ecf20Sopenharmony_ci	ct_pkt->vp_index = vha->vp_idx;
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	vha->qla_stats.control_requests++;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	return (ct_pkt);
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci/**
988c2ecf20Sopenharmony_ci * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
998c2ecf20Sopenharmony_ci * @p: CT request buffer
1008c2ecf20Sopenharmony_ci * @cmd: GS command
1018c2ecf20Sopenharmony_ci * @rsp_size: response size in bytes
1028c2ecf20Sopenharmony_ci *
1038c2ecf20Sopenharmony_ci * Returns a pointer to the intitialized @ct_req.
1048c2ecf20Sopenharmony_ci */
1058c2ecf20Sopenharmony_cistatic inline struct ct_sns_req *
1068c2ecf20Sopenharmony_ciqla2x00_prep_ct_req(struct ct_sns_pkt *p, uint16_t cmd, uint16_t rsp_size)
1078c2ecf20Sopenharmony_ci{
1088c2ecf20Sopenharmony_ci	memset(p, 0, sizeof(struct ct_sns_pkt));
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	p->p.req.header.revision = 0x01;
1118c2ecf20Sopenharmony_ci	p->p.req.header.gs_type = 0xFC;
1128c2ecf20Sopenharmony_ci	p->p.req.header.gs_subtype = 0x02;
1138c2ecf20Sopenharmony_ci	p->p.req.command = cpu_to_be16(cmd);
1148c2ecf20Sopenharmony_ci	p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	return &p->p.req;
1178c2ecf20Sopenharmony_ci}
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ciint
1208c2ecf20Sopenharmony_ciqla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
1218c2ecf20Sopenharmony_ci    struct ct_sns_rsp *ct_rsp, const char *routine)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	int rval;
1248c2ecf20Sopenharmony_ci	uint16_t comp_status;
1258c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
1268c2ecf20Sopenharmony_ci	bool lid_is_sns = false;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	rval = QLA_FUNCTION_FAILED;
1298c2ecf20Sopenharmony_ci	if (ms_pkt->entry_status != 0) {
1308c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x2031,
1318c2ecf20Sopenharmony_ci		    "%s failed, error status (%x) on port_id: %02x%02x%02x.\n",
1328c2ecf20Sopenharmony_ci		    routine, ms_pkt->entry_status, vha->d_id.b.domain,
1338c2ecf20Sopenharmony_ci		    vha->d_id.b.area, vha->d_id.b.al_pa);
1348c2ecf20Sopenharmony_ci	} else {
1358c2ecf20Sopenharmony_ci		if (IS_FWI2_CAPABLE(ha))
1368c2ecf20Sopenharmony_ci			comp_status = le16_to_cpu(
1378c2ecf20Sopenharmony_ci			    ((struct ct_entry_24xx *)ms_pkt)->comp_status);
1388c2ecf20Sopenharmony_ci		else
1398c2ecf20Sopenharmony_ci			comp_status = le16_to_cpu(ms_pkt->status);
1408c2ecf20Sopenharmony_ci		switch (comp_status) {
1418c2ecf20Sopenharmony_ci		case CS_COMPLETE:
1428c2ecf20Sopenharmony_ci		case CS_DATA_UNDERRUN:
1438c2ecf20Sopenharmony_ci		case CS_DATA_OVERRUN:		/* Overrun? */
1448c2ecf20Sopenharmony_ci			if (ct_rsp->header.response !=
1458c2ecf20Sopenharmony_ci			    cpu_to_be16(CT_ACCEPT_RESPONSE)) {
1468c2ecf20Sopenharmony_ci				ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2077,
1478c2ecf20Sopenharmony_ci				    "%s failed rejected request on port_id: %02x%02x%02x Completion status 0x%x, response 0x%x\n",
1488c2ecf20Sopenharmony_ci				    routine, vha->d_id.b.domain,
1498c2ecf20Sopenharmony_ci				    vha->d_id.b.area, vha->d_id.b.al_pa,
1508c2ecf20Sopenharmony_ci				    comp_status, ct_rsp->header.response);
1518c2ecf20Sopenharmony_ci				ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha,
1528c2ecf20Sopenharmony_ci				    0x2078, ct_rsp,
1538c2ecf20Sopenharmony_ci				    offsetof(typeof(*ct_rsp), rsp));
1548c2ecf20Sopenharmony_ci				rval = QLA_INVALID_COMMAND;
1558c2ecf20Sopenharmony_ci			} else
1568c2ecf20Sopenharmony_ci				rval = QLA_SUCCESS;
1578c2ecf20Sopenharmony_ci			break;
1588c2ecf20Sopenharmony_ci		case CS_PORT_LOGGED_OUT:
1598c2ecf20Sopenharmony_ci			if (IS_FWI2_CAPABLE(ha)) {
1608c2ecf20Sopenharmony_ci				if (le16_to_cpu(ms_pkt->loop_id.extended) ==
1618c2ecf20Sopenharmony_ci				    NPH_SNS)
1628c2ecf20Sopenharmony_ci					lid_is_sns = true;
1638c2ecf20Sopenharmony_ci			} else {
1648c2ecf20Sopenharmony_ci				if (le16_to_cpu(ms_pkt->loop_id.extended) ==
1658c2ecf20Sopenharmony_ci				    SIMPLE_NAME_SERVER)
1668c2ecf20Sopenharmony_ci					lid_is_sns = true;
1678c2ecf20Sopenharmony_ci			}
1688c2ecf20Sopenharmony_ci			if (lid_is_sns) {
1698c2ecf20Sopenharmony_ci				ql_dbg(ql_dbg_async, vha, 0x502b,
1708c2ecf20Sopenharmony_ci					"%s failed, Name server has logged out",
1718c2ecf20Sopenharmony_ci					routine);
1728c2ecf20Sopenharmony_ci				rval = QLA_NOT_LOGGED_IN;
1738c2ecf20Sopenharmony_ci				set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
1748c2ecf20Sopenharmony_ci				set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
1758c2ecf20Sopenharmony_ci			}
1768c2ecf20Sopenharmony_ci			break;
1778c2ecf20Sopenharmony_ci		case CS_TIMEOUT:
1788c2ecf20Sopenharmony_ci			rval = QLA_FUNCTION_TIMEOUT;
1798c2ecf20Sopenharmony_ci			fallthrough;
1808c2ecf20Sopenharmony_ci		default:
1818c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x2033,
1828c2ecf20Sopenharmony_ci			    "%s failed, completion status (%x) on port_id: "
1838c2ecf20Sopenharmony_ci			    "%02x%02x%02x.\n", routine, comp_status,
1848c2ecf20Sopenharmony_ci			    vha->d_id.b.domain, vha->d_id.b.area,
1858c2ecf20Sopenharmony_ci			    vha->d_id.b.al_pa);
1868c2ecf20Sopenharmony_ci			break;
1878c2ecf20Sopenharmony_ci		}
1888c2ecf20Sopenharmony_ci	}
1898c2ecf20Sopenharmony_ci	return rval;
1908c2ecf20Sopenharmony_ci}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci/**
1938c2ecf20Sopenharmony_ci * qla2x00_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
1948c2ecf20Sopenharmony_ci * @vha: HA context
1958c2ecf20Sopenharmony_ci * @fcport: fcport entry to updated
1968c2ecf20Sopenharmony_ci *
1978c2ecf20Sopenharmony_ci * Returns 0 on success.
1988c2ecf20Sopenharmony_ci */
1998c2ecf20Sopenharmony_ciint
2008c2ecf20Sopenharmony_ciqla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
2018c2ecf20Sopenharmony_ci{
2028c2ecf20Sopenharmony_ci	int		rval;
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	ms_iocb_entry_t	*ms_pkt;
2058c2ecf20Sopenharmony_ci	struct ct_sns_req	*ct_req;
2068c2ecf20Sopenharmony_ci	struct ct_sns_rsp	*ct_rsp;
2078c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
2088c2ecf20Sopenharmony_ci	struct ct_arg arg;
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	if (IS_QLA2100(ha) || IS_QLA2200(ha))
2118c2ecf20Sopenharmony_ci		return qla2x00_sns_ga_nxt(vha, fcport);
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	arg.iocb = ha->ms_iocb;
2148c2ecf20Sopenharmony_ci	arg.req_dma = ha->ct_sns_dma;
2158c2ecf20Sopenharmony_ci	arg.rsp_dma = ha->ct_sns_dma;
2168c2ecf20Sopenharmony_ci	arg.req_size = GA_NXT_REQ_SIZE;
2178c2ecf20Sopenharmony_ci	arg.rsp_size = GA_NXT_RSP_SIZE;
2188c2ecf20Sopenharmony_ci	arg.nport_handle = NPH_SNS;
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	/* Issue GA_NXT */
2218c2ecf20Sopenharmony_ci	/* Prepare common MS IOCB */
2228c2ecf20Sopenharmony_ci	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	/* Prepare CT request */
2258c2ecf20Sopenharmony_ci	ct_req = qla2x00_prep_ct_req(ha->ct_sns, GA_NXT_CMD,
2268c2ecf20Sopenharmony_ci	    GA_NXT_RSP_SIZE);
2278c2ecf20Sopenharmony_ci	ct_rsp = &ha->ct_sns->p.rsp;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	/* Prepare CT arguments -- port_id */
2308c2ecf20Sopenharmony_ci	ct_req->req.port_id.port_id = port_id_to_be_id(fcport->d_id);
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	/* Execute MS IOCB */
2338c2ecf20Sopenharmony_ci	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2348c2ecf20Sopenharmony_ci	    sizeof(ms_iocb_entry_t));
2358c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS) {
2368c2ecf20Sopenharmony_ci		/*EMPTY*/
2378c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x2062,
2388c2ecf20Sopenharmony_ci		    "GA_NXT issue IOCB failed (%d).\n", rval);
2398c2ecf20Sopenharmony_ci	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GA_NXT") !=
2408c2ecf20Sopenharmony_ci	    QLA_SUCCESS) {
2418c2ecf20Sopenharmony_ci		rval = QLA_FUNCTION_FAILED;
2428c2ecf20Sopenharmony_ci	} else {
2438c2ecf20Sopenharmony_ci		/* Populate fc_port_t entry. */
2448c2ecf20Sopenharmony_ci		fcport->d_id = be_to_port_id(ct_rsp->rsp.ga_nxt.port_id);
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci		memcpy(fcport->node_name, ct_rsp->rsp.ga_nxt.node_name,
2478c2ecf20Sopenharmony_ci		    WWN_SIZE);
2488c2ecf20Sopenharmony_ci		memcpy(fcport->port_name, ct_rsp->rsp.ga_nxt.port_name,
2498c2ecf20Sopenharmony_ci		    WWN_SIZE);
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci		fcport->fc4_type = (ct_rsp->rsp.ga_nxt.fc4_types[2] & BIT_0) ?
2528c2ecf20Sopenharmony_ci		    FS_FC4TYPE_FCP : FC4_TYPE_OTHER;
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci		if (ct_rsp->rsp.ga_nxt.port_type != NS_N_PORT_TYPE &&
2558c2ecf20Sopenharmony_ci		    ct_rsp->rsp.ga_nxt.port_type != NS_NL_PORT_TYPE)
2568c2ecf20Sopenharmony_ci			fcport->d_id.b.domain = 0xf0;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x2063,
2598c2ecf20Sopenharmony_ci		    "GA_NXT entry - nn %8phN pn %8phN "
2608c2ecf20Sopenharmony_ci		    "port_id=%02x%02x%02x.\n",
2618c2ecf20Sopenharmony_ci		    fcport->node_name, fcport->port_name,
2628c2ecf20Sopenharmony_ci		    fcport->d_id.b.domain, fcport->d_id.b.area,
2638c2ecf20Sopenharmony_ci		    fcport->d_id.b.al_pa);
2648c2ecf20Sopenharmony_ci	}
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	return (rval);
2678c2ecf20Sopenharmony_ci}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_cistatic inline int
2708c2ecf20Sopenharmony_ciqla2x00_gid_pt_rsp_size(scsi_qla_host_t *vha)
2718c2ecf20Sopenharmony_ci{
2728c2ecf20Sopenharmony_ci	return vha->hw->max_fibre_devices * 4 + 16;
2738c2ecf20Sopenharmony_ci}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci/**
2768c2ecf20Sopenharmony_ci * qla2x00_gid_pt() - SNS scan for fabric devices via GID_PT command.
2778c2ecf20Sopenharmony_ci * @vha: HA context
2788c2ecf20Sopenharmony_ci * @list: switch info entries to populate
2798c2ecf20Sopenharmony_ci *
2808c2ecf20Sopenharmony_ci * NOTE: Non-Nx_Ports are not requested.
2818c2ecf20Sopenharmony_ci *
2828c2ecf20Sopenharmony_ci * Returns 0 on success.
2838c2ecf20Sopenharmony_ci */
2848c2ecf20Sopenharmony_ciint
2858c2ecf20Sopenharmony_ciqla2x00_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
2868c2ecf20Sopenharmony_ci{
2878c2ecf20Sopenharmony_ci	int		rval;
2888c2ecf20Sopenharmony_ci	uint16_t	i;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	ms_iocb_entry_t	*ms_pkt;
2918c2ecf20Sopenharmony_ci	struct ct_sns_req	*ct_req;
2928c2ecf20Sopenharmony_ci	struct ct_sns_rsp	*ct_rsp;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	struct ct_sns_gid_pt_data *gid_data;
2958c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
2968c2ecf20Sopenharmony_ci	uint16_t gid_pt_rsp_size;
2978c2ecf20Sopenharmony_ci	struct ct_arg arg;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	if (IS_QLA2100(ha) || IS_QLA2200(ha))
3008c2ecf20Sopenharmony_ci		return qla2x00_sns_gid_pt(vha, list);
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	gid_data = NULL;
3038c2ecf20Sopenharmony_ci	gid_pt_rsp_size = qla2x00_gid_pt_rsp_size(vha);
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	arg.iocb = ha->ms_iocb;
3068c2ecf20Sopenharmony_ci	arg.req_dma = ha->ct_sns_dma;
3078c2ecf20Sopenharmony_ci	arg.rsp_dma = ha->ct_sns_dma;
3088c2ecf20Sopenharmony_ci	arg.req_size = GID_PT_REQ_SIZE;
3098c2ecf20Sopenharmony_ci	arg.rsp_size = gid_pt_rsp_size;
3108c2ecf20Sopenharmony_ci	arg.nport_handle = NPH_SNS;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	/* Issue GID_PT */
3138c2ecf20Sopenharmony_ci	/* Prepare common MS IOCB */
3148c2ecf20Sopenharmony_ci	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	/* Prepare CT request */
3178c2ecf20Sopenharmony_ci	ct_req = qla2x00_prep_ct_req(ha->ct_sns, GID_PT_CMD, gid_pt_rsp_size);
3188c2ecf20Sopenharmony_ci	ct_rsp = &ha->ct_sns->p.rsp;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	/* Prepare CT arguments -- port_type */
3218c2ecf20Sopenharmony_ci	ct_req->req.gid_pt.port_type = NS_NX_PORT_TYPE;
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	/* Execute MS IOCB */
3248c2ecf20Sopenharmony_ci	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
3258c2ecf20Sopenharmony_ci	    sizeof(ms_iocb_entry_t));
3268c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS) {
3278c2ecf20Sopenharmony_ci		/*EMPTY*/
3288c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x2055,
3298c2ecf20Sopenharmony_ci		    "GID_PT issue IOCB failed (%d).\n", rval);
3308c2ecf20Sopenharmony_ci	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GID_PT") !=
3318c2ecf20Sopenharmony_ci	    QLA_SUCCESS) {
3328c2ecf20Sopenharmony_ci		rval = QLA_FUNCTION_FAILED;
3338c2ecf20Sopenharmony_ci	} else {
3348c2ecf20Sopenharmony_ci		/* Set port IDs in switch info list. */
3358c2ecf20Sopenharmony_ci		for (i = 0; i < ha->max_fibre_devices; i++) {
3368c2ecf20Sopenharmony_ci			gid_data = &ct_rsp->rsp.gid_pt.entries[i];
3378c2ecf20Sopenharmony_ci			list[i].d_id = be_to_port_id(gid_data->port_id);
3388c2ecf20Sopenharmony_ci			memset(list[i].fabric_port_name, 0, WWN_SIZE);
3398c2ecf20Sopenharmony_ci			list[i].fp_speed = PORT_SPEED_UNKNOWN;
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci			/* Last one exit. */
3428c2ecf20Sopenharmony_ci			if (gid_data->control_byte & BIT_7) {
3438c2ecf20Sopenharmony_ci				list[i].d_id.b.rsvd_1 = gid_data->control_byte;
3448c2ecf20Sopenharmony_ci				break;
3458c2ecf20Sopenharmony_ci			}
3468c2ecf20Sopenharmony_ci		}
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci		/*
3498c2ecf20Sopenharmony_ci		 * If we've used all available slots, then the switch is
3508c2ecf20Sopenharmony_ci		 * reporting back more devices than we can handle with this
3518c2ecf20Sopenharmony_ci		 * single call.  Return a failed status, and let GA_NXT handle
3528c2ecf20Sopenharmony_ci		 * the overload.
3538c2ecf20Sopenharmony_ci		 */
3548c2ecf20Sopenharmony_ci		if (i == ha->max_fibre_devices)
3558c2ecf20Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
3568c2ecf20Sopenharmony_ci	}
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	return (rval);
3598c2ecf20Sopenharmony_ci}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci/**
3628c2ecf20Sopenharmony_ci * qla2x00_gpn_id() - SNS Get Port Name (GPN_ID) query.
3638c2ecf20Sopenharmony_ci * @vha: HA context
3648c2ecf20Sopenharmony_ci * @list: switch info entries to populate
3658c2ecf20Sopenharmony_ci *
3668c2ecf20Sopenharmony_ci * Returns 0 on success.
3678c2ecf20Sopenharmony_ci */
3688c2ecf20Sopenharmony_ciint
3698c2ecf20Sopenharmony_ciqla2x00_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
3708c2ecf20Sopenharmony_ci{
3718c2ecf20Sopenharmony_ci	int		rval = QLA_SUCCESS;
3728c2ecf20Sopenharmony_ci	uint16_t	i;
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	ms_iocb_entry_t	*ms_pkt;
3758c2ecf20Sopenharmony_ci	struct ct_sns_req	*ct_req;
3768c2ecf20Sopenharmony_ci	struct ct_sns_rsp	*ct_rsp;
3778c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
3788c2ecf20Sopenharmony_ci	struct ct_arg arg;
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	if (IS_QLA2100(ha) || IS_QLA2200(ha))
3818c2ecf20Sopenharmony_ci		return qla2x00_sns_gpn_id(vha, list);
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	arg.iocb = ha->ms_iocb;
3848c2ecf20Sopenharmony_ci	arg.req_dma = ha->ct_sns_dma;
3858c2ecf20Sopenharmony_ci	arg.rsp_dma = ha->ct_sns_dma;
3868c2ecf20Sopenharmony_ci	arg.req_size = GPN_ID_REQ_SIZE;
3878c2ecf20Sopenharmony_ci	arg.rsp_size = GPN_ID_RSP_SIZE;
3888c2ecf20Sopenharmony_ci	arg.nport_handle = NPH_SNS;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	for (i = 0; i < ha->max_fibre_devices; i++) {
3918c2ecf20Sopenharmony_ci		/* Issue GPN_ID */
3928c2ecf20Sopenharmony_ci		/* Prepare common MS IOCB */
3938c2ecf20Sopenharmony_ci		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci		/* Prepare CT request */
3968c2ecf20Sopenharmony_ci		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GPN_ID_CMD,
3978c2ecf20Sopenharmony_ci		    GPN_ID_RSP_SIZE);
3988c2ecf20Sopenharmony_ci		ct_rsp = &ha->ct_sns->p.rsp;
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci		/* Prepare CT arguments -- port_id */
4018c2ecf20Sopenharmony_ci		ct_req->req.port_id.port_id = port_id_to_be_id(list[i].d_id);
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci		/* Execute MS IOCB */
4048c2ecf20Sopenharmony_ci		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
4058c2ecf20Sopenharmony_ci		    sizeof(ms_iocb_entry_t));
4068c2ecf20Sopenharmony_ci		if (rval != QLA_SUCCESS) {
4078c2ecf20Sopenharmony_ci			/*EMPTY*/
4088c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x2056,
4098c2ecf20Sopenharmony_ci			    "GPN_ID issue IOCB failed (%d).\n", rval);
4108c2ecf20Sopenharmony_ci			break;
4118c2ecf20Sopenharmony_ci		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
4128c2ecf20Sopenharmony_ci		    "GPN_ID") != QLA_SUCCESS) {
4138c2ecf20Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
4148c2ecf20Sopenharmony_ci			break;
4158c2ecf20Sopenharmony_ci		} else {
4168c2ecf20Sopenharmony_ci			/* Save portname */
4178c2ecf20Sopenharmony_ci			memcpy(list[i].port_name,
4188c2ecf20Sopenharmony_ci			    ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);
4198c2ecf20Sopenharmony_ci		}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci		/* Last device exit. */
4228c2ecf20Sopenharmony_ci		if (list[i].d_id.b.rsvd_1 != 0)
4238c2ecf20Sopenharmony_ci			break;
4248c2ecf20Sopenharmony_ci	}
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	return (rval);
4278c2ecf20Sopenharmony_ci}
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci/**
4308c2ecf20Sopenharmony_ci * qla2x00_gnn_id() - SNS Get Node Name (GNN_ID) query.
4318c2ecf20Sopenharmony_ci * @vha: HA context
4328c2ecf20Sopenharmony_ci * @list: switch info entries to populate
4338c2ecf20Sopenharmony_ci *
4348c2ecf20Sopenharmony_ci * Returns 0 on success.
4358c2ecf20Sopenharmony_ci */
4368c2ecf20Sopenharmony_ciint
4378c2ecf20Sopenharmony_ciqla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
4388c2ecf20Sopenharmony_ci{
4398c2ecf20Sopenharmony_ci	int		rval = QLA_SUCCESS;
4408c2ecf20Sopenharmony_ci	uint16_t	i;
4418c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
4428c2ecf20Sopenharmony_ci	ms_iocb_entry_t	*ms_pkt;
4438c2ecf20Sopenharmony_ci	struct ct_sns_req	*ct_req;
4448c2ecf20Sopenharmony_ci	struct ct_sns_rsp	*ct_rsp;
4458c2ecf20Sopenharmony_ci	struct ct_arg arg;
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	if (IS_QLA2100(ha) || IS_QLA2200(ha))
4488c2ecf20Sopenharmony_ci		return qla2x00_sns_gnn_id(vha, list);
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	arg.iocb = ha->ms_iocb;
4518c2ecf20Sopenharmony_ci	arg.req_dma = ha->ct_sns_dma;
4528c2ecf20Sopenharmony_ci	arg.rsp_dma = ha->ct_sns_dma;
4538c2ecf20Sopenharmony_ci	arg.req_size = GNN_ID_REQ_SIZE;
4548c2ecf20Sopenharmony_ci	arg.rsp_size = GNN_ID_RSP_SIZE;
4558c2ecf20Sopenharmony_ci	arg.nport_handle = NPH_SNS;
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	for (i = 0; i < ha->max_fibre_devices; i++) {
4588c2ecf20Sopenharmony_ci		/* Issue GNN_ID */
4598c2ecf20Sopenharmony_ci		/* Prepare common MS IOCB */
4608c2ecf20Sopenharmony_ci		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci		/* Prepare CT request */
4638c2ecf20Sopenharmony_ci		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GNN_ID_CMD,
4648c2ecf20Sopenharmony_ci		    GNN_ID_RSP_SIZE);
4658c2ecf20Sopenharmony_ci		ct_rsp = &ha->ct_sns->p.rsp;
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci		/* Prepare CT arguments -- port_id */
4688c2ecf20Sopenharmony_ci		ct_req->req.port_id.port_id = port_id_to_be_id(list[i].d_id);
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci		/* Execute MS IOCB */
4718c2ecf20Sopenharmony_ci		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
4728c2ecf20Sopenharmony_ci		    sizeof(ms_iocb_entry_t));
4738c2ecf20Sopenharmony_ci		if (rval != QLA_SUCCESS) {
4748c2ecf20Sopenharmony_ci			/*EMPTY*/
4758c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x2057,
4768c2ecf20Sopenharmony_ci			    "GNN_ID issue IOCB failed (%d).\n", rval);
4778c2ecf20Sopenharmony_ci			break;
4788c2ecf20Sopenharmony_ci		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
4798c2ecf20Sopenharmony_ci		    "GNN_ID") != QLA_SUCCESS) {
4808c2ecf20Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
4818c2ecf20Sopenharmony_ci			break;
4828c2ecf20Sopenharmony_ci		} else {
4838c2ecf20Sopenharmony_ci			/* Save nodename */
4848c2ecf20Sopenharmony_ci			memcpy(list[i].node_name,
4858c2ecf20Sopenharmony_ci			    ct_rsp->rsp.gnn_id.node_name, WWN_SIZE);
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x2058,
4888c2ecf20Sopenharmony_ci			    "GID_PT entry - nn %8phN pn %8phN "
4898c2ecf20Sopenharmony_ci			    "portid=%02x%02x%02x.\n",
4908c2ecf20Sopenharmony_ci			    list[i].node_name, list[i].port_name,
4918c2ecf20Sopenharmony_ci			    list[i].d_id.b.domain, list[i].d_id.b.area,
4928c2ecf20Sopenharmony_ci			    list[i].d_id.b.al_pa);
4938c2ecf20Sopenharmony_ci		}
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci		/* Last device exit. */
4968c2ecf20Sopenharmony_ci		if (list[i].d_id.b.rsvd_1 != 0)
4978c2ecf20Sopenharmony_ci			break;
4988c2ecf20Sopenharmony_ci	}
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	return (rval);
5018c2ecf20Sopenharmony_ci}
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_cistatic void qla2x00_async_sns_sp_done(srb_t *sp, int rc)
5048c2ecf20Sopenharmony_ci{
5058c2ecf20Sopenharmony_ci	struct scsi_qla_host *vha = sp->vha;
5068c2ecf20Sopenharmony_ci	struct ct_sns_pkt *ct_sns;
5078c2ecf20Sopenharmony_ci	struct qla_work_evt *e;
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	sp->rc = rc;
5108c2ecf20Sopenharmony_ci	if (rc == QLA_SUCCESS) {
5118c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x204f,
5128c2ecf20Sopenharmony_ci		    "Async done-%s exiting normally.\n",
5138c2ecf20Sopenharmony_ci		    sp->name);
5148c2ecf20Sopenharmony_ci	} else if (rc == QLA_FUNCTION_TIMEOUT) {
5158c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x204f,
5168c2ecf20Sopenharmony_ci		    "Async done-%s timeout\n", sp->name);
5178c2ecf20Sopenharmony_ci	} else {
5188c2ecf20Sopenharmony_ci		ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
5198c2ecf20Sopenharmony_ci		memset(ct_sns, 0, sizeof(*ct_sns));
5208c2ecf20Sopenharmony_ci		sp->retry_count++;
5218c2ecf20Sopenharmony_ci		if (sp->retry_count > 3)
5228c2ecf20Sopenharmony_ci			goto err;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x204f,
5258c2ecf20Sopenharmony_ci		    "Async done-%s fail rc %x.  Retry count %d\n",
5268c2ecf20Sopenharmony_ci		    sp->name, rc, sp->retry_count);
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci		e = qla2x00_alloc_work(vha, QLA_EVT_SP_RETRY);
5298c2ecf20Sopenharmony_ci		if (!e)
5308c2ecf20Sopenharmony_ci			goto err2;
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci		del_timer(&sp->u.iocb_cmd.timer);
5338c2ecf20Sopenharmony_ci		e->u.iosb.sp = sp;
5348c2ecf20Sopenharmony_ci		qla2x00_post_work(vha, e);
5358c2ecf20Sopenharmony_ci		return;
5368c2ecf20Sopenharmony_ci	}
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_cierr:
5398c2ecf20Sopenharmony_ci	e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP);
5408c2ecf20Sopenharmony_cierr2:
5418c2ecf20Sopenharmony_ci	if (!e) {
5428c2ecf20Sopenharmony_ci		/* please ignore kernel warning. otherwise, we have mem leak. */
5438c2ecf20Sopenharmony_ci		if (sp->u.iocb_cmd.u.ctarg.req) {
5448c2ecf20Sopenharmony_ci			dma_free_coherent(&vha->hw->pdev->dev,
5458c2ecf20Sopenharmony_ci			    sp->u.iocb_cmd.u.ctarg.req_allocated_size,
5468c2ecf20Sopenharmony_ci			    sp->u.iocb_cmd.u.ctarg.req,
5478c2ecf20Sopenharmony_ci			    sp->u.iocb_cmd.u.ctarg.req_dma);
5488c2ecf20Sopenharmony_ci			sp->u.iocb_cmd.u.ctarg.req = NULL;
5498c2ecf20Sopenharmony_ci		}
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci		if (sp->u.iocb_cmd.u.ctarg.rsp) {
5528c2ecf20Sopenharmony_ci			dma_free_coherent(&vha->hw->pdev->dev,
5538c2ecf20Sopenharmony_ci			    sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
5548c2ecf20Sopenharmony_ci			    sp->u.iocb_cmd.u.ctarg.rsp,
5558c2ecf20Sopenharmony_ci			    sp->u.iocb_cmd.u.ctarg.rsp_dma);
5568c2ecf20Sopenharmony_ci			sp->u.iocb_cmd.u.ctarg.rsp = NULL;
5578c2ecf20Sopenharmony_ci		}
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci		sp->free(sp);
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci		return;
5628c2ecf20Sopenharmony_ci	}
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	e->u.iosb.sp = sp;
5658c2ecf20Sopenharmony_ci	qla2x00_post_work(vha, e);
5668c2ecf20Sopenharmony_ci}
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci/**
5698c2ecf20Sopenharmony_ci * qla2x00_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
5708c2ecf20Sopenharmony_ci * @vha: HA context
5718c2ecf20Sopenharmony_ci *
5728c2ecf20Sopenharmony_ci * Returns 0 on success.
5738c2ecf20Sopenharmony_ci */
5748c2ecf20Sopenharmony_ciint
5758c2ecf20Sopenharmony_ciqla2x00_rft_id(scsi_qla_host_t *vha)
5768c2ecf20Sopenharmony_ci{
5778c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	if (IS_QLA2100(ha) || IS_QLA2200(ha))
5808c2ecf20Sopenharmony_ci		return qla2x00_sns_rft_id(vha);
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	return qla_async_rftid(vha, &vha->d_id);
5838c2ecf20Sopenharmony_ci}
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_cistatic int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id)
5868c2ecf20Sopenharmony_ci{
5878c2ecf20Sopenharmony_ci	int rval = QLA_MEMORY_ALLOC_FAILED;
5888c2ecf20Sopenharmony_ci	struct ct_sns_req *ct_req;
5898c2ecf20Sopenharmony_ci	srb_t *sp;
5908c2ecf20Sopenharmony_ci	struct ct_sns_pkt *ct_sns;
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_ci	if (!vha->flags.online)
5938c2ecf20Sopenharmony_ci		goto done;
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
5968c2ecf20Sopenharmony_ci	if (!sp)
5978c2ecf20Sopenharmony_ci		goto done;
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	sp->type = SRB_CT_PTHRU_CMD;
6008c2ecf20Sopenharmony_ci	sp->name = "rft_id";
6018c2ecf20Sopenharmony_ci	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
6048c2ecf20Sopenharmony_ci	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
6058c2ecf20Sopenharmony_ci	    GFP_KERNEL);
6068c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt);
6078c2ecf20Sopenharmony_ci	if (!sp->u.iocb_cmd.u.ctarg.req) {
6088c2ecf20Sopenharmony_ci		ql_log(ql_log_warn, vha, 0xd041,
6098c2ecf20Sopenharmony_ci		    "%s: Failed to allocate ct_sns request.\n",
6108c2ecf20Sopenharmony_ci		    __func__);
6118c2ecf20Sopenharmony_ci		goto done_free_sp;
6128c2ecf20Sopenharmony_ci	}
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
6158c2ecf20Sopenharmony_ci	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
6168c2ecf20Sopenharmony_ci	    GFP_KERNEL);
6178c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = sizeof(struct ct_sns_pkt);
6188c2ecf20Sopenharmony_ci	if (!sp->u.iocb_cmd.u.ctarg.rsp) {
6198c2ecf20Sopenharmony_ci		ql_log(ql_log_warn, vha, 0xd042,
6208c2ecf20Sopenharmony_ci		    "%s: Failed to allocate ct_sns request.\n",
6218c2ecf20Sopenharmony_ci		    __func__);
6228c2ecf20Sopenharmony_ci		goto done_free_sp;
6238c2ecf20Sopenharmony_ci	}
6248c2ecf20Sopenharmony_ci	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
6258c2ecf20Sopenharmony_ci	memset(ct_sns, 0, sizeof(*ct_sns));
6268c2ecf20Sopenharmony_ci	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci	/* Prepare CT request */
6298c2ecf20Sopenharmony_ci	ct_req = qla2x00_prep_ct_req(ct_sns, RFT_ID_CMD, RFT_ID_RSP_SIZE);
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ci	/* Prepare CT arguments -- port_id, FC-4 types */
6328c2ecf20Sopenharmony_ci	ct_req->req.rft_id.port_id = port_id_to_be_id(vha->d_id);
6338c2ecf20Sopenharmony_ci	ct_req->req.rft_id.fc4_types[2] = 0x01;		/* FCP-3 */
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	if (vha->flags.nvme_enabled)
6368c2ecf20Sopenharmony_ci		ct_req->req.rft_id.fc4_types[6] = 1;    /* NVMe type 28h */
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_size = RFT_ID_REQ_SIZE;
6398c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp_size = RFT_ID_RSP_SIZE;
6408c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
6418c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
6428c2ecf20Sopenharmony_ci	sp->done = qla2x00_async_sns_sp_done;
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0xffff,
6458c2ecf20Sopenharmony_ci	    "Async-%s - hdl=%x portid %06x.\n",
6468c2ecf20Sopenharmony_ci	    sp->name, sp->handle, d_id->b24);
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	rval = qla2x00_start_sp(sp);
6498c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS) {
6508c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x2043,
6518c2ecf20Sopenharmony_ci		    "RFT_ID issue IOCB failed (%d).\n", rval);
6528c2ecf20Sopenharmony_ci		goto done_free_sp;
6538c2ecf20Sopenharmony_ci	}
6548c2ecf20Sopenharmony_ci	return rval;
6558c2ecf20Sopenharmony_cidone_free_sp:
6568c2ecf20Sopenharmony_ci	sp->free(sp);
6578c2ecf20Sopenharmony_cidone:
6588c2ecf20Sopenharmony_ci	return rval;
6598c2ecf20Sopenharmony_ci}
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci/**
6628c2ecf20Sopenharmony_ci * qla2x00_rff_id() - SNS Register FC-4 Features (RFF_ID) supported by the HBA.
6638c2ecf20Sopenharmony_ci * @vha: HA context
6648c2ecf20Sopenharmony_ci * @type: not used
6658c2ecf20Sopenharmony_ci *
6668c2ecf20Sopenharmony_ci * Returns 0 on success.
6678c2ecf20Sopenharmony_ci */
6688c2ecf20Sopenharmony_ciint
6698c2ecf20Sopenharmony_ciqla2x00_rff_id(scsi_qla_host_t *vha, u8 type)
6708c2ecf20Sopenharmony_ci{
6718c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
6748c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x2046,
6758c2ecf20Sopenharmony_ci		    "RFF_ID call not supported on ISP2100/ISP2200.\n");
6768c2ecf20Sopenharmony_ci		return (QLA_SUCCESS);
6778c2ecf20Sopenharmony_ci	}
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci	return qla_async_rffid(vha, &vha->d_id, qlt_rff_id(vha), type);
6808c2ecf20Sopenharmony_ci}
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_cistatic int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id,
6838c2ecf20Sopenharmony_ci    u8 fc4feature, u8 fc4type)
6848c2ecf20Sopenharmony_ci{
6858c2ecf20Sopenharmony_ci	int rval = QLA_MEMORY_ALLOC_FAILED;
6868c2ecf20Sopenharmony_ci	struct ct_sns_req *ct_req;
6878c2ecf20Sopenharmony_ci	srb_t *sp;
6888c2ecf20Sopenharmony_ci	struct ct_sns_pkt *ct_sns;
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
6918c2ecf20Sopenharmony_ci	if (!sp)
6928c2ecf20Sopenharmony_ci		goto done;
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci	sp->type = SRB_CT_PTHRU_CMD;
6958c2ecf20Sopenharmony_ci	sp->name = "rff_id";
6968c2ecf20Sopenharmony_ci	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
6998c2ecf20Sopenharmony_ci	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
7008c2ecf20Sopenharmony_ci	    GFP_KERNEL);
7018c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt);
7028c2ecf20Sopenharmony_ci	if (!sp->u.iocb_cmd.u.ctarg.req) {
7038c2ecf20Sopenharmony_ci		ql_log(ql_log_warn, vha, 0xd041,
7048c2ecf20Sopenharmony_ci		    "%s: Failed to allocate ct_sns request.\n",
7058c2ecf20Sopenharmony_ci		    __func__);
7068c2ecf20Sopenharmony_ci		goto done_free_sp;
7078c2ecf20Sopenharmony_ci	}
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
7108c2ecf20Sopenharmony_ci	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
7118c2ecf20Sopenharmony_ci	    GFP_KERNEL);
7128c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = sizeof(struct ct_sns_pkt);
7138c2ecf20Sopenharmony_ci	if (!sp->u.iocb_cmd.u.ctarg.rsp) {
7148c2ecf20Sopenharmony_ci		ql_log(ql_log_warn, vha, 0xd042,
7158c2ecf20Sopenharmony_ci		    "%s: Failed to allocate ct_sns request.\n",
7168c2ecf20Sopenharmony_ci		    __func__);
7178c2ecf20Sopenharmony_ci		goto done_free_sp;
7188c2ecf20Sopenharmony_ci	}
7198c2ecf20Sopenharmony_ci	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
7208c2ecf20Sopenharmony_ci	memset(ct_sns, 0, sizeof(*ct_sns));
7218c2ecf20Sopenharmony_ci	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	/* Prepare CT request */
7248c2ecf20Sopenharmony_ci	ct_req = qla2x00_prep_ct_req(ct_sns, RFF_ID_CMD, RFF_ID_RSP_SIZE);
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	/* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */
7278c2ecf20Sopenharmony_ci	ct_req->req.rff_id.port_id = port_id_to_be_id(*d_id);
7288c2ecf20Sopenharmony_ci	ct_req->req.rff_id.fc4_feature = fc4feature;
7298c2ecf20Sopenharmony_ci	ct_req->req.rff_id.fc4_type = fc4type;		/* SCSI-FCP or FC-NVMe */
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_size = RFF_ID_REQ_SIZE;
7328c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp_size = RFF_ID_RSP_SIZE;
7338c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
7348c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
7358c2ecf20Sopenharmony_ci	sp->done = qla2x00_async_sns_sp_done;
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0xffff,
7388c2ecf20Sopenharmony_ci	    "Async-%s - hdl=%x portid %06x feature %x type %x.\n",
7398c2ecf20Sopenharmony_ci	    sp->name, sp->handle, d_id->b24, fc4feature, fc4type);
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci	rval = qla2x00_start_sp(sp);
7428c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS) {
7438c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x2047,
7448c2ecf20Sopenharmony_ci		    "RFF_ID issue IOCB failed (%d).\n", rval);
7458c2ecf20Sopenharmony_ci		goto done_free_sp;
7468c2ecf20Sopenharmony_ci	}
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	return rval;
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_cidone_free_sp:
7518c2ecf20Sopenharmony_ci	sp->free(sp);
7528c2ecf20Sopenharmony_cidone:
7538c2ecf20Sopenharmony_ci	return rval;
7548c2ecf20Sopenharmony_ci}
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci/**
7578c2ecf20Sopenharmony_ci * qla2x00_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
7588c2ecf20Sopenharmony_ci * @vha: HA context
7598c2ecf20Sopenharmony_ci *
7608c2ecf20Sopenharmony_ci * Returns 0 on success.
7618c2ecf20Sopenharmony_ci */
7628c2ecf20Sopenharmony_ciint
7638c2ecf20Sopenharmony_ciqla2x00_rnn_id(scsi_qla_host_t *vha)
7648c2ecf20Sopenharmony_ci{
7658c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	if (IS_QLA2100(ha) || IS_QLA2200(ha))
7688c2ecf20Sopenharmony_ci		return qla2x00_sns_rnn_id(vha);
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci	return  qla_async_rnnid(vha, &vha->d_id, vha->node_name);
7718c2ecf20Sopenharmony_ci}
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_cistatic int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t *d_id,
7748c2ecf20Sopenharmony_ci	u8 *node_name)
7758c2ecf20Sopenharmony_ci{
7768c2ecf20Sopenharmony_ci	int rval = QLA_MEMORY_ALLOC_FAILED;
7778c2ecf20Sopenharmony_ci	struct ct_sns_req *ct_req;
7788c2ecf20Sopenharmony_ci	srb_t *sp;
7798c2ecf20Sopenharmony_ci	struct ct_sns_pkt *ct_sns;
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_ci	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
7828c2ecf20Sopenharmony_ci	if (!sp)
7838c2ecf20Sopenharmony_ci		goto done;
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_ci	sp->type = SRB_CT_PTHRU_CMD;
7868c2ecf20Sopenharmony_ci	sp->name = "rnid";
7878c2ecf20Sopenharmony_ci	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
7908c2ecf20Sopenharmony_ci	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
7918c2ecf20Sopenharmony_ci	    GFP_KERNEL);
7928c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt);
7938c2ecf20Sopenharmony_ci	if (!sp->u.iocb_cmd.u.ctarg.req) {
7948c2ecf20Sopenharmony_ci		ql_log(ql_log_warn, vha, 0xd041,
7958c2ecf20Sopenharmony_ci		    "%s: Failed to allocate ct_sns request.\n",
7968c2ecf20Sopenharmony_ci		    __func__);
7978c2ecf20Sopenharmony_ci		goto done_free_sp;
7988c2ecf20Sopenharmony_ci	}
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
8018c2ecf20Sopenharmony_ci	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
8028c2ecf20Sopenharmony_ci	    GFP_KERNEL);
8038c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = sizeof(struct ct_sns_pkt);
8048c2ecf20Sopenharmony_ci	if (!sp->u.iocb_cmd.u.ctarg.rsp) {
8058c2ecf20Sopenharmony_ci		ql_log(ql_log_warn, vha, 0xd042,
8068c2ecf20Sopenharmony_ci		    "%s: Failed to allocate ct_sns request.\n",
8078c2ecf20Sopenharmony_ci		    __func__);
8088c2ecf20Sopenharmony_ci		goto done_free_sp;
8098c2ecf20Sopenharmony_ci	}
8108c2ecf20Sopenharmony_ci	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
8118c2ecf20Sopenharmony_ci	memset(ct_sns, 0, sizeof(*ct_sns));
8128c2ecf20Sopenharmony_ci	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci	/* Prepare CT request */
8158c2ecf20Sopenharmony_ci	ct_req = qla2x00_prep_ct_req(ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE);
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	/* Prepare CT arguments -- port_id, node_name */
8188c2ecf20Sopenharmony_ci	ct_req->req.rnn_id.port_id = port_id_to_be_id(vha->d_id);
8198c2ecf20Sopenharmony_ci	memcpy(ct_req->req.rnn_id.node_name, vha->node_name, WWN_SIZE);
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_size = RNN_ID_REQ_SIZE;
8228c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp_size = RNN_ID_RSP_SIZE;
8238c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
8268c2ecf20Sopenharmony_ci	sp->done = qla2x00_async_sns_sp_done;
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0xffff,
8298c2ecf20Sopenharmony_ci	    "Async-%s - hdl=%x portid %06x\n",
8308c2ecf20Sopenharmony_ci	    sp->name, sp->handle, d_id->b24);
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_ci	rval = qla2x00_start_sp(sp);
8338c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS) {
8348c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x204d,
8358c2ecf20Sopenharmony_ci		    "RNN_ID issue IOCB failed (%d).\n", rval);
8368c2ecf20Sopenharmony_ci		goto done_free_sp;
8378c2ecf20Sopenharmony_ci	}
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci	return rval;
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_cidone_free_sp:
8428c2ecf20Sopenharmony_ci	sp->free(sp);
8438c2ecf20Sopenharmony_cidone:
8448c2ecf20Sopenharmony_ci	return rval;
8458c2ecf20Sopenharmony_ci}
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_cisize_t
8488c2ecf20Sopenharmony_ciqla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn, size_t size)
8498c2ecf20Sopenharmony_ci{
8508c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	if (IS_QLAFX00(ha))
8538c2ecf20Sopenharmony_ci		return scnprintf(snn, size, "%s FW:v%s DVR:v%s",
8548c2ecf20Sopenharmony_ci		    ha->model_number, ha->mr.fw_version, qla2x00_version_str);
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci	return scnprintf(snn, size, "%s FW:v%d.%02d.%02d DVR:v%s",
8578c2ecf20Sopenharmony_ci	    ha->model_number, ha->fw_major_version, ha->fw_minor_version,
8588c2ecf20Sopenharmony_ci	    ha->fw_subminor_version, qla2x00_version_str);
8598c2ecf20Sopenharmony_ci}
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ci/**
8628c2ecf20Sopenharmony_ci * qla2x00_rsnn_nn() - SNS Register Symbolic Node Name (RSNN_NN) of the HBA.
8638c2ecf20Sopenharmony_ci * @vha: HA context
8648c2ecf20Sopenharmony_ci *
8658c2ecf20Sopenharmony_ci * Returns 0 on success.
8668c2ecf20Sopenharmony_ci */
8678c2ecf20Sopenharmony_ciint
8688c2ecf20Sopenharmony_ciqla2x00_rsnn_nn(scsi_qla_host_t *vha)
8698c2ecf20Sopenharmony_ci{
8708c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
8738c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x2050,
8748c2ecf20Sopenharmony_ci		    "RSNN_ID call unsupported on ISP2100/ISP2200.\n");
8758c2ecf20Sopenharmony_ci		return (QLA_SUCCESS);
8768c2ecf20Sopenharmony_ci	}
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	return qla_async_rsnn_nn(vha);
8798c2ecf20Sopenharmony_ci}
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_cistatic int qla_async_rsnn_nn(scsi_qla_host_t *vha)
8828c2ecf20Sopenharmony_ci{
8838c2ecf20Sopenharmony_ci	int rval = QLA_MEMORY_ALLOC_FAILED;
8848c2ecf20Sopenharmony_ci	struct ct_sns_req *ct_req;
8858c2ecf20Sopenharmony_ci	srb_t *sp;
8868c2ecf20Sopenharmony_ci	struct ct_sns_pkt *ct_sns;
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_ci	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
8898c2ecf20Sopenharmony_ci	if (!sp)
8908c2ecf20Sopenharmony_ci		goto done;
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci	sp->type = SRB_CT_PTHRU_CMD;
8938c2ecf20Sopenharmony_ci	sp->name = "rsnn_nn";
8948c2ecf20Sopenharmony_ci	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
8978c2ecf20Sopenharmony_ci	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
8988c2ecf20Sopenharmony_ci	    GFP_KERNEL);
8998c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt);
9008c2ecf20Sopenharmony_ci	if (!sp->u.iocb_cmd.u.ctarg.req) {
9018c2ecf20Sopenharmony_ci		ql_log(ql_log_warn, vha, 0xd041,
9028c2ecf20Sopenharmony_ci		    "%s: Failed to allocate ct_sns request.\n",
9038c2ecf20Sopenharmony_ci		    __func__);
9048c2ecf20Sopenharmony_ci		goto done_free_sp;
9058c2ecf20Sopenharmony_ci	}
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
9088c2ecf20Sopenharmony_ci	    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
9098c2ecf20Sopenharmony_ci	    GFP_KERNEL);
9108c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = sizeof(struct ct_sns_pkt);
9118c2ecf20Sopenharmony_ci	if (!sp->u.iocb_cmd.u.ctarg.rsp) {
9128c2ecf20Sopenharmony_ci		ql_log(ql_log_warn, vha, 0xd042,
9138c2ecf20Sopenharmony_ci		    "%s: Failed to allocate ct_sns request.\n",
9148c2ecf20Sopenharmony_ci		    __func__);
9158c2ecf20Sopenharmony_ci		goto done_free_sp;
9168c2ecf20Sopenharmony_ci	}
9178c2ecf20Sopenharmony_ci	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
9188c2ecf20Sopenharmony_ci	memset(ct_sns, 0, sizeof(*ct_sns));
9198c2ecf20Sopenharmony_ci	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_ci	/* Prepare CT request */
9228c2ecf20Sopenharmony_ci	ct_req = qla2x00_prep_ct_req(ct_sns, RSNN_NN_CMD, RSNN_NN_RSP_SIZE);
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci	/* Prepare CT arguments -- node_name, symbolic node_name, size */
9258c2ecf20Sopenharmony_ci	memcpy(ct_req->req.rsnn_nn.node_name, vha->node_name, WWN_SIZE);
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci	/* Prepare the Symbolic Node Name */
9288c2ecf20Sopenharmony_ci	qla2x00_get_sym_node_name(vha, ct_req->req.rsnn_nn.sym_node_name,
9298c2ecf20Sopenharmony_ci	    sizeof(ct_req->req.rsnn_nn.sym_node_name));
9308c2ecf20Sopenharmony_ci	ct_req->req.rsnn_nn.name_len =
9318c2ecf20Sopenharmony_ci	    (uint8_t)strlen(ct_req->req.rsnn_nn.sym_node_name);
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_size = 24 + 1 + ct_req->req.rsnn_nn.name_len;
9358c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp_size = RSNN_NN_RSP_SIZE;
9368c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
9398c2ecf20Sopenharmony_ci	sp->done = qla2x00_async_sns_sp_done;
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0xffff,
9428c2ecf20Sopenharmony_ci	    "Async-%s - hdl=%x.\n",
9438c2ecf20Sopenharmony_ci	    sp->name, sp->handle);
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci	rval = qla2x00_start_sp(sp);
9468c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS) {
9478c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x2043,
9488c2ecf20Sopenharmony_ci		    "RFT_ID issue IOCB failed (%d).\n", rval);
9498c2ecf20Sopenharmony_ci		goto done_free_sp;
9508c2ecf20Sopenharmony_ci	}
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci	return rval;
9538c2ecf20Sopenharmony_ci
9548c2ecf20Sopenharmony_cidone_free_sp:
9558c2ecf20Sopenharmony_ci	sp->free(sp);
9568c2ecf20Sopenharmony_cidone:
9578c2ecf20Sopenharmony_ci	return rval;
9588c2ecf20Sopenharmony_ci}
9598c2ecf20Sopenharmony_ci
9608c2ecf20Sopenharmony_ci/**
9618c2ecf20Sopenharmony_ci * qla2x00_prep_sns_cmd() - Prepare common SNS command request fields for query.
9628c2ecf20Sopenharmony_ci * @vha: HA context
9638c2ecf20Sopenharmony_ci * @cmd: GS command
9648c2ecf20Sopenharmony_ci * @scmd_len: Subcommand length
9658c2ecf20Sopenharmony_ci * @data_size: response size in bytes
9668c2ecf20Sopenharmony_ci *
9678c2ecf20Sopenharmony_ci * Returns a pointer to the @ha's sns_cmd.
9688c2ecf20Sopenharmony_ci */
9698c2ecf20Sopenharmony_cistatic inline struct sns_cmd_pkt *
9708c2ecf20Sopenharmony_ciqla2x00_prep_sns_cmd(scsi_qla_host_t *vha, uint16_t cmd, uint16_t scmd_len,
9718c2ecf20Sopenharmony_ci    uint16_t data_size)
9728c2ecf20Sopenharmony_ci{
9738c2ecf20Sopenharmony_ci	uint16_t		wc;
9748c2ecf20Sopenharmony_ci	struct sns_cmd_pkt	*sns_cmd;
9758c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
9768c2ecf20Sopenharmony_ci
9778c2ecf20Sopenharmony_ci	sns_cmd = ha->sns_cmd;
9788c2ecf20Sopenharmony_ci	memset(sns_cmd, 0, sizeof(struct sns_cmd_pkt));
9798c2ecf20Sopenharmony_ci	wc = data_size / 2;			/* Size in 16bit words. */
9808c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.buffer_length = cpu_to_le16(wc);
9818c2ecf20Sopenharmony_ci	put_unaligned_le64(ha->sns_cmd_dma, &sns_cmd->p.cmd.buffer_address);
9828c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.subcommand_length = cpu_to_le16(scmd_len);
9838c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.subcommand = cpu_to_le16(cmd);
9848c2ecf20Sopenharmony_ci	wc = (data_size - 16) / 4;		/* Size in 32bit words. */
9858c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.size = cpu_to_le16(wc);
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci	vha->qla_stats.control_requests++;
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_ci	return (sns_cmd);
9908c2ecf20Sopenharmony_ci}
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci/**
9938c2ecf20Sopenharmony_ci * qla2x00_sns_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
9948c2ecf20Sopenharmony_ci * @vha: HA context
9958c2ecf20Sopenharmony_ci * @fcport: fcport entry to updated
9968c2ecf20Sopenharmony_ci *
9978c2ecf20Sopenharmony_ci * This command uses the old Exectute SNS Command mailbox routine.
9988c2ecf20Sopenharmony_ci *
9998c2ecf20Sopenharmony_ci * Returns 0 on success.
10008c2ecf20Sopenharmony_ci */
10018c2ecf20Sopenharmony_cistatic int
10028c2ecf20Sopenharmony_ciqla2x00_sns_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
10038c2ecf20Sopenharmony_ci{
10048c2ecf20Sopenharmony_ci	int		rval = QLA_SUCCESS;
10058c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
10068c2ecf20Sopenharmony_ci	struct sns_cmd_pkt	*sns_cmd;
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci	/* Issue GA_NXT. */
10098c2ecf20Sopenharmony_ci	/* Prepare SNS command request. */
10108c2ecf20Sopenharmony_ci	sns_cmd = qla2x00_prep_sns_cmd(vha, GA_NXT_CMD, GA_NXT_SNS_SCMD_LEN,
10118c2ecf20Sopenharmony_ci	    GA_NXT_SNS_DATA_SIZE);
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	/* Prepare SNS command arguments -- port_id. */
10148c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[0] = fcport->d_id.b.al_pa;
10158c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[1] = fcport->d_id.b.area;
10168c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[2] = fcport->d_id.b.domain;
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci	/* Execute SNS command. */
10198c2ecf20Sopenharmony_ci	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GA_NXT_SNS_CMD_SIZE / 2,
10208c2ecf20Sopenharmony_ci	    sizeof(struct sns_cmd_pkt));
10218c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS) {
10228c2ecf20Sopenharmony_ci		/*EMPTY*/
10238c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x205f,
10248c2ecf20Sopenharmony_ci		    "GA_NXT Send SNS failed (%d).\n", rval);
10258c2ecf20Sopenharmony_ci	} else if (sns_cmd->p.gan_data[8] != 0x80 ||
10268c2ecf20Sopenharmony_ci	    sns_cmd->p.gan_data[9] != 0x02) {
10278c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2084,
10288c2ecf20Sopenharmony_ci		    "GA_NXT failed, rejected request ga_nxt_rsp:\n");
10298c2ecf20Sopenharmony_ci		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2074,
10308c2ecf20Sopenharmony_ci		    sns_cmd->p.gan_data, 16);
10318c2ecf20Sopenharmony_ci		rval = QLA_FUNCTION_FAILED;
10328c2ecf20Sopenharmony_ci	} else {
10338c2ecf20Sopenharmony_ci		/* Populate fc_port_t entry. */
10348c2ecf20Sopenharmony_ci		fcport->d_id.b.domain = sns_cmd->p.gan_data[17];
10358c2ecf20Sopenharmony_ci		fcport->d_id.b.area = sns_cmd->p.gan_data[18];
10368c2ecf20Sopenharmony_ci		fcport->d_id.b.al_pa = sns_cmd->p.gan_data[19];
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci		memcpy(fcport->node_name, &sns_cmd->p.gan_data[284], WWN_SIZE);
10398c2ecf20Sopenharmony_ci		memcpy(fcport->port_name, &sns_cmd->p.gan_data[20], WWN_SIZE);
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci		if (sns_cmd->p.gan_data[16] != NS_N_PORT_TYPE &&
10428c2ecf20Sopenharmony_ci		    sns_cmd->p.gan_data[16] != NS_NL_PORT_TYPE)
10438c2ecf20Sopenharmony_ci			fcport->d_id.b.domain = 0xf0;
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x2061,
10468c2ecf20Sopenharmony_ci		    "GA_NXT entry - nn %8phN pn %8phN "
10478c2ecf20Sopenharmony_ci		    "port_id=%02x%02x%02x.\n",
10488c2ecf20Sopenharmony_ci		    fcport->node_name, fcport->port_name,
10498c2ecf20Sopenharmony_ci		    fcport->d_id.b.domain, fcport->d_id.b.area,
10508c2ecf20Sopenharmony_ci		    fcport->d_id.b.al_pa);
10518c2ecf20Sopenharmony_ci	}
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ci	return (rval);
10548c2ecf20Sopenharmony_ci}
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci/**
10578c2ecf20Sopenharmony_ci * qla2x00_sns_gid_pt() - SNS scan for fabric devices via GID_PT command.
10588c2ecf20Sopenharmony_ci * @vha: HA context
10598c2ecf20Sopenharmony_ci * @list: switch info entries to populate
10608c2ecf20Sopenharmony_ci *
10618c2ecf20Sopenharmony_ci * This command uses the old Exectute SNS Command mailbox routine.
10628c2ecf20Sopenharmony_ci *
10638c2ecf20Sopenharmony_ci * NOTE: Non-Nx_Ports are not requested.
10648c2ecf20Sopenharmony_ci *
10658c2ecf20Sopenharmony_ci * Returns 0 on success.
10668c2ecf20Sopenharmony_ci */
10678c2ecf20Sopenharmony_cistatic int
10688c2ecf20Sopenharmony_ciqla2x00_sns_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
10698c2ecf20Sopenharmony_ci{
10708c2ecf20Sopenharmony_ci	int		rval;
10718c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
10728c2ecf20Sopenharmony_ci	uint16_t	i;
10738c2ecf20Sopenharmony_ci	uint8_t		*entry;
10748c2ecf20Sopenharmony_ci	struct sns_cmd_pkt	*sns_cmd;
10758c2ecf20Sopenharmony_ci	uint16_t gid_pt_sns_data_size;
10768c2ecf20Sopenharmony_ci
10778c2ecf20Sopenharmony_ci	gid_pt_sns_data_size = qla2x00_gid_pt_rsp_size(vha);
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_ci	/* Issue GID_PT. */
10808c2ecf20Sopenharmony_ci	/* Prepare SNS command request. */
10818c2ecf20Sopenharmony_ci	sns_cmd = qla2x00_prep_sns_cmd(vha, GID_PT_CMD, GID_PT_SNS_SCMD_LEN,
10828c2ecf20Sopenharmony_ci	    gid_pt_sns_data_size);
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci	/* Prepare SNS command arguments -- port_type. */
10858c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[0] = NS_NX_PORT_TYPE;
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci	/* Execute SNS command. */
10888c2ecf20Sopenharmony_ci	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GID_PT_SNS_CMD_SIZE / 2,
10898c2ecf20Sopenharmony_ci	    sizeof(struct sns_cmd_pkt));
10908c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS) {
10918c2ecf20Sopenharmony_ci		/*EMPTY*/
10928c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x206d,
10938c2ecf20Sopenharmony_ci		    "GID_PT Send SNS failed (%d).\n", rval);
10948c2ecf20Sopenharmony_ci	} else if (sns_cmd->p.gid_data[8] != 0x80 ||
10958c2ecf20Sopenharmony_ci	    sns_cmd->p.gid_data[9] != 0x02) {
10968c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x202f,
10978c2ecf20Sopenharmony_ci		    "GID_PT failed, rejected request, gid_rsp:\n");
10988c2ecf20Sopenharmony_ci		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2081,
10998c2ecf20Sopenharmony_ci		    sns_cmd->p.gid_data, 16);
11008c2ecf20Sopenharmony_ci		rval = QLA_FUNCTION_FAILED;
11018c2ecf20Sopenharmony_ci	} else {
11028c2ecf20Sopenharmony_ci		/* Set port IDs in switch info list. */
11038c2ecf20Sopenharmony_ci		for (i = 0; i < ha->max_fibre_devices; i++) {
11048c2ecf20Sopenharmony_ci			entry = &sns_cmd->p.gid_data[(i * 4) + 16];
11058c2ecf20Sopenharmony_ci			list[i].d_id.b.domain = entry[1];
11068c2ecf20Sopenharmony_ci			list[i].d_id.b.area = entry[2];
11078c2ecf20Sopenharmony_ci			list[i].d_id.b.al_pa = entry[3];
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ci			/* Last one exit. */
11108c2ecf20Sopenharmony_ci			if (entry[0] & BIT_7) {
11118c2ecf20Sopenharmony_ci				list[i].d_id.b.rsvd_1 = entry[0];
11128c2ecf20Sopenharmony_ci				break;
11138c2ecf20Sopenharmony_ci			}
11148c2ecf20Sopenharmony_ci		}
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci		/*
11178c2ecf20Sopenharmony_ci		 * If we've used all available slots, then the switch is
11188c2ecf20Sopenharmony_ci		 * reporting back more devices that we can handle with this
11198c2ecf20Sopenharmony_ci		 * single call.  Return a failed status, and let GA_NXT handle
11208c2ecf20Sopenharmony_ci		 * the overload.
11218c2ecf20Sopenharmony_ci		 */
11228c2ecf20Sopenharmony_ci		if (i == ha->max_fibre_devices)
11238c2ecf20Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
11248c2ecf20Sopenharmony_ci	}
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_ci	return (rval);
11278c2ecf20Sopenharmony_ci}
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci/**
11308c2ecf20Sopenharmony_ci * qla2x00_sns_gpn_id() - SNS Get Port Name (GPN_ID) query.
11318c2ecf20Sopenharmony_ci * @vha: HA context
11328c2ecf20Sopenharmony_ci * @list: switch info entries to populate
11338c2ecf20Sopenharmony_ci *
11348c2ecf20Sopenharmony_ci * This command uses the old Exectute SNS Command mailbox routine.
11358c2ecf20Sopenharmony_ci *
11368c2ecf20Sopenharmony_ci * Returns 0 on success.
11378c2ecf20Sopenharmony_ci */
11388c2ecf20Sopenharmony_cistatic int
11398c2ecf20Sopenharmony_ciqla2x00_sns_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
11408c2ecf20Sopenharmony_ci{
11418c2ecf20Sopenharmony_ci	int		rval = QLA_SUCCESS;
11428c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
11438c2ecf20Sopenharmony_ci	uint16_t	i;
11448c2ecf20Sopenharmony_ci	struct sns_cmd_pkt	*sns_cmd;
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	for (i = 0; i < ha->max_fibre_devices; i++) {
11478c2ecf20Sopenharmony_ci		/* Issue GPN_ID */
11488c2ecf20Sopenharmony_ci		/* Prepare SNS command request. */
11498c2ecf20Sopenharmony_ci		sns_cmd = qla2x00_prep_sns_cmd(vha, GPN_ID_CMD,
11508c2ecf20Sopenharmony_ci		    GPN_ID_SNS_SCMD_LEN, GPN_ID_SNS_DATA_SIZE);
11518c2ecf20Sopenharmony_ci
11528c2ecf20Sopenharmony_ci		/* Prepare SNS command arguments -- port_id. */
11538c2ecf20Sopenharmony_ci		sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
11548c2ecf20Sopenharmony_ci		sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
11558c2ecf20Sopenharmony_ci		sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci		/* Execute SNS command. */
11588c2ecf20Sopenharmony_ci		rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,
11598c2ecf20Sopenharmony_ci		    GPN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
11608c2ecf20Sopenharmony_ci		if (rval != QLA_SUCCESS) {
11618c2ecf20Sopenharmony_ci			/*EMPTY*/
11628c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x2032,
11638c2ecf20Sopenharmony_ci			    "GPN_ID Send SNS failed (%d).\n", rval);
11648c2ecf20Sopenharmony_ci		} else if (sns_cmd->p.gpn_data[8] != 0x80 ||
11658c2ecf20Sopenharmony_ci		    sns_cmd->p.gpn_data[9] != 0x02) {
11668c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207e,
11678c2ecf20Sopenharmony_ci			    "GPN_ID failed, rejected request, gpn_rsp:\n");
11688c2ecf20Sopenharmony_ci			ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207f,
11698c2ecf20Sopenharmony_ci			    sns_cmd->p.gpn_data, 16);
11708c2ecf20Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
11718c2ecf20Sopenharmony_ci		} else {
11728c2ecf20Sopenharmony_ci			/* Save portname */
11738c2ecf20Sopenharmony_ci			memcpy(list[i].port_name, &sns_cmd->p.gpn_data[16],
11748c2ecf20Sopenharmony_ci			    WWN_SIZE);
11758c2ecf20Sopenharmony_ci		}
11768c2ecf20Sopenharmony_ci
11778c2ecf20Sopenharmony_ci		/* Last device exit. */
11788c2ecf20Sopenharmony_ci		if (list[i].d_id.b.rsvd_1 != 0)
11798c2ecf20Sopenharmony_ci			break;
11808c2ecf20Sopenharmony_ci	}
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_ci	return (rval);
11838c2ecf20Sopenharmony_ci}
11848c2ecf20Sopenharmony_ci
11858c2ecf20Sopenharmony_ci/**
11868c2ecf20Sopenharmony_ci * qla2x00_sns_gnn_id() - SNS Get Node Name (GNN_ID) query.
11878c2ecf20Sopenharmony_ci * @vha: HA context
11888c2ecf20Sopenharmony_ci * @list: switch info entries to populate
11898c2ecf20Sopenharmony_ci *
11908c2ecf20Sopenharmony_ci * This command uses the old Exectute SNS Command mailbox routine.
11918c2ecf20Sopenharmony_ci *
11928c2ecf20Sopenharmony_ci * Returns 0 on success.
11938c2ecf20Sopenharmony_ci */
11948c2ecf20Sopenharmony_cistatic int
11958c2ecf20Sopenharmony_ciqla2x00_sns_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
11968c2ecf20Sopenharmony_ci{
11978c2ecf20Sopenharmony_ci	int		rval = QLA_SUCCESS;
11988c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
11998c2ecf20Sopenharmony_ci	uint16_t	i;
12008c2ecf20Sopenharmony_ci	struct sns_cmd_pkt	*sns_cmd;
12018c2ecf20Sopenharmony_ci
12028c2ecf20Sopenharmony_ci	for (i = 0; i < ha->max_fibre_devices; i++) {
12038c2ecf20Sopenharmony_ci		/* Issue GNN_ID */
12048c2ecf20Sopenharmony_ci		/* Prepare SNS command request. */
12058c2ecf20Sopenharmony_ci		sns_cmd = qla2x00_prep_sns_cmd(vha, GNN_ID_CMD,
12068c2ecf20Sopenharmony_ci		    GNN_ID_SNS_SCMD_LEN, GNN_ID_SNS_DATA_SIZE);
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci		/* Prepare SNS command arguments -- port_id. */
12098c2ecf20Sopenharmony_ci		sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
12108c2ecf20Sopenharmony_ci		sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
12118c2ecf20Sopenharmony_ci		sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci		/* Execute SNS command. */
12148c2ecf20Sopenharmony_ci		rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,
12158c2ecf20Sopenharmony_ci		    GNN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
12168c2ecf20Sopenharmony_ci		if (rval != QLA_SUCCESS) {
12178c2ecf20Sopenharmony_ci			/*EMPTY*/
12188c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x203f,
12198c2ecf20Sopenharmony_ci			    "GNN_ID Send SNS failed (%d).\n", rval);
12208c2ecf20Sopenharmony_ci		} else if (sns_cmd->p.gnn_data[8] != 0x80 ||
12218c2ecf20Sopenharmony_ci		    sns_cmd->p.gnn_data[9] != 0x02) {
12228c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2082,
12238c2ecf20Sopenharmony_ci			    "GNN_ID failed, rejected request, gnn_rsp:\n");
12248c2ecf20Sopenharmony_ci			ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207a,
12258c2ecf20Sopenharmony_ci			    sns_cmd->p.gnn_data, 16);
12268c2ecf20Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
12278c2ecf20Sopenharmony_ci		} else {
12288c2ecf20Sopenharmony_ci			/* Save nodename */
12298c2ecf20Sopenharmony_ci			memcpy(list[i].node_name, &sns_cmd->p.gnn_data[16],
12308c2ecf20Sopenharmony_ci			    WWN_SIZE);
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x206e,
12338c2ecf20Sopenharmony_ci			    "GID_PT entry - nn %8phN pn %8phN "
12348c2ecf20Sopenharmony_ci			    "port_id=%02x%02x%02x.\n",
12358c2ecf20Sopenharmony_ci			    list[i].node_name, list[i].port_name,
12368c2ecf20Sopenharmony_ci			    list[i].d_id.b.domain, list[i].d_id.b.area,
12378c2ecf20Sopenharmony_ci			    list[i].d_id.b.al_pa);
12388c2ecf20Sopenharmony_ci		}
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_ci		/* Last device exit. */
12418c2ecf20Sopenharmony_ci		if (list[i].d_id.b.rsvd_1 != 0)
12428c2ecf20Sopenharmony_ci			break;
12438c2ecf20Sopenharmony_ci	}
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_ci	return (rval);
12468c2ecf20Sopenharmony_ci}
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_ci/**
12498c2ecf20Sopenharmony_ci * qla2x00_snd_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
12508c2ecf20Sopenharmony_ci * @vha: HA context
12518c2ecf20Sopenharmony_ci *
12528c2ecf20Sopenharmony_ci * This command uses the old Exectute SNS Command mailbox routine.
12538c2ecf20Sopenharmony_ci *
12548c2ecf20Sopenharmony_ci * Returns 0 on success.
12558c2ecf20Sopenharmony_ci */
12568c2ecf20Sopenharmony_cistatic int
12578c2ecf20Sopenharmony_ciqla2x00_sns_rft_id(scsi_qla_host_t *vha)
12588c2ecf20Sopenharmony_ci{
12598c2ecf20Sopenharmony_ci	int		rval;
12608c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
12618c2ecf20Sopenharmony_ci	struct sns_cmd_pkt	*sns_cmd;
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci	/* Issue RFT_ID. */
12648c2ecf20Sopenharmony_ci	/* Prepare SNS command request. */
12658c2ecf20Sopenharmony_ci	sns_cmd = qla2x00_prep_sns_cmd(vha, RFT_ID_CMD, RFT_ID_SNS_SCMD_LEN,
12668c2ecf20Sopenharmony_ci	    RFT_ID_SNS_DATA_SIZE);
12678c2ecf20Sopenharmony_ci
12688c2ecf20Sopenharmony_ci	/* Prepare SNS command arguments -- port_id, FC-4 types */
12698c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;
12708c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[1] = vha->d_id.b.area;
12718c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[5] = 0x01;			/* FCP-3 */
12748c2ecf20Sopenharmony_ci
12758c2ecf20Sopenharmony_ci	/* Execute SNS command. */
12768c2ecf20Sopenharmony_ci	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RFT_ID_SNS_CMD_SIZE / 2,
12778c2ecf20Sopenharmony_ci	    sizeof(struct sns_cmd_pkt));
12788c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS) {
12798c2ecf20Sopenharmony_ci		/*EMPTY*/
12808c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x2060,
12818c2ecf20Sopenharmony_ci		    "RFT_ID Send SNS failed (%d).\n", rval);
12828c2ecf20Sopenharmony_ci	} else if (sns_cmd->p.rft_data[8] != 0x80 ||
12838c2ecf20Sopenharmony_ci	    sns_cmd->p.rft_data[9] != 0x02) {
12848c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2083,
12858c2ecf20Sopenharmony_ci		    "RFT_ID failed, rejected request rft_rsp:\n");
12868c2ecf20Sopenharmony_ci		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2080,
12878c2ecf20Sopenharmony_ci		    sns_cmd->p.rft_data, 16);
12888c2ecf20Sopenharmony_ci		rval = QLA_FUNCTION_FAILED;
12898c2ecf20Sopenharmony_ci	} else {
12908c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x2073,
12918c2ecf20Sopenharmony_ci		    "RFT_ID exiting normally.\n");
12928c2ecf20Sopenharmony_ci	}
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci	return (rval);
12958c2ecf20Sopenharmony_ci}
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci/**
12988c2ecf20Sopenharmony_ci * qla2x00_sns_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
12998c2ecf20Sopenharmony_ci * @vha: HA context
13008c2ecf20Sopenharmony_ci *
13018c2ecf20Sopenharmony_ci * This command uses the old Exectute SNS Command mailbox routine.
13028c2ecf20Sopenharmony_ci *
13038c2ecf20Sopenharmony_ci * Returns 0 on success.
13048c2ecf20Sopenharmony_ci */
13058c2ecf20Sopenharmony_cistatic int
13068c2ecf20Sopenharmony_ciqla2x00_sns_rnn_id(scsi_qla_host_t *vha)
13078c2ecf20Sopenharmony_ci{
13088c2ecf20Sopenharmony_ci	int		rval;
13098c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
13108c2ecf20Sopenharmony_ci	struct sns_cmd_pkt	*sns_cmd;
13118c2ecf20Sopenharmony_ci
13128c2ecf20Sopenharmony_ci	/* Issue RNN_ID. */
13138c2ecf20Sopenharmony_ci	/* Prepare SNS command request. */
13148c2ecf20Sopenharmony_ci	sns_cmd = qla2x00_prep_sns_cmd(vha, RNN_ID_CMD, RNN_ID_SNS_SCMD_LEN,
13158c2ecf20Sopenharmony_ci	    RNN_ID_SNS_DATA_SIZE);
13168c2ecf20Sopenharmony_ci
13178c2ecf20Sopenharmony_ci	/* Prepare SNS command arguments -- port_id, nodename. */
13188c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;
13198c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[1] = vha->d_id.b.area;
13208c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;
13218c2ecf20Sopenharmony_ci
13228c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[4] = vha->node_name[7];
13238c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[5] = vha->node_name[6];
13248c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[6] = vha->node_name[5];
13258c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[7] = vha->node_name[4];
13268c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[8] = vha->node_name[3];
13278c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[9] = vha->node_name[2];
13288c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[10] = vha->node_name[1];
13298c2ecf20Sopenharmony_ci	sns_cmd->p.cmd.param[11] = vha->node_name[0];
13308c2ecf20Sopenharmony_ci
13318c2ecf20Sopenharmony_ci	/* Execute SNS command. */
13328c2ecf20Sopenharmony_ci	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RNN_ID_SNS_CMD_SIZE / 2,
13338c2ecf20Sopenharmony_ci	    sizeof(struct sns_cmd_pkt));
13348c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS) {
13358c2ecf20Sopenharmony_ci		/*EMPTY*/
13368c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x204a,
13378c2ecf20Sopenharmony_ci		    "RNN_ID Send SNS failed (%d).\n", rval);
13388c2ecf20Sopenharmony_ci	} else if (sns_cmd->p.rnn_data[8] != 0x80 ||
13398c2ecf20Sopenharmony_ci	    sns_cmd->p.rnn_data[9] != 0x02) {
13408c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207b,
13418c2ecf20Sopenharmony_ci		    "RNN_ID failed, rejected request, rnn_rsp:\n");
13428c2ecf20Sopenharmony_ci		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207c,
13438c2ecf20Sopenharmony_ci		    sns_cmd->p.rnn_data, 16);
13448c2ecf20Sopenharmony_ci		rval = QLA_FUNCTION_FAILED;
13458c2ecf20Sopenharmony_ci	} else {
13468c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x204c,
13478c2ecf20Sopenharmony_ci		    "RNN_ID exiting normally.\n");
13488c2ecf20Sopenharmony_ci	}
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci	return (rval);
13518c2ecf20Sopenharmony_ci}
13528c2ecf20Sopenharmony_ci
13538c2ecf20Sopenharmony_ci/**
13548c2ecf20Sopenharmony_ci * qla2x00_mgmt_svr_login() - Login to fabric Management Service.
13558c2ecf20Sopenharmony_ci * @vha: HA context
13568c2ecf20Sopenharmony_ci *
13578c2ecf20Sopenharmony_ci * Returns 0 on success.
13588c2ecf20Sopenharmony_ci */
13598c2ecf20Sopenharmony_ciint
13608c2ecf20Sopenharmony_ciqla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
13618c2ecf20Sopenharmony_ci{
13628c2ecf20Sopenharmony_ci	int ret, rval;
13638c2ecf20Sopenharmony_ci	uint16_t mb[MAILBOX_REGISTER_COUNT];
13648c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_ci	ret = QLA_SUCCESS;
13678c2ecf20Sopenharmony_ci	if (vha->flags.management_server_logged_in)
13688c2ecf20Sopenharmony_ci		return ret;
13698c2ecf20Sopenharmony_ci
13708c2ecf20Sopenharmony_ci	rval = ha->isp_ops->fabric_login(vha, vha->mgmt_svr_loop_id, 0xff, 0xff,
13718c2ecf20Sopenharmony_ci	    0xfa, mb, BIT_1);
13728c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS || mb[0] != MBS_COMMAND_COMPLETE) {
13738c2ecf20Sopenharmony_ci		if (rval == QLA_MEMORY_ALLOC_FAILED)
13748c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x2085,
13758c2ecf20Sopenharmony_ci			    "Failed management_server login: loopid=%x "
13768c2ecf20Sopenharmony_ci			    "rval=%d\n", vha->mgmt_svr_loop_id, rval);
13778c2ecf20Sopenharmony_ci		else
13788c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x2024,
13798c2ecf20Sopenharmony_ci			    "Failed management_server login: loopid=%x "
13808c2ecf20Sopenharmony_ci			    "mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x.\n",
13818c2ecf20Sopenharmony_ci			    vha->mgmt_svr_loop_id, mb[0], mb[1], mb[2], mb[6],
13828c2ecf20Sopenharmony_ci			    mb[7]);
13838c2ecf20Sopenharmony_ci		ret = QLA_FUNCTION_FAILED;
13848c2ecf20Sopenharmony_ci	} else
13858c2ecf20Sopenharmony_ci		vha->flags.management_server_logged_in = 1;
13868c2ecf20Sopenharmony_ci
13878c2ecf20Sopenharmony_ci	return ret;
13888c2ecf20Sopenharmony_ci}
13898c2ecf20Sopenharmony_ci
13908c2ecf20Sopenharmony_ci/**
13918c2ecf20Sopenharmony_ci * qla2x00_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
13928c2ecf20Sopenharmony_ci * @vha: HA context
13938c2ecf20Sopenharmony_ci * @req_size: request size in bytes
13948c2ecf20Sopenharmony_ci * @rsp_size: response size in bytes
13958c2ecf20Sopenharmony_ci *
13968c2ecf20Sopenharmony_ci * Returns a pointer to the @ha's ms_iocb.
13978c2ecf20Sopenharmony_ci */
13988c2ecf20Sopenharmony_civoid *
13998c2ecf20Sopenharmony_ciqla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
14008c2ecf20Sopenharmony_ci    uint32_t rsp_size)
14018c2ecf20Sopenharmony_ci{
14028c2ecf20Sopenharmony_ci	ms_iocb_entry_t *ms_pkt;
14038c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
14048c2ecf20Sopenharmony_ci
14058c2ecf20Sopenharmony_ci	ms_pkt = ha->ms_iocb;
14068c2ecf20Sopenharmony_ci	memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
14078c2ecf20Sopenharmony_ci
14088c2ecf20Sopenharmony_ci	ms_pkt->entry_type = MS_IOCB_TYPE;
14098c2ecf20Sopenharmony_ci	ms_pkt->entry_count = 1;
14108c2ecf20Sopenharmony_ci	SET_TARGET_ID(ha, ms_pkt->loop_id, vha->mgmt_svr_loop_id);
14118c2ecf20Sopenharmony_ci	ms_pkt->control_flags = cpu_to_le16(CF_READ | CF_HEAD_TAG);
14128c2ecf20Sopenharmony_ci	ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
14138c2ecf20Sopenharmony_ci	ms_pkt->cmd_dsd_count = cpu_to_le16(1);
14148c2ecf20Sopenharmony_ci	ms_pkt->total_dsd_count = cpu_to_le16(2);
14158c2ecf20Sopenharmony_ci	ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
14168c2ecf20Sopenharmony_ci	ms_pkt->req_bytecount = cpu_to_le32(req_size);
14178c2ecf20Sopenharmony_ci
14188c2ecf20Sopenharmony_ci	put_unaligned_le64(ha->ct_sns_dma, &ms_pkt->req_dsd.address);
14198c2ecf20Sopenharmony_ci	ms_pkt->req_dsd.length = ms_pkt->req_bytecount;
14208c2ecf20Sopenharmony_ci
14218c2ecf20Sopenharmony_ci	put_unaligned_le64(ha->ct_sns_dma, &ms_pkt->rsp_dsd.address);
14228c2ecf20Sopenharmony_ci	ms_pkt->rsp_dsd.length = ms_pkt->rsp_bytecount;
14238c2ecf20Sopenharmony_ci
14248c2ecf20Sopenharmony_ci	return ms_pkt;
14258c2ecf20Sopenharmony_ci}
14268c2ecf20Sopenharmony_ci
14278c2ecf20Sopenharmony_ci/**
14288c2ecf20Sopenharmony_ci * qla24xx_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
14298c2ecf20Sopenharmony_ci * @vha: HA context
14308c2ecf20Sopenharmony_ci * @req_size: request size in bytes
14318c2ecf20Sopenharmony_ci * @rsp_size: response size in bytes
14328c2ecf20Sopenharmony_ci *
14338c2ecf20Sopenharmony_ci * Returns a pointer to the @ha's ms_iocb.
14348c2ecf20Sopenharmony_ci */
14358c2ecf20Sopenharmony_civoid *
14368c2ecf20Sopenharmony_ciqla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
14378c2ecf20Sopenharmony_ci    uint32_t rsp_size)
14388c2ecf20Sopenharmony_ci{
14398c2ecf20Sopenharmony_ci	struct ct_entry_24xx *ct_pkt;
14408c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
14418c2ecf20Sopenharmony_ci
14428c2ecf20Sopenharmony_ci	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
14438c2ecf20Sopenharmony_ci	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
14448c2ecf20Sopenharmony_ci
14458c2ecf20Sopenharmony_ci	ct_pkt->entry_type = CT_IOCB_TYPE;
14468c2ecf20Sopenharmony_ci	ct_pkt->entry_count = 1;
14478c2ecf20Sopenharmony_ci	ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);
14488c2ecf20Sopenharmony_ci	ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
14498c2ecf20Sopenharmony_ci	ct_pkt->cmd_dsd_count = cpu_to_le16(1);
14508c2ecf20Sopenharmony_ci	ct_pkt->rsp_dsd_count = cpu_to_le16(1);
14518c2ecf20Sopenharmony_ci	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
14528c2ecf20Sopenharmony_ci	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
14538c2ecf20Sopenharmony_ci
14548c2ecf20Sopenharmony_ci	put_unaligned_le64(ha->ct_sns_dma, &ct_pkt->dsd[0].address);
14558c2ecf20Sopenharmony_ci	ct_pkt->dsd[0].length = ct_pkt->cmd_byte_count;
14568c2ecf20Sopenharmony_ci
14578c2ecf20Sopenharmony_ci	put_unaligned_le64(ha->ct_sns_dma, &ct_pkt->dsd[1].address);
14588c2ecf20Sopenharmony_ci	ct_pkt->dsd[1].length = ct_pkt->rsp_byte_count;
14598c2ecf20Sopenharmony_ci	ct_pkt->vp_index = vha->vp_idx;
14608c2ecf20Sopenharmony_ci
14618c2ecf20Sopenharmony_ci	return ct_pkt;
14628c2ecf20Sopenharmony_ci}
14638c2ecf20Sopenharmony_ci
14648c2ecf20Sopenharmony_cistatic void
14658c2ecf20Sopenharmony_ciqla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size)
14668c2ecf20Sopenharmony_ci{
14678c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
14688c2ecf20Sopenharmony_ci	ms_iocb_entry_t *ms_pkt = ha->ms_iocb;
14698c2ecf20Sopenharmony_ci	struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
14708c2ecf20Sopenharmony_ci
14718c2ecf20Sopenharmony_ci	if (IS_FWI2_CAPABLE(ha)) {
14728c2ecf20Sopenharmony_ci		ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
14738c2ecf20Sopenharmony_ci		ct_pkt->dsd[0].length = ct_pkt->cmd_byte_count;
14748c2ecf20Sopenharmony_ci	} else {
14758c2ecf20Sopenharmony_ci		ms_pkt->req_bytecount = cpu_to_le32(req_size);
14768c2ecf20Sopenharmony_ci		ms_pkt->req_dsd.length = ms_pkt->req_bytecount;
14778c2ecf20Sopenharmony_ci	}
14788c2ecf20Sopenharmony_ci}
14798c2ecf20Sopenharmony_ci
14808c2ecf20Sopenharmony_ci/**
14818c2ecf20Sopenharmony_ci * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
14828c2ecf20Sopenharmony_ci * @p: CT request buffer
14838c2ecf20Sopenharmony_ci * @cmd: GS command
14848c2ecf20Sopenharmony_ci * @rsp_size: response size in bytes
14858c2ecf20Sopenharmony_ci *
14868c2ecf20Sopenharmony_ci * Returns a pointer to the intitialized @ct_req.
14878c2ecf20Sopenharmony_ci */
14888c2ecf20Sopenharmony_cistatic inline struct ct_sns_req *
14898c2ecf20Sopenharmony_ciqla2x00_prep_ct_fdmi_req(struct ct_sns_pkt *p, uint16_t cmd,
14908c2ecf20Sopenharmony_ci    uint16_t rsp_size)
14918c2ecf20Sopenharmony_ci{
14928c2ecf20Sopenharmony_ci	memset(p, 0, sizeof(struct ct_sns_pkt));
14938c2ecf20Sopenharmony_ci
14948c2ecf20Sopenharmony_ci	p->p.req.header.revision = 0x01;
14958c2ecf20Sopenharmony_ci	p->p.req.header.gs_type = 0xFA;
14968c2ecf20Sopenharmony_ci	p->p.req.header.gs_subtype = 0x10;
14978c2ecf20Sopenharmony_ci	p->p.req.command = cpu_to_be16(cmd);
14988c2ecf20Sopenharmony_ci	p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
14998c2ecf20Sopenharmony_ci
15008c2ecf20Sopenharmony_ci	return &p->p.req;
15018c2ecf20Sopenharmony_ci}
15028c2ecf20Sopenharmony_ci
15038c2ecf20Sopenharmony_ciuint
15048c2ecf20Sopenharmony_ciqla25xx_fdmi_port_speed_capability(struct qla_hw_data *ha)
15058c2ecf20Sopenharmony_ci{
15068c2ecf20Sopenharmony_ci	uint speeds = 0;
15078c2ecf20Sopenharmony_ci
15088c2ecf20Sopenharmony_ci	if (IS_CNA_CAPABLE(ha))
15098c2ecf20Sopenharmony_ci		return FDMI_PORT_SPEED_10GB;
15108c2ecf20Sopenharmony_ci	if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) {
15118c2ecf20Sopenharmony_ci		if (ha->max_supported_speed == 2) {
15128c2ecf20Sopenharmony_ci			if (ha->min_supported_speed <= 6)
15138c2ecf20Sopenharmony_ci				speeds |= FDMI_PORT_SPEED_64GB;
15148c2ecf20Sopenharmony_ci		}
15158c2ecf20Sopenharmony_ci		if (ha->max_supported_speed == 2 ||
15168c2ecf20Sopenharmony_ci		    ha->max_supported_speed == 1) {
15178c2ecf20Sopenharmony_ci			if (ha->min_supported_speed <= 5)
15188c2ecf20Sopenharmony_ci				speeds |= FDMI_PORT_SPEED_32GB;
15198c2ecf20Sopenharmony_ci		}
15208c2ecf20Sopenharmony_ci		if (ha->max_supported_speed == 2 ||
15218c2ecf20Sopenharmony_ci		    ha->max_supported_speed == 1 ||
15228c2ecf20Sopenharmony_ci		    ha->max_supported_speed == 0) {
15238c2ecf20Sopenharmony_ci			if (ha->min_supported_speed <= 4)
15248c2ecf20Sopenharmony_ci				speeds |= FDMI_PORT_SPEED_16GB;
15258c2ecf20Sopenharmony_ci		}
15268c2ecf20Sopenharmony_ci		if (ha->max_supported_speed == 1 ||
15278c2ecf20Sopenharmony_ci		    ha->max_supported_speed == 0) {
15288c2ecf20Sopenharmony_ci			if (ha->min_supported_speed <= 3)
15298c2ecf20Sopenharmony_ci				speeds |= FDMI_PORT_SPEED_8GB;
15308c2ecf20Sopenharmony_ci		}
15318c2ecf20Sopenharmony_ci		if (ha->max_supported_speed == 0) {
15328c2ecf20Sopenharmony_ci			if (ha->min_supported_speed <= 2)
15338c2ecf20Sopenharmony_ci				speeds |= FDMI_PORT_SPEED_4GB;
15348c2ecf20Sopenharmony_ci		}
15358c2ecf20Sopenharmony_ci		return speeds;
15368c2ecf20Sopenharmony_ci	}
15378c2ecf20Sopenharmony_ci	if (IS_QLA2031(ha)) {
15388c2ecf20Sopenharmony_ci		if ((ha->pdev->subsystem_vendor == 0x103C) &&
15398c2ecf20Sopenharmony_ci		    (ha->pdev->subsystem_device == 0x8002)) {
15408c2ecf20Sopenharmony_ci			speeds = FDMI_PORT_SPEED_16GB;
15418c2ecf20Sopenharmony_ci		} else {
15428c2ecf20Sopenharmony_ci			speeds = FDMI_PORT_SPEED_16GB|FDMI_PORT_SPEED_8GB|
15438c2ecf20Sopenharmony_ci				FDMI_PORT_SPEED_4GB;
15448c2ecf20Sopenharmony_ci		}
15458c2ecf20Sopenharmony_ci		return speeds;
15468c2ecf20Sopenharmony_ci	}
15478c2ecf20Sopenharmony_ci	if (IS_QLA25XX(ha) || IS_QLAFX00(ha))
15488c2ecf20Sopenharmony_ci		return FDMI_PORT_SPEED_8GB|FDMI_PORT_SPEED_4GB|
15498c2ecf20Sopenharmony_ci			FDMI_PORT_SPEED_2GB|FDMI_PORT_SPEED_1GB;
15508c2ecf20Sopenharmony_ci	if (IS_QLA24XX_TYPE(ha))
15518c2ecf20Sopenharmony_ci		return FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_2GB|
15528c2ecf20Sopenharmony_ci			FDMI_PORT_SPEED_1GB;
15538c2ecf20Sopenharmony_ci	if (IS_QLA23XX(ha))
15548c2ecf20Sopenharmony_ci		return FDMI_PORT_SPEED_2GB|FDMI_PORT_SPEED_1GB;
15558c2ecf20Sopenharmony_ci	return FDMI_PORT_SPEED_1GB;
15568c2ecf20Sopenharmony_ci}
15578c2ecf20Sopenharmony_ci
15588c2ecf20Sopenharmony_ciuint
15598c2ecf20Sopenharmony_ciqla25xx_fdmi_port_speed_currently(struct qla_hw_data *ha)
15608c2ecf20Sopenharmony_ci{
15618c2ecf20Sopenharmony_ci	switch (ha->link_data_rate) {
15628c2ecf20Sopenharmony_ci	case PORT_SPEED_1GB:
15638c2ecf20Sopenharmony_ci		return FDMI_PORT_SPEED_1GB;
15648c2ecf20Sopenharmony_ci	case PORT_SPEED_2GB:
15658c2ecf20Sopenharmony_ci		return FDMI_PORT_SPEED_2GB;
15668c2ecf20Sopenharmony_ci	case PORT_SPEED_4GB:
15678c2ecf20Sopenharmony_ci		return FDMI_PORT_SPEED_4GB;
15688c2ecf20Sopenharmony_ci	case PORT_SPEED_8GB:
15698c2ecf20Sopenharmony_ci		return FDMI_PORT_SPEED_8GB;
15708c2ecf20Sopenharmony_ci	case PORT_SPEED_10GB:
15718c2ecf20Sopenharmony_ci		return FDMI_PORT_SPEED_10GB;
15728c2ecf20Sopenharmony_ci	case PORT_SPEED_16GB:
15738c2ecf20Sopenharmony_ci		return FDMI_PORT_SPEED_16GB;
15748c2ecf20Sopenharmony_ci	case PORT_SPEED_32GB:
15758c2ecf20Sopenharmony_ci		return FDMI_PORT_SPEED_32GB;
15768c2ecf20Sopenharmony_ci	case PORT_SPEED_64GB:
15778c2ecf20Sopenharmony_ci		return FDMI_PORT_SPEED_64GB;
15788c2ecf20Sopenharmony_ci	default:
15798c2ecf20Sopenharmony_ci		return FDMI_PORT_SPEED_UNKNOWN;
15808c2ecf20Sopenharmony_ci	}
15818c2ecf20Sopenharmony_ci}
15828c2ecf20Sopenharmony_ci
15838c2ecf20Sopenharmony_ci/**
15848c2ecf20Sopenharmony_ci * qla2x00_hba_attributes() perform HBA attributes registration
15858c2ecf20Sopenharmony_ci * @vha: HA context
15868c2ecf20Sopenharmony_ci * @entries: number of entries to use
15878c2ecf20Sopenharmony_ci * @callopt: Option to issue extended or standard FDMI
15888c2ecf20Sopenharmony_ci *           command parameter
15898c2ecf20Sopenharmony_ci *
15908c2ecf20Sopenharmony_ci * Returns 0 on success.
15918c2ecf20Sopenharmony_ci */
15928c2ecf20Sopenharmony_cistatic unsigned long
15938c2ecf20Sopenharmony_ciqla2x00_hba_attributes(scsi_qla_host_t *vha, void *entries,
15948c2ecf20Sopenharmony_ci	unsigned int callopt)
15958c2ecf20Sopenharmony_ci{
15968c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
15978c2ecf20Sopenharmony_ci	struct new_utsname *p_sysid = utsname();
15988c2ecf20Sopenharmony_ci	struct ct_fdmi_hba_attr *eiter;
15998c2ecf20Sopenharmony_ci	uint16_t alen;
16008c2ecf20Sopenharmony_ci	unsigned long size = 0;
16018c2ecf20Sopenharmony_ci
16028c2ecf20Sopenharmony_ci	/* Nodename. */
16038c2ecf20Sopenharmony_ci	eiter = entries + size;
16048c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME);
16058c2ecf20Sopenharmony_ci	memcpy(eiter->a.node_name, vha->node_name, sizeof(eiter->a.node_name));
16068c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.node_name);
16078c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
16088c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
16098c2ecf20Sopenharmony_ci	size += alen;
16108c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20a0,
16118c2ecf20Sopenharmony_ci	    "NODENAME = %016llx.\n", wwn_to_u64(eiter->a.node_name));
16128c2ecf20Sopenharmony_ci	/* Manufacturer. */
16138c2ecf20Sopenharmony_ci	eiter = entries + size;
16148c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER);
16158c2ecf20Sopenharmony_ci	alen = scnprintf(
16168c2ecf20Sopenharmony_ci		eiter->a.manufacturer, sizeof(eiter->a.manufacturer),
16178c2ecf20Sopenharmony_ci		"%s", "QLogic Corporation");
16188c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_ALIGNMENT(alen);
16198c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
16208c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
16218c2ecf20Sopenharmony_ci	size += alen;
16228c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20a1,
16238c2ecf20Sopenharmony_ci	    "MANUFACTURER = %s.\n", eiter->a.manufacturer);
16248c2ecf20Sopenharmony_ci	/* Serial number. */
16258c2ecf20Sopenharmony_ci	eiter = entries + size;
16268c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
16278c2ecf20Sopenharmony_ci	alen = 0;
16288c2ecf20Sopenharmony_ci	if (IS_FWI2_CAPABLE(ha)) {
16298c2ecf20Sopenharmony_ci		alen = qla2xxx_get_vpd_field(vha, "SN",
16308c2ecf20Sopenharmony_ci		    eiter->a.serial_num, sizeof(eiter->a.serial_num));
16318c2ecf20Sopenharmony_ci	}
16328c2ecf20Sopenharmony_ci	if (!alen) {
16338c2ecf20Sopenharmony_ci		uint32_t sn = ((ha->serial0 & 0x1f) << 16) |
16348c2ecf20Sopenharmony_ci			(ha->serial2 << 8) | ha->serial1;
16358c2ecf20Sopenharmony_ci		alen = scnprintf(
16368c2ecf20Sopenharmony_ci			eiter->a.serial_num, sizeof(eiter->a.serial_num),
16378c2ecf20Sopenharmony_ci			"%c%05d", 'A' + sn / 100000, sn % 100000);
16388c2ecf20Sopenharmony_ci	}
16398c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_ALIGNMENT(alen);
16408c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
16418c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
16428c2ecf20Sopenharmony_ci	size += alen;
16438c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20a2,
16448c2ecf20Sopenharmony_ci	    "SERIAL NUMBER = %s.\n", eiter->a.serial_num);
16458c2ecf20Sopenharmony_ci	/* Model name. */
16468c2ecf20Sopenharmony_ci	eiter = entries + size;
16478c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_HBA_MODEL);
16488c2ecf20Sopenharmony_ci	alen = scnprintf(
16498c2ecf20Sopenharmony_ci		eiter->a.model, sizeof(eiter->a.model),
16508c2ecf20Sopenharmony_ci		"%s", ha->model_number);
16518c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_ALIGNMENT(alen);
16528c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
16538c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
16548c2ecf20Sopenharmony_ci	size += alen;
16558c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20a3,
16568c2ecf20Sopenharmony_ci	    "MODEL NAME = %s.\n", eiter->a.model);
16578c2ecf20Sopenharmony_ci	/* Model description. */
16588c2ecf20Sopenharmony_ci	eiter = entries + size;
16598c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
16608c2ecf20Sopenharmony_ci	alen = scnprintf(
16618c2ecf20Sopenharmony_ci		eiter->a.model_desc, sizeof(eiter->a.model_desc),
16628c2ecf20Sopenharmony_ci		"%s", ha->model_desc);
16638c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_ALIGNMENT(alen);
16648c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
16658c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
16668c2ecf20Sopenharmony_ci	size += alen;
16678c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20a4,
16688c2ecf20Sopenharmony_ci	    "MODEL DESCRIPTION = %s.\n", eiter->a.model_desc);
16698c2ecf20Sopenharmony_ci	/* Hardware version. */
16708c2ecf20Sopenharmony_ci	eiter = entries + size;
16718c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
16728c2ecf20Sopenharmony_ci	alen = 0;
16738c2ecf20Sopenharmony_ci	if (IS_FWI2_CAPABLE(ha)) {
16748c2ecf20Sopenharmony_ci		if (!alen) {
16758c2ecf20Sopenharmony_ci			alen = qla2xxx_get_vpd_field(vha, "MN",
16768c2ecf20Sopenharmony_ci			    eiter->a.hw_version, sizeof(eiter->a.hw_version));
16778c2ecf20Sopenharmony_ci		}
16788c2ecf20Sopenharmony_ci		if (!alen) {
16798c2ecf20Sopenharmony_ci			alen = qla2xxx_get_vpd_field(vha, "EC",
16808c2ecf20Sopenharmony_ci			    eiter->a.hw_version, sizeof(eiter->a.hw_version));
16818c2ecf20Sopenharmony_ci		}
16828c2ecf20Sopenharmony_ci	}
16838c2ecf20Sopenharmony_ci	if (!alen) {
16848c2ecf20Sopenharmony_ci		alen = scnprintf(
16858c2ecf20Sopenharmony_ci			eiter->a.hw_version, sizeof(eiter->a.hw_version),
16868c2ecf20Sopenharmony_ci			"HW:%s", ha->adapter_id);
16878c2ecf20Sopenharmony_ci	}
16888c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_ALIGNMENT(alen);
16898c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
16908c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
16918c2ecf20Sopenharmony_ci	size += alen;
16928c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20a5,
16938c2ecf20Sopenharmony_ci	    "HARDWARE VERSION = %s.\n", eiter->a.hw_version);
16948c2ecf20Sopenharmony_ci	/* Driver version. */
16958c2ecf20Sopenharmony_ci	eiter = entries + size;
16968c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
16978c2ecf20Sopenharmony_ci	alen = scnprintf(
16988c2ecf20Sopenharmony_ci		eiter->a.driver_version, sizeof(eiter->a.driver_version),
16998c2ecf20Sopenharmony_ci		"%s", qla2x00_version_str);
17008c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_ALIGNMENT(alen);
17018c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
17028c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
17038c2ecf20Sopenharmony_ci	size += alen;
17048c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20a6,
17058c2ecf20Sopenharmony_ci	    "DRIVER VERSION = %s.\n", eiter->a.driver_version);
17068c2ecf20Sopenharmony_ci	/* Option ROM version. */
17078c2ecf20Sopenharmony_ci	eiter = entries + size;
17088c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
17098c2ecf20Sopenharmony_ci	alen = scnprintf(
17108c2ecf20Sopenharmony_ci		eiter->a.orom_version, sizeof(eiter->a.orom_version),
17118c2ecf20Sopenharmony_ci		"%d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
17128c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_ALIGNMENT(alen);
17138c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
17148c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
17158c2ecf20Sopenharmony_ci	size += alen;
17168c2ecf20Sopenharmony_ci
17178c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20a7,
17188c2ecf20Sopenharmony_ci	    "OPTROM VERSION = %d.%02d.\n",
17198c2ecf20Sopenharmony_ci	    eiter->a.orom_version[1], eiter->a.orom_version[0]);
17208c2ecf20Sopenharmony_ci	/* Firmware version */
17218c2ecf20Sopenharmony_ci	eiter = entries + size;
17228c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
17238c2ecf20Sopenharmony_ci	ha->isp_ops->fw_version_str(vha, eiter->a.fw_version,
17248c2ecf20Sopenharmony_ci	    sizeof(eiter->a.fw_version));
17258c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_ALIGNMENT(alen);
17268c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
17278c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
17288c2ecf20Sopenharmony_ci	size += alen;
17298c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20a8,
17308c2ecf20Sopenharmony_ci	    "FIRMWARE VERSION = %s.\n", eiter->a.fw_version);
17318c2ecf20Sopenharmony_ci	if (callopt == CALLOPT_FDMI1)
17328c2ecf20Sopenharmony_ci		goto done;
17338c2ecf20Sopenharmony_ci	/* OS Name and Version */
17348c2ecf20Sopenharmony_ci	eiter = entries + size;
17358c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_HBA_OS_NAME_AND_VERSION);
17368c2ecf20Sopenharmony_ci	alen = 0;
17378c2ecf20Sopenharmony_ci	if (p_sysid) {
17388c2ecf20Sopenharmony_ci		alen = scnprintf(
17398c2ecf20Sopenharmony_ci			eiter->a.os_version, sizeof(eiter->a.os_version),
17408c2ecf20Sopenharmony_ci			"%s %s %s",
17418c2ecf20Sopenharmony_ci			p_sysid->sysname, p_sysid->release, p_sysid->machine);
17428c2ecf20Sopenharmony_ci	}
17438c2ecf20Sopenharmony_ci	if (!alen) {
17448c2ecf20Sopenharmony_ci		alen = scnprintf(
17458c2ecf20Sopenharmony_ci			eiter->a.os_version, sizeof(eiter->a.os_version),
17468c2ecf20Sopenharmony_ci			"%s %s",
17478c2ecf20Sopenharmony_ci			"Linux", fc_host_system_hostname(vha->host));
17488c2ecf20Sopenharmony_ci	}
17498c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_ALIGNMENT(alen);
17508c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
17518c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
17528c2ecf20Sopenharmony_ci	size += alen;
17538c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20a9,
17548c2ecf20Sopenharmony_ci	    "OS VERSION = %s.\n", eiter->a.os_version);
17558c2ecf20Sopenharmony_ci	/* MAX CT Payload Length */
17568c2ecf20Sopenharmony_ci	eiter = entries + size;
17578c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH);
17588c2ecf20Sopenharmony_ci	eiter->a.max_ct_len = cpu_to_be32(ha->frame_payload_size >> 2);
17598c2ecf20Sopenharmony_ci
17608c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.max_ct_len);
17618c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
17628c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
17638c2ecf20Sopenharmony_ci	size += alen;
17648c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20aa,
17658c2ecf20Sopenharmony_ci	    "CT PAYLOAD LENGTH = 0x%x.\n", be32_to_cpu(eiter->a.max_ct_len));
17668c2ecf20Sopenharmony_ci	/* Node Sybolic Name */
17678c2ecf20Sopenharmony_ci	eiter = entries + size;
17688c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_HBA_NODE_SYMBOLIC_NAME);
17698c2ecf20Sopenharmony_ci	alen = qla2x00_get_sym_node_name(vha, eiter->a.sym_name,
17708c2ecf20Sopenharmony_ci	    sizeof(eiter->a.sym_name));
17718c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_ALIGNMENT(alen);
17728c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
17738c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
17748c2ecf20Sopenharmony_ci	size += alen;
17758c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20ab,
17768c2ecf20Sopenharmony_ci	    "SYMBOLIC NAME = %s.\n", eiter->a.sym_name);
17778c2ecf20Sopenharmony_ci	/* Vendor Specific information */
17788c2ecf20Sopenharmony_ci	eiter = entries + size;
17798c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_SPECIFIC_INFO);
17808c2ecf20Sopenharmony_ci	eiter->a.vendor_specific_info = cpu_to_be32(PCI_VENDOR_ID_QLOGIC);
17818c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.vendor_specific_info);
17828c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
17838c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
17848c2ecf20Sopenharmony_ci	size += alen;
17858c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20ac,
17868c2ecf20Sopenharmony_ci	    "VENDOR SPECIFIC INFO = 0x%x.\n",
17878c2ecf20Sopenharmony_ci	    be32_to_cpu(eiter->a.vendor_specific_info));
17888c2ecf20Sopenharmony_ci	/* Num Ports */
17898c2ecf20Sopenharmony_ci	eiter = entries + size;
17908c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_HBA_NUM_PORTS);
17918c2ecf20Sopenharmony_ci	eiter->a.num_ports = cpu_to_be32(1);
17928c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.num_ports);
17938c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
17948c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
17958c2ecf20Sopenharmony_ci	size += alen;
17968c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20ad,
17978c2ecf20Sopenharmony_ci	    "PORT COUNT = %x.\n", be32_to_cpu(eiter->a.num_ports));
17988c2ecf20Sopenharmony_ci	/* Fabric Name */
17998c2ecf20Sopenharmony_ci	eiter = entries + size;
18008c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_HBA_FABRIC_NAME);
18018c2ecf20Sopenharmony_ci	memcpy(eiter->a.fabric_name, vha->fabric_node_name,
18028c2ecf20Sopenharmony_ci	    sizeof(eiter->a.fabric_name));
18038c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.fabric_name);
18048c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
18058c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
18068c2ecf20Sopenharmony_ci	size += alen;
18078c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20ae,
18088c2ecf20Sopenharmony_ci	    "FABRIC NAME = %016llx.\n", wwn_to_u64(eiter->a.fabric_name));
18098c2ecf20Sopenharmony_ci	/* BIOS Version */
18108c2ecf20Sopenharmony_ci	eiter = entries + size;
18118c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_HBA_BOOT_BIOS_NAME);
18128c2ecf20Sopenharmony_ci	alen = scnprintf(
18138c2ecf20Sopenharmony_ci		eiter->a.bios_name, sizeof(eiter->a.bios_name),
18148c2ecf20Sopenharmony_ci		"BIOS %d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
18158c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_ALIGNMENT(alen);
18168c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
18178c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
18188c2ecf20Sopenharmony_ci	size += alen;
18198c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20af,
18208c2ecf20Sopenharmony_ci	    "BIOS NAME = %s\n", eiter->a.bios_name);
18218c2ecf20Sopenharmony_ci	/* Vendor Identifier */
18228c2ecf20Sopenharmony_ci	eiter = entries + size;
18238c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_IDENTIFIER);
18248c2ecf20Sopenharmony_ci	alen = scnprintf(
18258c2ecf20Sopenharmony_ci		eiter->a.vendor_identifier, sizeof(eiter->a.vendor_identifier),
18268c2ecf20Sopenharmony_ci		"%s", "QLGC");
18278c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_ALIGNMENT(alen);
18288c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
18298c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
18308c2ecf20Sopenharmony_ci	size += alen;
18318c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20b0,
18328c2ecf20Sopenharmony_ci	    "VENDOR IDENTIFIER = %s.\n", eiter->a.vendor_identifier);
18338c2ecf20Sopenharmony_cidone:
18348c2ecf20Sopenharmony_ci	return size;
18358c2ecf20Sopenharmony_ci}
18368c2ecf20Sopenharmony_ci
18378c2ecf20Sopenharmony_ci/**
18388c2ecf20Sopenharmony_ci * qla2x00_port_attributes() perform Port attributes registration
18398c2ecf20Sopenharmony_ci * @vha: HA context
18408c2ecf20Sopenharmony_ci * @entries: number of entries to use
18418c2ecf20Sopenharmony_ci * @callopt: Option to issue extended or standard FDMI
18428c2ecf20Sopenharmony_ci *           command parameter
18438c2ecf20Sopenharmony_ci *
18448c2ecf20Sopenharmony_ci * Returns 0 on success.
18458c2ecf20Sopenharmony_ci */
18468c2ecf20Sopenharmony_cistatic unsigned long
18478c2ecf20Sopenharmony_ciqla2x00_port_attributes(scsi_qla_host_t *vha, void *entries,
18488c2ecf20Sopenharmony_ci	unsigned int callopt)
18498c2ecf20Sopenharmony_ci{
18508c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
18518c2ecf20Sopenharmony_ci	struct new_utsname *p_sysid = utsname();
18528c2ecf20Sopenharmony_ci	char *hostname = p_sysid ?
18538c2ecf20Sopenharmony_ci		p_sysid->nodename : fc_host_system_hostname(vha->host);
18548c2ecf20Sopenharmony_ci	struct ct_fdmi_port_attr *eiter;
18558c2ecf20Sopenharmony_ci	uint16_t alen;
18568c2ecf20Sopenharmony_ci	unsigned long size = 0;
18578c2ecf20Sopenharmony_ci
18588c2ecf20Sopenharmony_ci	/* FC4 types. */
18598c2ecf20Sopenharmony_ci	eiter = entries + size;
18608c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES);
18618c2ecf20Sopenharmony_ci	eiter->a.fc4_types[0] = 0x00;
18628c2ecf20Sopenharmony_ci	eiter->a.fc4_types[1] = 0x00;
18638c2ecf20Sopenharmony_ci	eiter->a.fc4_types[2] = 0x01;
18648c2ecf20Sopenharmony_ci	eiter->a.fc4_types[3] = 0x00;
18658c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.fc4_types);
18668c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
18678c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
18688c2ecf20Sopenharmony_ci	size += alen;
18698c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20c0,
18708c2ecf20Sopenharmony_ci	    "FC4 TYPES = %016llx.\n", *(uint64_t *)eiter->a.fc4_types);
18718c2ecf20Sopenharmony_ci	if (vha->flags.nvme_enabled) {
18728c2ecf20Sopenharmony_ci		eiter->a.fc4_types[6] = 1;      /* NVMe type 28h */
18738c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x211f,
18748c2ecf20Sopenharmony_ci		    "NVME FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n",
18758c2ecf20Sopenharmony_ci		    eiter->a.fc4_types[6]);
18768c2ecf20Sopenharmony_ci	}
18778c2ecf20Sopenharmony_ci	/* Supported speed. */
18788c2ecf20Sopenharmony_ci	eiter = entries + size;
18798c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
18808c2ecf20Sopenharmony_ci	eiter->a.sup_speed = cpu_to_be32(
18818c2ecf20Sopenharmony_ci		qla25xx_fdmi_port_speed_capability(ha));
18828c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.sup_speed);
18838c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
18848c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
18858c2ecf20Sopenharmony_ci	size += alen;
18868c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20c1,
18878c2ecf20Sopenharmony_ci	    "SUPPORTED SPEED = %x.\n", be32_to_cpu(eiter->a.sup_speed));
18888c2ecf20Sopenharmony_ci	/* Current speed. */
18898c2ecf20Sopenharmony_ci	eiter = entries + size;
18908c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
18918c2ecf20Sopenharmony_ci	eiter->a.cur_speed = cpu_to_be32(
18928c2ecf20Sopenharmony_ci		qla25xx_fdmi_port_speed_currently(ha));
18938c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.cur_speed);
18948c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
18958c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
18968c2ecf20Sopenharmony_ci	size += alen;
18978c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20c2,
18988c2ecf20Sopenharmony_ci	    "CURRENT SPEED = %x.\n", be32_to_cpu(eiter->a.cur_speed));
18998c2ecf20Sopenharmony_ci	/* Max frame size. */
19008c2ecf20Sopenharmony_ci	eiter = entries + size;
19018c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
19028c2ecf20Sopenharmony_ci	eiter->a.max_frame_size = cpu_to_be32(ha->frame_payload_size);
19038c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.max_frame_size);
19048c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
19058c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
19068c2ecf20Sopenharmony_ci	size += alen;
19078c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20c3,
19088c2ecf20Sopenharmony_ci	    "MAX FRAME SIZE = %x.\n", be32_to_cpu(eiter->a.max_frame_size));
19098c2ecf20Sopenharmony_ci	/* OS device name. */
19108c2ecf20Sopenharmony_ci	eiter = entries + size;
19118c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
19128c2ecf20Sopenharmony_ci	alen = scnprintf(
19138c2ecf20Sopenharmony_ci		eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name),
19148c2ecf20Sopenharmony_ci		"%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no);
19158c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_ALIGNMENT(alen);
19168c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
19178c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
19188c2ecf20Sopenharmony_ci	size += alen;
19198c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20c4,
19208c2ecf20Sopenharmony_ci	    "OS DEVICE NAME = %s.\n", eiter->a.os_dev_name);
19218c2ecf20Sopenharmony_ci	/* Hostname. */
19228c2ecf20Sopenharmony_ci	eiter = entries + size;
19238c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME);
19248c2ecf20Sopenharmony_ci	if (!*hostname || !strncmp(hostname, "(none)", 6))
19258c2ecf20Sopenharmony_ci		hostname = "Linux-default";
19268c2ecf20Sopenharmony_ci	alen = scnprintf(
19278c2ecf20Sopenharmony_ci		eiter->a.host_name, sizeof(eiter->a.host_name),
19288c2ecf20Sopenharmony_ci		"%s", hostname);
19298c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_ALIGNMENT(alen);
19308c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
19318c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
19328c2ecf20Sopenharmony_ci	size += alen;
19338c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20c5,
19348c2ecf20Sopenharmony_ci	    "HOSTNAME = %s.\n", eiter->a.host_name);
19358c2ecf20Sopenharmony_ci
19368c2ecf20Sopenharmony_ci	if (callopt == CALLOPT_FDMI1)
19378c2ecf20Sopenharmony_ci		goto done;
19388c2ecf20Sopenharmony_ci
19398c2ecf20Sopenharmony_ci	/* Node Name */
19408c2ecf20Sopenharmony_ci	eiter = entries + size;
19418c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_PORT_NODE_NAME);
19428c2ecf20Sopenharmony_ci	memcpy(eiter->a.node_name, vha->node_name, sizeof(eiter->a.node_name));
19438c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.node_name);
19448c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
19458c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
19468c2ecf20Sopenharmony_ci	size += alen;
19478c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20c6,
19488c2ecf20Sopenharmony_ci	    "NODENAME = %016llx.\n", wwn_to_u64(eiter->a.node_name));
19498c2ecf20Sopenharmony_ci
19508c2ecf20Sopenharmony_ci	/* Port Name */
19518c2ecf20Sopenharmony_ci	eiter = entries + size;
19528c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_PORT_NAME);
19538c2ecf20Sopenharmony_ci	memcpy(eiter->a.port_name, vha->port_name, sizeof(eiter->a.port_name));
19548c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.port_name);
19558c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
19568c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
19578c2ecf20Sopenharmony_ci	size += alen;
19588c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20c7,
19598c2ecf20Sopenharmony_ci	    "PORTNAME = %016llx.\n", wwn_to_u64(eiter->a.port_name));
19608c2ecf20Sopenharmony_ci
19618c2ecf20Sopenharmony_ci	/* Port Symbolic Name */
19628c2ecf20Sopenharmony_ci	eiter = entries + size;
19638c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_PORT_SYM_NAME);
19648c2ecf20Sopenharmony_ci	alen = qla2x00_get_sym_node_name(vha, eiter->a.port_sym_name,
19658c2ecf20Sopenharmony_ci	    sizeof(eiter->a.port_sym_name));
19668c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_ALIGNMENT(alen);
19678c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
19688c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
19698c2ecf20Sopenharmony_ci	size += alen;
19708c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20c8,
19718c2ecf20Sopenharmony_ci	    "PORT SYMBOLIC NAME = %s\n", eiter->a.port_sym_name);
19728c2ecf20Sopenharmony_ci
19738c2ecf20Sopenharmony_ci	/* Port Type */
19748c2ecf20Sopenharmony_ci	eiter = entries + size;
19758c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_PORT_TYPE);
19768c2ecf20Sopenharmony_ci	eiter->a.port_type = cpu_to_be32(NS_NX_PORT_TYPE);
19778c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.port_type);
19788c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
19798c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
19808c2ecf20Sopenharmony_ci	size += alen;
19818c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20c9,
19828c2ecf20Sopenharmony_ci	    "PORT TYPE = %x.\n", be32_to_cpu(eiter->a.port_type));
19838c2ecf20Sopenharmony_ci
19848c2ecf20Sopenharmony_ci	/* Supported Class of Service */
19858c2ecf20Sopenharmony_ci	eiter = entries + size;
19868c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_PORT_SUPP_COS);
19878c2ecf20Sopenharmony_ci	eiter->a.port_supported_cos = cpu_to_be32(FC_CLASS_3);
19888c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.port_supported_cos);
19898c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
19908c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
19918c2ecf20Sopenharmony_ci	size += alen;
19928c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20ca,
19938c2ecf20Sopenharmony_ci	    "SUPPORTED COS = %08x\n", be32_to_cpu(eiter->a.port_supported_cos));
19948c2ecf20Sopenharmony_ci
19958c2ecf20Sopenharmony_ci	/* Port Fabric Name */
19968c2ecf20Sopenharmony_ci	eiter = entries + size;
19978c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_PORT_FABRIC_NAME);
19988c2ecf20Sopenharmony_ci	memcpy(eiter->a.fabric_name, vha->fabric_node_name,
19998c2ecf20Sopenharmony_ci	    sizeof(eiter->a.fabric_name));
20008c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.fabric_name);
20018c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
20028c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
20038c2ecf20Sopenharmony_ci	size += alen;
20048c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20cb,
20058c2ecf20Sopenharmony_ci	    "FABRIC NAME = %016llx.\n", wwn_to_u64(eiter->a.fabric_name));
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_ci	/* FC4_type */
20088c2ecf20Sopenharmony_ci	eiter = entries + size;
20098c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPE);
20108c2ecf20Sopenharmony_ci	eiter->a.port_fc4_type[0] = 0x00;
20118c2ecf20Sopenharmony_ci	eiter->a.port_fc4_type[1] = 0x00;
20128c2ecf20Sopenharmony_ci	eiter->a.port_fc4_type[2] = 0x01;
20138c2ecf20Sopenharmony_ci	eiter->a.port_fc4_type[3] = 0x00;
20148c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.port_fc4_type);
20158c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
20168c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
20178c2ecf20Sopenharmony_ci	size += alen;
20188c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20cc,
20198c2ecf20Sopenharmony_ci	    "PORT ACTIVE FC4 TYPE = %016llx.\n",
20208c2ecf20Sopenharmony_ci	    *(uint64_t *)eiter->a.port_fc4_type);
20218c2ecf20Sopenharmony_ci
20228c2ecf20Sopenharmony_ci	/* Port State */
20238c2ecf20Sopenharmony_ci	eiter = entries + size;
20248c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_PORT_STATE);
20258c2ecf20Sopenharmony_ci	eiter->a.port_state = cpu_to_be32(2);
20268c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.port_state);
20278c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
20288c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
20298c2ecf20Sopenharmony_ci	size += alen;
20308c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20cd,
20318c2ecf20Sopenharmony_ci	    "PORT_STATE = %x.\n", be32_to_cpu(eiter->a.port_state));
20328c2ecf20Sopenharmony_ci
20338c2ecf20Sopenharmony_ci	/* Number of Ports */
20348c2ecf20Sopenharmony_ci	eiter = entries + size;
20358c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_PORT_COUNT);
20368c2ecf20Sopenharmony_ci	eiter->a.num_ports = cpu_to_be32(1);
20378c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.num_ports);
20388c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
20398c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
20408c2ecf20Sopenharmony_ci	size += alen;
20418c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20ce,
20428c2ecf20Sopenharmony_ci	    "PORT COUNT = %x.\n", be32_to_cpu(eiter->a.num_ports));
20438c2ecf20Sopenharmony_ci
20448c2ecf20Sopenharmony_ci	/* Port Identifier */
20458c2ecf20Sopenharmony_ci	eiter = entries + size;
20468c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_PORT_IDENTIFIER);
20478c2ecf20Sopenharmony_ci	eiter->a.port_id = cpu_to_be32(vha->d_id.b24);
20488c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.port_id);
20498c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
20508c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
20518c2ecf20Sopenharmony_ci	size += alen;
20528c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20cf,
20538c2ecf20Sopenharmony_ci	    "PORT ID = %x.\n", be32_to_cpu(eiter->a.port_id));
20548c2ecf20Sopenharmony_ci
20558c2ecf20Sopenharmony_ci	if (callopt == CALLOPT_FDMI2 || !ql2xsmartsan)
20568c2ecf20Sopenharmony_ci		goto done;
20578c2ecf20Sopenharmony_ci
20588c2ecf20Sopenharmony_ci	/* Smart SAN Service Category (Populate Smart SAN Initiator)*/
20598c2ecf20Sopenharmony_ci	eiter = entries + size;
20608c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_SMARTSAN_SERVICE);
20618c2ecf20Sopenharmony_ci	alen = scnprintf(
20628c2ecf20Sopenharmony_ci		eiter->a.smartsan_service, sizeof(eiter->a.smartsan_service),
20638c2ecf20Sopenharmony_ci		"%s", "Smart SAN Initiator");
20648c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_ALIGNMENT(alen);
20658c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
20668c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
20678c2ecf20Sopenharmony_ci	size += alen;
20688c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20d0,
20698c2ecf20Sopenharmony_ci	    "SMARTSAN SERVICE CATEGORY = %s.\n", eiter->a.smartsan_service);
20708c2ecf20Sopenharmony_ci
20718c2ecf20Sopenharmony_ci	/* Smart SAN GUID (NWWN+PWWN) */
20728c2ecf20Sopenharmony_ci	eiter = entries + size;
20738c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_SMARTSAN_GUID);
20748c2ecf20Sopenharmony_ci	memcpy(eiter->a.smartsan_guid, vha->node_name, WWN_SIZE);
20758c2ecf20Sopenharmony_ci	memcpy(eiter->a.smartsan_guid + WWN_SIZE, vha->port_name, WWN_SIZE);
20768c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.smartsan_guid);
20778c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
20788c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
20798c2ecf20Sopenharmony_ci	size += alen;
20808c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20d1,
20818c2ecf20Sopenharmony_ci	    "Smart SAN GUID = %016llx-%016llx\n",
20828c2ecf20Sopenharmony_ci	    wwn_to_u64(eiter->a.smartsan_guid),
20838c2ecf20Sopenharmony_ci	    wwn_to_u64(eiter->a.smartsan_guid + WWN_SIZE));
20848c2ecf20Sopenharmony_ci
20858c2ecf20Sopenharmony_ci	/* Smart SAN Version (populate "Smart SAN Version 1.0") */
20868c2ecf20Sopenharmony_ci	eiter = entries + size;
20878c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_SMARTSAN_VERSION);
20888c2ecf20Sopenharmony_ci	alen = scnprintf(
20898c2ecf20Sopenharmony_ci		eiter->a.smartsan_version, sizeof(eiter->a.smartsan_version),
20908c2ecf20Sopenharmony_ci		"%s", "Smart SAN Version 2.0");
20918c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_ALIGNMENT(alen);
20928c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
20938c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
20948c2ecf20Sopenharmony_ci	size += alen;
20958c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20d2,
20968c2ecf20Sopenharmony_ci	    "SMARTSAN VERSION = %s\n", eiter->a.smartsan_version);
20978c2ecf20Sopenharmony_ci
20988c2ecf20Sopenharmony_ci	/* Smart SAN Product Name (Specify Adapter Model No) */
20998c2ecf20Sopenharmony_ci	eiter = entries + size;
21008c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_SMARTSAN_PROD_NAME);
21018c2ecf20Sopenharmony_ci	alen = scnprintf(eiter->a.smartsan_prod_name,
21028c2ecf20Sopenharmony_ci		sizeof(eiter->a.smartsan_prod_name),
21038c2ecf20Sopenharmony_ci		"ISP%04x", ha->pdev->device);
21048c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_ALIGNMENT(alen);
21058c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
21068c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
21078c2ecf20Sopenharmony_ci	size += alen;
21088c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20d3,
21098c2ecf20Sopenharmony_ci	    "SMARTSAN PRODUCT NAME = %s\n", eiter->a.smartsan_prod_name);
21108c2ecf20Sopenharmony_ci
21118c2ecf20Sopenharmony_ci	/* Smart SAN Port Info (specify: 1=Physical, 2=NPIV, 3=SRIOV) */
21128c2ecf20Sopenharmony_ci	eiter = entries + size;
21138c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_SMARTSAN_PORT_INFO);
21148c2ecf20Sopenharmony_ci	eiter->a.smartsan_port_info = cpu_to_be32(vha->vp_idx ? 2 : 1);
21158c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.smartsan_port_info);
21168c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
21178c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
21188c2ecf20Sopenharmony_ci	size += alen;
21198c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20d4,
21208c2ecf20Sopenharmony_ci	    "SMARTSAN PORT INFO = %x\n", eiter->a.smartsan_port_info);
21218c2ecf20Sopenharmony_ci
21228c2ecf20Sopenharmony_ci	/* Smart SAN Security Support */
21238c2ecf20Sopenharmony_ci	eiter = entries + size;
21248c2ecf20Sopenharmony_ci	eiter->type = cpu_to_be16(FDMI_SMARTSAN_SECURITY_SUPPORT);
21258c2ecf20Sopenharmony_ci	eiter->a.smartsan_security_support = cpu_to_be32(1);
21268c2ecf20Sopenharmony_ci	alen = sizeof(eiter->a.smartsan_security_support);
21278c2ecf20Sopenharmony_ci	alen += FDMI_ATTR_TYPELEN(eiter);
21288c2ecf20Sopenharmony_ci	eiter->len = cpu_to_be16(alen);
21298c2ecf20Sopenharmony_ci	size += alen;
21308c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20d6,
21318c2ecf20Sopenharmony_ci	    "SMARTSAN SECURITY SUPPORT = %d\n",
21328c2ecf20Sopenharmony_ci	    be32_to_cpu(eiter->a.smartsan_security_support));
21338c2ecf20Sopenharmony_ci
21348c2ecf20Sopenharmony_cidone:
21358c2ecf20Sopenharmony_ci	return size;
21368c2ecf20Sopenharmony_ci}
21378c2ecf20Sopenharmony_ci
21388c2ecf20Sopenharmony_ci/**
21398c2ecf20Sopenharmony_ci * qla2x00_fdmi_rhba() - perform RHBA FDMI registration
21408c2ecf20Sopenharmony_ci * @vha: HA context
21418c2ecf20Sopenharmony_ci * @callopt: Option to issue FDMI registration
21428c2ecf20Sopenharmony_ci *
21438c2ecf20Sopenharmony_ci * Returns 0 on success.
21448c2ecf20Sopenharmony_ci */
21458c2ecf20Sopenharmony_cistatic int
21468c2ecf20Sopenharmony_ciqla2x00_fdmi_rhba(scsi_qla_host_t *vha, unsigned int callopt)
21478c2ecf20Sopenharmony_ci{
21488c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
21498c2ecf20Sopenharmony_ci	unsigned long size = 0;
21508c2ecf20Sopenharmony_ci	unsigned int rval, count;
21518c2ecf20Sopenharmony_ci	ms_iocb_entry_t *ms_pkt;
21528c2ecf20Sopenharmony_ci	struct ct_sns_req *ct_req;
21538c2ecf20Sopenharmony_ci	struct ct_sns_rsp *ct_rsp;
21548c2ecf20Sopenharmony_ci	void *entries;
21558c2ecf20Sopenharmony_ci
21568c2ecf20Sopenharmony_ci	count = callopt != CALLOPT_FDMI1 ?
21578c2ecf20Sopenharmony_ci	    FDMI2_HBA_ATTR_COUNT : FDMI1_HBA_ATTR_COUNT;
21588c2ecf20Sopenharmony_ci
21598c2ecf20Sopenharmony_ci	size = RHBA_RSP_SIZE;
21608c2ecf20Sopenharmony_ci
21618c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20e0,
21628c2ecf20Sopenharmony_ci	    "RHBA (callopt=%x count=%u size=%lu).\n", callopt, count, size);
21638c2ecf20Sopenharmony_ci
21648c2ecf20Sopenharmony_ci	/*   Request size adjusted after CT preparation */
21658c2ecf20Sopenharmony_ci	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size);
21668c2ecf20Sopenharmony_ci
21678c2ecf20Sopenharmony_ci	/* Prepare CT request */
21688c2ecf20Sopenharmony_ci	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, size);
21698c2ecf20Sopenharmony_ci	ct_rsp = &ha->ct_sns->p.rsp;
21708c2ecf20Sopenharmony_ci
21718c2ecf20Sopenharmony_ci	/* Prepare FDMI command entries */
21728c2ecf20Sopenharmony_ci	memcpy(ct_req->req.rhba.hba_identifier, vha->port_name,
21738c2ecf20Sopenharmony_ci	    sizeof(ct_req->req.rhba.hba_identifier));
21748c2ecf20Sopenharmony_ci	size += sizeof(ct_req->req.rhba.hba_identifier);
21758c2ecf20Sopenharmony_ci
21768c2ecf20Sopenharmony_ci	ct_req->req.rhba.entry_count = cpu_to_be32(1);
21778c2ecf20Sopenharmony_ci	size += sizeof(ct_req->req.rhba.entry_count);
21788c2ecf20Sopenharmony_ci
21798c2ecf20Sopenharmony_ci	memcpy(ct_req->req.rhba.port_name, vha->port_name,
21808c2ecf20Sopenharmony_ci	    sizeof(ct_req->req.rhba.port_name));
21818c2ecf20Sopenharmony_ci	size += sizeof(ct_req->req.rhba.port_name);
21828c2ecf20Sopenharmony_ci
21838c2ecf20Sopenharmony_ci	/* Attribute count */
21848c2ecf20Sopenharmony_ci	ct_req->req.rhba.attrs.count = cpu_to_be32(count);
21858c2ecf20Sopenharmony_ci	size += sizeof(ct_req->req.rhba.attrs.count);
21868c2ecf20Sopenharmony_ci
21878c2ecf20Sopenharmony_ci	/* Attribute block */
21888c2ecf20Sopenharmony_ci	entries = &ct_req->req.rhba.attrs.entry;
21898c2ecf20Sopenharmony_ci
21908c2ecf20Sopenharmony_ci	size += qla2x00_hba_attributes(vha, entries, callopt);
21918c2ecf20Sopenharmony_ci
21928c2ecf20Sopenharmony_ci	/* Update MS request size. */
21938c2ecf20Sopenharmony_ci	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
21948c2ecf20Sopenharmony_ci
21958c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20e1,
21968c2ecf20Sopenharmony_ci	    "RHBA %016llx %016llx.\n",
21978c2ecf20Sopenharmony_ci	    wwn_to_u64(ct_req->req.rhba.hba_identifier),
21988c2ecf20Sopenharmony_ci	    wwn_to_u64(ct_req->req.rhba.port_name));
21998c2ecf20Sopenharmony_ci
22008c2ecf20Sopenharmony_ci	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20e2,
22018c2ecf20Sopenharmony_ci	    entries, size);
22028c2ecf20Sopenharmony_ci
22038c2ecf20Sopenharmony_ci	/* Execute MS IOCB */
22048c2ecf20Sopenharmony_ci	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
22058c2ecf20Sopenharmony_ci	    sizeof(*ha->ms_iocb));
22068c2ecf20Sopenharmony_ci	if (rval) {
22078c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x20e3,
22088c2ecf20Sopenharmony_ci		    "RHBA iocb failed (%d).\n", rval);
22098c2ecf20Sopenharmony_ci		return rval;
22108c2ecf20Sopenharmony_ci	}
22118c2ecf20Sopenharmony_ci
22128c2ecf20Sopenharmony_ci	rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA");
22138c2ecf20Sopenharmony_ci	if (rval) {
22148c2ecf20Sopenharmony_ci		if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
22158c2ecf20Sopenharmony_ci		    ct_rsp->header.explanation_code ==
22168c2ecf20Sopenharmony_ci		    CT_EXPL_ALREADY_REGISTERED) {
22178c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x20e4,
22188c2ecf20Sopenharmony_ci			    "RHBA already registered.\n");
22198c2ecf20Sopenharmony_ci			return QLA_ALREADY_REGISTERED;
22208c2ecf20Sopenharmony_ci		}
22218c2ecf20Sopenharmony_ci
22228c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x20e5,
22238c2ecf20Sopenharmony_ci		    "RHBA failed, CT Reason %#x, CT Explanation %#x\n",
22248c2ecf20Sopenharmony_ci		    ct_rsp->header.reason_code,
22258c2ecf20Sopenharmony_ci		    ct_rsp->header.explanation_code);
22268c2ecf20Sopenharmony_ci		return rval;
22278c2ecf20Sopenharmony_ci	}
22288c2ecf20Sopenharmony_ci
22298c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20e6, "RHBA exiting normally.\n");
22308c2ecf20Sopenharmony_ci	return rval;
22318c2ecf20Sopenharmony_ci}
22328c2ecf20Sopenharmony_ci
22338c2ecf20Sopenharmony_ci
22348c2ecf20Sopenharmony_cistatic int
22358c2ecf20Sopenharmony_ciqla2x00_fdmi_dhba(scsi_qla_host_t *vha)
22368c2ecf20Sopenharmony_ci{
22378c2ecf20Sopenharmony_ci	int rval;
22388c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
22398c2ecf20Sopenharmony_ci	ms_iocb_entry_t *ms_pkt;
22408c2ecf20Sopenharmony_ci	struct ct_sns_req *ct_req;
22418c2ecf20Sopenharmony_ci	struct ct_sns_rsp *ct_rsp;
22428c2ecf20Sopenharmony_ci	/* Issue RPA */
22438c2ecf20Sopenharmony_ci	/* Prepare common MS IOCB */
22448c2ecf20Sopenharmony_ci	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, DHBA_REQ_SIZE,
22458c2ecf20Sopenharmony_ci	    DHBA_RSP_SIZE);
22468c2ecf20Sopenharmony_ci	/* Prepare CT request */
22478c2ecf20Sopenharmony_ci	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, DHBA_CMD, DHBA_RSP_SIZE);
22488c2ecf20Sopenharmony_ci	ct_rsp = &ha->ct_sns->p.rsp;
22498c2ecf20Sopenharmony_ci	/* Prepare FDMI command arguments -- portname. */
22508c2ecf20Sopenharmony_ci	memcpy(ct_req->req.dhba.port_name, vha->port_name, WWN_SIZE);
22518c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x2036,
22528c2ecf20Sopenharmony_ci	    "DHBA portname = %8phN.\n", ct_req->req.dhba.port_name);
22538c2ecf20Sopenharmony_ci	/* Execute MS IOCB */
22548c2ecf20Sopenharmony_ci	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
22558c2ecf20Sopenharmony_ci	    sizeof(ms_iocb_entry_t));
22568c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS) {
22578c2ecf20Sopenharmony_ci		/*EMPTY*/
22588c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x2037,
22598c2ecf20Sopenharmony_ci		    "DHBA issue IOCB failed (%d).\n", rval);
22608c2ecf20Sopenharmony_ci	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "DHBA") !=
22618c2ecf20Sopenharmony_ci	    QLA_SUCCESS) {
22628c2ecf20Sopenharmony_ci		rval = QLA_FUNCTION_FAILED;
22638c2ecf20Sopenharmony_ci	} else {
22648c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x2038,
22658c2ecf20Sopenharmony_ci		    "DHBA exiting normally.\n");
22668c2ecf20Sopenharmony_ci	}
22678c2ecf20Sopenharmony_ci	return rval;
22688c2ecf20Sopenharmony_ci}
22698c2ecf20Sopenharmony_ci
22708c2ecf20Sopenharmony_ci/**
22718c2ecf20Sopenharmony_ci * qla2x00_fdmi_rprt() perform RPRT registration
22728c2ecf20Sopenharmony_ci * @vha: HA context
22738c2ecf20Sopenharmony_ci * @callopt: Option to issue extended or standard FDMI
22748c2ecf20Sopenharmony_ci *           command parameter
22758c2ecf20Sopenharmony_ci *
22768c2ecf20Sopenharmony_ci * Returns 0 on success.
22778c2ecf20Sopenharmony_ci */
22788c2ecf20Sopenharmony_cistatic int
22798c2ecf20Sopenharmony_ciqla2x00_fdmi_rprt(scsi_qla_host_t *vha, int callopt)
22808c2ecf20Sopenharmony_ci{
22818c2ecf20Sopenharmony_ci	struct scsi_qla_host *base_vha = pci_get_drvdata(vha->hw->pdev);
22828c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
22838c2ecf20Sopenharmony_ci	ulong size = 0;
22848c2ecf20Sopenharmony_ci	uint rval, count;
22858c2ecf20Sopenharmony_ci	ms_iocb_entry_t *ms_pkt;
22868c2ecf20Sopenharmony_ci	struct ct_sns_req *ct_req;
22878c2ecf20Sopenharmony_ci	struct ct_sns_rsp *ct_rsp;
22888c2ecf20Sopenharmony_ci	void *entries;
22898c2ecf20Sopenharmony_ci	count = callopt == CALLOPT_FDMI2_SMARTSAN && ql2xsmartsan ?
22908c2ecf20Sopenharmony_ci		FDMI2_SMARTSAN_PORT_ATTR_COUNT :
22918c2ecf20Sopenharmony_ci		callopt != CALLOPT_FDMI1 ?
22928c2ecf20Sopenharmony_ci		FDMI2_PORT_ATTR_COUNT : FDMI1_PORT_ATTR_COUNT;
22938c2ecf20Sopenharmony_ci
22948c2ecf20Sopenharmony_ci	size = RPRT_RSP_SIZE;
22958c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20e8,
22968c2ecf20Sopenharmony_ci	    "RPRT (callopt=%x count=%u size=%lu).\n", callopt, count, size);
22978c2ecf20Sopenharmony_ci	/* Request size adjusted after CT preparation */
22988c2ecf20Sopenharmony_ci	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size);
22998c2ecf20Sopenharmony_ci	/* Prepare CT request */
23008c2ecf20Sopenharmony_ci	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPRT_CMD, size);
23018c2ecf20Sopenharmony_ci	ct_rsp = &ha->ct_sns->p.rsp;
23028c2ecf20Sopenharmony_ci	/* Prepare FDMI command entries */
23038c2ecf20Sopenharmony_ci	memcpy(ct_req->req.rprt.hba_identifier, base_vha->port_name,
23048c2ecf20Sopenharmony_ci	    sizeof(ct_req->req.rprt.hba_identifier));
23058c2ecf20Sopenharmony_ci	size += sizeof(ct_req->req.rprt.hba_identifier);
23068c2ecf20Sopenharmony_ci	memcpy(ct_req->req.rprt.port_name, vha->port_name,
23078c2ecf20Sopenharmony_ci	    sizeof(ct_req->req.rprt.port_name));
23088c2ecf20Sopenharmony_ci	size += sizeof(ct_req->req.rprt.port_name);
23098c2ecf20Sopenharmony_ci	/* Attribute count */
23108c2ecf20Sopenharmony_ci	ct_req->req.rprt.attrs.count = cpu_to_be32(count);
23118c2ecf20Sopenharmony_ci	size += sizeof(ct_req->req.rprt.attrs.count);
23128c2ecf20Sopenharmony_ci	/* Attribute block */
23138c2ecf20Sopenharmony_ci	entries = ct_req->req.rprt.attrs.entry;
23148c2ecf20Sopenharmony_ci	size += qla2x00_port_attributes(vha, entries, callopt);
23158c2ecf20Sopenharmony_ci	/* Update MS request size. */
23168c2ecf20Sopenharmony_ci	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
23178c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20e9,
23188c2ecf20Sopenharmony_ci	    "RPRT %016llx  %016llx.\n",
23198c2ecf20Sopenharmony_ci	    wwn_to_u64(ct_req->req.rprt.port_name),
23208c2ecf20Sopenharmony_ci	    wwn_to_u64(ct_req->req.rprt.port_name));
23218c2ecf20Sopenharmony_ci	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20ea,
23228c2ecf20Sopenharmony_ci	    entries, size);
23238c2ecf20Sopenharmony_ci	/* Execute MS IOCB */
23248c2ecf20Sopenharmony_ci	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
23258c2ecf20Sopenharmony_ci	    sizeof(*ha->ms_iocb));
23268c2ecf20Sopenharmony_ci	if (rval) {
23278c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x20eb,
23288c2ecf20Sopenharmony_ci		    "RPRT iocb failed (%d).\n", rval);
23298c2ecf20Sopenharmony_ci		return rval;
23308c2ecf20Sopenharmony_ci	}
23318c2ecf20Sopenharmony_ci	rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPRT");
23328c2ecf20Sopenharmony_ci	if (rval) {
23338c2ecf20Sopenharmony_ci		if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
23348c2ecf20Sopenharmony_ci		    ct_rsp->header.explanation_code ==
23358c2ecf20Sopenharmony_ci		    CT_EXPL_ALREADY_REGISTERED) {
23368c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x20ec,
23378c2ecf20Sopenharmony_ci			    "RPRT already registered.\n");
23388c2ecf20Sopenharmony_ci			return QLA_ALREADY_REGISTERED;
23398c2ecf20Sopenharmony_ci		}
23408c2ecf20Sopenharmony_ci
23418c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x20ed,
23428c2ecf20Sopenharmony_ci		    "RPRT failed, CT Reason code: %#x, CT Explanation %#x\n",
23438c2ecf20Sopenharmony_ci		    ct_rsp->header.reason_code,
23448c2ecf20Sopenharmony_ci		    ct_rsp->header.explanation_code);
23458c2ecf20Sopenharmony_ci		return rval;
23468c2ecf20Sopenharmony_ci	}
23478c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20ee, "RPRT exiting normally.\n");
23488c2ecf20Sopenharmony_ci	return rval;
23498c2ecf20Sopenharmony_ci}
23508c2ecf20Sopenharmony_ci
23518c2ecf20Sopenharmony_ci/**
23528c2ecf20Sopenharmony_ci * qla2x00_fdmi_rpa() - perform RPA registration
23538c2ecf20Sopenharmony_ci * @vha: HA context
23548c2ecf20Sopenharmony_ci * @callopt: Option to issue FDMI registration
23558c2ecf20Sopenharmony_ci *
23568c2ecf20Sopenharmony_ci * Returns 0 on success.
23578c2ecf20Sopenharmony_ci */
23588c2ecf20Sopenharmony_cistatic int
23598c2ecf20Sopenharmony_ciqla2x00_fdmi_rpa(scsi_qla_host_t *vha, uint callopt)
23608c2ecf20Sopenharmony_ci{
23618c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
23628c2ecf20Sopenharmony_ci	ulong size = 0;
23638c2ecf20Sopenharmony_ci	uint rval, count;
23648c2ecf20Sopenharmony_ci	ms_iocb_entry_t *ms_pkt;
23658c2ecf20Sopenharmony_ci	struct ct_sns_req *ct_req;
23668c2ecf20Sopenharmony_ci	struct ct_sns_rsp *ct_rsp;
23678c2ecf20Sopenharmony_ci	void *entries;
23688c2ecf20Sopenharmony_ci
23698c2ecf20Sopenharmony_ci	count =
23708c2ecf20Sopenharmony_ci	    callopt == CALLOPT_FDMI2_SMARTSAN && ql2xsmartsan ?
23718c2ecf20Sopenharmony_ci		FDMI2_SMARTSAN_PORT_ATTR_COUNT :
23728c2ecf20Sopenharmony_ci	    callopt != CALLOPT_FDMI1 ?
23738c2ecf20Sopenharmony_ci		FDMI2_PORT_ATTR_COUNT : FDMI1_PORT_ATTR_COUNT;
23748c2ecf20Sopenharmony_ci
23758c2ecf20Sopenharmony_ci	size =
23768c2ecf20Sopenharmony_ci	    callopt != CALLOPT_FDMI1 ?
23778c2ecf20Sopenharmony_ci		SMARTSAN_RPA_RSP_SIZE : RPA_RSP_SIZE;
23788c2ecf20Sopenharmony_ci
23798c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20f0,
23808c2ecf20Sopenharmony_ci	    "RPA (callopt=%x count=%u size=%lu).\n", callopt, count, size);
23818c2ecf20Sopenharmony_ci
23828c2ecf20Sopenharmony_ci	/* Request size adjusted after CT preparation */
23838c2ecf20Sopenharmony_ci	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size);
23848c2ecf20Sopenharmony_ci
23858c2ecf20Sopenharmony_ci	/* Prepare CT request */
23868c2ecf20Sopenharmony_ci	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, size);
23878c2ecf20Sopenharmony_ci	ct_rsp = &ha->ct_sns->p.rsp;
23888c2ecf20Sopenharmony_ci
23898c2ecf20Sopenharmony_ci	/* Prepare FDMI command entries. */
23908c2ecf20Sopenharmony_ci	memcpy(ct_req->req.rpa.port_name, vha->port_name,
23918c2ecf20Sopenharmony_ci	    sizeof(ct_req->req.rpa.port_name));
23928c2ecf20Sopenharmony_ci	size += sizeof(ct_req->req.rpa.port_name);
23938c2ecf20Sopenharmony_ci
23948c2ecf20Sopenharmony_ci	/* Attribute count */
23958c2ecf20Sopenharmony_ci	ct_req->req.rpa.attrs.count = cpu_to_be32(count);
23968c2ecf20Sopenharmony_ci	size += sizeof(ct_req->req.rpa.attrs.count);
23978c2ecf20Sopenharmony_ci
23988c2ecf20Sopenharmony_ci	/* Attribute block */
23998c2ecf20Sopenharmony_ci	entries = ct_req->req.rpa.attrs.entry;
24008c2ecf20Sopenharmony_ci
24018c2ecf20Sopenharmony_ci	size += qla2x00_port_attributes(vha, entries, callopt);
24028c2ecf20Sopenharmony_ci
24038c2ecf20Sopenharmony_ci	/* Update MS request size. */
24048c2ecf20Sopenharmony_ci	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
24058c2ecf20Sopenharmony_ci
24068c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20f1,
24078c2ecf20Sopenharmony_ci	    "RPA %016llx.\n", wwn_to_u64(ct_req->req.rpa.port_name));
24088c2ecf20Sopenharmony_ci
24098c2ecf20Sopenharmony_ci	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20f2,
24108c2ecf20Sopenharmony_ci	    entries, size);
24118c2ecf20Sopenharmony_ci
24128c2ecf20Sopenharmony_ci	/* Execute MS IOCB */
24138c2ecf20Sopenharmony_ci	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
24148c2ecf20Sopenharmony_ci	    sizeof(*ha->ms_iocb));
24158c2ecf20Sopenharmony_ci	if (rval) {
24168c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x20f3,
24178c2ecf20Sopenharmony_ci		    "RPA iocb failed (%d).\n", rval);
24188c2ecf20Sopenharmony_ci		return rval;
24198c2ecf20Sopenharmony_ci	}
24208c2ecf20Sopenharmony_ci
24218c2ecf20Sopenharmony_ci	rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA");
24228c2ecf20Sopenharmony_ci	if (rval) {
24238c2ecf20Sopenharmony_ci		if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
24248c2ecf20Sopenharmony_ci		    ct_rsp->header.explanation_code ==
24258c2ecf20Sopenharmony_ci		    CT_EXPL_ALREADY_REGISTERED) {
24268c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x20f4,
24278c2ecf20Sopenharmony_ci			    "RPA already registered.\n");
24288c2ecf20Sopenharmony_ci			return QLA_ALREADY_REGISTERED;
24298c2ecf20Sopenharmony_ci		}
24308c2ecf20Sopenharmony_ci
24318c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x20f5,
24328c2ecf20Sopenharmony_ci		    "RPA failed, CT Reason code: %#x, CT Explanation %#x\n",
24338c2ecf20Sopenharmony_ci		    ct_rsp->header.reason_code,
24348c2ecf20Sopenharmony_ci		    ct_rsp->header.explanation_code);
24358c2ecf20Sopenharmony_ci		return rval;
24368c2ecf20Sopenharmony_ci	}
24378c2ecf20Sopenharmony_ci
24388c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20f6, "RPA exiting normally.\n");
24398c2ecf20Sopenharmony_ci	return rval;
24408c2ecf20Sopenharmony_ci}
24418c2ecf20Sopenharmony_ci
24428c2ecf20Sopenharmony_ci/**
24438c2ecf20Sopenharmony_ci * qla2x00_fdmi_register() -
24448c2ecf20Sopenharmony_ci * @vha: HA context
24458c2ecf20Sopenharmony_ci *
24468c2ecf20Sopenharmony_ci * Returns 0 on success.
24478c2ecf20Sopenharmony_ci */
24488c2ecf20Sopenharmony_ciint
24498c2ecf20Sopenharmony_ciqla2x00_fdmi_register(scsi_qla_host_t *vha)
24508c2ecf20Sopenharmony_ci{
24518c2ecf20Sopenharmony_ci	int rval = QLA_SUCCESS;
24528c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
24538c2ecf20Sopenharmony_ci
24548c2ecf20Sopenharmony_ci	if (IS_QLA2100(ha) || IS_QLA2200(ha) ||
24558c2ecf20Sopenharmony_ci	    IS_QLAFX00(ha))
24568c2ecf20Sopenharmony_ci		return rval;
24578c2ecf20Sopenharmony_ci
24588c2ecf20Sopenharmony_ci	rval = qla2x00_mgmt_svr_login(vha);
24598c2ecf20Sopenharmony_ci	if (rval)
24608c2ecf20Sopenharmony_ci		return rval;
24618c2ecf20Sopenharmony_ci
24628c2ecf20Sopenharmony_ci	/* For npiv/vport send rprt only */
24638c2ecf20Sopenharmony_ci	if (vha->vp_idx) {
24648c2ecf20Sopenharmony_ci		if (ql2xsmartsan)
24658c2ecf20Sopenharmony_ci			rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI2_SMARTSAN);
24668c2ecf20Sopenharmony_ci		if (rval || !ql2xsmartsan)
24678c2ecf20Sopenharmony_ci			rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI2);
24688c2ecf20Sopenharmony_ci		if (rval)
24698c2ecf20Sopenharmony_ci			rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI1);
24708c2ecf20Sopenharmony_ci
24718c2ecf20Sopenharmony_ci		return rval;
24728c2ecf20Sopenharmony_ci	}
24738c2ecf20Sopenharmony_ci
24748c2ecf20Sopenharmony_ci	/* Try fdmi2 first, if fails then try fdmi1 */
24758c2ecf20Sopenharmony_ci	rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI2);
24768c2ecf20Sopenharmony_ci	if (rval) {
24778c2ecf20Sopenharmony_ci		if (rval != QLA_ALREADY_REGISTERED)
24788c2ecf20Sopenharmony_ci			goto try_fdmi;
24798c2ecf20Sopenharmony_ci
24808c2ecf20Sopenharmony_ci		rval = qla2x00_fdmi_dhba(vha);
24818c2ecf20Sopenharmony_ci		if (rval)
24828c2ecf20Sopenharmony_ci			goto try_fdmi;
24838c2ecf20Sopenharmony_ci
24848c2ecf20Sopenharmony_ci		rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI2);
24858c2ecf20Sopenharmony_ci		if (rval)
24868c2ecf20Sopenharmony_ci			goto try_fdmi;
24878c2ecf20Sopenharmony_ci	}
24888c2ecf20Sopenharmony_ci
24898c2ecf20Sopenharmony_ci	if (ql2xsmartsan)
24908c2ecf20Sopenharmony_ci		rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI2_SMARTSAN);
24918c2ecf20Sopenharmony_ci	if (rval || !ql2xsmartsan)
24928c2ecf20Sopenharmony_ci		rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI2);
24938c2ecf20Sopenharmony_ci	if (rval)
24948c2ecf20Sopenharmony_ci		goto try_fdmi;
24958c2ecf20Sopenharmony_ci
24968c2ecf20Sopenharmony_ci	return rval;
24978c2ecf20Sopenharmony_ci
24988c2ecf20Sopenharmony_citry_fdmi:
24998c2ecf20Sopenharmony_ci	rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI1);
25008c2ecf20Sopenharmony_ci	if (rval) {
25018c2ecf20Sopenharmony_ci		if (rval != QLA_ALREADY_REGISTERED)
25028c2ecf20Sopenharmony_ci			return rval;
25038c2ecf20Sopenharmony_ci
25048c2ecf20Sopenharmony_ci		rval = qla2x00_fdmi_dhba(vha);
25058c2ecf20Sopenharmony_ci		if (rval)
25068c2ecf20Sopenharmony_ci			return rval;
25078c2ecf20Sopenharmony_ci
25088c2ecf20Sopenharmony_ci		rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI1);
25098c2ecf20Sopenharmony_ci		if (rval)
25108c2ecf20Sopenharmony_ci			return rval;
25118c2ecf20Sopenharmony_ci	}
25128c2ecf20Sopenharmony_ci
25138c2ecf20Sopenharmony_ci	rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI1);
25148c2ecf20Sopenharmony_ci
25158c2ecf20Sopenharmony_ci	return rval;
25168c2ecf20Sopenharmony_ci}
25178c2ecf20Sopenharmony_ci
25188c2ecf20Sopenharmony_ci/**
25198c2ecf20Sopenharmony_ci * qla2x00_gfpn_id() - SNS Get Fabric Port Name (GFPN_ID) query.
25208c2ecf20Sopenharmony_ci * @vha: HA context
25218c2ecf20Sopenharmony_ci * @list: switch info entries to populate
25228c2ecf20Sopenharmony_ci *
25238c2ecf20Sopenharmony_ci * Returns 0 on success.
25248c2ecf20Sopenharmony_ci */
25258c2ecf20Sopenharmony_ciint
25268c2ecf20Sopenharmony_ciqla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)
25278c2ecf20Sopenharmony_ci{
25288c2ecf20Sopenharmony_ci	int		rval = QLA_SUCCESS;
25298c2ecf20Sopenharmony_ci	uint16_t	i;
25308c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
25318c2ecf20Sopenharmony_ci	ms_iocb_entry_t	*ms_pkt;
25328c2ecf20Sopenharmony_ci	struct ct_sns_req	*ct_req;
25338c2ecf20Sopenharmony_ci	struct ct_sns_rsp	*ct_rsp;
25348c2ecf20Sopenharmony_ci	struct ct_arg arg;
25358c2ecf20Sopenharmony_ci
25368c2ecf20Sopenharmony_ci	if (!IS_IIDMA_CAPABLE(ha))
25378c2ecf20Sopenharmony_ci		return QLA_FUNCTION_FAILED;
25388c2ecf20Sopenharmony_ci
25398c2ecf20Sopenharmony_ci	arg.iocb = ha->ms_iocb;
25408c2ecf20Sopenharmony_ci	arg.req_dma = ha->ct_sns_dma;
25418c2ecf20Sopenharmony_ci	arg.rsp_dma = ha->ct_sns_dma;
25428c2ecf20Sopenharmony_ci	arg.req_size = GFPN_ID_REQ_SIZE;
25438c2ecf20Sopenharmony_ci	arg.rsp_size = GFPN_ID_RSP_SIZE;
25448c2ecf20Sopenharmony_ci	arg.nport_handle = NPH_SNS;
25458c2ecf20Sopenharmony_ci
25468c2ecf20Sopenharmony_ci	for (i = 0; i < ha->max_fibre_devices; i++) {
25478c2ecf20Sopenharmony_ci		/* Issue GFPN_ID */
25488c2ecf20Sopenharmony_ci		/* Prepare common MS IOCB */
25498c2ecf20Sopenharmony_ci		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
25508c2ecf20Sopenharmony_ci
25518c2ecf20Sopenharmony_ci		/* Prepare CT request */
25528c2ecf20Sopenharmony_ci		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFPN_ID_CMD,
25538c2ecf20Sopenharmony_ci		    GFPN_ID_RSP_SIZE);
25548c2ecf20Sopenharmony_ci		ct_rsp = &ha->ct_sns->p.rsp;
25558c2ecf20Sopenharmony_ci
25568c2ecf20Sopenharmony_ci		/* Prepare CT arguments -- port_id */
25578c2ecf20Sopenharmony_ci		ct_req->req.port_id.port_id = port_id_to_be_id(list[i].d_id);
25588c2ecf20Sopenharmony_ci
25598c2ecf20Sopenharmony_ci		/* Execute MS IOCB */
25608c2ecf20Sopenharmony_ci		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
25618c2ecf20Sopenharmony_ci		    sizeof(ms_iocb_entry_t));
25628c2ecf20Sopenharmony_ci		if (rval != QLA_SUCCESS) {
25638c2ecf20Sopenharmony_ci			/*EMPTY*/
25648c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x2023,
25658c2ecf20Sopenharmony_ci			    "GFPN_ID issue IOCB failed (%d).\n", rval);
25668c2ecf20Sopenharmony_ci			break;
25678c2ecf20Sopenharmony_ci		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
25688c2ecf20Sopenharmony_ci		    "GFPN_ID") != QLA_SUCCESS) {
25698c2ecf20Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
25708c2ecf20Sopenharmony_ci			break;
25718c2ecf20Sopenharmony_ci		} else {
25728c2ecf20Sopenharmony_ci			/* Save fabric portname */
25738c2ecf20Sopenharmony_ci			memcpy(list[i].fabric_port_name,
25748c2ecf20Sopenharmony_ci			    ct_rsp->rsp.gfpn_id.port_name, WWN_SIZE);
25758c2ecf20Sopenharmony_ci		}
25768c2ecf20Sopenharmony_ci
25778c2ecf20Sopenharmony_ci		/* Last device exit. */
25788c2ecf20Sopenharmony_ci		if (list[i].d_id.b.rsvd_1 != 0)
25798c2ecf20Sopenharmony_ci			break;
25808c2ecf20Sopenharmony_ci	}
25818c2ecf20Sopenharmony_ci
25828c2ecf20Sopenharmony_ci	return (rval);
25838c2ecf20Sopenharmony_ci}
25848c2ecf20Sopenharmony_ci
25858c2ecf20Sopenharmony_ci
25868c2ecf20Sopenharmony_cistatic inline struct ct_sns_req *
25878c2ecf20Sopenharmony_ciqla24xx_prep_ct_fm_req(struct ct_sns_pkt *p, uint16_t cmd,
25888c2ecf20Sopenharmony_ci    uint16_t rsp_size)
25898c2ecf20Sopenharmony_ci{
25908c2ecf20Sopenharmony_ci	memset(p, 0, sizeof(struct ct_sns_pkt));
25918c2ecf20Sopenharmony_ci
25928c2ecf20Sopenharmony_ci	p->p.req.header.revision = 0x01;
25938c2ecf20Sopenharmony_ci	p->p.req.header.gs_type = 0xFA;
25948c2ecf20Sopenharmony_ci	p->p.req.header.gs_subtype = 0x01;
25958c2ecf20Sopenharmony_ci	p->p.req.command = cpu_to_be16(cmd);
25968c2ecf20Sopenharmony_ci	p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
25978c2ecf20Sopenharmony_ci
25988c2ecf20Sopenharmony_ci	return &p->p.req;
25998c2ecf20Sopenharmony_ci}
26008c2ecf20Sopenharmony_ci
26018c2ecf20Sopenharmony_cistatic uint16_t
26028c2ecf20Sopenharmony_ciqla2x00_port_speed_capability(uint16_t speed)
26038c2ecf20Sopenharmony_ci{
26048c2ecf20Sopenharmony_ci	switch (speed) {
26058c2ecf20Sopenharmony_ci	case BIT_15:
26068c2ecf20Sopenharmony_ci		return PORT_SPEED_1GB;
26078c2ecf20Sopenharmony_ci	case BIT_14:
26088c2ecf20Sopenharmony_ci		return PORT_SPEED_2GB;
26098c2ecf20Sopenharmony_ci	case BIT_13:
26108c2ecf20Sopenharmony_ci		return PORT_SPEED_4GB;
26118c2ecf20Sopenharmony_ci	case BIT_12:
26128c2ecf20Sopenharmony_ci		return PORT_SPEED_10GB;
26138c2ecf20Sopenharmony_ci	case BIT_11:
26148c2ecf20Sopenharmony_ci		return PORT_SPEED_8GB;
26158c2ecf20Sopenharmony_ci	case BIT_10:
26168c2ecf20Sopenharmony_ci		return PORT_SPEED_16GB;
26178c2ecf20Sopenharmony_ci	case BIT_8:
26188c2ecf20Sopenharmony_ci		return PORT_SPEED_32GB;
26198c2ecf20Sopenharmony_ci	case BIT_7:
26208c2ecf20Sopenharmony_ci		return PORT_SPEED_64GB;
26218c2ecf20Sopenharmony_ci	default:
26228c2ecf20Sopenharmony_ci		return PORT_SPEED_UNKNOWN;
26238c2ecf20Sopenharmony_ci	}
26248c2ecf20Sopenharmony_ci}
26258c2ecf20Sopenharmony_ci
26268c2ecf20Sopenharmony_ci/**
26278c2ecf20Sopenharmony_ci * qla2x00_gpsc() - FCS Get Port Speed Capabilities (GPSC) query.
26288c2ecf20Sopenharmony_ci * @vha: HA context
26298c2ecf20Sopenharmony_ci * @list: switch info entries to populate
26308c2ecf20Sopenharmony_ci *
26318c2ecf20Sopenharmony_ci * Returns 0 on success.
26328c2ecf20Sopenharmony_ci */
26338c2ecf20Sopenharmony_ciint
26348c2ecf20Sopenharmony_ciqla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
26358c2ecf20Sopenharmony_ci{
26368c2ecf20Sopenharmony_ci	int		rval;
26378c2ecf20Sopenharmony_ci	uint16_t	i;
26388c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
26398c2ecf20Sopenharmony_ci	ms_iocb_entry_t *ms_pkt;
26408c2ecf20Sopenharmony_ci	struct ct_sns_req	*ct_req;
26418c2ecf20Sopenharmony_ci	struct ct_sns_rsp	*ct_rsp;
26428c2ecf20Sopenharmony_ci	struct ct_arg arg;
26438c2ecf20Sopenharmony_ci
26448c2ecf20Sopenharmony_ci	if (!IS_IIDMA_CAPABLE(ha))
26458c2ecf20Sopenharmony_ci		return QLA_FUNCTION_FAILED;
26468c2ecf20Sopenharmony_ci	if (!ha->flags.gpsc_supported)
26478c2ecf20Sopenharmony_ci		return QLA_FUNCTION_FAILED;
26488c2ecf20Sopenharmony_ci
26498c2ecf20Sopenharmony_ci	rval = qla2x00_mgmt_svr_login(vha);
26508c2ecf20Sopenharmony_ci	if (rval)
26518c2ecf20Sopenharmony_ci		return rval;
26528c2ecf20Sopenharmony_ci
26538c2ecf20Sopenharmony_ci	arg.iocb = ha->ms_iocb;
26548c2ecf20Sopenharmony_ci	arg.req_dma = ha->ct_sns_dma;
26558c2ecf20Sopenharmony_ci	arg.rsp_dma = ha->ct_sns_dma;
26568c2ecf20Sopenharmony_ci	arg.req_size = GPSC_REQ_SIZE;
26578c2ecf20Sopenharmony_ci	arg.rsp_size = GPSC_RSP_SIZE;
26588c2ecf20Sopenharmony_ci	arg.nport_handle = vha->mgmt_svr_loop_id;
26598c2ecf20Sopenharmony_ci
26608c2ecf20Sopenharmony_ci	for (i = 0; i < ha->max_fibre_devices; i++) {
26618c2ecf20Sopenharmony_ci		/* Issue GFPN_ID */
26628c2ecf20Sopenharmony_ci		/* Prepare common MS IOCB */
26638c2ecf20Sopenharmony_ci		ms_pkt = qla24xx_prep_ms_iocb(vha, &arg);
26648c2ecf20Sopenharmony_ci
26658c2ecf20Sopenharmony_ci		/* Prepare CT request */
26668c2ecf20Sopenharmony_ci		ct_req = qla24xx_prep_ct_fm_req(ha->ct_sns, GPSC_CMD,
26678c2ecf20Sopenharmony_ci		    GPSC_RSP_SIZE);
26688c2ecf20Sopenharmony_ci		ct_rsp = &ha->ct_sns->p.rsp;
26698c2ecf20Sopenharmony_ci
26708c2ecf20Sopenharmony_ci		/* Prepare CT arguments -- port_name */
26718c2ecf20Sopenharmony_ci		memcpy(ct_req->req.gpsc.port_name, list[i].fabric_port_name,
26728c2ecf20Sopenharmony_ci		    WWN_SIZE);
26738c2ecf20Sopenharmony_ci
26748c2ecf20Sopenharmony_ci		/* Execute MS IOCB */
26758c2ecf20Sopenharmony_ci		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
26768c2ecf20Sopenharmony_ci		    sizeof(ms_iocb_entry_t));
26778c2ecf20Sopenharmony_ci		if (rval != QLA_SUCCESS) {
26788c2ecf20Sopenharmony_ci			/*EMPTY*/
26798c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x2059,
26808c2ecf20Sopenharmony_ci			    "GPSC issue IOCB failed (%d).\n", rval);
26818c2ecf20Sopenharmony_ci		} else if ((rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
26828c2ecf20Sopenharmony_ci		    "GPSC")) != QLA_SUCCESS) {
26838c2ecf20Sopenharmony_ci			/* FM command unsupported? */
26848c2ecf20Sopenharmony_ci			if (rval == QLA_INVALID_COMMAND &&
26858c2ecf20Sopenharmony_ci			    (ct_rsp->header.reason_code ==
26868c2ecf20Sopenharmony_ci				CT_REASON_INVALID_COMMAND_CODE ||
26878c2ecf20Sopenharmony_ci			     ct_rsp->header.reason_code ==
26888c2ecf20Sopenharmony_ci				CT_REASON_COMMAND_UNSUPPORTED)) {
26898c2ecf20Sopenharmony_ci				ql_dbg(ql_dbg_disc, vha, 0x205a,
26908c2ecf20Sopenharmony_ci				    "GPSC command unsupported, disabling "
26918c2ecf20Sopenharmony_ci				    "query.\n");
26928c2ecf20Sopenharmony_ci				ha->flags.gpsc_supported = 0;
26938c2ecf20Sopenharmony_ci				rval = QLA_FUNCTION_FAILED;
26948c2ecf20Sopenharmony_ci				break;
26958c2ecf20Sopenharmony_ci			}
26968c2ecf20Sopenharmony_ci			rval = QLA_FUNCTION_FAILED;
26978c2ecf20Sopenharmony_ci		} else {
26988c2ecf20Sopenharmony_ci			list->fp_speed = qla2x00_port_speed_capability(
26998c2ecf20Sopenharmony_ci			    be16_to_cpu(ct_rsp->rsp.gpsc.speed));
27008c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x205b,
27018c2ecf20Sopenharmony_ci			    "GPSC ext entry - fpn "
27028c2ecf20Sopenharmony_ci			    "%8phN speeds=%04x speed=%04x.\n",
27038c2ecf20Sopenharmony_ci			    list[i].fabric_port_name,
27048c2ecf20Sopenharmony_ci			    be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
27058c2ecf20Sopenharmony_ci			    be16_to_cpu(ct_rsp->rsp.gpsc.speed));
27068c2ecf20Sopenharmony_ci		}
27078c2ecf20Sopenharmony_ci
27088c2ecf20Sopenharmony_ci		/* Last device exit. */
27098c2ecf20Sopenharmony_ci		if (list[i].d_id.b.rsvd_1 != 0)
27108c2ecf20Sopenharmony_ci			break;
27118c2ecf20Sopenharmony_ci	}
27128c2ecf20Sopenharmony_ci
27138c2ecf20Sopenharmony_ci	return (rval);
27148c2ecf20Sopenharmony_ci}
27158c2ecf20Sopenharmony_ci
27168c2ecf20Sopenharmony_ci/**
27178c2ecf20Sopenharmony_ci * qla2x00_gff_id() - SNS Get FC-4 Features (GFF_ID) query.
27188c2ecf20Sopenharmony_ci *
27198c2ecf20Sopenharmony_ci * @vha: HA context
27208c2ecf20Sopenharmony_ci * @list: switch info entries to populate
27218c2ecf20Sopenharmony_ci *
27228c2ecf20Sopenharmony_ci */
27238c2ecf20Sopenharmony_civoid
27248c2ecf20Sopenharmony_ciqla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
27258c2ecf20Sopenharmony_ci{
27268c2ecf20Sopenharmony_ci	int		rval;
27278c2ecf20Sopenharmony_ci	uint16_t	i;
27288c2ecf20Sopenharmony_ci
27298c2ecf20Sopenharmony_ci	ms_iocb_entry_t	*ms_pkt;
27308c2ecf20Sopenharmony_ci	struct ct_sns_req	*ct_req;
27318c2ecf20Sopenharmony_ci	struct ct_sns_rsp	*ct_rsp;
27328c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
27338c2ecf20Sopenharmony_ci	uint8_t fcp_scsi_features = 0, nvme_features = 0;
27348c2ecf20Sopenharmony_ci	struct ct_arg arg;
27358c2ecf20Sopenharmony_ci
27368c2ecf20Sopenharmony_ci	for (i = 0; i < ha->max_fibre_devices; i++) {
27378c2ecf20Sopenharmony_ci		/* Set default FC4 Type as UNKNOWN so the default is to
27388c2ecf20Sopenharmony_ci		 * Process this port */
27398c2ecf20Sopenharmony_ci		list[i].fc4_type = 0;
27408c2ecf20Sopenharmony_ci
27418c2ecf20Sopenharmony_ci		/* Do not attempt GFF_ID if we are not FWI_2 capable */
27428c2ecf20Sopenharmony_ci		if (!IS_FWI2_CAPABLE(ha))
27438c2ecf20Sopenharmony_ci			continue;
27448c2ecf20Sopenharmony_ci
27458c2ecf20Sopenharmony_ci		arg.iocb = ha->ms_iocb;
27468c2ecf20Sopenharmony_ci		arg.req_dma = ha->ct_sns_dma;
27478c2ecf20Sopenharmony_ci		arg.rsp_dma = ha->ct_sns_dma;
27488c2ecf20Sopenharmony_ci		arg.req_size = GFF_ID_REQ_SIZE;
27498c2ecf20Sopenharmony_ci		arg.rsp_size = GFF_ID_RSP_SIZE;
27508c2ecf20Sopenharmony_ci		arg.nport_handle = NPH_SNS;
27518c2ecf20Sopenharmony_ci
27528c2ecf20Sopenharmony_ci		/* Prepare common MS IOCB */
27538c2ecf20Sopenharmony_ci		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
27548c2ecf20Sopenharmony_ci
27558c2ecf20Sopenharmony_ci		/* Prepare CT request */
27568c2ecf20Sopenharmony_ci		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFF_ID_CMD,
27578c2ecf20Sopenharmony_ci		    GFF_ID_RSP_SIZE);
27588c2ecf20Sopenharmony_ci		ct_rsp = &ha->ct_sns->p.rsp;
27598c2ecf20Sopenharmony_ci
27608c2ecf20Sopenharmony_ci		/* Prepare CT arguments -- port_id */
27618c2ecf20Sopenharmony_ci		ct_req->req.port_id.port_id = port_id_to_be_id(list[i].d_id);
27628c2ecf20Sopenharmony_ci
27638c2ecf20Sopenharmony_ci		/* Execute MS IOCB */
27648c2ecf20Sopenharmony_ci		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
27658c2ecf20Sopenharmony_ci		   sizeof(ms_iocb_entry_t));
27668c2ecf20Sopenharmony_ci
27678c2ecf20Sopenharmony_ci		if (rval != QLA_SUCCESS) {
27688c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x205c,
27698c2ecf20Sopenharmony_ci			    "GFF_ID issue IOCB failed (%d).\n", rval);
27708c2ecf20Sopenharmony_ci		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
27718c2ecf20Sopenharmony_ci			       "GFF_ID") != QLA_SUCCESS) {
27728c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x205d,
27738c2ecf20Sopenharmony_ci			    "GFF_ID IOCB status had a failure status code.\n");
27748c2ecf20Sopenharmony_ci		} else {
27758c2ecf20Sopenharmony_ci			fcp_scsi_features =
27768c2ecf20Sopenharmony_ci			   ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
27778c2ecf20Sopenharmony_ci			fcp_scsi_features &= 0x0f;
27788c2ecf20Sopenharmony_ci
27798c2ecf20Sopenharmony_ci			if (fcp_scsi_features) {
27808c2ecf20Sopenharmony_ci				list[i].fc4_type = FS_FC4TYPE_FCP;
27818c2ecf20Sopenharmony_ci				list[i].fc4_features = fcp_scsi_features;
27828c2ecf20Sopenharmony_ci			}
27838c2ecf20Sopenharmony_ci
27848c2ecf20Sopenharmony_ci			nvme_features =
27858c2ecf20Sopenharmony_ci			    ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];
27868c2ecf20Sopenharmony_ci			nvme_features &= 0xf;
27878c2ecf20Sopenharmony_ci
27888c2ecf20Sopenharmony_ci			if (nvme_features) {
27898c2ecf20Sopenharmony_ci				list[i].fc4_type |= FS_FC4TYPE_NVME;
27908c2ecf20Sopenharmony_ci				list[i].fc4_features = nvme_features;
27918c2ecf20Sopenharmony_ci			}
27928c2ecf20Sopenharmony_ci		}
27938c2ecf20Sopenharmony_ci
27948c2ecf20Sopenharmony_ci		/* Last device exit. */
27958c2ecf20Sopenharmony_ci		if (list[i].d_id.b.rsvd_1 != 0)
27968c2ecf20Sopenharmony_ci			break;
27978c2ecf20Sopenharmony_ci	}
27988c2ecf20Sopenharmony_ci}
27998c2ecf20Sopenharmony_ci
28008c2ecf20Sopenharmony_ciint qla24xx_post_gpsc_work(struct scsi_qla_host *vha, fc_port_t *fcport)
28018c2ecf20Sopenharmony_ci{
28028c2ecf20Sopenharmony_ci	struct qla_work_evt *e;
28038c2ecf20Sopenharmony_ci
28048c2ecf20Sopenharmony_ci	e = qla2x00_alloc_work(vha, QLA_EVT_GPSC);
28058c2ecf20Sopenharmony_ci	if (!e)
28068c2ecf20Sopenharmony_ci		return QLA_FUNCTION_FAILED;
28078c2ecf20Sopenharmony_ci
28088c2ecf20Sopenharmony_ci	e->u.fcport.fcport = fcport;
28098c2ecf20Sopenharmony_ci	return qla2x00_post_work(vha, e);
28108c2ecf20Sopenharmony_ci}
28118c2ecf20Sopenharmony_ci
28128c2ecf20Sopenharmony_civoid qla24xx_handle_gpsc_event(scsi_qla_host_t *vha, struct event_arg *ea)
28138c2ecf20Sopenharmony_ci{
28148c2ecf20Sopenharmony_ci	struct fc_port *fcport = ea->fcport;
28158c2ecf20Sopenharmony_ci
28168c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x20d8,
28178c2ecf20Sopenharmony_ci	    "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n",
28188c2ecf20Sopenharmony_ci	    __func__, fcport->port_name, fcport->disc_state,
28198c2ecf20Sopenharmony_ci	    fcport->fw_login_state, ea->rc, ea->sp->gen2, fcport->login_gen,
28208c2ecf20Sopenharmony_ci	    ea->sp->gen2, fcport->rscn_gen|ea->sp->gen1, fcport->loop_id);
28218c2ecf20Sopenharmony_ci
28228c2ecf20Sopenharmony_ci	if (fcport->disc_state == DSC_DELETE_PEND)
28238c2ecf20Sopenharmony_ci		return;
28248c2ecf20Sopenharmony_ci
28258c2ecf20Sopenharmony_ci	if (ea->sp->gen2 != fcport->login_gen) {
28268c2ecf20Sopenharmony_ci		/* target side must have changed it. */
28278c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x20d3,
28288c2ecf20Sopenharmony_ci		    "%s %8phC generation changed\n",
28298c2ecf20Sopenharmony_ci		    __func__, fcport->port_name);
28308c2ecf20Sopenharmony_ci		return;
28318c2ecf20Sopenharmony_ci	} else if (ea->sp->gen1 != fcport->rscn_gen) {
28328c2ecf20Sopenharmony_ci		return;
28338c2ecf20Sopenharmony_ci	}
28348c2ecf20Sopenharmony_ci
28358c2ecf20Sopenharmony_ci	qla_post_iidma_work(vha, fcport);
28368c2ecf20Sopenharmony_ci}
28378c2ecf20Sopenharmony_ci
28388c2ecf20Sopenharmony_cistatic void qla24xx_async_gpsc_sp_done(srb_t *sp, int res)
28398c2ecf20Sopenharmony_ci{
28408c2ecf20Sopenharmony_ci	struct scsi_qla_host *vha = sp->vha;
28418c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
28428c2ecf20Sopenharmony_ci	fc_port_t *fcport = sp->fcport;
28438c2ecf20Sopenharmony_ci	struct ct_sns_rsp       *ct_rsp;
28448c2ecf20Sopenharmony_ci	struct event_arg ea;
28458c2ecf20Sopenharmony_ci
28468c2ecf20Sopenharmony_ci	ct_rsp = &fcport->ct_desc.ct_sns->p.rsp;
28478c2ecf20Sopenharmony_ci
28488c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x2053,
28498c2ecf20Sopenharmony_ci	    "Async done-%s res %x, WWPN %8phC \n",
28508c2ecf20Sopenharmony_ci	    sp->name, res, fcport->port_name);
28518c2ecf20Sopenharmony_ci
28528c2ecf20Sopenharmony_ci	fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
28538c2ecf20Sopenharmony_ci
28548c2ecf20Sopenharmony_ci	if (res == QLA_FUNCTION_TIMEOUT)
28558c2ecf20Sopenharmony_ci		goto done;
28568c2ecf20Sopenharmony_ci
28578c2ecf20Sopenharmony_ci	if (res == (DID_ERROR << 16)) {
28588c2ecf20Sopenharmony_ci		/* entry status error */
28598c2ecf20Sopenharmony_ci		goto done;
28608c2ecf20Sopenharmony_ci	} else if (res) {
28618c2ecf20Sopenharmony_ci		if ((ct_rsp->header.reason_code ==
28628c2ecf20Sopenharmony_ci			 CT_REASON_INVALID_COMMAND_CODE) ||
28638c2ecf20Sopenharmony_ci			(ct_rsp->header.reason_code ==
28648c2ecf20Sopenharmony_ci			CT_REASON_COMMAND_UNSUPPORTED)) {
28658c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x2019,
28668c2ecf20Sopenharmony_ci			    "GPSC command unsupported, disabling query.\n");
28678c2ecf20Sopenharmony_ci			ha->flags.gpsc_supported = 0;
28688c2ecf20Sopenharmony_ci			goto done;
28698c2ecf20Sopenharmony_ci		}
28708c2ecf20Sopenharmony_ci	} else {
28718c2ecf20Sopenharmony_ci		fcport->fp_speed = qla2x00_port_speed_capability(
28728c2ecf20Sopenharmony_ci		    be16_to_cpu(ct_rsp->rsp.gpsc.speed));
28738c2ecf20Sopenharmony_ci
28748c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x2054,
28758c2ecf20Sopenharmony_ci		    "Async-%s OUT WWPN %8phC speeds=%04x speed=%04x.\n",
28768c2ecf20Sopenharmony_ci		    sp->name, fcport->fabric_port_name,
28778c2ecf20Sopenharmony_ci		    be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
28788c2ecf20Sopenharmony_ci		    be16_to_cpu(ct_rsp->rsp.gpsc.speed));
28798c2ecf20Sopenharmony_ci	}
28808c2ecf20Sopenharmony_ci	memset(&ea, 0, sizeof(ea));
28818c2ecf20Sopenharmony_ci	ea.rc = res;
28828c2ecf20Sopenharmony_ci	ea.fcport = fcport;
28838c2ecf20Sopenharmony_ci	ea.sp = sp;
28848c2ecf20Sopenharmony_ci	qla24xx_handle_gpsc_event(vha, &ea);
28858c2ecf20Sopenharmony_ci
28868c2ecf20Sopenharmony_cidone:
28878c2ecf20Sopenharmony_ci	sp->free(sp);
28888c2ecf20Sopenharmony_ci}
28898c2ecf20Sopenharmony_ci
28908c2ecf20Sopenharmony_ciint qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
28918c2ecf20Sopenharmony_ci{
28928c2ecf20Sopenharmony_ci	int rval = QLA_FUNCTION_FAILED;
28938c2ecf20Sopenharmony_ci	struct ct_sns_req       *ct_req;
28948c2ecf20Sopenharmony_ci	srb_t *sp;
28958c2ecf20Sopenharmony_ci
28968c2ecf20Sopenharmony_ci	if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
28978c2ecf20Sopenharmony_ci		return rval;
28988c2ecf20Sopenharmony_ci
28998c2ecf20Sopenharmony_ci	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
29008c2ecf20Sopenharmony_ci	if (!sp)
29018c2ecf20Sopenharmony_ci		goto done;
29028c2ecf20Sopenharmony_ci
29038c2ecf20Sopenharmony_ci	sp->type = SRB_CT_PTHRU_CMD;
29048c2ecf20Sopenharmony_ci	sp->name = "gpsc";
29058c2ecf20Sopenharmony_ci	sp->gen1 = fcport->rscn_gen;
29068c2ecf20Sopenharmony_ci	sp->gen2 = fcport->login_gen;
29078c2ecf20Sopenharmony_ci
29088c2ecf20Sopenharmony_ci	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
29098c2ecf20Sopenharmony_ci
29108c2ecf20Sopenharmony_ci	/* CT_IU preamble  */
29118c2ecf20Sopenharmony_ci	ct_req = qla24xx_prep_ct_fm_req(fcport->ct_desc.ct_sns, GPSC_CMD,
29128c2ecf20Sopenharmony_ci		GPSC_RSP_SIZE);
29138c2ecf20Sopenharmony_ci
29148c2ecf20Sopenharmony_ci	/* GPSC req */
29158c2ecf20Sopenharmony_ci	memcpy(ct_req->req.gpsc.port_name, fcport->fabric_port_name,
29168c2ecf20Sopenharmony_ci		WWN_SIZE);
29178c2ecf20Sopenharmony_ci
29188c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
29198c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
29208c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
29218c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
29228c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_size = GPSC_REQ_SIZE;
29238c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp_size = GPSC_RSP_SIZE;
29248c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.nport_handle = vha->mgmt_svr_loop_id;
29258c2ecf20Sopenharmony_ci
29268c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
29278c2ecf20Sopenharmony_ci	sp->done = qla24xx_async_gpsc_sp_done;
29288c2ecf20Sopenharmony_ci
29298c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x205e,
29308c2ecf20Sopenharmony_ci	    "Async-%s %8phC hdl=%x loopid=%x portid=%02x%02x%02x.\n",
29318c2ecf20Sopenharmony_ci	    sp->name, fcport->port_name, sp->handle,
29328c2ecf20Sopenharmony_ci	    fcport->loop_id, fcport->d_id.b.domain,
29338c2ecf20Sopenharmony_ci	    fcport->d_id.b.area, fcport->d_id.b.al_pa);
29348c2ecf20Sopenharmony_ci
29358c2ecf20Sopenharmony_ci	rval = qla2x00_start_sp(sp);
29368c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS)
29378c2ecf20Sopenharmony_ci		goto done_free_sp;
29388c2ecf20Sopenharmony_ci	return rval;
29398c2ecf20Sopenharmony_ci
29408c2ecf20Sopenharmony_cidone_free_sp:
29418c2ecf20Sopenharmony_ci	sp->free(sp);
29428c2ecf20Sopenharmony_cidone:
29438c2ecf20Sopenharmony_ci	return rval;
29448c2ecf20Sopenharmony_ci}
29458c2ecf20Sopenharmony_ci
29468c2ecf20Sopenharmony_ciint qla24xx_post_gpnid_work(struct scsi_qla_host *vha, port_id_t *id)
29478c2ecf20Sopenharmony_ci{
29488c2ecf20Sopenharmony_ci	struct qla_work_evt *e;
29498c2ecf20Sopenharmony_ci
29508c2ecf20Sopenharmony_ci	if (test_bit(UNLOADING, &vha->dpc_flags) ||
29518c2ecf20Sopenharmony_ci	    (vha->vp_idx && test_bit(VPORT_DELETE, &vha->dpc_flags)))
29528c2ecf20Sopenharmony_ci		return 0;
29538c2ecf20Sopenharmony_ci
29548c2ecf20Sopenharmony_ci	e = qla2x00_alloc_work(vha, QLA_EVT_GPNID);
29558c2ecf20Sopenharmony_ci	if (!e)
29568c2ecf20Sopenharmony_ci		return QLA_FUNCTION_FAILED;
29578c2ecf20Sopenharmony_ci
29588c2ecf20Sopenharmony_ci	e->u.gpnid.id = *id;
29598c2ecf20Sopenharmony_ci	return qla2x00_post_work(vha, e);
29608c2ecf20Sopenharmony_ci}
29618c2ecf20Sopenharmony_ci
29628c2ecf20Sopenharmony_civoid qla24xx_sp_unmap(scsi_qla_host_t *vha, srb_t *sp)
29638c2ecf20Sopenharmony_ci{
29648c2ecf20Sopenharmony_ci	struct srb_iocb *c = &sp->u.iocb_cmd;
29658c2ecf20Sopenharmony_ci
29668c2ecf20Sopenharmony_ci	switch (sp->type) {
29678c2ecf20Sopenharmony_ci	case SRB_ELS_DCMD:
29688c2ecf20Sopenharmony_ci		qla2x00_els_dcmd2_free(vha, &c->u.els_plogi);
29698c2ecf20Sopenharmony_ci		break;
29708c2ecf20Sopenharmony_ci	case SRB_CT_PTHRU_CMD:
29718c2ecf20Sopenharmony_ci	default:
29728c2ecf20Sopenharmony_ci		if (sp->u.iocb_cmd.u.ctarg.req) {
29738c2ecf20Sopenharmony_ci			dma_free_coherent(&vha->hw->pdev->dev,
29748c2ecf20Sopenharmony_ci			    sp->u.iocb_cmd.u.ctarg.req_allocated_size,
29758c2ecf20Sopenharmony_ci			    sp->u.iocb_cmd.u.ctarg.req,
29768c2ecf20Sopenharmony_ci			    sp->u.iocb_cmd.u.ctarg.req_dma);
29778c2ecf20Sopenharmony_ci			sp->u.iocb_cmd.u.ctarg.req = NULL;
29788c2ecf20Sopenharmony_ci		}
29798c2ecf20Sopenharmony_ci
29808c2ecf20Sopenharmony_ci		if (sp->u.iocb_cmd.u.ctarg.rsp) {
29818c2ecf20Sopenharmony_ci			dma_free_coherent(&vha->hw->pdev->dev,
29828c2ecf20Sopenharmony_ci			    sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
29838c2ecf20Sopenharmony_ci			    sp->u.iocb_cmd.u.ctarg.rsp,
29848c2ecf20Sopenharmony_ci			    sp->u.iocb_cmd.u.ctarg.rsp_dma);
29858c2ecf20Sopenharmony_ci			sp->u.iocb_cmd.u.ctarg.rsp = NULL;
29868c2ecf20Sopenharmony_ci		}
29878c2ecf20Sopenharmony_ci		break;
29888c2ecf20Sopenharmony_ci	}
29898c2ecf20Sopenharmony_ci
29908c2ecf20Sopenharmony_ci	sp->free(sp);
29918c2ecf20Sopenharmony_ci}
29928c2ecf20Sopenharmony_ci
29938c2ecf20Sopenharmony_civoid qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
29948c2ecf20Sopenharmony_ci{
29958c2ecf20Sopenharmony_ci	fc_port_t *fcport, *conflict, *t;
29968c2ecf20Sopenharmony_ci	u16 data[2];
29978c2ecf20Sopenharmony_ci
29988c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0xffff,
29998c2ecf20Sopenharmony_ci	    "%s %d port_id: %06x\n",
30008c2ecf20Sopenharmony_ci	    __func__, __LINE__, ea->id.b24);
30018c2ecf20Sopenharmony_ci
30028c2ecf20Sopenharmony_ci	if (ea->rc) {
30038c2ecf20Sopenharmony_ci		/* cable is disconnected */
30048c2ecf20Sopenharmony_ci		list_for_each_entry_safe(fcport, t, &vha->vp_fcports, list) {
30058c2ecf20Sopenharmony_ci			if (fcport->d_id.b24 == ea->id.b24)
30068c2ecf20Sopenharmony_ci				fcport->scan_state = QLA_FCPORT_SCAN;
30078c2ecf20Sopenharmony_ci
30088c2ecf20Sopenharmony_ci			qlt_schedule_sess_for_deletion(fcport);
30098c2ecf20Sopenharmony_ci		}
30108c2ecf20Sopenharmony_ci	} else {
30118c2ecf20Sopenharmony_ci		/* cable is connected */
30128c2ecf20Sopenharmony_ci		fcport = qla2x00_find_fcport_by_wwpn(vha, ea->port_name, 1);
30138c2ecf20Sopenharmony_ci		if (fcport) {
30148c2ecf20Sopenharmony_ci			list_for_each_entry_safe(conflict, t, &vha->vp_fcports,
30158c2ecf20Sopenharmony_ci			    list) {
30168c2ecf20Sopenharmony_ci				if ((conflict->d_id.b24 == ea->id.b24) &&
30178c2ecf20Sopenharmony_ci				    (fcport != conflict))
30188c2ecf20Sopenharmony_ci					/*
30198c2ecf20Sopenharmony_ci					 * 2 fcports with conflict Nport ID or
30208c2ecf20Sopenharmony_ci					 * an existing fcport is having nport ID
30218c2ecf20Sopenharmony_ci					 * conflict with new fcport.
30228c2ecf20Sopenharmony_ci					 */
30238c2ecf20Sopenharmony_ci
30248c2ecf20Sopenharmony_ci					conflict->scan_state = QLA_FCPORT_SCAN;
30258c2ecf20Sopenharmony_ci
30268c2ecf20Sopenharmony_ci				qlt_schedule_sess_for_deletion(conflict);
30278c2ecf20Sopenharmony_ci			}
30288c2ecf20Sopenharmony_ci
30298c2ecf20Sopenharmony_ci			fcport->scan_needed = 0;
30308c2ecf20Sopenharmony_ci			fcport->rscn_gen++;
30318c2ecf20Sopenharmony_ci			fcport->scan_state = QLA_FCPORT_FOUND;
30328c2ecf20Sopenharmony_ci			fcport->flags |= FCF_FABRIC_DEVICE;
30338c2ecf20Sopenharmony_ci			if (fcport->login_retry == 0) {
30348c2ecf20Sopenharmony_ci				fcport->login_retry =
30358c2ecf20Sopenharmony_ci					vha->hw->login_retry_count;
30368c2ecf20Sopenharmony_ci				ql_dbg(ql_dbg_disc, vha, 0xffff,
30378c2ecf20Sopenharmony_ci				    "Port login retry %8phN, lid 0x%04x cnt=%d.\n",
30388c2ecf20Sopenharmony_ci				    fcport->port_name, fcport->loop_id,
30398c2ecf20Sopenharmony_ci				    fcport->login_retry);
30408c2ecf20Sopenharmony_ci			}
30418c2ecf20Sopenharmony_ci			switch (fcport->disc_state) {
30428c2ecf20Sopenharmony_ci			case DSC_LOGIN_COMPLETE:
30438c2ecf20Sopenharmony_ci				/* recheck session is still intact. */
30448c2ecf20Sopenharmony_ci				ql_dbg(ql_dbg_disc, vha, 0x210d,
30458c2ecf20Sopenharmony_ci				    "%s %d %8phC revalidate session with ADISC\n",
30468c2ecf20Sopenharmony_ci				    __func__, __LINE__, fcport->port_name);
30478c2ecf20Sopenharmony_ci				data[0] = data[1] = 0;
30488c2ecf20Sopenharmony_ci				qla2x00_post_async_adisc_work(vha, fcport,
30498c2ecf20Sopenharmony_ci				    data);
30508c2ecf20Sopenharmony_ci				break;
30518c2ecf20Sopenharmony_ci			case DSC_DELETED:
30528c2ecf20Sopenharmony_ci				ql_dbg(ql_dbg_disc, vha, 0x210d,
30538c2ecf20Sopenharmony_ci				    "%s %d %8phC login\n", __func__, __LINE__,
30548c2ecf20Sopenharmony_ci				    fcport->port_name);
30558c2ecf20Sopenharmony_ci				fcport->d_id = ea->id;
30568c2ecf20Sopenharmony_ci				qla24xx_fcport_handle_login(vha, fcport);
30578c2ecf20Sopenharmony_ci				break;
30588c2ecf20Sopenharmony_ci			case DSC_DELETE_PEND:
30598c2ecf20Sopenharmony_ci				fcport->d_id = ea->id;
30608c2ecf20Sopenharmony_ci				break;
30618c2ecf20Sopenharmony_ci			default:
30628c2ecf20Sopenharmony_ci				fcport->d_id = ea->id;
30638c2ecf20Sopenharmony_ci				break;
30648c2ecf20Sopenharmony_ci			}
30658c2ecf20Sopenharmony_ci		} else {
30668c2ecf20Sopenharmony_ci			list_for_each_entry_safe(conflict, t, &vha->vp_fcports,
30678c2ecf20Sopenharmony_ci			    list) {
30688c2ecf20Sopenharmony_ci				if (conflict->d_id.b24 == ea->id.b24) {
30698c2ecf20Sopenharmony_ci					/* 2 fcports with conflict Nport ID or
30708c2ecf20Sopenharmony_ci					 * an existing fcport is having nport ID
30718c2ecf20Sopenharmony_ci					 * conflict with new fcport.
30728c2ecf20Sopenharmony_ci					 */
30738c2ecf20Sopenharmony_ci					ql_dbg(ql_dbg_disc, vha, 0xffff,
30748c2ecf20Sopenharmony_ci					    "%s %d %8phC DS %d\n",
30758c2ecf20Sopenharmony_ci					    __func__, __LINE__,
30768c2ecf20Sopenharmony_ci					    conflict->port_name,
30778c2ecf20Sopenharmony_ci					    conflict->disc_state);
30788c2ecf20Sopenharmony_ci
30798c2ecf20Sopenharmony_ci					conflict->scan_state = QLA_FCPORT_SCAN;
30808c2ecf20Sopenharmony_ci					qlt_schedule_sess_for_deletion(conflict);
30818c2ecf20Sopenharmony_ci				}
30828c2ecf20Sopenharmony_ci			}
30838c2ecf20Sopenharmony_ci
30848c2ecf20Sopenharmony_ci			/* create new fcport */
30858c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0x2065,
30868c2ecf20Sopenharmony_ci			    "%s %d %8phC post new sess\n",
30878c2ecf20Sopenharmony_ci			    __func__, __LINE__, ea->port_name);
30888c2ecf20Sopenharmony_ci			qla24xx_post_newsess_work(vha, &ea->id,
30898c2ecf20Sopenharmony_ci			    ea->port_name, NULL, NULL, 0);
30908c2ecf20Sopenharmony_ci		}
30918c2ecf20Sopenharmony_ci	}
30928c2ecf20Sopenharmony_ci}
30938c2ecf20Sopenharmony_ci
30948c2ecf20Sopenharmony_cistatic void qla2x00_async_gpnid_sp_done(srb_t *sp, int res)
30958c2ecf20Sopenharmony_ci{
30968c2ecf20Sopenharmony_ci	struct scsi_qla_host *vha = sp->vha;
30978c2ecf20Sopenharmony_ci	struct ct_sns_req *ct_req =
30988c2ecf20Sopenharmony_ci	    (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
30998c2ecf20Sopenharmony_ci	struct ct_sns_rsp *ct_rsp =
31008c2ecf20Sopenharmony_ci	    (struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp;
31018c2ecf20Sopenharmony_ci	struct event_arg ea;
31028c2ecf20Sopenharmony_ci	struct qla_work_evt *e;
31038c2ecf20Sopenharmony_ci	unsigned long flags;
31048c2ecf20Sopenharmony_ci
31058c2ecf20Sopenharmony_ci	if (res)
31068c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x2066,
31078c2ecf20Sopenharmony_ci		    "Async done-%s fail res %x rscn gen %d ID %3phC. %8phC\n",
31088c2ecf20Sopenharmony_ci		    sp->name, res, sp->gen1, &ct_req->req.port_id.port_id,
31098c2ecf20Sopenharmony_ci		    ct_rsp->rsp.gpn_id.port_name);
31108c2ecf20Sopenharmony_ci	else
31118c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x2066,
31128c2ecf20Sopenharmony_ci		    "Async done-%s good rscn gen %d ID %3phC. %8phC\n",
31138c2ecf20Sopenharmony_ci		    sp->name, sp->gen1, &ct_req->req.port_id.port_id,
31148c2ecf20Sopenharmony_ci		    ct_rsp->rsp.gpn_id.port_name);
31158c2ecf20Sopenharmony_ci
31168c2ecf20Sopenharmony_ci	memset(&ea, 0, sizeof(ea));
31178c2ecf20Sopenharmony_ci	memcpy(ea.port_name, ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);
31188c2ecf20Sopenharmony_ci	ea.sp = sp;
31198c2ecf20Sopenharmony_ci	ea.id = be_to_port_id(ct_req->req.port_id.port_id);
31208c2ecf20Sopenharmony_ci	ea.rc = res;
31218c2ecf20Sopenharmony_ci
31228c2ecf20Sopenharmony_ci	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
31238c2ecf20Sopenharmony_ci	list_del(&sp->elem);
31248c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
31258c2ecf20Sopenharmony_ci
31268c2ecf20Sopenharmony_ci	if (res) {
31278c2ecf20Sopenharmony_ci		if (res == QLA_FUNCTION_TIMEOUT) {
31288c2ecf20Sopenharmony_ci			qla24xx_post_gpnid_work(sp->vha, &ea.id);
31298c2ecf20Sopenharmony_ci			sp->free(sp);
31308c2ecf20Sopenharmony_ci			return;
31318c2ecf20Sopenharmony_ci		}
31328c2ecf20Sopenharmony_ci	} else if (sp->gen1) {
31338c2ecf20Sopenharmony_ci		/* There was another RSCN for this Nport ID */
31348c2ecf20Sopenharmony_ci		qla24xx_post_gpnid_work(sp->vha, &ea.id);
31358c2ecf20Sopenharmony_ci		sp->free(sp);
31368c2ecf20Sopenharmony_ci		return;
31378c2ecf20Sopenharmony_ci	}
31388c2ecf20Sopenharmony_ci
31398c2ecf20Sopenharmony_ci	qla24xx_handle_gpnid_event(vha, &ea);
31408c2ecf20Sopenharmony_ci
31418c2ecf20Sopenharmony_ci	e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP);
31428c2ecf20Sopenharmony_ci	if (!e) {
31438c2ecf20Sopenharmony_ci		/* please ignore kernel warning. otherwise, we have mem leak. */
31448c2ecf20Sopenharmony_ci		dma_free_coherent(&vha->hw->pdev->dev,
31458c2ecf20Sopenharmony_ci				  sp->u.iocb_cmd.u.ctarg.req_allocated_size,
31468c2ecf20Sopenharmony_ci				  sp->u.iocb_cmd.u.ctarg.req,
31478c2ecf20Sopenharmony_ci				  sp->u.iocb_cmd.u.ctarg.req_dma);
31488c2ecf20Sopenharmony_ci		sp->u.iocb_cmd.u.ctarg.req = NULL;
31498c2ecf20Sopenharmony_ci
31508c2ecf20Sopenharmony_ci		dma_free_coherent(&vha->hw->pdev->dev,
31518c2ecf20Sopenharmony_ci				  sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
31528c2ecf20Sopenharmony_ci				  sp->u.iocb_cmd.u.ctarg.rsp,
31538c2ecf20Sopenharmony_ci				  sp->u.iocb_cmd.u.ctarg.rsp_dma);
31548c2ecf20Sopenharmony_ci		sp->u.iocb_cmd.u.ctarg.rsp = NULL;
31558c2ecf20Sopenharmony_ci
31568c2ecf20Sopenharmony_ci		sp->free(sp);
31578c2ecf20Sopenharmony_ci		return;
31588c2ecf20Sopenharmony_ci	}
31598c2ecf20Sopenharmony_ci
31608c2ecf20Sopenharmony_ci	e->u.iosb.sp = sp;
31618c2ecf20Sopenharmony_ci	qla2x00_post_work(vha, e);
31628c2ecf20Sopenharmony_ci}
31638c2ecf20Sopenharmony_ci
31648c2ecf20Sopenharmony_ci/* Get WWPN with Nport ID. */
31658c2ecf20Sopenharmony_ciint qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
31668c2ecf20Sopenharmony_ci{
31678c2ecf20Sopenharmony_ci	int rval = QLA_FUNCTION_FAILED;
31688c2ecf20Sopenharmony_ci	struct ct_sns_req       *ct_req;
31698c2ecf20Sopenharmony_ci	srb_t *sp, *tsp;
31708c2ecf20Sopenharmony_ci	struct ct_sns_pkt *ct_sns;
31718c2ecf20Sopenharmony_ci	unsigned long flags;
31728c2ecf20Sopenharmony_ci
31738c2ecf20Sopenharmony_ci	if (!vha->flags.online)
31748c2ecf20Sopenharmony_ci		goto done;
31758c2ecf20Sopenharmony_ci
31768c2ecf20Sopenharmony_ci	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
31778c2ecf20Sopenharmony_ci	if (!sp)
31788c2ecf20Sopenharmony_ci		goto done;
31798c2ecf20Sopenharmony_ci
31808c2ecf20Sopenharmony_ci	sp->type = SRB_CT_PTHRU_CMD;
31818c2ecf20Sopenharmony_ci	sp->name = "gpnid";
31828c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.id = *id;
31838c2ecf20Sopenharmony_ci	sp->gen1 = 0;
31848c2ecf20Sopenharmony_ci	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
31858c2ecf20Sopenharmony_ci
31868c2ecf20Sopenharmony_ci	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
31878c2ecf20Sopenharmony_ci	list_for_each_entry(tsp, &vha->gpnid_list, elem) {
31888c2ecf20Sopenharmony_ci		if (tsp->u.iocb_cmd.u.ctarg.id.b24 == id->b24) {
31898c2ecf20Sopenharmony_ci			tsp->gen1++;
31908c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
31918c2ecf20Sopenharmony_ci			sp->free(sp);
31928c2ecf20Sopenharmony_ci			goto done;
31938c2ecf20Sopenharmony_ci		}
31948c2ecf20Sopenharmony_ci	}
31958c2ecf20Sopenharmony_ci	list_add_tail(&sp->elem, &vha->gpnid_list);
31968c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
31978c2ecf20Sopenharmony_ci
31988c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
31998c2ecf20Sopenharmony_ci		sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
32008c2ecf20Sopenharmony_ci		GFP_KERNEL);
32018c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt);
32028c2ecf20Sopenharmony_ci	if (!sp->u.iocb_cmd.u.ctarg.req) {
32038c2ecf20Sopenharmony_ci		ql_log(ql_log_warn, vha, 0xd041,
32048c2ecf20Sopenharmony_ci		    "Failed to allocate ct_sns request.\n");
32058c2ecf20Sopenharmony_ci		goto done_free_sp;
32068c2ecf20Sopenharmony_ci	}
32078c2ecf20Sopenharmony_ci
32088c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
32098c2ecf20Sopenharmony_ci		sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
32108c2ecf20Sopenharmony_ci		GFP_KERNEL);
32118c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = sizeof(struct ct_sns_pkt);
32128c2ecf20Sopenharmony_ci	if (!sp->u.iocb_cmd.u.ctarg.rsp) {
32138c2ecf20Sopenharmony_ci		ql_log(ql_log_warn, vha, 0xd042,
32148c2ecf20Sopenharmony_ci		    "Failed to allocate ct_sns request.\n");
32158c2ecf20Sopenharmony_ci		goto done_free_sp;
32168c2ecf20Sopenharmony_ci	}
32178c2ecf20Sopenharmony_ci
32188c2ecf20Sopenharmony_ci	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
32198c2ecf20Sopenharmony_ci	memset(ct_sns, 0, sizeof(*ct_sns));
32208c2ecf20Sopenharmony_ci
32218c2ecf20Sopenharmony_ci	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
32228c2ecf20Sopenharmony_ci	/* CT_IU preamble  */
32238c2ecf20Sopenharmony_ci	ct_req = qla2x00_prep_ct_req(ct_sns, GPN_ID_CMD, GPN_ID_RSP_SIZE);
32248c2ecf20Sopenharmony_ci
32258c2ecf20Sopenharmony_ci	/* GPN_ID req */
32268c2ecf20Sopenharmony_ci	ct_req->req.port_id.port_id = port_id_to_be_id(*id);
32278c2ecf20Sopenharmony_ci
32288c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_size = GPN_ID_REQ_SIZE;
32298c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp_size = GPN_ID_RSP_SIZE;
32308c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
32318c2ecf20Sopenharmony_ci
32328c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
32338c2ecf20Sopenharmony_ci	sp->done = qla2x00_async_gpnid_sp_done;
32348c2ecf20Sopenharmony_ci
32358c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x2067,
32368c2ecf20Sopenharmony_ci	    "Async-%s hdl=%x ID %3phC.\n", sp->name,
32378c2ecf20Sopenharmony_ci	    sp->handle, &ct_req->req.port_id.port_id);
32388c2ecf20Sopenharmony_ci
32398c2ecf20Sopenharmony_ci	rval = qla2x00_start_sp(sp);
32408c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS)
32418c2ecf20Sopenharmony_ci		goto done_free_sp;
32428c2ecf20Sopenharmony_ci
32438c2ecf20Sopenharmony_ci	return rval;
32448c2ecf20Sopenharmony_ci
32458c2ecf20Sopenharmony_cidone_free_sp:
32468c2ecf20Sopenharmony_ci	spin_lock_irqsave(&vha->hw->vport_slock, flags);
32478c2ecf20Sopenharmony_ci	list_del(&sp->elem);
32488c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&vha->hw->vport_slock, flags);
32498c2ecf20Sopenharmony_ci
32508c2ecf20Sopenharmony_ci	if (sp->u.iocb_cmd.u.ctarg.req) {
32518c2ecf20Sopenharmony_ci		dma_free_coherent(&vha->hw->pdev->dev,
32528c2ecf20Sopenharmony_ci			sizeof(struct ct_sns_pkt),
32538c2ecf20Sopenharmony_ci			sp->u.iocb_cmd.u.ctarg.req,
32548c2ecf20Sopenharmony_ci			sp->u.iocb_cmd.u.ctarg.req_dma);
32558c2ecf20Sopenharmony_ci		sp->u.iocb_cmd.u.ctarg.req = NULL;
32568c2ecf20Sopenharmony_ci	}
32578c2ecf20Sopenharmony_ci	if (sp->u.iocb_cmd.u.ctarg.rsp) {
32588c2ecf20Sopenharmony_ci		dma_free_coherent(&vha->hw->pdev->dev,
32598c2ecf20Sopenharmony_ci			sizeof(struct ct_sns_pkt),
32608c2ecf20Sopenharmony_ci			sp->u.iocb_cmd.u.ctarg.rsp,
32618c2ecf20Sopenharmony_ci			sp->u.iocb_cmd.u.ctarg.rsp_dma);
32628c2ecf20Sopenharmony_ci		sp->u.iocb_cmd.u.ctarg.rsp = NULL;
32638c2ecf20Sopenharmony_ci	}
32648c2ecf20Sopenharmony_ci
32658c2ecf20Sopenharmony_ci	sp->free(sp);
32668c2ecf20Sopenharmony_cidone:
32678c2ecf20Sopenharmony_ci	return rval;
32688c2ecf20Sopenharmony_ci}
32698c2ecf20Sopenharmony_ci
32708c2ecf20Sopenharmony_civoid qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea)
32718c2ecf20Sopenharmony_ci{
32728c2ecf20Sopenharmony_ci	fc_port_t *fcport = ea->fcport;
32738c2ecf20Sopenharmony_ci
32748c2ecf20Sopenharmony_ci	qla24xx_post_gnl_work(vha, fcport);
32758c2ecf20Sopenharmony_ci}
32768c2ecf20Sopenharmony_ci
32778c2ecf20Sopenharmony_civoid qla24xx_async_gffid_sp_done(srb_t *sp, int res)
32788c2ecf20Sopenharmony_ci{
32798c2ecf20Sopenharmony_ci	struct scsi_qla_host *vha = sp->vha;
32808c2ecf20Sopenharmony_ci	fc_port_t *fcport = sp->fcport;
32818c2ecf20Sopenharmony_ci	struct ct_sns_rsp *ct_rsp;
32828c2ecf20Sopenharmony_ci	struct event_arg ea;
32838c2ecf20Sopenharmony_ci	uint8_t fc4_scsi_feat;
32848c2ecf20Sopenharmony_ci	uint8_t fc4_nvme_feat;
32858c2ecf20Sopenharmony_ci
32868c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x2133,
32878c2ecf20Sopenharmony_ci	       "Async done-%s res %x ID %x. %8phC\n",
32888c2ecf20Sopenharmony_ci	       sp->name, res, fcport->d_id.b24, fcport->port_name);
32898c2ecf20Sopenharmony_ci
32908c2ecf20Sopenharmony_ci	fcport->flags &= ~FCF_ASYNC_SENT;
32918c2ecf20Sopenharmony_ci	ct_rsp = &fcport->ct_desc.ct_sns->p.rsp;
32928c2ecf20Sopenharmony_ci	fc4_scsi_feat = ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
32938c2ecf20Sopenharmony_ci	fc4_nvme_feat = ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];
32948c2ecf20Sopenharmony_ci
32958c2ecf20Sopenharmony_ci	/*
32968c2ecf20Sopenharmony_ci	 * FC-GS-7, 5.2.3.12 FC-4 Features - format
32978c2ecf20Sopenharmony_ci	 * The format of the FC-4 Features object, as defined by the FC-4,
32988c2ecf20Sopenharmony_ci	 * Shall be an array of 4-bit values, one for each type code value
32998c2ecf20Sopenharmony_ci	 */
33008c2ecf20Sopenharmony_ci	if (!res) {
33018c2ecf20Sopenharmony_ci		if (fc4_scsi_feat & 0xf) {
33028c2ecf20Sopenharmony_ci			/* w1 b00:03 */
33038c2ecf20Sopenharmony_ci			fcport->fc4_type = FS_FC4TYPE_FCP;
33048c2ecf20Sopenharmony_ci			fcport->fc4_features = fc4_scsi_feat & 0xf;
33058c2ecf20Sopenharmony_ci		}
33068c2ecf20Sopenharmony_ci
33078c2ecf20Sopenharmony_ci		if (fc4_nvme_feat & 0xf) {
33088c2ecf20Sopenharmony_ci			/* w5 [00:03]/28h */
33098c2ecf20Sopenharmony_ci			fcport->fc4_type |= FS_FC4TYPE_NVME;
33108c2ecf20Sopenharmony_ci			fcport->fc4_features = fc4_nvme_feat & 0xf;
33118c2ecf20Sopenharmony_ci		}
33128c2ecf20Sopenharmony_ci	}
33138c2ecf20Sopenharmony_ci
33148c2ecf20Sopenharmony_ci	memset(&ea, 0, sizeof(ea));
33158c2ecf20Sopenharmony_ci	ea.sp = sp;
33168c2ecf20Sopenharmony_ci	ea.fcport = sp->fcport;
33178c2ecf20Sopenharmony_ci	ea.rc = res;
33188c2ecf20Sopenharmony_ci
33198c2ecf20Sopenharmony_ci	qla24xx_handle_gffid_event(vha, &ea);
33208c2ecf20Sopenharmony_ci	sp->free(sp);
33218c2ecf20Sopenharmony_ci}
33228c2ecf20Sopenharmony_ci
33238c2ecf20Sopenharmony_ci/* Get FC4 Feature with Nport ID. */
33248c2ecf20Sopenharmony_ciint qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
33258c2ecf20Sopenharmony_ci{
33268c2ecf20Sopenharmony_ci	int rval = QLA_FUNCTION_FAILED;
33278c2ecf20Sopenharmony_ci	struct ct_sns_req       *ct_req;
33288c2ecf20Sopenharmony_ci	srb_t *sp;
33298c2ecf20Sopenharmony_ci
33308c2ecf20Sopenharmony_ci	if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
33318c2ecf20Sopenharmony_ci		return rval;
33328c2ecf20Sopenharmony_ci
33338c2ecf20Sopenharmony_ci	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
33348c2ecf20Sopenharmony_ci	if (!sp)
33358c2ecf20Sopenharmony_ci		return rval;
33368c2ecf20Sopenharmony_ci
33378c2ecf20Sopenharmony_ci	fcport->flags |= FCF_ASYNC_SENT;
33388c2ecf20Sopenharmony_ci	sp->type = SRB_CT_PTHRU_CMD;
33398c2ecf20Sopenharmony_ci	sp->name = "gffid";
33408c2ecf20Sopenharmony_ci	sp->gen1 = fcport->rscn_gen;
33418c2ecf20Sopenharmony_ci	sp->gen2 = fcport->login_gen;
33428c2ecf20Sopenharmony_ci
33438c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
33448c2ecf20Sopenharmony_ci	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
33458c2ecf20Sopenharmony_ci
33468c2ecf20Sopenharmony_ci	/* CT_IU preamble  */
33478c2ecf20Sopenharmony_ci	ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GFF_ID_CMD,
33488c2ecf20Sopenharmony_ci	    GFF_ID_RSP_SIZE);
33498c2ecf20Sopenharmony_ci
33508c2ecf20Sopenharmony_ci	ct_req->req.gff_id.port_id[0] = fcport->d_id.b.domain;
33518c2ecf20Sopenharmony_ci	ct_req->req.gff_id.port_id[1] = fcport->d_id.b.area;
33528c2ecf20Sopenharmony_ci	ct_req->req.gff_id.port_id[2] = fcport->d_id.b.al_pa;
33538c2ecf20Sopenharmony_ci
33548c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
33558c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
33568c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
33578c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
33588c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_size = GFF_ID_REQ_SIZE;
33598c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp_size = GFF_ID_RSP_SIZE;
33608c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
33618c2ecf20Sopenharmony_ci
33628c2ecf20Sopenharmony_ci	sp->done = qla24xx_async_gffid_sp_done;
33638c2ecf20Sopenharmony_ci
33648c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x2132,
33658c2ecf20Sopenharmony_ci	    "Async-%s hdl=%x  %8phC.\n", sp->name,
33668c2ecf20Sopenharmony_ci	    sp->handle, fcport->port_name);
33678c2ecf20Sopenharmony_ci
33688c2ecf20Sopenharmony_ci	rval = qla2x00_start_sp(sp);
33698c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS)
33708c2ecf20Sopenharmony_ci		goto done_free_sp;
33718c2ecf20Sopenharmony_ci
33728c2ecf20Sopenharmony_ci	return rval;
33738c2ecf20Sopenharmony_cidone_free_sp:
33748c2ecf20Sopenharmony_ci	sp->free(sp);
33758c2ecf20Sopenharmony_ci	fcport->flags &= ~FCF_ASYNC_SENT;
33768c2ecf20Sopenharmony_ci	return rval;
33778c2ecf20Sopenharmony_ci}
33788c2ecf20Sopenharmony_ci
33798c2ecf20Sopenharmony_ci/* GPN_FT + GNN_FT*/
33808c2ecf20Sopenharmony_cistatic int qla2x00_is_a_vp(scsi_qla_host_t *vha, u64 wwn)
33818c2ecf20Sopenharmony_ci{
33828c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
33838c2ecf20Sopenharmony_ci	scsi_qla_host_t *vp;
33848c2ecf20Sopenharmony_ci	unsigned long flags;
33858c2ecf20Sopenharmony_ci	u64 twwn;
33868c2ecf20Sopenharmony_ci	int rc = 0;
33878c2ecf20Sopenharmony_ci
33888c2ecf20Sopenharmony_ci	if (!ha->num_vhosts)
33898c2ecf20Sopenharmony_ci		return 0;
33908c2ecf20Sopenharmony_ci
33918c2ecf20Sopenharmony_ci	spin_lock_irqsave(&ha->vport_slock, flags);
33928c2ecf20Sopenharmony_ci	list_for_each_entry(vp, &ha->vp_list, list) {
33938c2ecf20Sopenharmony_ci		twwn = wwn_to_u64(vp->port_name);
33948c2ecf20Sopenharmony_ci		if (wwn == twwn) {
33958c2ecf20Sopenharmony_ci			rc = 1;
33968c2ecf20Sopenharmony_ci			break;
33978c2ecf20Sopenharmony_ci		}
33988c2ecf20Sopenharmony_ci	}
33998c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&ha->vport_slock, flags);
34008c2ecf20Sopenharmony_ci
34018c2ecf20Sopenharmony_ci	return rc;
34028c2ecf20Sopenharmony_ci}
34038c2ecf20Sopenharmony_ci
34048c2ecf20Sopenharmony_civoid qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
34058c2ecf20Sopenharmony_ci{
34068c2ecf20Sopenharmony_ci	fc_port_t *fcport;
34078c2ecf20Sopenharmony_ci	u32 i, rc;
34088c2ecf20Sopenharmony_ci	bool found;
34098c2ecf20Sopenharmony_ci	struct fab_scan_rp *rp, *trp;
34108c2ecf20Sopenharmony_ci	unsigned long flags;
34118c2ecf20Sopenharmony_ci	u8 recheck = 0;
34128c2ecf20Sopenharmony_ci	u16 dup = 0, dup_cnt = 0;
34138c2ecf20Sopenharmony_ci
34148c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
34158c2ecf20Sopenharmony_ci	    "%s enter\n", __func__);
34168c2ecf20Sopenharmony_ci
34178c2ecf20Sopenharmony_ci	if (sp->gen1 != vha->hw->base_qpair->chip_reset) {
34188c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0xffff,
34198c2ecf20Sopenharmony_ci		    "%s scan stop due to chip reset %x/%x\n",
34208c2ecf20Sopenharmony_ci		    sp->name, sp->gen1, vha->hw->base_qpair->chip_reset);
34218c2ecf20Sopenharmony_ci		goto out;
34228c2ecf20Sopenharmony_ci	}
34238c2ecf20Sopenharmony_ci
34248c2ecf20Sopenharmony_ci	rc = sp->rc;
34258c2ecf20Sopenharmony_ci	if (rc) {
34268c2ecf20Sopenharmony_ci		vha->scan.scan_retry++;
34278c2ecf20Sopenharmony_ci		if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {
34288c2ecf20Sopenharmony_ci			set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
34298c2ecf20Sopenharmony_ci			set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
34308c2ecf20Sopenharmony_ci			goto out;
34318c2ecf20Sopenharmony_ci		} else {
34328c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0xffff,
34338c2ecf20Sopenharmony_ci			    "%s: Fabric scan failed for %d retries.\n",
34348c2ecf20Sopenharmony_ci			    __func__, vha->scan.scan_retry);
34358c2ecf20Sopenharmony_ci			/*
34368c2ecf20Sopenharmony_ci			 * Unable to scan any rports. logout loop below
34378c2ecf20Sopenharmony_ci			 * will unregister all sessions.
34388c2ecf20Sopenharmony_ci			 */
34398c2ecf20Sopenharmony_ci			list_for_each_entry(fcport, &vha->vp_fcports, list) {
34408c2ecf20Sopenharmony_ci				if ((fcport->flags & FCF_FABRIC_DEVICE) != 0) {
34418c2ecf20Sopenharmony_ci					fcport->scan_state = QLA_FCPORT_SCAN;
34428c2ecf20Sopenharmony_ci				}
34438c2ecf20Sopenharmony_ci			}
34448c2ecf20Sopenharmony_ci			goto login_logout;
34458c2ecf20Sopenharmony_ci		}
34468c2ecf20Sopenharmony_ci	}
34478c2ecf20Sopenharmony_ci	vha->scan.scan_retry = 0;
34488c2ecf20Sopenharmony_ci
34498c2ecf20Sopenharmony_ci	list_for_each_entry(fcport, &vha->vp_fcports, list)
34508c2ecf20Sopenharmony_ci		fcport->scan_state = QLA_FCPORT_SCAN;
34518c2ecf20Sopenharmony_ci
34528c2ecf20Sopenharmony_ci	for (i = 0; i < vha->hw->max_fibre_devices; i++) {
34538c2ecf20Sopenharmony_ci		u64 wwn;
34548c2ecf20Sopenharmony_ci		int k;
34558c2ecf20Sopenharmony_ci
34568c2ecf20Sopenharmony_ci		rp = &vha->scan.l[i];
34578c2ecf20Sopenharmony_ci		found = false;
34588c2ecf20Sopenharmony_ci
34598c2ecf20Sopenharmony_ci		wwn = wwn_to_u64(rp->port_name);
34608c2ecf20Sopenharmony_ci		if (wwn == 0)
34618c2ecf20Sopenharmony_ci			continue;
34628c2ecf20Sopenharmony_ci
34638c2ecf20Sopenharmony_ci		/* Remove duplicate NPORT ID entries from switch data base */
34648c2ecf20Sopenharmony_ci		for (k = i + 1; k < vha->hw->max_fibre_devices; k++) {
34658c2ecf20Sopenharmony_ci			trp = &vha->scan.l[k];
34668c2ecf20Sopenharmony_ci			if (rp->id.b24 == trp->id.b24) {
34678c2ecf20Sopenharmony_ci				dup = 1;
34688c2ecf20Sopenharmony_ci				dup_cnt++;
34698c2ecf20Sopenharmony_ci				ql_dbg(ql_dbg_disc + ql_dbg_verbose,
34708c2ecf20Sopenharmony_ci				    vha, 0xffff,
34718c2ecf20Sopenharmony_ci				    "Detected duplicate NPORT ID from switch data base: ID %06x WWN %8phN WWN %8phN\n",
34728c2ecf20Sopenharmony_ci				    rp->id.b24, rp->port_name, trp->port_name);
34738c2ecf20Sopenharmony_ci				memset(trp, 0, sizeof(*trp));
34748c2ecf20Sopenharmony_ci			}
34758c2ecf20Sopenharmony_ci		}
34768c2ecf20Sopenharmony_ci
34778c2ecf20Sopenharmony_ci		if (!memcmp(rp->port_name, vha->port_name, WWN_SIZE))
34788c2ecf20Sopenharmony_ci			continue;
34798c2ecf20Sopenharmony_ci
34808c2ecf20Sopenharmony_ci		/* Bypass reserved domain fields. */
34818c2ecf20Sopenharmony_ci		if ((rp->id.b.domain & 0xf0) == 0xf0)
34828c2ecf20Sopenharmony_ci			continue;
34838c2ecf20Sopenharmony_ci
34848c2ecf20Sopenharmony_ci		/* Bypass virtual ports of the same host. */
34858c2ecf20Sopenharmony_ci		if (qla2x00_is_a_vp(vha, wwn))
34868c2ecf20Sopenharmony_ci			continue;
34878c2ecf20Sopenharmony_ci
34888c2ecf20Sopenharmony_ci		list_for_each_entry(fcport, &vha->vp_fcports, list) {
34898c2ecf20Sopenharmony_ci			if (memcmp(rp->port_name, fcport->port_name, WWN_SIZE))
34908c2ecf20Sopenharmony_ci				continue;
34918c2ecf20Sopenharmony_ci			fcport->scan_state = QLA_FCPORT_FOUND;
34928c2ecf20Sopenharmony_ci			fcport->last_rscn_gen = fcport->rscn_gen;
34938c2ecf20Sopenharmony_ci			found = true;
34948c2ecf20Sopenharmony_ci			/*
34958c2ecf20Sopenharmony_ci			 * If device was not a fabric device before.
34968c2ecf20Sopenharmony_ci			 */
34978c2ecf20Sopenharmony_ci			if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) {
34988c2ecf20Sopenharmony_ci				qla2x00_clear_loop_id(fcport);
34998c2ecf20Sopenharmony_ci				fcport->flags |= FCF_FABRIC_DEVICE;
35008c2ecf20Sopenharmony_ci			} else if (fcport->d_id.b24 != rp->id.b24 ||
35018c2ecf20Sopenharmony_ci				   (fcport->scan_needed &&
35028c2ecf20Sopenharmony_ci				    fcport->port_type != FCT_INITIATOR &&
35038c2ecf20Sopenharmony_ci				    fcport->port_type != FCT_NVME_INITIATOR)) {
35048c2ecf20Sopenharmony_ci				qlt_schedule_sess_for_deletion(fcport);
35058c2ecf20Sopenharmony_ci			}
35068c2ecf20Sopenharmony_ci			fcport->d_id.b24 = rp->id.b24;
35078c2ecf20Sopenharmony_ci			fcport->scan_needed = 0;
35088c2ecf20Sopenharmony_ci			break;
35098c2ecf20Sopenharmony_ci		}
35108c2ecf20Sopenharmony_ci
35118c2ecf20Sopenharmony_ci		if (!found) {
35128c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0xffff,
35138c2ecf20Sopenharmony_ci			    "%s %d %8phC post new sess\n",
35148c2ecf20Sopenharmony_ci			    __func__, __LINE__, rp->port_name);
35158c2ecf20Sopenharmony_ci			qla24xx_post_newsess_work(vha, &rp->id, rp->port_name,
35168c2ecf20Sopenharmony_ci			    rp->node_name, NULL, rp->fc4type);
35178c2ecf20Sopenharmony_ci		}
35188c2ecf20Sopenharmony_ci	}
35198c2ecf20Sopenharmony_ci
35208c2ecf20Sopenharmony_ci	if (dup) {
35218c2ecf20Sopenharmony_ci		ql_log(ql_log_warn, vha, 0xffff,
35228c2ecf20Sopenharmony_ci		    "Detected %d duplicate NPORT ID(s) from switch data base\n",
35238c2ecf20Sopenharmony_ci		    dup_cnt);
35248c2ecf20Sopenharmony_ci	}
35258c2ecf20Sopenharmony_ci
35268c2ecf20Sopenharmony_cilogin_logout:
35278c2ecf20Sopenharmony_ci	/*
35288c2ecf20Sopenharmony_ci	 * Logout all previous fabric dev marked lost, except FCP2 devices.
35298c2ecf20Sopenharmony_ci	 */
35308c2ecf20Sopenharmony_ci	list_for_each_entry(fcport, &vha->vp_fcports, list) {
35318c2ecf20Sopenharmony_ci		if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) {
35328c2ecf20Sopenharmony_ci			fcport->scan_needed = 0;
35338c2ecf20Sopenharmony_ci			continue;
35348c2ecf20Sopenharmony_ci		}
35358c2ecf20Sopenharmony_ci
35368c2ecf20Sopenharmony_ci		if (fcport->scan_state != QLA_FCPORT_FOUND) {
35378c2ecf20Sopenharmony_ci			bool do_delete = false;
35388c2ecf20Sopenharmony_ci
35398c2ecf20Sopenharmony_ci			if (fcport->scan_needed &&
35408c2ecf20Sopenharmony_ci			    fcport->disc_state == DSC_LOGIN_PEND) {
35418c2ecf20Sopenharmony_ci				/* Cable got disconnected after we sent
35428c2ecf20Sopenharmony_ci				 * a login. Do delete to prevent timeout.
35438c2ecf20Sopenharmony_ci				 */
35448c2ecf20Sopenharmony_ci				fcport->logout_on_delete = 1;
35458c2ecf20Sopenharmony_ci				do_delete = true;
35468c2ecf20Sopenharmony_ci			}
35478c2ecf20Sopenharmony_ci
35488c2ecf20Sopenharmony_ci			fcport->scan_needed = 0;
35498c2ecf20Sopenharmony_ci			if (((qla_dual_mode_enabled(vha) ||
35508c2ecf20Sopenharmony_ci			      qla_ini_mode_enabled(vha)) &&
35518c2ecf20Sopenharmony_ci			    atomic_read(&fcport->state) == FCS_ONLINE) ||
35528c2ecf20Sopenharmony_ci				do_delete) {
35538c2ecf20Sopenharmony_ci				if (fcport->loop_id != FC_NO_LOOP_ID) {
35548c2ecf20Sopenharmony_ci					if (fcport->flags & FCF_FCP2_DEVICE)
35558c2ecf20Sopenharmony_ci						continue;
35568c2ecf20Sopenharmony_ci
35578c2ecf20Sopenharmony_ci					ql_dbg(ql_dbg_disc, vha, 0x20f0,
35588c2ecf20Sopenharmony_ci					    "%s %d %8phC post del sess\n",
35598c2ecf20Sopenharmony_ci					    __func__, __LINE__,
35608c2ecf20Sopenharmony_ci					    fcport->port_name);
35618c2ecf20Sopenharmony_ci
35628c2ecf20Sopenharmony_ci					qlt_schedule_sess_for_deletion(fcport);
35638c2ecf20Sopenharmony_ci					continue;
35648c2ecf20Sopenharmony_ci				}
35658c2ecf20Sopenharmony_ci			}
35668c2ecf20Sopenharmony_ci		} else {
35678c2ecf20Sopenharmony_ci			if (fcport->scan_needed ||
35688c2ecf20Sopenharmony_ci			    fcport->disc_state != DSC_LOGIN_COMPLETE) {
35698c2ecf20Sopenharmony_ci				if (fcport->login_retry == 0) {
35708c2ecf20Sopenharmony_ci					fcport->login_retry =
35718c2ecf20Sopenharmony_ci						vha->hw->login_retry_count;
35728c2ecf20Sopenharmony_ci					ql_dbg(ql_dbg_disc, vha, 0x20a3,
35738c2ecf20Sopenharmony_ci					    "Port login retry %8phN, lid 0x%04x retry cnt=%d.\n",
35748c2ecf20Sopenharmony_ci					    fcport->port_name, fcport->loop_id,
35758c2ecf20Sopenharmony_ci					    fcport->login_retry);
35768c2ecf20Sopenharmony_ci				}
35778c2ecf20Sopenharmony_ci				fcport->scan_needed = 0;
35788c2ecf20Sopenharmony_ci				qla24xx_fcport_handle_login(vha, fcport);
35798c2ecf20Sopenharmony_ci			}
35808c2ecf20Sopenharmony_ci		}
35818c2ecf20Sopenharmony_ci	}
35828c2ecf20Sopenharmony_ci
35838c2ecf20Sopenharmony_ci	recheck = 1;
35848c2ecf20Sopenharmony_ciout:
35858c2ecf20Sopenharmony_ci	qla24xx_sp_unmap(vha, sp);
35868c2ecf20Sopenharmony_ci	spin_lock_irqsave(&vha->work_lock, flags);
35878c2ecf20Sopenharmony_ci	vha->scan.scan_flags &= ~SF_SCANNING;
35888c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&vha->work_lock, flags);
35898c2ecf20Sopenharmony_ci
35908c2ecf20Sopenharmony_ci	if (recheck) {
35918c2ecf20Sopenharmony_ci		list_for_each_entry(fcport, &vha->vp_fcports, list) {
35928c2ecf20Sopenharmony_ci			if (fcport->scan_needed) {
35938c2ecf20Sopenharmony_ci				set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
35948c2ecf20Sopenharmony_ci				set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
35958c2ecf20Sopenharmony_ci				break;
35968c2ecf20Sopenharmony_ci			}
35978c2ecf20Sopenharmony_ci		}
35988c2ecf20Sopenharmony_ci	}
35998c2ecf20Sopenharmony_ci}
36008c2ecf20Sopenharmony_ci
36018c2ecf20Sopenharmony_cistatic int qla2x00_post_gnnft_gpnft_done_work(struct scsi_qla_host *vha,
36028c2ecf20Sopenharmony_ci    srb_t *sp, int cmd)
36038c2ecf20Sopenharmony_ci{
36048c2ecf20Sopenharmony_ci	struct qla_work_evt *e;
36058c2ecf20Sopenharmony_ci
36068c2ecf20Sopenharmony_ci	if (cmd != QLA_EVT_GPNFT_DONE && cmd != QLA_EVT_GNNFT_DONE)
36078c2ecf20Sopenharmony_ci		return QLA_PARAMETER_ERROR;
36088c2ecf20Sopenharmony_ci
36098c2ecf20Sopenharmony_ci	e = qla2x00_alloc_work(vha, cmd);
36108c2ecf20Sopenharmony_ci	if (!e)
36118c2ecf20Sopenharmony_ci		return QLA_FUNCTION_FAILED;
36128c2ecf20Sopenharmony_ci
36138c2ecf20Sopenharmony_ci	e->u.iosb.sp = sp;
36148c2ecf20Sopenharmony_ci
36158c2ecf20Sopenharmony_ci	return qla2x00_post_work(vha, e);
36168c2ecf20Sopenharmony_ci}
36178c2ecf20Sopenharmony_ci
36188c2ecf20Sopenharmony_cistatic int qla2x00_post_nvme_gpnft_work(struct scsi_qla_host *vha,
36198c2ecf20Sopenharmony_ci    srb_t *sp, int cmd)
36208c2ecf20Sopenharmony_ci{
36218c2ecf20Sopenharmony_ci	struct qla_work_evt *e;
36228c2ecf20Sopenharmony_ci
36238c2ecf20Sopenharmony_ci	if (cmd != QLA_EVT_GPNFT)
36248c2ecf20Sopenharmony_ci		return QLA_PARAMETER_ERROR;
36258c2ecf20Sopenharmony_ci
36268c2ecf20Sopenharmony_ci	e = qla2x00_alloc_work(vha, cmd);
36278c2ecf20Sopenharmony_ci	if (!e)
36288c2ecf20Sopenharmony_ci		return QLA_FUNCTION_FAILED;
36298c2ecf20Sopenharmony_ci
36308c2ecf20Sopenharmony_ci	e->u.gpnft.fc4_type = FC4_TYPE_NVME;
36318c2ecf20Sopenharmony_ci	e->u.gpnft.sp = sp;
36328c2ecf20Sopenharmony_ci
36338c2ecf20Sopenharmony_ci	return qla2x00_post_work(vha, e);
36348c2ecf20Sopenharmony_ci}
36358c2ecf20Sopenharmony_ci
36368c2ecf20Sopenharmony_cistatic void qla2x00_find_free_fcp_nvme_slot(struct scsi_qla_host *vha,
36378c2ecf20Sopenharmony_ci	struct srb *sp)
36388c2ecf20Sopenharmony_ci{
36398c2ecf20Sopenharmony_ci	struct qla_hw_data *ha = vha->hw;
36408c2ecf20Sopenharmony_ci	int num_fibre_dev = ha->max_fibre_devices;
36418c2ecf20Sopenharmony_ci	struct ct_sns_req *ct_req =
36428c2ecf20Sopenharmony_ci		(struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
36438c2ecf20Sopenharmony_ci	struct ct_sns_gpnft_rsp *ct_rsp =
36448c2ecf20Sopenharmony_ci		(struct ct_sns_gpnft_rsp *)sp->u.iocb_cmd.u.ctarg.rsp;
36458c2ecf20Sopenharmony_ci	struct ct_sns_gpn_ft_data *d;
36468c2ecf20Sopenharmony_ci	struct fab_scan_rp *rp;
36478c2ecf20Sopenharmony_ci	u16 cmd = be16_to_cpu(ct_req->command);
36488c2ecf20Sopenharmony_ci	u8 fc4_type = sp->gen2;
36498c2ecf20Sopenharmony_ci	int i, j, k;
36508c2ecf20Sopenharmony_ci	port_id_t id;
36518c2ecf20Sopenharmony_ci	u8 found;
36528c2ecf20Sopenharmony_ci	u64 wwn;
36538c2ecf20Sopenharmony_ci
36548c2ecf20Sopenharmony_ci	j = 0;
36558c2ecf20Sopenharmony_ci	for (i = 0; i < num_fibre_dev; i++) {
36568c2ecf20Sopenharmony_ci		d  = &ct_rsp->entries[i];
36578c2ecf20Sopenharmony_ci
36588c2ecf20Sopenharmony_ci		id.b.rsvd_1 = 0;
36598c2ecf20Sopenharmony_ci		id.b.domain = d->port_id[0];
36608c2ecf20Sopenharmony_ci		id.b.area   = d->port_id[1];
36618c2ecf20Sopenharmony_ci		id.b.al_pa  = d->port_id[2];
36628c2ecf20Sopenharmony_ci		wwn = wwn_to_u64(d->port_name);
36638c2ecf20Sopenharmony_ci
36648c2ecf20Sopenharmony_ci		if (id.b24 == 0 || wwn == 0)
36658c2ecf20Sopenharmony_ci			continue;
36668c2ecf20Sopenharmony_ci
36678c2ecf20Sopenharmony_ci		if (fc4_type == FC4_TYPE_FCP_SCSI) {
36688c2ecf20Sopenharmony_ci			if (cmd == GPN_FT_CMD) {
36698c2ecf20Sopenharmony_ci				rp = &vha->scan.l[j];
36708c2ecf20Sopenharmony_ci				rp->id = id;
36718c2ecf20Sopenharmony_ci				memcpy(rp->port_name, d->port_name, 8);
36728c2ecf20Sopenharmony_ci				j++;
36738c2ecf20Sopenharmony_ci				rp->fc4type = FS_FC4TYPE_FCP;
36748c2ecf20Sopenharmony_ci			} else {
36758c2ecf20Sopenharmony_ci				for (k = 0; k < num_fibre_dev; k++) {
36768c2ecf20Sopenharmony_ci					rp = &vha->scan.l[k];
36778c2ecf20Sopenharmony_ci					if (id.b24 == rp->id.b24) {
36788c2ecf20Sopenharmony_ci						memcpy(rp->node_name,
36798c2ecf20Sopenharmony_ci						    d->port_name, 8);
36808c2ecf20Sopenharmony_ci						break;
36818c2ecf20Sopenharmony_ci					}
36828c2ecf20Sopenharmony_ci				}
36838c2ecf20Sopenharmony_ci			}
36848c2ecf20Sopenharmony_ci		} else {
36858c2ecf20Sopenharmony_ci			/* Search if the fibre device supports FC4_TYPE_NVME */
36868c2ecf20Sopenharmony_ci			if (cmd == GPN_FT_CMD) {
36878c2ecf20Sopenharmony_ci				found = 0;
36888c2ecf20Sopenharmony_ci
36898c2ecf20Sopenharmony_ci				for (k = 0; k < num_fibre_dev; k++) {
36908c2ecf20Sopenharmony_ci					rp = &vha->scan.l[k];
36918c2ecf20Sopenharmony_ci					if (!memcmp(rp->port_name,
36928c2ecf20Sopenharmony_ci					    d->port_name, 8)) {
36938c2ecf20Sopenharmony_ci						/*
36948c2ecf20Sopenharmony_ci						 * Supports FC-NVMe & FCP
36958c2ecf20Sopenharmony_ci						 */
36968c2ecf20Sopenharmony_ci						rp->fc4type |= FS_FC4TYPE_NVME;
36978c2ecf20Sopenharmony_ci						found = 1;
36988c2ecf20Sopenharmony_ci						break;
36998c2ecf20Sopenharmony_ci					}
37008c2ecf20Sopenharmony_ci				}
37018c2ecf20Sopenharmony_ci
37028c2ecf20Sopenharmony_ci				/* We found new FC-NVMe only port */
37038c2ecf20Sopenharmony_ci				if (!found) {
37048c2ecf20Sopenharmony_ci					for (k = 0; k < num_fibre_dev; k++) {
37058c2ecf20Sopenharmony_ci						rp = &vha->scan.l[k];
37068c2ecf20Sopenharmony_ci						if (wwn_to_u64(rp->port_name)) {
37078c2ecf20Sopenharmony_ci							continue;
37088c2ecf20Sopenharmony_ci						} else {
37098c2ecf20Sopenharmony_ci							rp->id = id;
37108c2ecf20Sopenharmony_ci							memcpy(rp->port_name,
37118c2ecf20Sopenharmony_ci							    d->port_name, 8);
37128c2ecf20Sopenharmony_ci							rp->fc4type =
37138c2ecf20Sopenharmony_ci							    FS_FC4TYPE_NVME;
37148c2ecf20Sopenharmony_ci							break;
37158c2ecf20Sopenharmony_ci						}
37168c2ecf20Sopenharmony_ci					}
37178c2ecf20Sopenharmony_ci				}
37188c2ecf20Sopenharmony_ci			} else {
37198c2ecf20Sopenharmony_ci				for (k = 0; k < num_fibre_dev; k++) {
37208c2ecf20Sopenharmony_ci					rp = &vha->scan.l[k];
37218c2ecf20Sopenharmony_ci					if (id.b24 == rp->id.b24) {
37228c2ecf20Sopenharmony_ci						memcpy(rp->node_name,
37238c2ecf20Sopenharmony_ci						    d->port_name, 8);
37248c2ecf20Sopenharmony_ci						break;
37258c2ecf20Sopenharmony_ci					}
37268c2ecf20Sopenharmony_ci				}
37278c2ecf20Sopenharmony_ci			}
37288c2ecf20Sopenharmony_ci		}
37298c2ecf20Sopenharmony_ci	}
37308c2ecf20Sopenharmony_ci}
37318c2ecf20Sopenharmony_ci
37328c2ecf20Sopenharmony_cistatic void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res)
37338c2ecf20Sopenharmony_ci{
37348c2ecf20Sopenharmony_ci	struct scsi_qla_host *vha = sp->vha;
37358c2ecf20Sopenharmony_ci	struct ct_sns_req *ct_req =
37368c2ecf20Sopenharmony_ci		(struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
37378c2ecf20Sopenharmony_ci	u16 cmd = be16_to_cpu(ct_req->command);
37388c2ecf20Sopenharmony_ci	u8 fc4_type = sp->gen2;
37398c2ecf20Sopenharmony_ci	unsigned long flags;
37408c2ecf20Sopenharmony_ci	int rc;
37418c2ecf20Sopenharmony_ci
37428c2ecf20Sopenharmony_ci	/* gen2 field is holding the fc4type */
37438c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0xffff,
37448c2ecf20Sopenharmony_ci	    "Async done-%s res %x FC4Type %x\n",
37458c2ecf20Sopenharmony_ci	    sp->name, res, sp->gen2);
37468c2ecf20Sopenharmony_ci
37478c2ecf20Sopenharmony_ci	del_timer(&sp->u.iocb_cmd.timer);
37488c2ecf20Sopenharmony_ci	sp->rc = res;
37498c2ecf20Sopenharmony_ci	if (res) {
37508c2ecf20Sopenharmony_ci		unsigned long flags;
37518c2ecf20Sopenharmony_ci		const char *name = sp->name;
37528c2ecf20Sopenharmony_ci
37538c2ecf20Sopenharmony_ci		if (res == QLA_OS_TIMER_EXPIRED) {
37548c2ecf20Sopenharmony_ci			/* switch is ignoring all commands.
37558c2ecf20Sopenharmony_ci			 * This might be a zone disable behavior.
37568c2ecf20Sopenharmony_ci			 * This means we hit 64s timeout.
37578c2ecf20Sopenharmony_ci			 * 22s GPNFT + 44s Abort = 64s
37588c2ecf20Sopenharmony_ci			 */
37598c2ecf20Sopenharmony_ci			ql_dbg(ql_dbg_disc, vha, 0xffff,
37608c2ecf20Sopenharmony_ci			       "%s: Switch Zone check please .\n",
37618c2ecf20Sopenharmony_ci			       name);
37628c2ecf20Sopenharmony_ci			qla2x00_mark_all_devices_lost(vha);
37638c2ecf20Sopenharmony_ci		}
37648c2ecf20Sopenharmony_ci
37658c2ecf20Sopenharmony_ci		/*
37668c2ecf20Sopenharmony_ci		 * We are in an Interrupt context, queue up this
37678c2ecf20Sopenharmony_ci		 * sp for GNNFT_DONE work. This will allow all
37688c2ecf20Sopenharmony_ci		 * the resource to get freed up.
37698c2ecf20Sopenharmony_ci		 */
37708c2ecf20Sopenharmony_ci		rc = qla2x00_post_gnnft_gpnft_done_work(vha, sp,
37718c2ecf20Sopenharmony_ci		    QLA_EVT_GNNFT_DONE);
37728c2ecf20Sopenharmony_ci		if (rc) {
37738c2ecf20Sopenharmony_ci			/* Cleanup here to prevent memory leak */
37748c2ecf20Sopenharmony_ci			qla24xx_sp_unmap(vha, sp);
37758c2ecf20Sopenharmony_ci
37768c2ecf20Sopenharmony_ci			spin_lock_irqsave(&vha->work_lock, flags);
37778c2ecf20Sopenharmony_ci			vha->scan.scan_flags &= ~SF_SCANNING;
37788c2ecf20Sopenharmony_ci			vha->scan.scan_retry++;
37798c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&vha->work_lock, flags);
37808c2ecf20Sopenharmony_ci
37818c2ecf20Sopenharmony_ci			if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {
37828c2ecf20Sopenharmony_ci				set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
37838c2ecf20Sopenharmony_ci				set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
37848c2ecf20Sopenharmony_ci				qla2xxx_wake_dpc(vha);
37858c2ecf20Sopenharmony_ci			} else {
37868c2ecf20Sopenharmony_ci				ql_dbg(ql_dbg_disc, vha, 0xffff,
37878c2ecf20Sopenharmony_ci				    "Async done-%s rescan failed on all retries.\n",
37888c2ecf20Sopenharmony_ci				    name);
37898c2ecf20Sopenharmony_ci			}
37908c2ecf20Sopenharmony_ci		}
37918c2ecf20Sopenharmony_ci		return;
37928c2ecf20Sopenharmony_ci	}
37938c2ecf20Sopenharmony_ci
37948c2ecf20Sopenharmony_ci	qla2x00_find_free_fcp_nvme_slot(vha, sp);
37958c2ecf20Sopenharmony_ci
37968c2ecf20Sopenharmony_ci	if ((fc4_type == FC4_TYPE_FCP_SCSI) && vha->flags.nvme_enabled &&
37978c2ecf20Sopenharmony_ci	    cmd == GNN_FT_CMD) {
37988c2ecf20Sopenharmony_ci		spin_lock_irqsave(&vha->work_lock, flags);
37998c2ecf20Sopenharmony_ci		vha->scan.scan_flags &= ~SF_SCANNING;
38008c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&vha->work_lock, flags);
38018c2ecf20Sopenharmony_ci
38028c2ecf20Sopenharmony_ci		sp->rc = res;
38038c2ecf20Sopenharmony_ci		rc = qla2x00_post_nvme_gpnft_work(vha, sp, QLA_EVT_GPNFT);
38048c2ecf20Sopenharmony_ci		if (rc) {
38058c2ecf20Sopenharmony_ci			qla24xx_sp_unmap(vha, sp);
38068c2ecf20Sopenharmony_ci			set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
38078c2ecf20Sopenharmony_ci			set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
38088c2ecf20Sopenharmony_ci		}
38098c2ecf20Sopenharmony_ci		return;
38108c2ecf20Sopenharmony_ci	}
38118c2ecf20Sopenharmony_ci
38128c2ecf20Sopenharmony_ci	if (cmd == GPN_FT_CMD) {
38138c2ecf20Sopenharmony_ci		rc = qla2x00_post_gnnft_gpnft_done_work(vha, sp,
38148c2ecf20Sopenharmony_ci		    QLA_EVT_GPNFT_DONE);
38158c2ecf20Sopenharmony_ci	} else {
38168c2ecf20Sopenharmony_ci		rc = qla2x00_post_gnnft_gpnft_done_work(vha, sp,
38178c2ecf20Sopenharmony_ci		    QLA_EVT_GNNFT_DONE);
38188c2ecf20Sopenharmony_ci	}
38198c2ecf20Sopenharmony_ci
38208c2ecf20Sopenharmony_ci	if (rc) {
38218c2ecf20Sopenharmony_ci		qla24xx_sp_unmap(vha, sp);
38228c2ecf20Sopenharmony_ci		set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
38238c2ecf20Sopenharmony_ci		set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
38248c2ecf20Sopenharmony_ci		return;
38258c2ecf20Sopenharmony_ci	}
38268c2ecf20Sopenharmony_ci}
38278c2ecf20Sopenharmony_ci
38288c2ecf20Sopenharmony_ci/*
38298c2ecf20Sopenharmony_ci * Get WWNN list for fc4_type
38308c2ecf20Sopenharmony_ci *
38318c2ecf20Sopenharmony_ci * It is assumed the same SRB is re-used from GPNFT to avoid
38328c2ecf20Sopenharmony_ci * mem free & re-alloc
38338c2ecf20Sopenharmony_ci */
38348c2ecf20Sopenharmony_cistatic int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
38358c2ecf20Sopenharmony_ci    u8 fc4_type)
38368c2ecf20Sopenharmony_ci{
38378c2ecf20Sopenharmony_ci	int rval = QLA_FUNCTION_FAILED;
38388c2ecf20Sopenharmony_ci	struct ct_sns_req *ct_req;
38398c2ecf20Sopenharmony_ci	struct ct_sns_pkt *ct_sns;
38408c2ecf20Sopenharmony_ci	unsigned long flags;
38418c2ecf20Sopenharmony_ci
38428c2ecf20Sopenharmony_ci	if (!vha->flags.online) {
38438c2ecf20Sopenharmony_ci		spin_lock_irqsave(&vha->work_lock, flags);
38448c2ecf20Sopenharmony_ci		vha->scan.scan_flags &= ~SF_SCANNING;
38458c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&vha->work_lock, flags);
38468c2ecf20Sopenharmony_ci		goto done_free_sp;
38478c2ecf20Sopenharmony_ci	}
38488c2ecf20Sopenharmony_ci
38498c2ecf20Sopenharmony_ci	if (!sp->u.iocb_cmd.u.ctarg.req || !sp->u.iocb_cmd.u.ctarg.rsp) {
38508c2ecf20Sopenharmony_ci		ql_log(ql_log_warn, vha, 0xffff,
38518c2ecf20Sopenharmony_ci		    "%s: req %p rsp %p are not setup\n",
38528c2ecf20Sopenharmony_ci		    __func__, sp->u.iocb_cmd.u.ctarg.req,
38538c2ecf20Sopenharmony_ci		    sp->u.iocb_cmd.u.ctarg.rsp);
38548c2ecf20Sopenharmony_ci		spin_lock_irqsave(&vha->work_lock, flags);
38558c2ecf20Sopenharmony_ci		vha->scan.scan_flags &= ~SF_SCANNING;
38568c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&vha->work_lock, flags);
38578c2ecf20Sopenharmony_ci		WARN_ON(1);
38588c2ecf20Sopenharmony_ci		set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
38598c2ecf20Sopenharmony_ci		set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
38608c2ecf20Sopenharmony_ci		goto done_free_sp;
38618c2ecf20Sopenharmony_ci	}
38628c2ecf20Sopenharmony_ci
38638c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0xfffff,
38648c2ecf20Sopenharmony_ci	    "%s: FC4Type %x, CT-PASSTHRU %s command ctarg rsp size %d, ctarg req size %d\n",
38658c2ecf20Sopenharmony_ci	    __func__, fc4_type, sp->name, sp->u.iocb_cmd.u.ctarg.rsp_size,
38668c2ecf20Sopenharmony_ci	     sp->u.iocb_cmd.u.ctarg.req_size);
38678c2ecf20Sopenharmony_ci
38688c2ecf20Sopenharmony_ci	sp->type = SRB_CT_PTHRU_CMD;
38698c2ecf20Sopenharmony_ci	sp->name = "gnnft";
38708c2ecf20Sopenharmony_ci	sp->gen1 = vha->hw->base_qpair->chip_reset;
38718c2ecf20Sopenharmony_ci	sp->gen2 = fc4_type;
38728c2ecf20Sopenharmony_ci
38738c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
38748c2ecf20Sopenharmony_ci	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
38758c2ecf20Sopenharmony_ci
38768c2ecf20Sopenharmony_ci	memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);
38778c2ecf20Sopenharmony_ci	memset(sp->u.iocb_cmd.u.ctarg.req, 0, sp->u.iocb_cmd.u.ctarg.req_size);
38788c2ecf20Sopenharmony_ci
38798c2ecf20Sopenharmony_ci	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
38808c2ecf20Sopenharmony_ci	/* CT_IU preamble  */
38818c2ecf20Sopenharmony_ci	ct_req = qla2x00_prep_ct_req(ct_sns, GNN_FT_CMD,
38828c2ecf20Sopenharmony_ci	    sp->u.iocb_cmd.u.ctarg.rsp_size);
38838c2ecf20Sopenharmony_ci
38848c2ecf20Sopenharmony_ci	/* GPN_FT req */
38858c2ecf20Sopenharmony_ci	ct_req->req.gpn_ft.port_type = fc4_type;
38868c2ecf20Sopenharmony_ci
38878c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE;
38888c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
38898c2ecf20Sopenharmony_ci
38908c2ecf20Sopenharmony_ci	sp->done = qla2x00_async_gpnft_gnnft_sp_done;
38918c2ecf20Sopenharmony_ci
38928c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0xffff,
38938c2ecf20Sopenharmony_ci	    "Async-%s hdl=%x FC4Type %x.\n", sp->name,
38948c2ecf20Sopenharmony_ci	    sp->handle, ct_req->req.gpn_ft.port_type);
38958c2ecf20Sopenharmony_ci
38968c2ecf20Sopenharmony_ci	rval = qla2x00_start_sp(sp);
38978c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS) {
38988c2ecf20Sopenharmony_ci		goto done_free_sp;
38998c2ecf20Sopenharmony_ci	}
39008c2ecf20Sopenharmony_ci
39018c2ecf20Sopenharmony_ci	return rval;
39028c2ecf20Sopenharmony_ci
39038c2ecf20Sopenharmony_cidone_free_sp:
39048c2ecf20Sopenharmony_ci	if (sp->u.iocb_cmd.u.ctarg.req) {
39058c2ecf20Sopenharmony_ci		dma_free_coherent(&vha->hw->pdev->dev,
39068c2ecf20Sopenharmony_ci		    sp->u.iocb_cmd.u.ctarg.req_allocated_size,
39078c2ecf20Sopenharmony_ci		    sp->u.iocb_cmd.u.ctarg.req,
39088c2ecf20Sopenharmony_ci		    sp->u.iocb_cmd.u.ctarg.req_dma);
39098c2ecf20Sopenharmony_ci		sp->u.iocb_cmd.u.ctarg.req = NULL;
39108c2ecf20Sopenharmony_ci	}
39118c2ecf20Sopenharmony_ci	if (sp->u.iocb_cmd.u.ctarg.rsp) {
39128c2ecf20Sopenharmony_ci		dma_free_coherent(&vha->hw->pdev->dev,
39138c2ecf20Sopenharmony_ci		    sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
39148c2ecf20Sopenharmony_ci		    sp->u.iocb_cmd.u.ctarg.rsp,
39158c2ecf20Sopenharmony_ci		    sp->u.iocb_cmd.u.ctarg.rsp_dma);
39168c2ecf20Sopenharmony_ci		sp->u.iocb_cmd.u.ctarg.rsp = NULL;
39178c2ecf20Sopenharmony_ci	}
39188c2ecf20Sopenharmony_ci
39198c2ecf20Sopenharmony_ci	sp->free(sp);
39208c2ecf20Sopenharmony_ci
39218c2ecf20Sopenharmony_ci	spin_lock_irqsave(&vha->work_lock, flags);
39228c2ecf20Sopenharmony_ci	vha->scan.scan_flags &= ~SF_SCANNING;
39238c2ecf20Sopenharmony_ci	if (vha->scan.scan_flags == 0) {
39248c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0xffff,
39258c2ecf20Sopenharmony_ci		    "%s: schedule\n", __func__);
39268c2ecf20Sopenharmony_ci		vha->scan.scan_flags |= SF_QUEUED;
39278c2ecf20Sopenharmony_ci		schedule_delayed_work(&vha->scan.scan_work, 5);
39288c2ecf20Sopenharmony_ci	}
39298c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&vha->work_lock, flags);
39308c2ecf20Sopenharmony_ci
39318c2ecf20Sopenharmony_ci
39328c2ecf20Sopenharmony_ci	return rval;
39338c2ecf20Sopenharmony_ci} /* GNNFT */
39348c2ecf20Sopenharmony_ci
39358c2ecf20Sopenharmony_civoid qla24xx_async_gpnft_done(scsi_qla_host_t *vha, srb_t *sp)
39368c2ecf20Sopenharmony_ci{
39378c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
39388c2ecf20Sopenharmony_ci	    "%s enter\n", __func__);
39398c2ecf20Sopenharmony_ci	qla24xx_async_gnnft(vha, sp, sp->gen2);
39408c2ecf20Sopenharmony_ci}
39418c2ecf20Sopenharmony_ci
39428c2ecf20Sopenharmony_ci/* Get WWPN list for certain fc4_type */
39438c2ecf20Sopenharmony_ciint qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
39448c2ecf20Sopenharmony_ci{
39458c2ecf20Sopenharmony_ci	int rval = QLA_FUNCTION_FAILED;
39468c2ecf20Sopenharmony_ci	struct ct_sns_req       *ct_req;
39478c2ecf20Sopenharmony_ci	struct ct_sns_pkt *ct_sns;
39488c2ecf20Sopenharmony_ci	u32 rspsz;
39498c2ecf20Sopenharmony_ci	unsigned long flags;
39508c2ecf20Sopenharmony_ci
39518c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
39528c2ecf20Sopenharmony_ci	    "%s enter\n", __func__);
39538c2ecf20Sopenharmony_ci
39548c2ecf20Sopenharmony_ci	if (!vha->flags.online)
39558c2ecf20Sopenharmony_ci		return rval;
39568c2ecf20Sopenharmony_ci
39578c2ecf20Sopenharmony_ci	spin_lock_irqsave(&vha->work_lock, flags);
39588c2ecf20Sopenharmony_ci	if (vha->scan.scan_flags & SF_SCANNING) {
39598c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&vha->work_lock, flags);
39608c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
39618c2ecf20Sopenharmony_ci		    "%s: scan active\n", __func__);
39628c2ecf20Sopenharmony_ci		return rval;
39638c2ecf20Sopenharmony_ci	}
39648c2ecf20Sopenharmony_ci	vha->scan.scan_flags |= SF_SCANNING;
39658c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&vha->work_lock, flags);
39668c2ecf20Sopenharmony_ci
39678c2ecf20Sopenharmony_ci	if (fc4_type == FC4_TYPE_FCP_SCSI) {
39688c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
39698c2ecf20Sopenharmony_ci		    "%s: Performing FCP Scan\n", __func__);
39708c2ecf20Sopenharmony_ci
39718c2ecf20Sopenharmony_ci		if (sp)
39728c2ecf20Sopenharmony_ci			sp->free(sp); /* should not happen */
39738c2ecf20Sopenharmony_ci
39748c2ecf20Sopenharmony_ci		sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
39758c2ecf20Sopenharmony_ci		if (!sp) {
39768c2ecf20Sopenharmony_ci			spin_lock_irqsave(&vha->work_lock, flags);
39778c2ecf20Sopenharmony_ci			vha->scan.scan_flags &= ~SF_SCANNING;
39788c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&vha->work_lock, flags);
39798c2ecf20Sopenharmony_ci			return rval;
39808c2ecf20Sopenharmony_ci		}
39818c2ecf20Sopenharmony_ci
39828c2ecf20Sopenharmony_ci		sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
39838c2ecf20Sopenharmony_ci								sizeof(struct ct_sns_pkt),
39848c2ecf20Sopenharmony_ci								&sp->u.iocb_cmd.u.ctarg.req_dma,
39858c2ecf20Sopenharmony_ci								GFP_KERNEL);
39868c2ecf20Sopenharmony_ci		sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt);
39878c2ecf20Sopenharmony_ci		if (!sp->u.iocb_cmd.u.ctarg.req) {
39888c2ecf20Sopenharmony_ci			ql_log(ql_log_warn, vha, 0xffff,
39898c2ecf20Sopenharmony_ci			    "Failed to allocate ct_sns request.\n");
39908c2ecf20Sopenharmony_ci			spin_lock_irqsave(&vha->work_lock, flags);
39918c2ecf20Sopenharmony_ci			vha->scan.scan_flags &= ~SF_SCANNING;
39928c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&vha->work_lock, flags);
39938c2ecf20Sopenharmony_ci			qla2x00_rel_sp(sp);
39948c2ecf20Sopenharmony_ci			return rval;
39958c2ecf20Sopenharmony_ci		}
39968c2ecf20Sopenharmony_ci		sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE;
39978c2ecf20Sopenharmony_ci
39988c2ecf20Sopenharmony_ci		rspsz = sizeof(struct ct_sns_gpnft_rsp) +
39998c2ecf20Sopenharmony_ci			((vha->hw->max_fibre_devices - 1) *
40008c2ecf20Sopenharmony_ci			    sizeof(struct ct_sns_gpn_ft_data));
40018c2ecf20Sopenharmony_ci
40028c2ecf20Sopenharmony_ci		sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
40038c2ecf20Sopenharmony_ci								rspsz,
40048c2ecf20Sopenharmony_ci								&sp->u.iocb_cmd.u.ctarg.rsp_dma,
40058c2ecf20Sopenharmony_ci								GFP_KERNEL);
40068c2ecf20Sopenharmony_ci		sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = rspsz;
40078c2ecf20Sopenharmony_ci		if (!sp->u.iocb_cmd.u.ctarg.rsp) {
40088c2ecf20Sopenharmony_ci			ql_log(ql_log_warn, vha, 0xffff,
40098c2ecf20Sopenharmony_ci			    "Failed to allocate ct_sns request.\n");
40108c2ecf20Sopenharmony_ci			spin_lock_irqsave(&vha->work_lock, flags);
40118c2ecf20Sopenharmony_ci			vha->scan.scan_flags &= ~SF_SCANNING;
40128c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&vha->work_lock, flags);
40138c2ecf20Sopenharmony_ci			dma_free_coherent(&vha->hw->pdev->dev,
40148c2ecf20Sopenharmony_ci			    sp->u.iocb_cmd.u.ctarg.req_allocated_size,
40158c2ecf20Sopenharmony_ci			    sp->u.iocb_cmd.u.ctarg.req,
40168c2ecf20Sopenharmony_ci			    sp->u.iocb_cmd.u.ctarg.req_dma);
40178c2ecf20Sopenharmony_ci			sp->u.iocb_cmd.u.ctarg.req = NULL;
40188c2ecf20Sopenharmony_ci			qla2x00_rel_sp(sp);
40198c2ecf20Sopenharmony_ci			return rval;
40208c2ecf20Sopenharmony_ci		}
40218c2ecf20Sopenharmony_ci		sp->u.iocb_cmd.u.ctarg.rsp_size = rspsz;
40228c2ecf20Sopenharmony_ci
40238c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
40248c2ecf20Sopenharmony_ci		    "%s scan list size %d\n", __func__, vha->scan.size);
40258c2ecf20Sopenharmony_ci
40268c2ecf20Sopenharmony_ci		memset(vha->scan.l, 0, vha->scan.size);
40278c2ecf20Sopenharmony_ci	} else if (!sp) {
40288c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0xffff,
40298c2ecf20Sopenharmony_ci		    "NVME scan did not provide SP\n");
40308c2ecf20Sopenharmony_ci		return rval;
40318c2ecf20Sopenharmony_ci	}
40328c2ecf20Sopenharmony_ci
40338c2ecf20Sopenharmony_ci	sp->type = SRB_CT_PTHRU_CMD;
40348c2ecf20Sopenharmony_ci	sp->name = "gpnft";
40358c2ecf20Sopenharmony_ci	sp->gen1 = vha->hw->base_qpair->chip_reset;
40368c2ecf20Sopenharmony_ci	sp->gen2 = fc4_type;
40378c2ecf20Sopenharmony_ci
40388c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
40398c2ecf20Sopenharmony_ci	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
40408c2ecf20Sopenharmony_ci
40418c2ecf20Sopenharmony_ci	rspsz = sp->u.iocb_cmd.u.ctarg.rsp_size;
40428c2ecf20Sopenharmony_ci	memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);
40438c2ecf20Sopenharmony_ci	memset(sp->u.iocb_cmd.u.ctarg.req, 0, sp->u.iocb_cmd.u.ctarg.req_size);
40448c2ecf20Sopenharmony_ci
40458c2ecf20Sopenharmony_ci	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
40468c2ecf20Sopenharmony_ci	/* CT_IU preamble  */
40478c2ecf20Sopenharmony_ci	ct_req = qla2x00_prep_ct_req(ct_sns, GPN_FT_CMD, rspsz);
40488c2ecf20Sopenharmony_ci
40498c2ecf20Sopenharmony_ci	/* GPN_FT req */
40508c2ecf20Sopenharmony_ci	ct_req->req.gpn_ft.port_type = fc4_type;
40518c2ecf20Sopenharmony_ci
40528c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
40538c2ecf20Sopenharmony_ci
40548c2ecf20Sopenharmony_ci	sp->done = qla2x00_async_gpnft_gnnft_sp_done;
40558c2ecf20Sopenharmony_ci
40568c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0xffff,
40578c2ecf20Sopenharmony_ci	    "Async-%s hdl=%x FC4Type %x.\n", sp->name,
40588c2ecf20Sopenharmony_ci	    sp->handle, ct_req->req.gpn_ft.port_type);
40598c2ecf20Sopenharmony_ci
40608c2ecf20Sopenharmony_ci	rval = qla2x00_start_sp(sp);
40618c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS) {
40628c2ecf20Sopenharmony_ci		goto done_free_sp;
40638c2ecf20Sopenharmony_ci	}
40648c2ecf20Sopenharmony_ci
40658c2ecf20Sopenharmony_ci	return rval;
40668c2ecf20Sopenharmony_ci
40678c2ecf20Sopenharmony_cidone_free_sp:
40688c2ecf20Sopenharmony_ci	if (sp->u.iocb_cmd.u.ctarg.req) {
40698c2ecf20Sopenharmony_ci		dma_free_coherent(&vha->hw->pdev->dev,
40708c2ecf20Sopenharmony_ci		    sp->u.iocb_cmd.u.ctarg.req_allocated_size,
40718c2ecf20Sopenharmony_ci		    sp->u.iocb_cmd.u.ctarg.req,
40728c2ecf20Sopenharmony_ci		    sp->u.iocb_cmd.u.ctarg.req_dma);
40738c2ecf20Sopenharmony_ci		sp->u.iocb_cmd.u.ctarg.req = NULL;
40748c2ecf20Sopenharmony_ci	}
40758c2ecf20Sopenharmony_ci	if (sp->u.iocb_cmd.u.ctarg.rsp) {
40768c2ecf20Sopenharmony_ci		dma_free_coherent(&vha->hw->pdev->dev,
40778c2ecf20Sopenharmony_ci		    sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
40788c2ecf20Sopenharmony_ci		    sp->u.iocb_cmd.u.ctarg.rsp,
40798c2ecf20Sopenharmony_ci		    sp->u.iocb_cmd.u.ctarg.rsp_dma);
40808c2ecf20Sopenharmony_ci		sp->u.iocb_cmd.u.ctarg.rsp = NULL;
40818c2ecf20Sopenharmony_ci	}
40828c2ecf20Sopenharmony_ci
40838c2ecf20Sopenharmony_ci	sp->free(sp);
40848c2ecf20Sopenharmony_ci
40858c2ecf20Sopenharmony_ci	spin_lock_irqsave(&vha->work_lock, flags);
40868c2ecf20Sopenharmony_ci	vha->scan.scan_flags &= ~SF_SCANNING;
40878c2ecf20Sopenharmony_ci	if (vha->scan.scan_flags == 0) {
40888c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
40898c2ecf20Sopenharmony_ci		    "%s: Scan scheduled.\n", __func__);
40908c2ecf20Sopenharmony_ci		vha->scan.scan_flags |= SF_QUEUED;
40918c2ecf20Sopenharmony_ci		schedule_delayed_work(&vha->scan.scan_work, 5);
40928c2ecf20Sopenharmony_ci	}
40938c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&vha->work_lock, flags);
40948c2ecf20Sopenharmony_ci
40958c2ecf20Sopenharmony_ci
40968c2ecf20Sopenharmony_ci	return rval;
40978c2ecf20Sopenharmony_ci}
40988c2ecf20Sopenharmony_ci
40998c2ecf20Sopenharmony_civoid qla_scan_work_fn(struct work_struct *work)
41008c2ecf20Sopenharmony_ci{
41018c2ecf20Sopenharmony_ci	struct fab_scan *s = container_of(to_delayed_work(work),
41028c2ecf20Sopenharmony_ci	    struct fab_scan, scan_work);
41038c2ecf20Sopenharmony_ci	struct scsi_qla_host *vha = container_of(s, struct scsi_qla_host,
41048c2ecf20Sopenharmony_ci	    scan);
41058c2ecf20Sopenharmony_ci	unsigned long flags;
41068c2ecf20Sopenharmony_ci
41078c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0xffff,
41088c2ecf20Sopenharmony_ci	    "%s: schedule loop resync\n", __func__);
41098c2ecf20Sopenharmony_ci	set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
41108c2ecf20Sopenharmony_ci	set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
41118c2ecf20Sopenharmony_ci	qla2xxx_wake_dpc(vha);
41128c2ecf20Sopenharmony_ci	spin_lock_irqsave(&vha->work_lock, flags);
41138c2ecf20Sopenharmony_ci	vha->scan.scan_flags &= ~SF_QUEUED;
41148c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&vha->work_lock, flags);
41158c2ecf20Sopenharmony_ci}
41168c2ecf20Sopenharmony_ci
41178c2ecf20Sopenharmony_ci/* GNN_ID */
41188c2ecf20Sopenharmony_civoid qla24xx_handle_gnnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
41198c2ecf20Sopenharmony_ci{
41208c2ecf20Sopenharmony_ci	qla24xx_post_gnl_work(vha, ea->fcport);
41218c2ecf20Sopenharmony_ci}
41228c2ecf20Sopenharmony_ci
41238c2ecf20Sopenharmony_cistatic void qla2x00_async_gnnid_sp_done(srb_t *sp, int res)
41248c2ecf20Sopenharmony_ci{
41258c2ecf20Sopenharmony_ci	struct scsi_qla_host *vha = sp->vha;
41268c2ecf20Sopenharmony_ci	fc_port_t *fcport = sp->fcport;
41278c2ecf20Sopenharmony_ci	u8 *node_name = fcport->ct_desc.ct_sns->p.rsp.rsp.gnn_id.node_name;
41288c2ecf20Sopenharmony_ci	struct event_arg ea;
41298c2ecf20Sopenharmony_ci	u64 wwnn;
41308c2ecf20Sopenharmony_ci
41318c2ecf20Sopenharmony_ci	fcport->flags &= ~FCF_ASYNC_SENT;
41328c2ecf20Sopenharmony_ci	wwnn = wwn_to_u64(node_name);
41338c2ecf20Sopenharmony_ci	if (wwnn)
41348c2ecf20Sopenharmony_ci		memcpy(fcport->node_name, node_name, WWN_SIZE);
41358c2ecf20Sopenharmony_ci
41368c2ecf20Sopenharmony_ci	memset(&ea, 0, sizeof(ea));
41378c2ecf20Sopenharmony_ci	ea.fcport = fcport;
41388c2ecf20Sopenharmony_ci	ea.sp = sp;
41398c2ecf20Sopenharmony_ci	ea.rc = res;
41408c2ecf20Sopenharmony_ci
41418c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x204f,
41428c2ecf20Sopenharmony_ci	    "Async done-%s res %x, WWPN %8phC %8phC\n",
41438c2ecf20Sopenharmony_ci	    sp->name, res, fcport->port_name, fcport->node_name);
41448c2ecf20Sopenharmony_ci
41458c2ecf20Sopenharmony_ci	qla24xx_handle_gnnid_event(vha, &ea);
41468c2ecf20Sopenharmony_ci
41478c2ecf20Sopenharmony_ci	sp->free(sp);
41488c2ecf20Sopenharmony_ci}
41498c2ecf20Sopenharmony_ci
41508c2ecf20Sopenharmony_ciint qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
41518c2ecf20Sopenharmony_ci{
41528c2ecf20Sopenharmony_ci	int rval = QLA_FUNCTION_FAILED;
41538c2ecf20Sopenharmony_ci	struct ct_sns_req       *ct_req;
41548c2ecf20Sopenharmony_ci	srb_t *sp;
41558c2ecf20Sopenharmony_ci
41568c2ecf20Sopenharmony_ci	if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
41578c2ecf20Sopenharmony_ci		return rval;
41588c2ecf20Sopenharmony_ci
41598c2ecf20Sopenharmony_ci	qla2x00_set_fcport_disc_state(fcport, DSC_GNN_ID);
41608c2ecf20Sopenharmony_ci	sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
41618c2ecf20Sopenharmony_ci	if (!sp)
41628c2ecf20Sopenharmony_ci		goto done;
41638c2ecf20Sopenharmony_ci
41648c2ecf20Sopenharmony_ci	fcport->flags |= FCF_ASYNC_SENT;
41658c2ecf20Sopenharmony_ci	sp->type = SRB_CT_PTHRU_CMD;
41668c2ecf20Sopenharmony_ci	sp->name = "gnnid";
41678c2ecf20Sopenharmony_ci	sp->gen1 = fcport->rscn_gen;
41688c2ecf20Sopenharmony_ci	sp->gen2 = fcport->login_gen;
41698c2ecf20Sopenharmony_ci
41708c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
41718c2ecf20Sopenharmony_ci	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
41728c2ecf20Sopenharmony_ci
41738c2ecf20Sopenharmony_ci	/* CT_IU preamble  */
41748c2ecf20Sopenharmony_ci	ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GNN_ID_CMD,
41758c2ecf20Sopenharmony_ci	    GNN_ID_RSP_SIZE);
41768c2ecf20Sopenharmony_ci
41778c2ecf20Sopenharmony_ci	/* GNN_ID req */
41788c2ecf20Sopenharmony_ci	ct_req->req.port_id.port_id = port_id_to_be_id(fcport->d_id);
41798c2ecf20Sopenharmony_ci
41808c2ecf20Sopenharmony_ci
41818c2ecf20Sopenharmony_ci	/* req & rsp use the same buffer */
41828c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
41838c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
41848c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
41858c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
41868c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_size = GNN_ID_REQ_SIZE;
41878c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp_size = GNN_ID_RSP_SIZE;
41888c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
41898c2ecf20Sopenharmony_ci
41908c2ecf20Sopenharmony_ci	sp->done = qla2x00_async_gnnid_sp_done;
41918c2ecf20Sopenharmony_ci
41928c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0xffff,
41938c2ecf20Sopenharmony_ci	    "Async-%s - %8phC hdl=%x loopid=%x portid %06x.\n",
41948c2ecf20Sopenharmony_ci	    sp->name, fcport->port_name,
41958c2ecf20Sopenharmony_ci	    sp->handle, fcport->loop_id, fcport->d_id.b24);
41968c2ecf20Sopenharmony_ci
41978c2ecf20Sopenharmony_ci	rval = qla2x00_start_sp(sp);
41988c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS)
41998c2ecf20Sopenharmony_ci		goto done_free_sp;
42008c2ecf20Sopenharmony_ci	return rval;
42018c2ecf20Sopenharmony_ci
42028c2ecf20Sopenharmony_cidone_free_sp:
42038c2ecf20Sopenharmony_ci	sp->free(sp);
42048c2ecf20Sopenharmony_ci	fcport->flags &= ~FCF_ASYNC_SENT;
42058c2ecf20Sopenharmony_cidone:
42068c2ecf20Sopenharmony_ci	return rval;
42078c2ecf20Sopenharmony_ci}
42088c2ecf20Sopenharmony_ci
42098c2ecf20Sopenharmony_ciint qla24xx_post_gnnid_work(struct scsi_qla_host *vha, fc_port_t *fcport)
42108c2ecf20Sopenharmony_ci{
42118c2ecf20Sopenharmony_ci	struct qla_work_evt *e;
42128c2ecf20Sopenharmony_ci	int ls;
42138c2ecf20Sopenharmony_ci
42148c2ecf20Sopenharmony_ci	ls = atomic_read(&vha->loop_state);
42158c2ecf20Sopenharmony_ci	if (((ls != LOOP_READY) && (ls != LOOP_UP)) ||
42168c2ecf20Sopenharmony_ci		test_bit(UNLOADING, &vha->dpc_flags))
42178c2ecf20Sopenharmony_ci		return 0;
42188c2ecf20Sopenharmony_ci
42198c2ecf20Sopenharmony_ci	e = qla2x00_alloc_work(vha, QLA_EVT_GNNID);
42208c2ecf20Sopenharmony_ci	if (!e)
42218c2ecf20Sopenharmony_ci		return QLA_FUNCTION_FAILED;
42228c2ecf20Sopenharmony_ci
42238c2ecf20Sopenharmony_ci	e->u.fcport.fcport = fcport;
42248c2ecf20Sopenharmony_ci	return qla2x00_post_work(vha, e);
42258c2ecf20Sopenharmony_ci}
42268c2ecf20Sopenharmony_ci
42278c2ecf20Sopenharmony_ci/* GPFN_ID */
42288c2ecf20Sopenharmony_civoid qla24xx_handle_gfpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
42298c2ecf20Sopenharmony_ci{
42308c2ecf20Sopenharmony_ci	fc_port_t *fcport = ea->fcport;
42318c2ecf20Sopenharmony_ci
42328c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0xffff,
42338c2ecf20Sopenharmony_ci	    "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d fcpcnt %d\n",
42348c2ecf20Sopenharmony_ci	    __func__, fcport->port_name, fcport->disc_state,
42358c2ecf20Sopenharmony_ci	    fcport->fw_login_state, ea->rc, fcport->login_gen, ea->sp->gen2,
42368c2ecf20Sopenharmony_ci	    fcport->rscn_gen, ea->sp->gen1, vha->fcport_count);
42378c2ecf20Sopenharmony_ci
42388c2ecf20Sopenharmony_ci	if (fcport->disc_state == DSC_DELETE_PEND)
42398c2ecf20Sopenharmony_ci		return;
42408c2ecf20Sopenharmony_ci
42418c2ecf20Sopenharmony_ci	if (ea->sp->gen2 != fcport->login_gen) {
42428c2ecf20Sopenharmony_ci		/* target side must have changed it. */
42438c2ecf20Sopenharmony_ci		ql_dbg(ql_dbg_disc, vha, 0x20d3,
42448c2ecf20Sopenharmony_ci		    "%s %8phC generation changed\n",
42458c2ecf20Sopenharmony_ci		    __func__, fcport->port_name);
42468c2ecf20Sopenharmony_ci		return;
42478c2ecf20Sopenharmony_ci	} else if (ea->sp->gen1 != fcport->rscn_gen) {
42488c2ecf20Sopenharmony_ci		return;
42498c2ecf20Sopenharmony_ci	}
42508c2ecf20Sopenharmony_ci
42518c2ecf20Sopenharmony_ci	qla24xx_post_gpsc_work(vha, fcport);
42528c2ecf20Sopenharmony_ci}
42538c2ecf20Sopenharmony_ci
42548c2ecf20Sopenharmony_cistatic void qla2x00_async_gfpnid_sp_done(srb_t *sp, int res)
42558c2ecf20Sopenharmony_ci{
42568c2ecf20Sopenharmony_ci	struct scsi_qla_host *vha = sp->vha;
42578c2ecf20Sopenharmony_ci	fc_port_t *fcport = sp->fcport;
42588c2ecf20Sopenharmony_ci	u8 *fpn = fcport->ct_desc.ct_sns->p.rsp.rsp.gfpn_id.port_name;
42598c2ecf20Sopenharmony_ci	struct event_arg ea;
42608c2ecf20Sopenharmony_ci	u64 wwn;
42618c2ecf20Sopenharmony_ci
42628c2ecf20Sopenharmony_ci	wwn = wwn_to_u64(fpn);
42638c2ecf20Sopenharmony_ci	if (wwn)
42648c2ecf20Sopenharmony_ci		memcpy(fcport->fabric_port_name, fpn, WWN_SIZE);
42658c2ecf20Sopenharmony_ci
42668c2ecf20Sopenharmony_ci	memset(&ea, 0, sizeof(ea));
42678c2ecf20Sopenharmony_ci	ea.fcport = fcport;
42688c2ecf20Sopenharmony_ci	ea.sp = sp;
42698c2ecf20Sopenharmony_ci	ea.rc = res;
42708c2ecf20Sopenharmony_ci
42718c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0x204f,
42728c2ecf20Sopenharmony_ci	    "Async done-%s res %x, WWPN %8phC %8phC\n",
42738c2ecf20Sopenharmony_ci	    sp->name, res, fcport->port_name, fcport->fabric_port_name);
42748c2ecf20Sopenharmony_ci
42758c2ecf20Sopenharmony_ci	qla24xx_handle_gfpnid_event(vha, &ea);
42768c2ecf20Sopenharmony_ci
42778c2ecf20Sopenharmony_ci	sp->free(sp);
42788c2ecf20Sopenharmony_ci}
42798c2ecf20Sopenharmony_ci
42808c2ecf20Sopenharmony_ciint qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
42818c2ecf20Sopenharmony_ci{
42828c2ecf20Sopenharmony_ci	int rval = QLA_FUNCTION_FAILED;
42838c2ecf20Sopenharmony_ci	struct ct_sns_req       *ct_req;
42848c2ecf20Sopenharmony_ci	srb_t *sp;
42858c2ecf20Sopenharmony_ci
42868c2ecf20Sopenharmony_ci	if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
42878c2ecf20Sopenharmony_ci		return rval;
42888c2ecf20Sopenharmony_ci
42898c2ecf20Sopenharmony_ci	sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
42908c2ecf20Sopenharmony_ci	if (!sp)
42918c2ecf20Sopenharmony_ci		goto done;
42928c2ecf20Sopenharmony_ci
42938c2ecf20Sopenharmony_ci	sp->type = SRB_CT_PTHRU_CMD;
42948c2ecf20Sopenharmony_ci	sp->name = "gfpnid";
42958c2ecf20Sopenharmony_ci	sp->gen1 = fcport->rscn_gen;
42968c2ecf20Sopenharmony_ci	sp->gen2 = fcport->login_gen;
42978c2ecf20Sopenharmony_ci
42988c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
42998c2ecf20Sopenharmony_ci	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
43008c2ecf20Sopenharmony_ci
43018c2ecf20Sopenharmony_ci	/* CT_IU preamble  */
43028c2ecf20Sopenharmony_ci	ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GFPN_ID_CMD,
43038c2ecf20Sopenharmony_ci	    GFPN_ID_RSP_SIZE);
43048c2ecf20Sopenharmony_ci
43058c2ecf20Sopenharmony_ci	/* GFPN_ID req */
43068c2ecf20Sopenharmony_ci	ct_req->req.port_id.port_id = port_id_to_be_id(fcport->d_id);
43078c2ecf20Sopenharmony_ci
43088c2ecf20Sopenharmony_ci
43098c2ecf20Sopenharmony_ci	/* req & rsp use the same buffer */
43108c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
43118c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
43128c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
43138c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
43148c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.req_size = GFPN_ID_REQ_SIZE;
43158c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.rsp_size = GFPN_ID_RSP_SIZE;
43168c2ecf20Sopenharmony_ci	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
43178c2ecf20Sopenharmony_ci
43188c2ecf20Sopenharmony_ci	sp->done = qla2x00_async_gfpnid_sp_done;
43198c2ecf20Sopenharmony_ci
43208c2ecf20Sopenharmony_ci	ql_dbg(ql_dbg_disc, vha, 0xffff,
43218c2ecf20Sopenharmony_ci	    "Async-%s - %8phC hdl=%x loopid=%x portid %06x.\n",
43228c2ecf20Sopenharmony_ci	    sp->name, fcport->port_name,
43238c2ecf20Sopenharmony_ci	    sp->handle, fcport->loop_id, fcport->d_id.b24);
43248c2ecf20Sopenharmony_ci
43258c2ecf20Sopenharmony_ci	rval = qla2x00_start_sp(sp);
43268c2ecf20Sopenharmony_ci	if (rval != QLA_SUCCESS)
43278c2ecf20Sopenharmony_ci		goto done_free_sp;
43288c2ecf20Sopenharmony_ci
43298c2ecf20Sopenharmony_ci	return rval;
43308c2ecf20Sopenharmony_ci
43318c2ecf20Sopenharmony_cidone_free_sp:
43328c2ecf20Sopenharmony_ci	sp->free(sp);
43338c2ecf20Sopenharmony_cidone:
43348c2ecf20Sopenharmony_ci	return rval;
43358c2ecf20Sopenharmony_ci}
43368c2ecf20Sopenharmony_ci
43378c2ecf20Sopenharmony_ciint qla24xx_post_gfpnid_work(struct scsi_qla_host *vha, fc_port_t *fcport)
43388c2ecf20Sopenharmony_ci{
43398c2ecf20Sopenharmony_ci	struct qla_work_evt *e;
43408c2ecf20Sopenharmony_ci	int ls;
43418c2ecf20Sopenharmony_ci
43428c2ecf20Sopenharmony_ci	ls = atomic_read(&vha->loop_state);
43438c2ecf20Sopenharmony_ci	if (((ls != LOOP_READY) && (ls != LOOP_UP)) ||
43448c2ecf20Sopenharmony_ci		test_bit(UNLOADING, &vha->dpc_flags))
43458c2ecf20Sopenharmony_ci		return 0;
43468c2ecf20Sopenharmony_ci
43478c2ecf20Sopenharmony_ci	e = qla2x00_alloc_work(vha, QLA_EVT_GFPNID);
43488c2ecf20Sopenharmony_ci	if (!e)
43498c2ecf20Sopenharmony_ci		return QLA_FUNCTION_FAILED;
43508c2ecf20Sopenharmony_ci
43518c2ecf20Sopenharmony_ci	e->u.fcport.fcport = fcport;
43528c2ecf20Sopenharmony_ci	return qla2x00_post_work(vha, e);
43538c2ecf20Sopenharmony_ci}
4354