xref: /openbmc/linux/drivers/scsi/qla2xxx/qla_gs.c (revision 68198dca)
1 /*
2  * QLogic Fibre Channel HBA Driver
3  * Copyright (c)  2003-2014 QLogic Corporation
4  *
5  * See LICENSE.qla2xxx for copyright and licensing details.
6  */
7 #include "qla_def.h"
8 #include "qla_target.h"
9 #include <linux/utsname.h>
10 
11 static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *);
12 static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *);
13 static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *);
14 static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *);
15 static int qla2x00_sns_rft_id(scsi_qla_host_t *);
16 static int qla2x00_sns_rnn_id(scsi_qla_host_t *);
17 
18 /**
19  * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query.
20  * @ha: HA context
21  * @req_size: request size in bytes
22  * @rsp_size: response size in bytes
23  *
24  * Returns a pointer to the @ha's ms_iocb.
25  */
26 void *
27 qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg)
28 {
29 	struct qla_hw_data *ha = vha->hw;
30 	ms_iocb_entry_t *ms_pkt;
31 
32 	ms_pkt = (ms_iocb_entry_t *)arg->iocb;
33 	memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
34 
35 	ms_pkt->entry_type = MS_IOCB_TYPE;
36 	ms_pkt->entry_count = 1;
37 	SET_TARGET_ID(ha, ms_pkt->loop_id, SIMPLE_NAME_SERVER);
38 	ms_pkt->control_flags = cpu_to_le16(CF_READ | CF_HEAD_TAG);
39 	ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
40 	ms_pkt->cmd_dsd_count = cpu_to_le16(1);
41 	ms_pkt->total_dsd_count = cpu_to_le16(2);
42 	ms_pkt->rsp_bytecount = cpu_to_le32(arg->rsp_size);
43 	ms_pkt->req_bytecount = cpu_to_le32(arg->req_size);
44 
45 	ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(arg->req_dma));
46 	ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(arg->req_dma));
47 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
48 
49 	ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(arg->rsp_dma));
50 	ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(arg->rsp_dma));
51 	ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
52 
53 	vha->qla_stats.control_requests++;
54 
55 	return (ms_pkt);
56 }
57 
58 /**
59  * qla24xx_prep_ms_iocb() - Prepare common CT IOCB fields for SNS CT query.
60  * @ha: HA context
61  * @req_size: request size in bytes
62  * @rsp_size: response size in bytes
63  *
64  * Returns a pointer to the @ha's ms_iocb.
65  */
66 void *
67 qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg)
68 {
69 	struct qla_hw_data *ha = vha->hw;
70 	struct ct_entry_24xx *ct_pkt;
71 
72 	ct_pkt = (struct ct_entry_24xx *)arg->iocb;
73 	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
74 
75 	ct_pkt->entry_type = CT_IOCB_TYPE;
76 	ct_pkt->entry_count = 1;
77 	ct_pkt->nport_handle = cpu_to_le16(arg->nport_handle);
78 	ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
79 	ct_pkt->cmd_dsd_count = cpu_to_le16(1);
80 	ct_pkt->rsp_dsd_count = cpu_to_le16(1);
81 	ct_pkt->rsp_byte_count = cpu_to_le32(arg->rsp_size);
82 	ct_pkt->cmd_byte_count = cpu_to_le32(arg->req_size);
83 
84 	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(arg->req_dma));
85 	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(arg->req_dma));
86 	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
87 
88 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(arg->rsp_dma));
89 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(arg->rsp_dma));
90 	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
91 	ct_pkt->vp_index = vha->vp_idx;
92 
93 	vha->qla_stats.control_requests++;
94 
95 	return (ct_pkt);
96 }
97 
98 /**
99  * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
100  * @ct_req: CT request buffer
101  * @cmd: GS command
102  * @rsp_size: response size in bytes
103  *
104  * Returns a pointer to the intitialized @ct_req.
105  */
106 static inline struct ct_sns_req *
107 qla2x00_prep_ct_req(struct ct_sns_pkt *p, uint16_t cmd, uint16_t rsp_size)
108 {
109 	memset(p, 0, sizeof(struct ct_sns_pkt));
110 
111 	p->p.req.header.revision = 0x01;
112 	p->p.req.header.gs_type = 0xFC;
113 	p->p.req.header.gs_subtype = 0x02;
114 	p->p.req.command = cpu_to_be16(cmd);
115 	p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
116 
117 	return &p->p.req;
118 }
119 
120 int
121 qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
122     struct ct_sns_rsp *ct_rsp, const char *routine)
123 {
124 	int rval;
125 	uint16_t comp_status;
126 	struct qla_hw_data *ha = vha->hw;
127 	bool lid_is_sns = false;
128 
129 	rval = QLA_FUNCTION_FAILED;
130 	if (ms_pkt->entry_status != 0) {
131 		ql_dbg(ql_dbg_disc, vha, 0x2031,
132 		    "%s failed, error status (%x) on port_id: %02x%02x%02x.\n",
133 		    routine, ms_pkt->entry_status, vha->d_id.b.domain,
134 		    vha->d_id.b.area, vha->d_id.b.al_pa);
135 	} else {
136 		if (IS_FWI2_CAPABLE(ha))
137 			comp_status = le16_to_cpu(
138 			    ((struct ct_entry_24xx *)ms_pkt)->comp_status);
139 		else
140 			comp_status = le16_to_cpu(ms_pkt->status);
141 		switch (comp_status) {
142 		case CS_COMPLETE:
143 		case CS_DATA_UNDERRUN:
144 		case CS_DATA_OVERRUN:		/* Overrun? */
145 			if (ct_rsp->header.response !=
146 			    cpu_to_be16(CT_ACCEPT_RESPONSE)) {
147 				ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2077,
148 				    "%s failed rejected request on port_id: %02x%02x%02x Completion status 0x%x, response 0x%x\n",
149 				    routine, vha->d_id.b.domain,
150 				    vha->d_id.b.area, vha->d_id.b.al_pa,
151 				    comp_status, ct_rsp->header.response);
152 				ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha,
153 				    0x2078, (uint8_t *)&ct_rsp->header,
154 				    sizeof(struct ct_rsp_hdr));
155 				rval = QLA_INVALID_COMMAND;
156 			} else
157 				rval = QLA_SUCCESS;
158 			break;
159 		case CS_PORT_LOGGED_OUT:
160 			if (IS_FWI2_CAPABLE(ha)) {
161 				if (le16_to_cpu(ms_pkt->loop_id.extended) ==
162 				    NPH_SNS)
163 					lid_is_sns = true;
164 			} else {
165 				if (le16_to_cpu(ms_pkt->loop_id.extended) ==
166 				    SIMPLE_NAME_SERVER)
167 					lid_is_sns = true;
168 			}
169 			if (lid_is_sns) {
170 				ql_dbg(ql_dbg_async, vha, 0x502b,
171 					"%s failed, Name server has logged out",
172 					routine);
173 				rval = QLA_NOT_LOGGED_IN;
174 				set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
175 				set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
176 			}
177 			break;
178 		default:
179 			ql_dbg(ql_dbg_disc, vha, 0x2033,
180 			    "%s failed, completion status (%x) on port_id: "
181 			    "%02x%02x%02x.\n", routine, comp_status,
182 			    vha->d_id.b.domain, vha->d_id.b.area,
183 			    vha->d_id.b.al_pa);
184 			break;
185 		}
186 	}
187 	return rval;
188 }
189 
190 /**
191  * qla2x00_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
192  * @ha: HA context
193  * @fcport: fcport entry to updated
194  *
195  * Returns 0 on success.
196  */
197 int
198 qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
199 {
200 	int		rval;
201 
202 	ms_iocb_entry_t	*ms_pkt;
203 	struct ct_sns_req	*ct_req;
204 	struct ct_sns_rsp	*ct_rsp;
205 	struct qla_hw_data *ha = vha->hw;
206 	struct ct_arg arg;
207 
208 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
209 		return qla2x00_sns_ga_nxt(vha, fcport);
210 
211 	arg.iocb = ha->ms_iocb;
212 	arg.req_dma = ha->ct_sns_dma;
213 	arg.rsp_dma = ha->ct_sns_dma;
214 	arg.req_size = GA_NXT_REQ_SIZE;
215 	arg.rsp_size = GA_NXT_RSP_SIZE;
216 	arg.nport_handle = NPH_SNS;
217 
218 	/* Issue GA_NXT */
219 	/* Prepare common MS IOCB */
220 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
221 
222 	/* Prepare CT request */
223 	ct_req = qla2x00_prep_ct_req(ha->ct_sns, GA_NXT_CMD,
224 	    GA_NXT_RSP_SIZE);
225 	ct_rsp = &ha->ct_sns->p.rsp;
226 
227 	/* Prepare CT arguments -- port_id */
228 	ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain;
229 	ct_req->req.port_id.port_id[1] = fcport->d_id.b.area;
230 	ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa;
231 
232 	/* Execute MS IOCB */
233 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
234 	    sizeof(ms_iocb_entry_t));
235 	if (rval != QLA_SUCCESS) {
236 		/*EMPTY*/
237 		ql_dbg(ql_dbg_disc, vha, 0x2062,
238 		    "GA_NXT issue IOCB failed (%d).\n", rval);
239 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GA_NXT") !=
240 	    QLA_SUCCESS) {
241 		rval = QLA_FUNCTION_FAILED;
242 	} else {
243 		/* Populate fc_port_t entry. */
244 		fcport->d_id.b.domain = ct_rsp->rsp.ga_nxt.port_id[0];
245 		fcport->d_id.b.area = ct_rsp->rsp.ga_nxt.port_id[1];
246 		fcport->d_id.b.al_pa = ct_rsp->rsp.ga_nxt.port_id[2];
247 
248 		memcpy(fcport->node_name, ct_rsp->rsp.ga_nxt.node_name,
249 		    WWN_SIZE);
250 		memcpy(fcport->port_name, ct_rsp->rsp.ga_nxt.port_name,
251 		    WWN_SIZE);
252 
253 		fcport->fc4_type = (ct_rsp->rsp.ga_nxt.fc4_types[2] & BIT_0) ?
254 		    FC4_TYPE_FCP_SCSI : FC4_TYPE_OTHER;
255 
256 		if (ct_rsp->rsp.ga_nxt.port_type != NS_N_PORT_TYPE &&
257 		    ct_rsp->rsp.ga_nxt.port_type != NS_NL_PORT_TYPE)
258 			fcport->d_id.b.domain = 0xf0;
259 
260 		ql_dbg(ql_dbg_disc, vha, 0x2063,
261 		    "GA_NXT entry - nn %8phN pn %8phN "
262 		    "port_id=%02x%02x%02x.\n",
263 		    fcport->node_name, fcport->port_name,
264 		    fcport->d_id.b.domain, fcport->d_id.b.area,
265 		    fcport->d_id.b.al_pa);
266 	}
267 
268 	return (rval);
269 }
270 
271 static inline int
272 qla2x00_gid_pt_rsp_size(scsi_qla_host_t *vha)
273 {
274 	return vha->hw->max_fibre_devices * 4 + 16;
275 }
276 
277 /**
278  * qla2x00_gid_pt() - SNS scan for fabric devices via GID_PT command.
279  * @ha: HA context
280  * @list: switch info entries to populate
281  *
282  * NOTE: Non-Nx_Ports are not requested.
283  *
284  * Returns 0 on success.
285  */
286 int
287 qla2x00_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
288 {
289 	int		rval;
290 	uint16_t	i;
291 
292 	ms_iocb_entry_t	*ms_pkt;
293 	struct ct_sns_req	*ct_req;
294 	struct ct_sns_rsp	*ct_rsp;
295 
296 	struct ct_sns_gid_pt_data *gid_data;
297 	struct qla_hw_data *ha = vha->hw;
298 	uint16_t gid_pt_rsp_size;
299 	struct ct_arg arg;
300 
301 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
302 		return qla2x00_sns_gid_pt(vha, list);
303 
304 	gid_data = NULL;
305 	gid_pt_rsp_size = qla2x00_gid_pt_rsp_size(vha);
306 
307 	arg.iocb = ha->ms_iocb;
308 	arg.req_dma = ha->ct_sns_dma;
309 	arg.rsp_dma = ha->ct_sns_dma;
310 	arg.req_size = GID_PT_REQ_SIZE;
311 	arg.rsp_size = gid_pt_rsp_size;
312 	arg.nport_handle = NPH_SNS;
313 
314 	/* Issue GID_PT */
315 	/* Prepare common MS IOCB */
316 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
317 
318 	/* Prepare CT request */
319 	ct_req = qla2x00_prep_ct_req(ha->ct_sns, GID_PT_CMD, gid_pt_rsp_size);
320 	ct_rsp = &ha->ct_sns->p.rsp;
321 
322 	/* Prepare CT arguments -- port_type */
323 	ct_req->req.gid_pt.port_type = NS_NX_PORT_TYPE;
324 
325 	/* Execute MS IOCB */
326 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
327 	    sizeof(ms_iocb_entry_t));
328 	if (rval != QLA_SUCCESS) {
329 		/*EMPTY*/
330 		ql_dbg(ql_dbg_disc, vha, 0x2055,
331 		    "GID_PT issue IOCB failed (%d).\n", rval);
332 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GID_PT") !=
333 	    QLA_SUCCESS) {
334 		rval = QLA_FUNCTION_FAILED;
335 	} else {
336 		/* Set port IDs in switch info list. */
337 		for (i = 0; i < ha->max_fibre_devices; i++) {
338 			gid_data = &ct_rsp->rsp.gid_pt.entries[i];
339 			list[i].d_id.b.domain = gid_data->port_id[0];
340 			list[i].d_id.b.area = gid_data->port_id[1];
341 			list[i].d_id.b.al_pa = gid_data->port_id[2];
342 			memset(list[i].fabric_port_name, 0, WWN_SIZE);
343 			list[i].fp_speed = PORT_SPEED_UNKNOWN;
344 
345 			/* Last one exit. */
346 			if (gid_data->control_byte & BIT_7) {
347 				list[i].d_id.b.rsvd_1 = gid_data->control_byte;
348 				break;
349 			}
350 		}
351 
352 		/*
353 		 * If we've used all available slots, then the switch is
354 		 * reporting back more devices than we can handle with this
355 		 * single call.  Return a failed status, and let GA_NXT handle
356 		 * the overload.
357 		 */
358 		if (i == ha->max_fibre_devices)
359 			rval = QLA_FUNCTION_FAILED;
360 	}
361 
362 	return (rval);
363 }
364 
365 /**
366  * qla2x00_gpn_id() - SNS Get Port Name (GPN_ID) query.
367  * @ha: HA context
368  * @list: switch info entries to populate
369  *
370  * Returns 0 on success.
371  */
372 int
373 qla2x00_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
374 {
375 	int		rval = QLA_SUCCESS;
376 	uint16_t	i;
377 
378 	ms_iocb_entry_t	*ms_pkt;
379 	struct ct_sns_req	*ct_req;
380 	struct ct_sns_rsp	*ct_rsp;
381 	struct qla_hw_data *ha = vha->hw;
382 	struct ct_arg arg;
383 
384 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
385 		return qla2x00_sns_gpn_id(vha, list);
386 
387 	arg.iocb = ha->ms_iocb;
388 	arg.req_dma = ha->ct_sns_dma;
389 	arg.rsp_dma = ha->ct_sns_dma;
390 	arg.req_size = GPN_ID_REQ_SIZE;
391 	arg.rsp_size = GPN_ID_RSP_SIZE;
392 	arg.nport_handle = NPH_SNS;
393 
394 	for (i = 0; i < ha->max_fibre_devices; i++) {
395 		/* Issue GPN_ID */
396 		/* Prepare common MS IOCB */
397 		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
398 
399 		/* Prepare CT request */
400 		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GPN_ID_CMD,
401 		    GPN_ID_RSP_SIZE);
402 		ct_rsp = &ha->ct_sns->p.rsp;
403 
404 		/* Prepare CT arguments -- port_id */
405 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
406 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
407 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
408 
409 		/* Execute MS IOCB */
410 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
411 		    sizeof(ms_iocb_entry_t));
412 		if (rval != QLA_SUCCESS) {
413 			/*EMPTY*/
414 			ql_dbg(ql_dbg_disc, vha, 0x2056,
415 			    "GPN_ID issue IOCB failed (%d).\n", rval);
416 			break;
417 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
418 		    "GPN_ID") != QLA_SUCCESS) {
419 			rval = QLA_FUNCTION_FAILED;
420 			break;
421 		} else {
422 			/* Save portname */
423 			memcpy(list[i].port_name,
424 			    ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);
425 		}
426 
427 		/* Last device exit. */
428 		if (list[i].d_id.b.rsvd_1 != 0)
429 			break;
430 	}
431 
432 	return (rval);
433 }
434 
435 /**
436  * qla2x00_gnn_id() - SNS Get Node Name (GNN_ID) query.
437  * @ha: HA context
438  * @list: switch info entries to populate
439  *
440  * Returns 0 on success.
441  */
442 int
443 qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
444 {
445 	int		rval = QLA_SUCCESS;
446 	uint16_t	i;
447 	struct qla_hw_data *ha = vha->hw;
448 	ms_iocb_entry_t	*ms_pkt;
449 	struct ct_sns_req	*ct_req;
450 	struct ct_sns_rsp	*ct_rsp;
451 	struct ct_arg arg;
452 
453 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
454 		return qla2x00_sns_gnn_id(vha, list);
455 
456 	arg.iocb = ha->ms_iocb;
457 	arg.req_dma = ha->ct_sns_dma;
458 	arg.rsp_dma = ha->ct_sns_dma;
459 	arg.req_size = GNN_ID_REQ_SIZE;
460 	arg.rsp_size = GNN_ID_RSP_SIZE;
461 	arg.nport_handle = NPH_SNS;
462 
463 	for (i = 0; i < ha->max_fibre_devices; i++) {
464 		/* Issue GNN_ID */
465 		/* Prepare common MS IOCB */
466 		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
467 
468 		/* Prepare CT request */
469 		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GNN_ID_CMD,
470 		    GNN_ID_RSP_SIZE);
471 		ct_rsp = &ha->ct_sns->p.rsp;
472 
473 		/* Prepare CT arguments -- port_id */
474 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
475 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
476 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
477 
478 		/* Execute MS IOCB */
479 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
480 		    sizeof(ms_iocb_entry_t));
481 		if (rval != QLA_SUCCESS) {
482 			/*EMPTY*/
483 			ql_dbg(ql_dbg_disc, vha, 0x2057,
484 			    "GNN_ID issue IOCB failed (%d).\n", rval);
485 			break;
486 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
487 		    "GNN_ID") != QLA_SUCCESS) {
488 			rval = QLA_FUNCTION_FAILED;
489 			break;
490 		} else {
491 			/* Save nodename */
492 			memcpy(list[i].node_name,
493 			    ct_rsp->rsp.gnn_id.node_name, WWN_SIZE);
494 
495 			ql_dbg(ql_dbg_disc, vha, 0x2058,
496 			    "GID_PT entry - nn %8phN pn %8phN "
497 			    "portid=%02x%02x%02x.\n",
498 			    list[i].node_name, list[i].port_name,
499 			    list[i].d_id.b.domain, list[i].d_id.b.area,
500 			    list[i].d_id.b.al_pa);
501 		}
502 
503 		/* Last device exit. */
504 		if (list[i].d_id.b.rsvd_1 != 0)
505 			break;
506 	}
507 
508 	return (rval);
509 }
510 
511 /**
512  * qla2x00_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
513  * @ha: HA context
514  *
515  * Returns 0 on success.
516  */
517 int
518 qla2x00_rft_id(scsi_qla_host_t *vha)
519 {
520 	int		rval;
521 	struct qla_hw_data *ha = vha->hw;
522 	ms_iocb_entry_t	*ms_pkt;
523 	struct ct_sns_req	*ct_req;
524 	struct ct_sns_rsp	*ct_rsp;
525 	struct ct_arg arg;
526 
527 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
528 		return qla2x00_sns_rft_id(vha);
529 
530 	arg.iocb = ha->ms_iocb;
531 	arg.req_dma = ha->ct_sns_dma;
532 	arg.rsp_dma = ha->ct_sns_dma;
533 	arg.req_size = RFT_ID_REQ_SIZE;
534 	arg.rsp_size = RFT_ID_RSP_SIZE;
535 	arg.nport_handle = NPH_SNS;
536 
537 	/* Issue RFT_ID */
538 	/* Prepare common MS IOCB */
539 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
540 
541 	/* Prepare CT request */
542 	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFT_ID_CMD,
543 	    RFT_ID_RSP_SIZE);
544 	ct_rsp = &ha->ct_sns->p.rsp;
545 
546 	/* Prepare CT arguments -- port_id, FC-4 types */
547 	ct_req->req.rft_id.port_id[0] = vha->d_id.b.domain;
548 	ct_req->req.rft_id.port_id[1] = vha->d_id.b.area;
549 	ct_req->req.rft_id.port_id[2] = vha->d_id.b.al_pa;
550 
551 	ct_req->req.rft_id.fc4_types[2] = 0x01;		/* FCP-3 */
552 
553 	if (vha->flags.nvme_enabled)
554 		ct_req->req.rft_id.fc4_types[6] = 1;    /* NVMe type 28h */
555 	/* Execute MS IOCB */
556 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
557 	    sizeof(ms_iocb_entry_t));
558 	if (rval != QLA_SUCCESS) {
559 		/*EMPTY*/
560 		ql_dbg(ql_dbg_disc, vha, 0x2043,
561 		    "RFT_ID issue IOCB failed (%d).\n", rval);
562 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFT_ID") !=
563 	    QLA_SUCCESS) {
564 		rval = QLA_FUNCTION_FAILED;
565 	} else {
566 		ql_dbg(ql_dbg_disc, vha, 0x2044,
567 		    "RFT_ID exiting normally.\n");
568 	}
569 
570 	return (rval);
571 }
572 
573 /**
574  * qla2x00_rff_id() - SNS Register FC-4 Features (RFF_ID) supported by the HBA.
575  * @ha: HA context
576  *
577  * Returns 0 on success.
578  */
579 int
580 qla2x00_rff_id(scsi_qla_host_t *vha, u8 type)
581 {
582 	int		rval;
583 	struct qla_hw_data *ha = vha->hw;
584 	ms_iocb_entry_t	*ms_pkt;
585 	struct ct_sns_req	*ct_req;
586 	struct ct_sns_rsp	*ct_rsp;
587 	struct ct_arg arg;
588 
589 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
590 		ql_dbg(ql_dbg_disc, vha, 0x2046,
591 		    "RFF_ID call not supported on ISP2100/ISP2200.\n");
592 		return (QLA_SUCCESS);
593 	}
594 
595 	arg.iocb = ha->ms_iocb;
596 	arg.req_dma = ha->ct_sns_dma;
597 	arg.rsp_dma = ha->ct_sns_dma;
598 	arg.req_size = RFF_ID_REQ_SIZE;
599 	arg.rsp_size = RFF_ID_RSP_SIZE;
600 	arg.nport_handle = NPH_SNS;
601 
602 	/* Issue RFF_ID */
603 	/* Prepare common MS IOCB */
604 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
605 
606 	/* Prepare CT request */
607 	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFF_ID_CMD,
608 	    RFF_ID_RSP_SIZE);
609 	ct_rsp = &ha->ct_sns->p.rsp;
610 
611 	/* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */
612 	ct_req->req.rff_id.port_id[0] = vha->d_id.b.domain;
613 	ct_req->req.rff_id.port_id[1] = vha->d_id.b.area;
614 	ct_req->req.rff_id.port_id[2] = vha->d_id.b.al_pa;
615 
616 	qlt_rff_id(vha, ct_req);
617 
618 	ct_req->req.rff_id.fc4_type = type;		/* SCSI - FCP */
619 
620 	/* Execute MS IOCB */
621 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
622 	    sizeof(ms_iocb_entry_t));
623 	if (rval != QLA_SUCCESS) {
624 		/*EMPTY*/
625 		ql_dbg(ql_dbg_disc, vha, 0x2047,
626 		    "RFF_ID issue IOCB failed (%d).\n", rval);
627 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFF_ID") !=
628 	    QLA_SUCCESS) {
629 		rval = QLA_FUNCTION_FAILED;
630 	} else {
631 		ql_dbg(ql_dbg_disc, vha, 0x2048,
632 		    "RFF_ID exiting normally.\n");
633 	}
634 
635 	return (rval);
636 }
637 
638 /**
639  * qla2x00_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
640  * @ha: HA context
641  *
642  * Returns 0 on success.
643  */
644 int
645 qla2x00_rnn_id(scsi_qla_host_t *vha)
646 {
647 	int		rval;
648 	struct qla_hw_data *ha = vha->hw;
649 	ms_iocb_entry_t	*ms_pkt;
650 	struct ct_sns_req	*ct_req;
651 	struct ct_sns_rsp	*ct_rsp;
652 	struct ct_arg arg;
653 
654 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
655 		return qla2x00_sns_rnn_id(vha);
656 
657 	arg.iocb = ha->ms_iocb;
658 	arg.req_dma = ha->ct_sns_dma;
659 	arg.rsp_dma = ha->ct_sns_dma;
660 	arg.req_size = RNN_ID_REQ_SIZE;
661 	arg.rsp_size = RNN_ID_RSP_SIZE;
662 	arg.nport_handle = NPH_SNS;
663 
664 	/* Issue RNN_ID */
665 	/* Prepare common MS IOCB */
666 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
667 
668 	/* Prepare CT request */
669 	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE);
670 	ct_rsp = &ha->ct_sns->p.rsp;
671 
672 	/* Prepare CT arguments -- port_id, node_name */
673 	ct_req->req.rnn_id.port_id[0] = vha->d_id.b.domain;
674 	ct_req->req.rnn_id.port_id[1] = vha->d_id.b.area;
675 	ct_req->req.rnn_id.port_id[2] = vha->d_id.b.al_pa;
676 
677 	memcpy(ct_req->req.rnn_id.node_name, vha->node_name, WWN_SIZE);
678 
679 	/* Execute MS IOCB */
680 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
681 	    sizeof(ms_iocb_entry_t));
682 	if (rval != QLA_SUCCESS) {
683 		/*EMPTY*/
684 		ql_dbg(ql_dbg_disc, vha, 0x204d,
685 		    "RNN_ID issue IOCB failed (%d).\n", rval);
686 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RNN_ID") !=
687 	    QLA_SUCCESS) {
688 		rval = QLA_FUNCTION_FAILED;
689 	} else {
690 		ql_dbg(ql_dbg_disc, vha, 0x204e,
691 		    "RNN_ID exiting normally.\n");
692 	}
693 
694 	return (rval);
695 }
696 
697 void
698 qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn, size_t size)
699 {
700 	struct qla_hw_data *ha = vha->hw;
701 
702 	if (IS_QLAFX00(ha))
703 		snprintf(snn, size, "%s FW:v%s DVR:v%s", ha->model_number,
704 		    ha->mr.fw_version, qla2x00_version_str);
705 	else
706 		snprintf(snn, size,
707 		    "%s FW:v%d.%02d.%02d DVR:v%s", ha->model_number,
708 		    ha->fw_major_version, ha->fw_minor_version,
709 		    ha->fw_subminor_version, qla2x00_version_str);
710 }
711 
712 /**
713  * qla2x00_rsnn_nn() - SNS Register Symbolic Node Name (RSNN_NN) of the HBA.
714  * @ha: HA context
715  *
716  * Returns 0 on success.
717  */
718 int
719 qla2x00_rsnn_nn(scsi_qla_host_t *vha)
720 {
721 	int		rval;
722 	struct qla_hw_data *ha = vha->hw;
723 	ms_iocb_entry_t	*ms_pkt;
724 	struct ct_sns_req	*ct_req;
725 	struct ct_sns_rsp	*ct_rsp;
726 	struct ct_arg arg;
727 
728 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
729 		ql_dbg(ql_dbg_disc, vha, 0x2050,
730 		    "RSNN_ID call unsupported on ISP2100/ISP2200.\n");
731 		return (QLA_SUCCESS);
732 	}
733 
734 	arg.iocb = ha->ms_iocb;
735 	arg.req_dma = ha->ct_sns_dma;
736 	arg.rsp_dma = ha->ct_sns_dma;
737 	arg.req_size = 0;
738 	arg.rsp_size = RSNN_NN_RSP_SIZE;
739 	arg.nport_handle = NPH_SNS;
740 
741 	/* Issue RSNN_NN */
742 	/* Prepare common MS IOCB */
743 	/*   Request size adjusted after CT preparation */
744 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
745 
746 	/* Prepare CT request */
747 	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RSNN_NN_CMD,
748 	    RSNN_NN_RSP_SIZE);
749 	ct_rsp = &ha->ct_sns->p.rsp;
750 
751 	/* Prepare CT arguments -- node_name, symbolic node_name, size */
752 	memcpy(ct_req->req.rsnn_nn.node_name, vha->node_name, WWN_SIZE);
753 
754 	/* Prepare the Symbolic Node Name */
755 	qla2x00_get_sym_node_name(vha, ct_req->req.rsnn_nn.sym_node_name,
756 	    sizeof(ct_req->req.rsnn_nn.sym_node_name));
757 
758 	/* Calculate SNN length */
759 	ct_req->req.rsnn_nn.name_len =
760 	    (uint8_t)strlen(ct_req->req.rsnn_nn.sym_node_name);
761 
762 	/* Update MS IOCB request */
763 	ms_pkt->req_bytecount =
764 	    cpu_to_le32(24 + 1 + ct_req->req.rsnn_nn.name_len);
765 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
766 
767 	/* Execute MS IOCB */
768 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
769 	    sizeof(ms_iocb_entry_t));
770 	if (rval != QLA_SUCCESS) {
771 		/*EMPTY*/
772 		ql_dbg(ql_dbg_disc, vha, 0x2051,
773 		    "RSNN_NN issue IOCB failed (%d).\n", rval);
774 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RSNN_NN") !=
775 	    QLA_SUCCESS) {
776 		rval = QLA_FUNCTION_FAILED;
777 	} else {
778 		ql_dbg(ql_dbg_disc, vha, 0x2052,
779 		    "RSNN_NN exiting normally.\n");
780 	}
781 
782 	return (rval);
783 }
784 
785 /**
786  * qla2x00_prep_sns_cmd() - Prepare common SNS command request fields for query.
787  * @ha: HA context
788  * @cmd: GS command
789  * @scmd_len: Subcommand length
790  * @data_size: response size in bytes
791  *
792  * Returns a pointer to the @ha's sns_cmd.
793  */
794 static inline struct sns_cmd_pkt *
795 qla2x00_prep_sns_cmd(scsi_qla_host_t *vha, uint16_t cmd, uint16_t scmd_len,
796     uint16_t data_size)
797 {
798 	uint16_t		wc;
799 	struct sns_cmd_pkt	*sns_cmd;
800 	struct qla_hw_data *ha = vha->hw;
801 
802 	sns_cmd = ha->sns_cmd;
803 	memset(sns_cmd, 0, sizeof(struct sns_cmd_pkt));
804 	wc = data_size / 2;			/* Size in 16bit words. */
805 	sns_cmd->p.cmd.buffer_length = cpu_to_le16(wc);
806 	sns_cmd->p.cmd.buffer_address[0] = cpu_to_le32(LSD(ha->sns_cmd_dma));
807 	sns_cmd->p.cmd.buffer_address[1] = cpu_to_le32(MSD(ha->sns_cmd_dma));
808 	sns_cmd->p.cmd.subcommand_length = cpu_to_le16(scmd_len);
809 	sns_cmd->p.cmd.subcommand = cpu_to_le16(cmd);
810 	wc = (data_size - 16) / 4;		/* Size in 32bit words. */
811 	sns_cmd->p.cmd.size = cpu_to_le16(wc);
812 
813 	vha->qla_stats.control_requests++;
814 
815 	return (sns_cmd);
816 }
817 
818 /**
819  * qla2x00_sns_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
820  * @ha: HA context
821  * @fcport: fcport entry to updated
822  *
823  * This command uses the old Exectute SNS Command mailbox routine.
824  *
825  * Returns 0 on success.
826  */
827 static int
828 qla2x00_sns_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
829 {
830 	int		rval = QLA_SUCCESS;
831 	struct qla_hw_data *ha = vha->hw;
832 	struct sns_cmd_pkt	*sns_cmd;
833 
834 	/* Issue GA_NXT. */
835 	/* Prepare SNS command request. */
836 	sns_cmd = qla2x00_prep_sns_cmd(vha, GA_NXT_CMD, GA_NXT_SNS_SCMD_LEN,
837 	    GA_NXT_SNS_DATA_SIZE);
838 
839 	/* Prepare SNS command arguments -- port_id. */
840 	sns_cmd->p.cmd.param[0] = fcport->d_id.b.al_pa;
841 	sns_cmd->p.cmd.param[1] = fcport->d_id.b.area;
842 	sns_cmd->p.cmd.param[2] = fcport->d_id.b.domain;
843 
844 	/* Execute SNS command. */
845 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GA_NXT_SNS_CMD_SIZE / 2,
846 	    sizeof(struct sns_cmd_pkt));
847 	if (rval != QLA_SUCCESS) {
848 		/*EMPTY*/
849 		ql_dbg(ql_dbg_disc, vha, 0x205f,
850 		    "GA_NXT Send SNS failed (%d).\n", rval);
851 	} else if (sns_cmd->p.gan_data[8] != 0x80 ||
852 	    sns_cmd->p.gan_data[9] != 0x02) {
853 		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2084,
854 		    "GA_NXT failed, rejected request ga_nxt_rsp:\n");
855 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2074,
856 		    sns_cmd->p.gan_data, 16);
857 		rval = QLA_FUNCTION_FAILED;
858 	} else {
859 		/* Populate fc_port_t entry. */
860 		fcport->d_id.b.domain = sns_cmd->p.gan_data[17];
861 		fcport->d_id.b.area = sns_cmd->p.gan_data[18];
862 		fcport->d_id.b.al_pa = sns_cmd->p.gan_data[19];
863 
864 		memcpy(fcport->node_name, &sns_cmd->p.gan_data[284], WWN_SIZE);
865 		memcpy(fcport->port_name, &sns_cmd->p.gan_data[20], WWN_SIZE);
866 
867 		if (sns_cmd->p.gan_data[16] != NS_N_PORT_TYPE &&
868 		    sns_cmd->p.gan_data[16] != NS_NL_PORT_TYPE)
869 			fcport->d_id.b.domain = 0xf0;
870 
871 		ql_dbg(ql_dbg_disc, vha, 0x2061,
872 		    "GA_NXT entry - nn %8phN pn %8phN "
873 		    "port_id=%02x%02x%02x.\n",
874 		    fcport->node_name, fcport->port_name,
875 		    fcport->d_id.b.domain, fcport->d_id.b.area,
876 		    fcport->d_id.b.al_pa);
877 	}
878 
879 	return (rval);
880 }
881 
882 /**
883  * qla2x00_sns_gid_pt() - SNS scan for fabric devices via GID_PT command.
884  * @ha: HA context
885  * @list: switch info entries to populate
886  *
887  * This command uses the old Exectute SNS Command mailbox routine.
888  *
889  * NOTE: Non-Nx_Ports are not requested.
890  *
891  * Returns 0 on success.
892  */
893 static int
894 qla2x00_sns_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
895 {
896 	int		rval;
897 	struct qla_hw_data *ha = vha->hw;
898 	uint16_t	i;
899 	uint8_t		*entry;
900 	struct sns_cmd_pkt	*sns_cmd;
901 	uint16_t gid_pt_sns_data_size;
902 
903 	gid_pt_sns_data_size = qla2x00_gid_pt_rsp_size(vha);
904 
905 	/* Issue GID_PT. */
906 	/* Prepare SNS command request. */
907 	sns_cmd = qla2x00_prep_sns_cmd(vha, GID_PT_CMD, GID_PT_SNS_SCMD_LEN,
908 	    gid_pt_sns_data_size);
909 
910 	/* Prepare SNS command arguments -- port_type. */
911 	sns_cmd->p.cmd.param[0] = NS_NX_PORT_TYPE;
912 
913 	/* Execute SNS command. */
914 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GID_PT_SNS_CMD_SIZE / 2,
915 	    sizeof(struct sns_cmd_pkt));
916 	if (rval != QLA_SUCCESS) {
917 		/*EMPTY*/
918 		ql_dbg(ql_dbg_disc, vha, 0x206d,
919 		    "GID_PT Send SNS failed (%d).\n", rval);
920 	} else if (sns_cmd->p.gid_data[8] != 0x80 ||
921 	    sns_cmd->p.gid_data[9] != 0x02) {
922 		ql_dbg(ql_dbg_disc, vha, 0x202f,
923 		    "GID_PT failed, rejected request, gid_rsp:\n");
924 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2081,
925 		    sns_cmd->p.gid_data, 16);
926 		rval = QLA_FUNCTION_FAILED;
927 	} else {
928 		/* Set port IDs in switch info list. */
929 		for (i = 0; i < ha->max_fibre_devices; i++) {
930 			entry = &sns_cmd->p.gid_data[(i * 4) + 16];
931 			list[i].d_id.b.domain = entry[1];
932 			list[i].d_id.b.area = entry[2];
933 			list[i].d_id.b.al_pa = entry[3];
934 
935 			/* Last one exit. */
936 			if (entry[0] & BIT_7) {
937 				list[i].d_id.b.rsvd_1 = entry[0];
938 				break;
939 			}
940 		}
941 
942 		/*
943 		 * If we've used all available slots, then the switch is
944 		 * reporting back more devices that we can handle with this
945 		 * single call.  Return a failed status, and let GA_NXT handle
946 		 * the overload.
947 		 */
948 		if (i == ha->max_fibre_devices)
949 			rval = QLA_FUNCTION_FAILED;
950 	}
951 
952 	return (rval);
953 }
954 
955 /**
956  * qla2x00_sns_gpn_id() - SNS Get Port Name (GPN_ID) query.
957  * @ha: HA context
958  * @list: switch info entries to populate
959  *
960  * This command uses the old Exectute SNS Command mailbox routine.
961  *
962  * Returns 0 on success.
963  */
964 static int
965 qla2x00_sns_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
966 {
967 	int		rval = QLA_SUCCESS;
968 	struct qla_hw_data *ha = vha->hw;
969 	uint16_t	i;
970 	struct sns_cmd_pkt	*sns_cmd;
971 
972 	for (i = 0; i < ha->max_fibre_devices; i++) {
973 		/* Issue GPN_ID */
974 		/* Prepare SNS command request. */
975 		sns_cmd = qla2x00_prep_sns_cmd(vha, GPN_ID_CMD,
976 		    GPN_ID_SNS_SCMD_LEN, GPN_ID_SNS_DATA_SIZE);
977 
978 		/* Prepare SNS command arguments -- port_id. */
979 		sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
980 		sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
981 		sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
982 
983 		/* Execute SNS command. */
984 		rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,
985 		    GPN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
986 		if (rval != QLA_SUCCESS) {
987 			/*EMPTY*/
988 			ql_dbg(ql_dbg_disc, vha, 0x2032,
989 			    "GPN_ID Send SNS failed (%d).\n", rval);
990 		} else if (sns_cmd->p.gpn_data[8] != 0x80 ||
991 		    sns_cmd->p.gpn_data[9] != 0x02) {
992 			ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207e,
993 			    "GPN_ID failed, rejected request, gpn_rsp:\n");
994 			ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207f,
995 			    sns_cmd->p.gpn_data, 16);
996 			rval = QLA_FUNCTION_FAILED;
997 		} else {
998 			/* Save portname */
999 			memcpy(list[i].port_name, &sns_cmd->p.gpn_data[16],
1000 			    WWN_SIZE);
1001 		}
1002 
1003 		/* Last device exit. */
1004 		if (list[i].d_id.b.rsvd_1 != 0)
1005 			break;
1006 	}
1007 
1008 	return (rval);
1009 }
1010 
1011 /**
1012  * qla2x00_sns_gnn_id() - SNS Get Node Name (GNN_ID) query.
1013  * @ha: HA context
1014  * @list: switch info entries to populate
1015  *
1016  * This command uses the old Exectute SNS Command mailbox routine.
1017  *
1018  * Returns 0 on success.
1019  */
1020 static int
1021 qla2x00_sns_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
1022 {
1023 	int		rval = QLA_SUCCESS;
1024 	struct qla_hw_data *ha = vha->hw;
1025 	uint16_t	i;
1026 	struct sns_cmd_pkt	*sns_cmd;
1027 
1028 	for (i = 0; i < ha->max_fibre_devices; i++) {
1029 		/* Issue GNN_ID */
1030 		/* Prepare SNS command request. */
1031 		sns_cmd = qla2x00_prep_sns_cmd(vha, GNN_ID_CMD,
1032 		    GNN_ID_SNS_SCMD_LEN, GNN_ID_SNS_DATA_SIZE);
1033 
1034 		/* Prepare SNS command arguments -- port_id. */
1035 		sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
1036 		sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
1037 		sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
1038 
1039 		/* Execute SNS command. */
1040 		rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,
1041 		    GNN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
1042 		if (rval != QLA_SUCCESS) {
1043 			/*EMPTY*/
1044 			ql_dbg(ql_dbg_disc, vha, 0x203f,
1045 			    "GNN_ID Send SNS failed (%d).\n", rval);
1046 		} else if (sns_cmd->p.gnn_data[8] != 0x80 ||
1047 		    sns_cmd->p.gnn_data[9] != 0x02) {
1048 			ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2082,
1049 			    "GNN_ID failed, rejected request, gnn_rsp:\n");
1050 			ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207a,
1051 			    sns_cmd->p.gnn_data, 16);
1052 			rval = QLA_FUNCTION_FAILED;
1053 		} else {
1054 			/* Save nodename */
1055 			memcpy(list[i].node_name, &sns_cmd->p.gnn_data[16],
1056 			    WWN_SIZE);
1057 
1058 			ql_dbg(ql_dbg_disc, vha, 0x206e,
1059 			    "GID_PT entry - nn %8phN pn %8phN "
1060 			    "port_id=%02x%02x%02x.\n",
1061 			    list[i].node_name, list[i].port_name,
1062 			    list[i].d_id.b.domain, list[i].d_id.b.area,
1063 			    list[i].d_id.b.al_pa);
1064 		}
1065 
1066 		/* Last device exit. */
1067 		if (list[i].d_id.b.rsvd_1 != 0)
1068 			break;
1069 	}
1070 
1071 	return (rval);
1072 }
1073 
1074 /**
1075  * qla2x00_snd_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
1076  * @ha: HA context
1077  *
1078  * This command uses the old Exectute SNS Command mailbox routine.
1079  *
1080  * Returns 0 on success.
1081  */
1082 static int
1083 qla2x00_sns_rft_id(scsi_qla_host_t *vha)
1084 {
1085 	int		rval;
1086 	struct qla_hw_data *ha = vha->hw;
1087 	struct sns_cmd_pkt	*sns_cmd;
1088 
1089 	/* Issue RFT_ID. */
1090 	/* Prepare SNS command request. */
1091 	sns_cmd = qla2x00_prep_sns_cmd(vha, RFT_ID_CMD, RFT_ID_SNS_SCMD_LEN,
1092 	    RFT_ID_SNS_DATA_SIZE);
1093 
1094 	/* Prepare SNS command arguments -- port_id, FC-4 types */
1095 	sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;
1096 	sns_cmd->p.cmd.param[1] = vha->d_id.b.area;
1097 	sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;
1098 
1099 	sns_cmd->p.cmd.param[5] = 0x01;			/* FCP-3 */
1100 
1101 	/* Execute SNS command. */
1102 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RFT_ID_SNS_CMD_SIZE / 2,
1103 	    sizeof(struct sns_cmd_pkt));
1104 	if (rval != QLA_SUCCESS) {
1105 		/*EMPTY*/
1106 		ql_dbg(ql_dbg_disc, vha, 0x2060,
1107 		    "RFT_ID Send SNS failed (%d).\n", rval);
1108 	} else if (sns_cmd->p.rft_data[8] != 0x80 ||
1109 	    sns_cmd->p.rft_data[9] != 0x02) {
1110 		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2083,
1111 		    "RFT_ID failed, rejected request rft_rsp:\n");
1112 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2080,
1113 		    sns_cmd->p.rft_data, 16);
1114 		rval = QLA_FUNCTION_FAILED;
1115 	} else {
1116 		ql_dbg(ql_dbg_disc, vha, 0x2073,
1117 		    "RFT_ID exiting normally.\n");
1118 	}
1119 
1120 	return (rval);
1121 }
1122 
1123 /**
1124  * qla2x00_sns_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
1125  * HBA.
1126  * @ha: HA context
1127  *
1128  * This command uses the old Exectute SNS Command mailbox routine.
1129  *
1130  * Returns 0 on success.
1131  */
1132 static int
1133 qla2x00_sns_rnn_id(scsi_qla_host_t *vha)
1134 {
1135 	int		rval;
1136 	struct qla_hw_data *ha = vha->hw;
1137 	struct sns_cmd_pkt	*sns_cmd;
1138 
1139 	/* Issue RNN_ID. */
1140 	/* Prepare SNS command request. */
1141 	sns_cmd = qla2x00_prep_sns_cmd(vha, RNN_ID_CMD, RNN_ID_SNS_SCMD_LEN,
1142 	    RNN_ID_SNS_DATA_SIZE);
1143 
1144 	/* Prepare SNS command arguments -- port_id, nodename. */
1145 	sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;
1146 	sns_cmd->p.cmd.param[1] = vha->d_id.b.area;
1147 	sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;
1148 
1149 	sns_cmd->p.cmd.param[4] = vha->node_name[7];
1150 	sns_cmd->p.cmd.param[5] = vha->node_name[6];
1151 	sns_cmd->p.cmd.param[6] = vha->node_name[5];
1152 	sns_cmd->p.cmd.param[7] = vha->node_name[4];
1153 	sns_cmd->p.cmd.param[8] = vha->node_name[3];
1154 	sns_cmd->p.cmd.param[9] = vha->node_name[2];
1155 	sns_cmd->p.cmd.param[10] = vha->node_name[1];
1156 	sns_cmd->p.cmd.param[11] = vha->node_name[0];
1157 
1158 	/* Execute SNS command. */
1159 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RNN_ID_SNS_CMD_SIZE / 2,
1160 	    sizeof(struct sns_cmd_pkt));
1161 	if (rval != QLA_SUCCESS) {
1162 		/*EMPTY*/
1163 		ql_dbg(ql_dbg_disc, vha, 0x204a,
1164 		    "RNN_ID Send SNS failed (%d).\n", rval);
1165 	} else if (sns_cmd->p.rnn_data[8] != 0x80 ||
1166 	    sns_cmd->p.rnn_data[9] != 0x02) {
1167 		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207b,
1168 		    "RNN_ID failed, rejected request, rnn_rsp:\n");
1169 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207c,
1170 		    sns_cmd->p.rnn_data, 16);
1171 		rval = QLA_FUNCTION_FAILED;
1172 	} else {
1173 		ql_dbg(ql_dbg_disc, vha, 0x204c,
1174 		    "RNN_ID exiting normally.\n");
1175 	}
1176 
1177 	return (rval);
1178 }
1179 
1180 /**
1181  * qla2x00_mgmt_svr_login() - Login to fabric Management Service.
1182  * @ha: HA context
1183  *
1184  * Returns 0 on success.
1185  */
1186 int
1187 qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
1188 {
1189 	int ret, rval;
1190 	uint16_t mb[MAILBOX_REGISTER_COUNT];
1191 	struct qla_hw_data *ha = vha->hw;
1192 	ret = QLA_SUCCESS;
1193 	if (vha->flags.management_server_logged_in)
1194 		return ret;
1195 
1196 	rval = ha->isp_ops->fabric_login(vha, vha->mgmt_svr_loop_id, 0xff, 0xff,
1197 	    0xfa, mb, BIT_1);
1198 	if (rval != QLA_SUCCESS || mb[0] != MBS_COMMAND_COMPLETE) {
1199 		if (rval == QLA_MEMORY_ALLOC_FAILED)
1200 			ql_dbg(ql_dbg_disc, vha, 0x2085,
1201 			    "Failed management_server login: loopid=%x "
1202 			    "rval=%d\n", vha->mgmt_svr_loop_id, rval);
1203 		else
1204 			ql_dbg(ql_dbg_disc, vha, 0x2024,
1205 			    "Failed management_server login: loopid=%x "
1206 			    "mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x.\n",
1207 			    vha->mgmt_svr_loop_id, mb[0], mb[1], mb[2], mb[6],
1208 			    mb[7]);
1209 		ret = QLA_FUNCTION_FAILED;
1210 	} else
1211 		vha->flags.management_server_logged_in = 1;
1212 
1213 	return ret;
1214 }
1215 
1216 /**
1217  * qla2x00_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
1218  * @ha: HA context
1219  * @req_size: request size in bytes
1220  * @rsp_size: response size in bytes
1221  *
1222  * Returns a pointer to the @ha's ms_iocb.
1223  */
1224 void *
1225 qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1226     uint32_t rsp_size)
1227 {
1228 	ms_iocb_entry_t *ms_pkt;
1229 	struct qla_hw_data *ha = vha->hw;
1230 	ms_pkt = ha->ms_iocb;
1231 	memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
1232 
1233 	ms_pkt->entry_type = MS_IOCB_TYPE;
1234 	ms_pkt->entry_count = 1;
1235 	SET_TARGET_ID(ha, ms_pkt->loop_id, vha->mgmt_svr_loop_id);
1236 	ms_pkt->control_flags = cpu_to_le16(CF_READ | CF_HEAD_TAG);
1237 	ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1238 	ms_pkt->cmd_dsd_count = cpu_to_le16(1);
1239 	ms_pkt->total_dsd_count = cpu_to_le16(2);
1240 	ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
1241 	ms_pkt->req_bytecount = cpu_to_le32(req_size);
1242 
1243 	ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1244 	ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1245 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
1246 
1247 	ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1248 	ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1249 	ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
1250 
1251 	return ms_pkt;
1252 }
1253 
1254 /**
1255  * qla24xx_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
1256  * @ha: HA context
1257  * @req_size: request size in bytes
1258  * @rsp_size: response size in bytes
1259  *
1260  * Returns a pointer to the @ha's ms_iocb.
1261  */
1262 void *
1263 qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1264     uint32_t rsp_size)
1265 {
1266 	struct ct_entry_24xx *ct_pkt;
1267 	struct qla_hw_data *ha = vha->hw;
1268 
1269 	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1270 	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
1271 
1272 	ct_pkt->entry_type = CT_IOCB_TYPE;
1273 	ct_pkt->entry_count = 1;
1274 	ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);
1275 	ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1276 	ct_pkt->cmd_dsd_count = cpu_to_le16(1);
1277 	ct_pkt->rsp_dsd_count = cpu_to_le16(1);
1278 	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
1279 	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1280 
1281 	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1282 	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1283 	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1284 
1285 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1286 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1287 	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
1288 	ct_pkt->vp_index = vha->vp_idx;
1289 
1290 	return ct_pkt;
1291 }
1292 
1293 static inline ms_iocb_entry_t *
1294 qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size)
1295 {
1296 	struct qla_hw_data *ha = vha->hw;
1297 	ms_iocb_entry_t *ms_pkt = ha->ms_iocb;
1298 	struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1299 
1300 	if (IS_FWI2_CAPABLE(ha)) {
1301 		ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1302 		ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1303 	} else {
1304 		ms_pkt->req_bytecount = cpu_to_le32(req_size);
1305 		ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
1306 	}
1307 
1308 	return ms_pkt;
1309 }
1310 
1311 /**
1312  * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
1313  * @ct_req: CT request buffer
1314  * @cmd: GS command
1315  * @rsp_size: response size in bytes
1316  *
1317  * Returns a pointer to the intitialized @ct_req.
1318  */
1319 static inline struct ct_sns_req *
1320 qla2x00_prep_ct_fdmi_req(struct ct_sns_pkt *p, uint16_t cmd,
1321     uint16_t rsp_size)
1322 {
1323 	memset(p, 0, sizeof(struct ct_sns_pkt));
1324 
1325 	p->p.req.header.revision = 0x01;
1326 	p->p.req.header.gs_type = 0xFA;
1327 	p->p.req.header.gs_subtype = 0x10;
1328 	p->p.req.command = cpu_to_be16(cmd);
1329 	p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
1330 
1331 	return &p->p.req;
1332 }
1333 
1334 /**
1335  * qla2x00_fdmi_rhba() -
1336  * @ha: HA context
1337  *
1338  * Returns 0 on success.
1339  */
1340 static int
1341 qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
1342 {
1343 	int rval, alen;
1344 	uint32_t size, sn;
1345 
1346 	ms_iocb_entry_t *ms_pkt;
1347 	struct ct_sns_req *ct_req;
1348 	struct ct_sns_rsp *ct_rsp;
1349 	void *entries;
1350 	struct ct_fdmi_hba_attr *eiter;
1351 	struct qla_hw_data *ha = vha->hw;
1352 
1353 	/* Issue RHBA */
1354 	/* Prepare common MS IOCB */
1355 	/*   Request size adjusted after CT preparation */
1356 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE);
1357 
1358 	/* Prepare CT request */
1359 	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, RHBA_RSP_SIZE);
1360 	ct_rsp = &ha->ct_sns->p.rsp;
1361 
1362 	/* Prepare FDMI command arguments -- attribute block, attributes. */
1363 	memcpy(ct_req->req.rhba.hba_identifier, vha->port_name, WWN_SIZE);
1364 	ct_req->req.rhba.entry_count = cpu_to_be32(1);
1365 	memcpy(ct_req->req.rhba.port_name, vha->port_name, WWN_SIZE);
1366 	size = 2 * WWN_SIZE + 4 + 4;
1367 
1368 	/* Attributes */
1369 	ct_req->req.rhba.attrs.count =
1370 	    cpu_to_be32(FDMI_HBA_ATTR_COUNT);
1371 	entries = ct_req->req.rhba.hba_identifier;
1372 
1373 	/* Nodename. */
1374 	eiter = entries + size;
1375 	eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME);
1376 	eiter->len = cpu_to_be16(4 + WWN_SIZE);
1377 	memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
1378 	size += 4 + WWN_SIZE;
1379 
1380 	ql_dbg(ql_dbg_disc, vha, 0x2025,
1381 	    "NodeName = %8phN.\n", eiter->a.node_name);
1382 
1383 	/* Manufacturer. */
1384 	eiter = entries + size;
1385 	eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER);
1386 	alen = strlen(QLA2XXX_MANUFACTURER);
1387 	snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer),
1388 	    "%s", "QLogic Corporation");
1389 	alen += 4 - (alen & 3);
1390 	eiter->len = cpu_to_be16(4 + alen);
1391 	size += 4 + alen;
1392 
1393 	ql_dbg(ql_dbg_disc, vha, 0x2026,
1394 	    "Manufacturer = %s.\n", eiter->a.manufacturer);
1395 
1396 	/* Serial number. */
1397 	eiter = entries + size;
1398 	eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
1399 	if (IS_FWI2_CAPABLE(ha))
1400 		qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num,
1401 		    sizeof(eiter->a.serial_num));
1402 	else {
1403 		sn = ((ha->serial0 & 0x1f) << 16) |
1404 			(ha->serial2 << 8) | ha->serial1;
1405 		snprintf(eiter->a.serial_num, sizeof(eiter->a.serial_num),
1406 		    "%c%05d", 'A' + sn / 100000, sn % 100000);
1407 	}
1408 	alen = strlen(eiter->a.serial_num);
1409 	alen += 4 - (alen & 3);
1410 	eiter->len = cpu_to_be16(4 + alen);
1411 	size += 4 + alen;
1412 
1413 	ql_dbg(ql_dbg_disc, vha, 0x2027,
1414 	    "Serial no. = %s.\n", eiter->a.serial_num);
1415 
1416 	/* Model name. */
1417 	eiter = entries + size;
1418 	eiter->type = cpu_to_be16(FDMI_HBA_MODEL);
1419 	snprintf(eiter->a.model, sizeof(eiter->a.model),
1420 	    "%s", ha->model_number);
1421 	alen = strlen(eiter->a.model);
1422 	alen += 4 - (alen & 3);
1423 	eiter->len = cpu_to_be16(4 + alen);
1424 	size += 4 + alen;
1425 
1426 	ql_dbg(ql_dbg_disc, vha, 0x2028,
1427 	    "Model Name = %s.\n", eiter->a.model);
1428 
1429 	/* Model description. */
1430 	eiter = entries + size;
1431 	eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
1432 	snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc),
1433 	    "%s", ha->model_desc);
1434 	alen = strlen(eiter->a.model_desc);
1435 	alen += 4 - (alen & 3);
1436 	eiter->len = cpu_to_be16(4 + alen);
1437 	size += 4 + alen;
1438 
1439 	ql_dbg(ql_dbg_disc, vha, 0x2029,
1440 	    "Model Desc = %s.\n", eiter->a.model_desc);
1441 
1442 	/* Hardware version. */
1443 	eiter = entries + size;
1444 	eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
1445 	if (!IS_FWI2_CAPABLE(ha)) {
1446 		snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
1447 		    "HW:%s", ha->adapter_id);
1448 	} else if (qla2xxx_get_vpd_field(vha, "MN", eiter->a.hw_version,
1449 		    sizeof(eiter->a.hw_version))) {
1450 		;
1451 	} else if (qla2xxx_get_vpd_field(vha, "EC", eiter->a.hw_version,
1452 		    sizeof(eiter->a.hw_version))) {
1453 		;
1454 	} else {
1455 		snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
1456 		    "HW:%s", ha->adapter_id);
1457 	}
1458 	alen = strlen(eiter->a.hw_version);
1459 	alen += 4 - (alen & 3);
1460 	eiter->len = cpu_to_be16(4 + alen);
1461 	size += 4 + alen;
1462 
1463 	ql_dbg(ql_dbg_disc, vha, 0x202a,
1464 	    "Hardware ver = %s.\n", eiter->a.hw_version);
1465 
1466 	/* Driver version. */
1467 	eiter = entries + size;
1468 	eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
1469 	snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version),
1470 	    "%s", qla2x00_version_str);
1471 	alen = strlen(eiter->a.driver_version);
1472 	alen += 4 - (alen & 3);
1473 	eiter->len = cpu_to_be16(4 + alen);
1474 	size += 4 + alen;
1475 
1476 	ql_dbg(ql_dbg_disc, vha, 0x202b,
1477 	    "Driver ver = %s.\n", eiter->a.driver_version);
1478 
1479 	/* Option ROM version. */
1480 	eiter = entries + size;
1481 	eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
1482 	snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version),
1483 	    "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
1484 	alen = strlen(eiter->a.orom_version);
1485 	alen += 4 - (alen & 3);
1486 	eiter->len = cpu_to_be16(4 + alen);
1487 	size += 4 + alen;
1488 
1489 	ql_dbg(ql_dbg_disc, vha , 0x202c,
1490 	    "Optrom vers = %s.\n", eiter->a.orom_version);
1491 
1492 	/* Firmware version */
1493 	eiter = entries + size;
1494 	eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
1495 	ha->isp_ops->fw_version_str(vha, eiter->a.fw_version,
1496 	    sizeof(eiter->a.fw_version));
1497 	alen = strlen(eiter->a.fw_version);
1498 	alen += 4 - (alen & 3);
1499 	eiter->len = cpu_to_be16(4 + alen);
1500 	size += 4 + alen;
1501 
1502 	ql_dbg(ql_dbg_disc, vha, 0x202d,
1503 	    "Firmware vers = %s.\n", eiter->a.fw_version);
1504 
1505 	/* Update MS request size. */
1506 	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
1507 
1508 	ql_dbg(ql_dbg_disc, vha, 0x202e,
1509 	    "RHBA identifier = %8phN size=%d.\n",
1510 	    ct_req->req.rhba.hba_identifier, size);
1511 	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2076,
1512 	    entries, size);
1513 
1514 	/* Execute MS IOCB */
1515 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1516 	    sizeof(ms_iocb_entry_t));
1517 	if (rval != QLA_SUCCESS) {
1518 		/*EMPTY*/
1519 		ql_dbg(ql_dbg_disc, vha, 0x2030,
1520 		    "RHBA issue IOCB failed (%d).\n", rval);
1521 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") !=
1522 	    QLA_SUCCESS) {
1523 		rval = QLA_FUNCTION_FAILED;
1524 		if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
1525 		    ct_rsp->header.explanation_code ==
1526 		    CT_EXPL_ALREADY_REGISTERED) {
1527 			ql_dbg(ql_dbg_disc, vha, 0x2034,
1528 			    "HBA already registered.\n");
1529 			rval = QLA_ALREADY_REGISTERED;
1530 		} else {
1531 			ql_dbg(ql_dbg_disc, vha, 0x20ad,
1532 			    "RHBA FDMI registration failed, CT Reason code: 0x%x, CT Explanation 0x%x\n",
1533 			    ct_rsp->header.reason_code,
1534 			    ct_rsp->header.explanation_code);
1535 		}
1536 	} else {
1537 		ql_dbg(ql_dbg_disc, vha, 0x2035,
1538 		    "RHBA exiting normally.\n");
1539 	}
1540 
1541 	return rval;
1542 }
1543 
1544 /**
1545  * qla2x00_fdmi_rpa() -
1546  * @ha: HA context
1547  *
1548  * Returns 0 on success.
1549  */
1550 static int
1551 qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
1552 {
1553 	int rval, alen;
1554 	uint32_t size;
1555 	struct qla_hw_data *ha = vha->hw;
1556 	ms_iocb_entry_t *ms_pkt;
1557 	struct ct_sns_req *ct_req;
1558 	struct ct_sns_rsp *ct_rsp;
1559 	void *entries;
1560 	struct ct_fdmi_port_attr *eiter;
1561 	struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
1562 	struct new_utsname *p_sysid = NULL;
1563 
1564 	/* Issue RPA */
1565 	/* Prepare common MS IOCB */
1566 	/*   Request size adjusted after CT preparation */
1567 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE);
1568 
1569 	/* Prepare CT request */
1570 	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD,
1571 	    RPA_RSP_SIZE);
1572 	ct_rsp = &ha->ct_sns->p.rsp;
1573 
1574 	/* Prepare FDMI command arguments -- attribute block, attributes. */
1575 	memcpy(ct_req->req.rpa.port_name, vha->port_name, WWN_SIZE);
1576 	size = WWN_SIZE + 4;
1577 
1578 	/* Attributes */
1579 	ct_req->req.rpa.attrs.count = cpu_to_be32(FDMI_PORT_ATTR_COUNT);
1580 	entries = ct_req->req.rpa.port_name;
1581 
1582 	/* FC4 types. */
1583 	eiter = entries + size;
1584 	eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES);
1585 	eiter->len = cpu_to_be16(4 + 32);
1586 	eiter->a.fc4_types[2] = 0x01;
1587 	size += 4 + 32;
1588 
1589 	ql_dbg(ql_dbg_disc, vha, 0x2039,
1590 	    "FC4_TYPES=%02x %02x.\n",
1591 	    eiter->a.fc4_types[2],
1592 	    eiter->a.fc4_types[1]);
1593 
1594 	/* Supported speed. */
1595 	eiter = entries + size;
1596 	eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
1597 	eiter->len = cpu_to_be16(4 + 4);
1598 	if (IS_CNA_CAPABLE(ha))
1599 		eiter->a.sup_speed = cpu_to_be32(
1600 		    FDMI_PORT_SPEED_10GB);
1601 	else if (IS_QLA27XX(ha))
1602 		eiter->a.sup_speed = cpu_to_be32(
1603 		    FDMI_PORT_SPEED_32GB|
1604 		    FDMI_PORT_SPEED_16GB|
1605 		    FDMI_PORT_SPEED_8GB);
1606 	else if (IS_QLA2031(ha))
1607 		eiter->a.sup_speed = cpu_to_be32(
1608 		    FDMI_PORT_SPEED_16GB|
1609 		    FDMI_PORT_SPEED_8GB|
1610 		    FDMI_PORT_SPEED_4GB);
1611 	else if (IS_QLA25XX(ha))
1612 		eiter->a.sup_speed = cpu_to_be32(
1613 		    FDMI_PORT_SPEED_8GB|
1614 		    FDMI_PORT_SPEED_4GB|
1615 		    FDMI_PORT_SPEED_2GB|
1616 		    FDMI_PORT_SPEED_1GB);
1617 	else if (IS_QLA24XX_TYPE(ha))
1618 		eiter->a.sup_speed = cpu_to_be32(
1619 		    FDMI_PORT_SPEED_4GB|
1620 		    FDMI_PORT_SPEED_2GB|
1621 		    FDMI_PORT_SPEED_1GB);
1622 	else if (IS_QLA23XX(ha))
1623 		eiter->a.sup_speed = cpu_to_be32(
1624 		    FDMI_PORT_SPEED_2GB|
1625 		    FDMI_PORT_SPEED_1GB);
1626 	else
1627 		eiter->a.sup_speed = cpu_to_be32(
1628 		    FDMI_PORT_SPEED_1GB);
1629 	size += 4 + 4;
1630 
1631 	ql_dbg(ql_dbg_disc, vha, 0x203a,
1632 	    "Supported_Speed=%x.\n", eiter->a.sup_speed);
1633 
1634 	/* Current speed. */
1635 	eiter = entries + size;
1636 	eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
1637 	eiter->len = cpu_to_be16(4 + 4);
1638 	switch (ha->link_data_rate) {
1639 	case PORT_SPEED_1GB:
1640 		eiter->a.cur_speed =
1641 		    cpu_to_be32(FDMI_PORT_SPEED_1GB);
1642 		break;
1643 	case PORT_SPEED_2GB:
1644 		eiter->a.cur_speed =
1645 		    cpu_to_be32(FDMI_PORT_SPEED_2GB);
1646 		break;
1647 	case PORT_SPEED_4GB:
1648 		eiter->a.cur_speed =
1649 		    cpu_to_be32(FDMI_PORT_SPEED_4GB);
1650 		break;
1651 	case PORT_SPEED_8GB:
1652 		eiter->a.cur_speed =
1653 		    cpu_to_be32(FDMI_PORT_SPEED_8GB);
1654 		break;
1655 	case PORT_SPEED_10GB:
1656 		eiter->a.cur_speed =
1657 		    cpu_to_be32(FDMI_PORT_SPEED_10GB);
1658 		break;
1659 	case PORT_SPEED_16GB:
1660 		eiter->a.cur_speed =
1661 		    cpu_to_be32(FDMI_PORT_SPEED_16GB);
1662 		break;
1663 	case PORT_SPEED_32GB:
1664 		eiter->a.cur_speed =
1665 		    cpu_to_be32(FDMI_PORT_SPEED_32GB);
1666 		break;
1667 	default:
1668 		eiter->a.cur_speed =
1669 		    cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN);
1670 		break;
1671 	}
1672 	size += 4 + 4;
1673 
1674 	ql_dbg(ql_dbg_disc, vha, 0x203b,
1675 	    "Current_Speed=%x.\n", eiter->a.cur_speed);
1676 
1677 	/* Max frame size. */
1678 	eiter = entries + size;
1679 	eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
1680 	eiter->len = cpu_to_be16(4 + 4);
1681 	eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ?
1682 	    le16_to_cpu(icb24->frame_payload_size) :
1683 	    le16_to_cpu(ha->init_cb->frame_payload_size);
1684 	eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size);
1685 	size += 4 + 4;
1686 
1687 	ql_dbg(ql_dbg_disc, vha, 0x203c,
1688 	    "Max_Frame_Size=%x.\n", eiter->a.max_frame_size);
1689 
1690 	/* OS device name. */
1691 	eiter = entries + size;
1692 	eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
1693 	snprintf(eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name),
1694 	    "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no);
1695 	alen = strlen(eiter->a.os_dev_name);
1696 	alen += 4 - (alen & 3);
1697 	eiter->len = cpu_to_be16(4 + alen);
1698 	size += 4 + alen;
1699 
1700 	ql_dbg(ql_dbg_disc, vha, 0x204b,
1701 	    "OS_Device_Name=%s.\n", eiter->a.os_dev_name);
1702 
1703 	/* Hostname. */
1704 	eiter = entries + size;
1705 	eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME);
1706 	p_sysid = utsname();
1707 	if (p_sysid) {
1708 		snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
1709 		    "%s", p_sysid->nodename);
1710 	} else {
1711 		snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
1712 		    "%s", fc_host_system_hostname(vha->host));
1713 	}
1714 	alen = strlen(eiter->a.host_name);
1715 	alen += 4 - (alen & 3);
1716 	eiter->len = cpu_to_be16(4 + alen);
1717 	size += 4 + alen;
1718 
1719 	ql_dbg(ql_dbg_disc, vha, 0x203d, "HostName=%s.\n", eiter->a.host_name);
1720 
1721 	/* Update MS request size. */
1722 	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
1723 
1724 	ql_dbg(ql_dbg_disc, vha, 0x203e,
1725 	    "RPA portname  %016llx, size = %d.\n",
1726 	    wwn_to_u64(ct_req->req.rpa.port_name), size);
1727 	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2079,
1728 	    entries, size);
1729 
1730 	/* Execute MS IOCB */
1731 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1732 	    sizeof(ms_iocb_entry_t));
1733 	if (rval != QLA_SUCCESS) {
1734 		/*EMPTY*/
1735 		ql_dbg(ql_dbg_disc, vha, 0x2040,
1736 		    "RPA issue IOCB failed (%d).\n", rval);
1737 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") !=
1738 	    QLA_SUCCESS) {
1739 		rval = QLA_FUNCTION_FAILED;
1740 		if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
1741 		    ct_rsp->header.explanation_code ==
1742 		    CT_EXPL_ALREADY_REGISTERED) {
1743 			ql_dbg(ql_dbg_disc, vha, 0x20cd,
1744 			    "RPA already registered.\n");
1745 			rval = QLA_ALREADY_REGISTERED;
1746 		}
1747 
1748 	} else {
1749 		ql_dbg(ql_dbg_disc, vha, 0x2041,
1750 		    "RPA exiting normally.\n");
1751 	}
1752 
1753 	return rval;
1754 }
1755 
1756 /**
1757  * qla2x00_fdmiv2_rhba() -
1758  * @ha: HA context
1759  *
1760  * Returns 0 on success.
1761  */
1762 static int
1763 qla2x00_fdmiv2_rhba(scsi_qla_host_t *vha)
1764 {
1765 	int rval, alen;
1766 	uint32_t size, sn;
1767 	ms_iocb_entry_t *ms_pkt;
1768 	struct ct_sns_req *ct_req;
1769 	struct ct_sns_rsp *ct_rsp;
1770 	void *entries;
1771 	struct ct_fdmiv2_hba_attr *eiter;
1772 	struct qla_hw_data *ha = vha->hw;
1773 	struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
1774 	struct new_utsname *p_sysid = NULL;
1775 
1776 	/* Issue RHBA */
1777 	/* Prepare common MS IOCB */
1778 	/*   Request size adjusted after CT preparation */
1779 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE);
1780 
1781 	/* Prepare CT request */
1782 	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD,
1783 	    RHBA_RSP_SIZE);
1784 	ct_rsp = &ha->ct_sns->p.rsp;
1785 
1786 	/* Prepare FDMI command arguments -- attribute block, attributes. */
1787 	memcpy(ct_req->req.rhba2.hba_identifier, vha->port_name, WWN_SIZE);
1788 	ct_req->req.rhba2.entry_count = cpu_to_be32(1);
1789 	memcpy(ct_req->req.rhba2.port_name, vha->port_name, WWN_SIZE);
1790 	size = 2 * WWN_SIZE + 4 + 4;
1791 
1792 	/* Attributes */
1793 	ct_req->req.rhba2.attrs.count = cpu_to_be32(FDMIV2_HBA_ATTR_COUNT);
1794 	entries = ct_req->req.rhba2.hba_identifier;
1795 
1796 	/* Nodename. */
1797 	eiter = entries + size;
1798 	eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME);
1799 	eiter->len = cpu_to_be16(4 + WWN_SIZE);
1800 	memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
1801 	size += 4 + WWN_SIZE;
1802 
1803 	ql_dbg(ql_dbg_disc, vha, 0x207d,
1804 	    "NodeName = %016llx.\n", wwn_to_u64(eiter->a.node_name));
1805 
1806 	/* Manufacturer. */
1807 	eiter = entries + size;
1808 	eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER);
1809 	snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer),
1810 	    "%s", "QLogic Corporation");
1811 	eiter->a.manufacturer[strlen("QLogic Corporation")] = '\0';
1812 	alen = strlen(eiter->a.manufacturer);
1813 	alen += 4 - (alen & 3);
1814 	eiter->len = cpu_to_be16(4 + alen);
1815 	size += 4 + alen;
1816 
1817 	ql_dbg(ql_dbg_disc, vha, 0x20a5,
1818 	    "Manufacturer = %s.\n", eiter->a.manufacturer);
1819 
1820 	/* Serial number. */
1821 	eiter = entries + size;
1822 	eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
1823 	if (IS_FWI2_CAPABLE(ha))
1824 		qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num,
1825 		    sizeof(eiter->a.serial_num));
1826 	else {
1827 		sn = ((ha->serial0 & 0x1f) << 16) |
1828 			(ha->serial2 << 8) | ha->serial1;
1829 		snprintf(eiter->a.serial_num, sizeof(eiter->a.serial_num),
1830 		    "%c%05d", 'A' + sn / 100000, sn % 100000);
1831 	}
1832 	alen = strlen(eiter->a.serial_num);
1833 	alen += 4 - (alen & 3);
1834 	eiter->len = cpu_to_be16(4 + alen);
1835 	size += 4 + alen;
1836 
1837 	ql_dbg(ql_dbg_disc, vha, 0x20a6,
1838 	    "Serial no. = %s.\n", eiter->a.serial_num);
1839 
1840 	/* Model name. */
1841 	eiter = entries + size;
1842 	eiter->type = cpu_to_be16(FDMI_HBA_MODEL);
1843 	snprintf(eiter->a.model, sizeof(eiter->a.model),
1844 	    "%s", ha->model_number);
1845 	alen = strlen(eiter->a.model);
1846 	alen += 4 - (alen & 3);
1847 	eiter->len = cpu_to_be16(4 + alen);
1848 	size += 4 + alen;
1849 
1850 	ql_dbg(ql_dbg_disc, vha, 0x20a7,
1851 	    "Model Name = %s.\n", eiter->a.model);
1852 
1853 	/* Model description. */
1854 	eiter = entries + size;
1855 	eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
1856 	snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc),
1857 	    "%s", ha->model_desc);
1858 	alen = strlen(eiter->a.model_desc);
1859 	alen += 4 - (alen & 3);
1860 	eiter->len = cpu_to_be16(4 + alen);
1861 	size += 4 + alen;
1862 
1863 	ql_dbg(ql_dbg_disc, vha, 0x20a8,
1864 	    "Model Desc = %s.\n", eiter->a.model_desc);
1865 
1866 	/* Hardware version. */
1867 	eiter = entries + size;
1868 	eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
1869 	if (!IS_FWI2_CAPABLE(ha)) {
1870 		snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
1871 		    "HW:%s", ha->adapter_id);
1872 	} else if (qla2xxx_get_vpd_field(vha, "MN", eiter->a.hw_version,
1873 		    sizeof(eiter->a.hw_version))) {
1874 		;
1875 	} else if (qla2xxx_get_vpd_field(vha, "EC", eiter->a.hw_version,
1876 		    sizeof(eiter->a.hw_version))) {
1877 		;
1878 	} else {
1879 		snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
1880 		    "HW:%s", ha->adapter_id);
1881 	}
1882 	alen = strlen(eiter->a.hw_version);
1883 	alen += 4 - (alen & 3);
1884 	eiter->len = cpu_to_be16(4 + alen);
1885 	size += 4 + alen;
1886 
1887 	ql_dbg(ql_dbg_disc, vha, 0x20a9,
1888 	    "Hardware ver = %s.\n", eiter->a.hw_version);
1889 
1890 	/* Driver version. */
1891 	eiter = entries + size;
1892 	eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
1893 	snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version),
1894 	    "%s", qla2x00_version_str);
1895 	alen = strlen(eiter->a.driver_version);
1896 	alen += 4 - (alen & 3);
1897 	eiter->len = cpu_to_be16(4 + alen);
1898 	size += 4 + alen;
1899 
1900 	ql_dbg(ql_dbg_disc, vha, 0x20aa,
1901 	    "Driver ver = %s.\n", eiter->a.driver_version);
1902 
1903 	/* Option ROM version. */
1904 	eiter = entries + size;
1905 	eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
1906 	snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version),
1907 	    "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
1908 	alen = strlen(eiter->a.orom_version);
1909 	alen += 4 - (alen & 3);
1910 	eiter->len = cpu_to_be16(4 + alen);
1911 	size += 4 + alen;
1912 
1913 	ql_dbg(ql_dbg_disc, vha , 0x20ab,
1914 	    "Optrom version = %d.%02d.\n", eiter->a.orom_version[1],
1915 	    eiter->a.orom_version[0]);
1916 
1917 	/* Firmware version */
1918 	eiter = entries + size;
1919 	eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
1920 	ha->isp_ops->fw_version_str(vha, eiter->a.fw_version,
1921 	    sizeof(eiter->a.fw_version));
1922 	alen = strlen(eiter->a.fw_version);
1923 	alen += 4 - (alen & 3);
1924 	eiter->len = cpu_to_be16(4 + alen);
1925 	size += 4 + alen;
1926 
1927 	ql_dbg(ql_dbg_disc, vha, 0x20ac,
1928 	    "Firmware vers = %s.\n", eiter->a.fw_version);
1929 
1930 	/* OS Name and Version */
1931 	eiter = entries + size;
1932 	eiter->type = cpu_to_be16(FDMI_HBA_OS_NAME_AND_VERSION);
1933 	p_sysid = utsname();
1934 	if (p_sysid) {
1935 		snprintf(eiter->a.os_version, sizeof(eiter->a.os_version),
1936 		    "%s %s %s",
1937 		    p_sysid->sysname, p_sysid->release, p_sysid->version);
1938 	} else {
1939 		snprintf(eiter->a.os_version, sizeof(eiter->a.os_version),
1940 		    "%s %s", "Linux", fc_host_system_hostname(vha->host));
1941 	}
1942 	alen = strlen(eiter->a.os_version);
1943 	alen += 4 - (alen & 3);
1944 	eiter->len = cpu_to_be16(4 + alen);
1945 	size += 4 + alen;
1946 
1947 	ql_dbg(ql_dbg_disc, vha, 0x20ae,
1948 	    "OS Name and Version = %s.\n", eiter->a.os_version);
1949 
1950 	/* MAX CT Payload Length */
1951 	eiter = entries + size;
1952 	eiter->type = cpu_to_be16(FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH);
1953 	eiter->a.max_ct_len = IS_FWI2_CAPABLE(ha) ?
1954 	    le16_to_cpu(icb24->frame_payload_size) :
1955 	    le16_to_cpu(ha->init_cb->frame_payload_size);
1956 	eiter->a.max_ct_len = cpu_to_be32(eiter->a.max_ct_len);
1957 	eiter->len = cpu_to_be16(4 + 4);
1958 	size += 4 + 4;
1959 
1960 	ql_dbg(ql_dbg_disc, vha, 0x20af,
1961 	    "CT Payload Length = 0x%x.\n", eiter->a.max_ct_len);
1962 
1963 	/* Node Sybolic Name */
1964 	eiter = entries + size;
1965 	eiter->type = cpu_to_be16(FDMI_HBA_NODE_SYMBOLIC_NAME);
1966 	qla2x00_get_sym_node_name(vha, eiter->a.sym_name,
1967 	    sizeof(eiter->a.sym_name));
1968 	alen = strlen(eiter->a.sym_name);
1969 	alen += 4 - (alen & 3);
1970 	eiter->len = cpu_to_be16(4 + alen);
1971 	size += 4 + alen;
1972 
1973 	ql_dbg(ql_dbg_disc, vha, 0x20b0,
1974 	    "Symbolic Name = %s.\n", eiter->a.sym_name);
1975 
1976 	/* Vendor Id */
1977 	eiter = entries + size;
1978 	eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_ID);
1979 	eiter->a.vendor_id = cpu_to_be32(0x1077);
1980 	eiter->len = cpu_to_be16(4 + 4);
1981 	size += 4 + 4;
1982 
1983 	ql_dbg(ql_dbg_disc, vha, 0x20b1,
1984 	    "Vendor Id = %x.\n", eiter->a.vendor_id);
1985 
1986 	/* Num Ports */
1987 	eiter = entries + size;
1988 	eiter->type = cpu_to_be16(FDMI_HBA_NUM_PORTS);
1989 	eiter->a.num_ports = cpu_to_be32(1);
1990 	eiter->len = cpu_to_be16(4 + 4);
1991 	size += 4 + 4;
1992 
1993 	ql_dbg(ql_dbg_disc, vha, 0x20b2,
1994 	    "Port Num = %x.\n", eiter->a.num_ports);
1995 
1996 	/* Fabric Name */
1997 	eiter = entries + size;
1998 	eiter->type = cpu_to_be16(FDMI_HBA_FABRIC_NAME);
1999 	memcpy(eiter->a.fabric_name, vha->fabric_node_name, WWN_SIZE);
2000 	eiter->len = cpu_to_be16(4 + WWN_SIZE);
2001 	size += 4 + WWN_SIZE;
2002 
2003 	ql_dbg(ql_dbg_disc, vha, 0x20b3,
2004 	    "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name));
2005 
2006 	/* BIOS Version */
2007 	eiter = entries + size;
2008 	eiter->type = cpu_to_be16(FDMI_HBA_BOOT_BIOS_NAME);
2009 	snprintf(eiter->a.bios_name, sizeof(eiter->a.bios_name),
2010 	    "BIOS %d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
2011 	alen = strlen(eiter->a.bios_name);
2012 	alen += 4 - (alen & 3);
2013 	eiter->len = cpu_to_be16(4 + alen);
2014 	size += 4 + alen;
2015 
2016 	ql_dbg(ql_dbg_disc, vha, 0x20b4,
2017 	    "BIOS Name = %s\n", eiter->a.bios_name);
2018 
2019 	/* Vendor Identifier */
2020 	eiter = entries + size;
2021 	eiter->type = cpu_to_be16(FDMI_HBA_TYPE_VENDOR_IDENTIFIER);
2022 	snprintf(eiter->a.vendor_identifier, sizeof(eiter->a.vendor_identifier),
2023 	    "%s", "QLGC");
2024 	alen = strlen(eiter->a.vendor_identifier);
2025 	alen += 4 - (alen & 3);
2026 	eiter->len = cpu_to_be16(4 + alen);
2027 	size += 4 + alen;
2028 
2029 	ql_dbg(ql_dbg_disc, vha, 0x201b,
2030 	    "Vendor Identifier = %s.\n", eiter->a.vendor_identifier);
2031 
2032 	/* Update MS request size. */
2033 	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
2034 
2035 	ql_dbg(ql_dbg_disc, vha, 0x20b5,
2036 	    "RHBA identifier = %016llx.\n",
2037 	    wwn_to_u64(ct_req->req.rhba2.hba_identifier));
2038 	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20b6,
2039 	    entries, size);
2040 
2041 	/* Execute MS IOCB */
2042 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2043 	    sizeof(ms_iocb_entry_t));
2044 	if (rval != QLA_SUCCESS) {
2045 		/*EMPTY*/
2046 		ql_dbg(ql_dbg_disc, vha, 0x20b7,
2047 		    "RHBA issue IOCB failed (%d).\n", rval);
2048 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") !=
2049 	    QLA_SUCCESS) {
2050 		rval = QLA_FUNCTION_FAILED;
2051 
2052 		if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
2053 		    ct_rsp->header.explanation_code ==
2054 		    CT_EXPL_ALREADY_REGISTERED) {
2055 			ql_dbg(ql_dbg_disc, vha, 0x20b8,
2056 			    "HBA already registered.\n");
2057 			rval = QLA_ALREADY_REGISTERED;
2058 		} else {
2059 			ql_dbg(ql_dbg_disc, vha, 0x2016,
2060 			    "RHBA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x\n",
2061 			    ct_rsp->header.reason_code,
2062 			    ct_rsp->header.explanation_code);
2063 		}
2064 	} else {
2065 		ql_dbg(ql_dbg_disc, vha, 0x20b9,
2066 		    "RHBA FDMI V2 exiting normally.\n");
2067 	}
2068 
2069 	return rval;
2070 }
2071 
2072 /**
2073  * qla2x00_fdmi_dhba() -
2074  * @ha: HA context
2075  *
2076  * Returns 0 on success.
2077  */
2078 static int
2079 qla2x00_fdmi_dhba(scsi_qla_host_t *vha)
2080 {
2081 	int rval;
2082 	struct qla_hw_data *ha = vha->hw;
2083 	ms_iocb_entry_t *ms_pkt;
2084 	struct ct_sns_req *ct_req;
2085 	struct ct_sns_rsp *ct_rsp;
2086 
2087 	/* Issue RPA */
2088 	/* Prepare common MS IOCB */
2089 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, DHBA_REQ_SIZE,
2090 	    DHBA_RSP_SIZE);
2091 
2092 	/* Prepare CT request */
2093 	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, DHBA_CMD, DHBA_RSP_SIZE);
2094 	ct_rsp = &ha->ct_sns->p.rsp;
2095 
2096 	/* Prepare FDMI command arguments -- portname. */
2097 	memcpy(ct_req->req.dhba.port_name, vha->port_name, WWN_SIZE);
2098 
2099 	ql_dbg(ql_dbg_disc, vha, 0x2036,
2100 	    "DHBA portname = %8phN.\n", ct_req->req.dhba.port_name);
2101 
2102 	/* Execute MS IOCB */
2103 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2104 	    sizeof(ms_iocb_entry_t));
2105 	if (rval != QLA_SUCCESS) {
2106 		/*EMPTY*/
2107 		ql_dbg(ql_dbg_disc, vha, 0x2037,
2108 		    "DHBA issue IOCB failed (%d).\n", rval);
2109 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "DHBA") !=
2110 	    QLA_SUCCESS) {
2111 		rval = QLA_FUNCTION_FAILED;
2112 	} else {
2113 		ql_dbg(ql_dbg_disc, vha, 0x2038,
2114 		    "DHBA exiting normally.\n");
2115 	}
2116 
2117 	return rval;
2118 }
2119 
2120 /**
2121  * qla2x00_fdmiv2_rpa() -
2122  * @ha: HA context
2123  *
2124  * Returns 0 on success.
2125  */
2126 static int
2127 qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha)
2128 {
2129 	int rval, alen;
2130 	uint32_t size;
2131 	struct qla_hw_data *ha = vha->hw;
2132 	ms_iocb_entry_t *ms_pkt;
2133 	struct ct_sns_req *ct_req;
2134 	struct ct_sns_rsp *ct_rsp;
2135 	void *entries;
2136 	struct ct_fdmiv2_port_attr *eiter;
2137 	struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
2138 	struct new_utsname *p_sysid = NULL;
2139 
2140 	/* Issue RPA */
2141 	/* Prepare common MS IOCB */
2142 	/*   Request size adjusted after CT preparation */
2143 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE);
2144 
2145 	/* Prepare CT request */
2146 	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, RPA_RSP_SIZE);
2147 	ct_rsp = &ha->ct_sns->p.rsp;
2148 
2149 	/* Prepare FDMI command arguments -- attribute block, attributes. */
2150 	memcpy(ct_req->req.rpa2.port_name, vha->port_name, WWN_SIZE);
2151 	size = WWN_SIZE + 4;
2152 
2153 	/* Attributes */
2154 	ct_req->req.rpa2.attrs.count = cpu_to_be32(FDMIV2_PORT_ATTR_COUNT);
2155 	entries = ct_req->req.rpa2.port_name;
2156 
2157 	/* FC4 types. */
2158 	eiter = entries + size;
2159 	eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES);
2160 	eiter->len = cpu_to_be16(4 + 32);
2161 	eiter->a.fc4_types[2] = 0x01;
2162 	size += 4 + 32;
2163 
2164 	ql_dbg(ql_dbg_disc, vha, 0x20ba,
2165 	    "FC4_TYPES=%02x %02x.\n",
2166 	    eiter->a.fc4_types[2],
2167 	    eiter->a.fc4_types[1]);
2168 
2169 	if (vha->flags.nvme_enabled) {
2170 		eiter->a.fc4_types[6] = 1;	/* NVMe type 28h */
2171 		ql_dbg(ql_dbg_disc, vha, 0x211f,
2172 		    "NVME FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n",
2173 		    eiter->a.fc4_types[6]);
2174 	}
2175 
2176 	/* Supported speed. */
2177 	eiter = entries + size;
2178 	eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
2179 	eiter->len = cpu_to_be16(4 + 4);
2180 	if (IS_CNA_CAPABLE(ha))
2181 		eiter->a.sup_speed = cpu_to_be32(
2182 		    FDMI_PORT_SPEED_10GB);
2183 	else if (IS_QLA27XX(ha))
2184 		eiter->a.sup_speed = cpu_to_be32(
2185 		    FDMI_PORT_SPEED_32GB|
2186 		    FDMI_PORT_SPEED_16GB|
2187 		    FDMI_PORT_SPEED_8GB);
2188 	else if (IS_QLA2031(ha))
2189 		eiter->a.sup_speed = cpu_to_be32(
2190 		    FDMI_PORT_SPEED_16GB|
2191 		    FDMI_PORT_SPEED_8GB|
2192 		    FDMI_PORT_SPEED_4GB);
2193 	else if (IS_QLA25XX(ha))
2194 		eiter->a.sup_speed = cpu_to_be32(
2195 		    FDMI_PORT_SPEED_8GB|
2196 		    FDMI_PORT_SPEED_4GB|
2197 		    FDMI_PORT_SPEED_2GB|
2198 		    FDMI_PORT_SPEED_1GB);
2199 	else if (IS_QLA24XX_TYPE(ha))
2200 		eiter->a.sup_speed = cpu_to_be32(
2201 		    FDMI_PORT_SPEED_4GB|
2202 		    FDMI_PORT_SPEED_2GB|
2203 		    FDMI_PORT_SPEED_1GB);
2204 	else if (IS_QLA23XX(ha))
2205 		eiter->a.sup_speed = cpu_to_be32(
2206 		    FDMI_PORT_SPEED_2GB|
2207 		    FDMI_PORT_SPEED_1GB);
2208 	else
2209 		eiter->a.sup_speed = cpu_to_be32(
2210 		    FDMI_PORT_SPEED_1GB);
2211 	size += 4 + 4;
2212 
2213 	ql_dbg(ql_dbg_disc, vha, 0x20bb,
2214 	    "Supported Port Speed = %x.\n", eiter->a.sup_speed);
2215 
2216 	/* Current speed. */
2217 	eiter = entries + size;
2218 	eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
2219 	eiter->len = cpu_to_be16(4 + 4);
2220 	switch (ha->link_data_rate) {
2221 	case PORT_SPEED_1GB:
2222 		eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_1GB);
2223 		break;
2224 	case PORT_SPEED_2GB:
2225 		eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_2GB);
2226 		break;
2227 	case PORT_SPEED_4GB:
2228 		eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_4GB);
2229 		break;
2230 	case PORT_SPEED_8GB:
2231 		eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_8GB);
2232 		break;
2233 	case PORT_SPEED_10GB:
2234 		eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_10GB);
2235 		break;
2236 	case PORT_SPEED_16GB:
2237 		eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_16GB);
2238 		break;
2239 	case PORT_SPEED_32GB:
2240 		eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_32GB);
2241 		break;
2242 	default:
2243 		eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN);
2244 		break;
2245 	}
2246 	size += 4 + 4;
2247 
2248 	ql_dbg(ql_dbg_disc, vha, 0x2017,
2249 	    "Current_Speed = %x.\n", eiter->a.cur_speed);
2250 
2251 	/* Max frame size. */
2252 	eiter = entries + size;
2253 	eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
2254 	eiter->len = cpu_to_be16(4 + 4);
2255 	eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ?
2256 	    le16_to_cpu(icb24->frame_payload_size):
2257 	    le16_to_cpu(ha->init_cb->frame_payload_size);
2258 	eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size);
2259 	size += 4 + 4;
2260 
2261 	ql_dbg(ql_dbg_disc, vha, 0x20bc,
2262 	    "Max_Frame_Size = %x.\n", eiter->a.max_frame_size);
2263 
2264 	/* OS device name. */
2265 	eiter = entries + size;
2266 	eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
2267 	alen = strlen(QLA2XXX_DRIVER_NAME);
2268 	snprintf(eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name),
2269 	    "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no);
2270 	alen += 4 - (alen & 3);
2271 	eiter->len = cpu_to_be16(4 + alen);
2272 	size += 4 + alen;
2273 
2274 	ql_dbg(ql_dbg_disc, vha, 0x20be,
2275 	    "OS_Device_Name = %s.\n", eiter->a.os_dev_name);
2276 
2277 	/* Hostname. */
2278 	eiter = entries + size;
2279 	eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME);
2280 	p_sysid = utsname();
2281 	if (p_sysid) {
2282 		snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
2283 		    "%s", p_sysid->nodename);
2284 	} else {
2285 		snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
2286 		    "%s", fc_host_system_hostname(vha->host));
2287 	}
2288 	alen = strlen(eiter->a.host_name);
2289 	alen += 4 - (alen & 3);
2290 	eiter->len = cpu_to_be16(4 + alen);
2291 	size += 4 + alen;
2292 
2293 	ql_dbg(ql_dbg_disc, vha, 0x201a,
2294 	    "HostName=%s.\n", eiter->a.host_name);
2295 
2296 	/* Node Name */
2297 	eiter = entries + size;
2298 	eiter->type = cpu_to_be16(FDMI_PORT_NODE_NAME);
2299 	memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
2300 	eiter->len = cpu_to_be16(4 + WWN_SIZE);
2301 	size += 4 + WWN_SIZE;
2302 
2303 	ql_dbg(ql_dbg_disc, vha, 0x20c0,
2304 	    "Node Name = %016llx.\n", wwn_to_u64(eiter->a.node_name));
2305 
2306 	/* Port Name */
2307 	eiter = entries + size;
2308 	eiter->type = cpu_to_be16(FDMI_PORT_NAME);
2309 	memcpy(eiter->a.port_name, vha->port_name, WWN_SIZE);
2310 	eiter->len = cpu_to_be16(4 + WWN_SIZE);
2311 	size += 4 + WWN_SIZE;
2312 
2313 	ql_dbg(ql_dbg_disc, vha, 0x20c1,
2314 	    "Port Name = %016llx.\n", wwn_to_u64(eiter->a.port_name));
2315 
2316 	/* Port Symbolic Name */
2317 	eiter = entries + size;
2318 	eiter->type = cpu_to_be16(FDMI_PORT_SYM_NAME);
2319 	qla2x00_get_sym_node_name(vha, eiter->a.port_sym_name,
2320 	    sizeof(eiter->a.port_sym_name));
2321 	alen = strlen(eiter->a.port_sym_name);
2322 	alen += 4 - (alen & 3);
2323 	eiter->len = cpu_to_be16(4 + alen);
2324 	size += 4 + alen;
2325 
2326 	ql_dbg(ql_dbg_disc, vha, 0x20c2,
2327 	    "port symbolic name = %s\n", eiter->a.port_sym_name);
2328 
2329 	/* Port Type */
2330 	eiter = entries + size;
2331 	eiter->type = cpu_to_be16(FDMI_PORT_TYPE);
2332 	eiter->a.port_type = cpu_to_be32(NS_NX_PORT_TYPE);
2333 	eiter->len = cpu_to_be16(4 + 4);
2334 	size += 4 + 4;
2335 
2336 	ql_dbg(ql_dbg_disc, vha, 0x20c3,
2337 	    "Port Type = %x.\n", eiter->a.port_type);
2338 
2339 	/* Class of Service  */
2340 	eiter = entries + size;
2341 	eiter->type = cpu_to_be16(FDMI_PORT_SUPP_COS);
2342 	eiter->a.port_supported_cos = cpu_to_be32(FC_CLASS_3);
2343 	eiter->len = cpu_to_be16(4 + 4);
2344 	size += 4 + 4;
2345 
2346 	ql_dbg(ql_dbg_disc, vha, 0x20c4,
2347 	    "Supported COS = %08x\n", eiter->a.port_supported_cos);
2348 
2349 	/* Port Fabric Name */
2350 	eiter = entries + size;
2351 	eiter->type = cpu_to_be16(FDMI_PORT_FABRIC_NAME);
2352 	memcpy(eiter->a.fabric_name, vha->fabric_node_name, WWN_SIZE);
2353 	eiter->len = cpu_to_be16(4 + WWN_SIZE);
2354 	size += 4 + WWN_SIZE;
2355 
2356 	ql_dbg(ql_dbg_disc, vha, 0x20c5,
2357 	    "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name));
2358 
2359 	/* FC4_type */
2360 	eiter = entries + size;
2361 	eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPE);
2362 	eiter->a.port_fc4_type[0] = 0;
2363 	eiter->a.port_fc4_type[1] = 0;
2364 	eiter->a.port_fc4_type[2] = 1;
2365 	eiter->a.port_fc4_type[3] = 0;
2366 	eiter->len = cpu_to_be16(4 + 32);
2367 	size += 4 + 32;
2368 
2369 	ql_dbg(ql_dbg_disc, vha, 0x20c6,
2370 	    "Port Active FC4 Type = %02x %02x.\n",
2371 	    eiter->a.port_fc4_type[2], eiter->a.port_fc4_type[1]);
2372 
2373 	if (vha->flags.nvme_enabled) {
2374 		eiter->a.port_fc4_type[4] = 0;
2375 		eiter->a.port_fc4_type[5] = 0;
2376 		eiter->a.port_fc4_type[6] = 1;	/* NVMe type 28h */
2377 		ql_dbg(ql_dbg_disc, vha, 0x2120,
2378 		    "NVME Port Active FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n",
2379 		    eiter->a.port_fc4_type[6]);
2380 	}
2381 
2382 	/* Port State */
2383 	eiter = entries + size;
2384 	eiter->type = cpu_to_be16(FDMI_PORT_STATE);
2385 	eiter->a.port_state = cpu_to_be32(1);
2386 	eiter->len = cpu_to_be16(4 + 4);
2387 	size += 4 + 4;
2388 
2389 	ql_dbg(ql_dbg_disc, vha, 0x20c7,
2390 	    "Port State = %x.\n", eiter->a.port_state);
2391 
2392 	/* Number of Ports */
2393 	eiter = entries + size;
2394 	eiter->type = cpu_to_be16(FDMI_PORT_COUNT);
2395 	eiter->a.num_ports = cpu_to_be32(1);
2396 	eiter->len = cpu_to_be16(4 + 4);
2397 	size += 4 + 4;
2398 
2399 	ql_dbg(ql_dbg_disc, vha, 0x20c8,
2400 	    "Number of ports = %x.\n", eiter->a.num_ports);
2401 
2402 	/* Port Id */
2403 	eiter = entries + size;
2404 	eiter->type = cpu_to_be16(FDMI_PORT_ID);
2405 	eiter->a.port_id = cpu_to_be32(vha->d_id.b24);
2406 	eiter->len = cpu_to_be16(4 + 4);
2407 	size += 4 + 4;
2408 
2409 	ql_dbg(ql_dbg_disc, vha, 0x201c,
2410 	    "Port Id = %x.\n", eiter->a.port_id);
2411 
2412 	/* Update MS request size. */
2413 	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
2414 
2415 	ql_dbg(ql_dbg_disc, vha, 0x2018,
2416 	    "RPA portname= %8phN size=%d.\n", ct_req->req.rpa.port_name, size);
2417 	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20ca,
2418 	    entries, size);
2419 
2420 	/* Execute MS IOCB */
2421 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2422 	    sizeof(ms_iocb_entry_t));
2423 	if (rval != QLA_SUCCESS) {
2424 		/*EMPTY*/
2425 		ql_dbg(ql_dbg_disc, vha, 0x20cb,
2426 		    "RPA FDMI v2 issue IOCB failed (%d).\n", rval);
2427 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") !=
2428 	    QLA_SUCCESS) {
2429 		rval = QLA_FUNCTION_FAILED;
2430 		if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
2431 		    ct_rsp->header.explanation_code ==
2432 		    CT_EXPL_ALREADY_REGISTERED) {
2433 			ql_dbg(ql_dbg_disc, vha, 0x20ce,
2434 			    "RPA FDMI v2 already registered\n");
2435 			rval = QLA_ALREADY_REGISTERED;
2436 		} else {
2437 			ql_dbg(ql_dbg_disc, vha, 0x2020,
2438 			    "RPA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x\n",
2439 			    ct_rsp->header.reason_code,
2440 			    ct_rsp->header.explanation_code);
2441 		}
2442 	} else {
2443 		ql_dbg(ql_dbg_disc, vha, 0x20cc,
2444 		    "RPA FDMI V2 exiting normally.\n");
2445 	}
2446 
2447 	return rval;
2448 }
2449 
2450 /**
2451  * qla2x00_fdmi_register() -
2452  * @ha: HA context
2453  *
2454  * Returns 0 on success.
2455  */
2456 int
2457 qla2x00_fdmi_register(scsi_qla_host_t *vha)
2458 {
2459 	int rval = QLA_FUNCTION_FAILED;
2460 	struct qla_hw_data *ha = vha->hw;
2461 
2462 	if (IS_QLA2100(ha) || IS_QLA2200(ha) ||
2463 	    IS_QLAFX00(ha))
2464 		return QLA_FUNCTION_FAILED;
2465 
2466 	rval = qla2x00_mgmt_svr_login(vha);
2467 	if (rval)
2468 		return rval;
2469 
2470 	rval = qla2x00_fdmiv2_rhba(vha);
2471 	if (rval) {
2472 		if (rval != QLA_ALREADY_REGISTERED)
2473 			goto try_fdmi;
2474 
2475 		rval = qla2x00_fdmi_dhba(vha);
2476 		if (rval)
2477 			goto try_fdmi;
2478 
2479 		rval = qla2x00_fdmiv2_rhba(vha);
2480 		if (rval)
2481 			goto try_fdmi;
2482 	}
2483 	rval = qla2x00_fdmiv2_rpa(vha);
2484 	if (rval)
2485 		goto try_fdmi;
2486 
2487 	goto out;
2488 
2489 try_fdmi:
2490 	rval = qla2x00_fdmi_rhba(vha);
2491 	if (rval) {
2492 		if (rval != QLA_ALREADY_REGISTERED)
2493 			return rval;
2494 
2495 		rval = qla2x00_fdmi_dhba(vha);
2496 		if (rval)
2497 			return rval;
2498 
2499 		rval = qla2x00_fdmi_rhba(vha);
2500 		if (rval)
2501 			return rval;
2502 	}
2503 	rval = qla2x00_fdmi_rpa(vha);
2504 out:
2505 	return rval;
2506 }
2507 
2508 /**
2509  * qla2x00_gfpn_id() - SNS Get Fabric Port Name (GFPN_ID) query.
2510  * @ha: HA context
2511  * @list: switch info entries to populate
2512  *
2513  * Returns 0 on success.
2514  */
2515 int
2516 qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)
2517 {
2518 	int		rval = QLA_SUCCESS;
2519 	uint16_t	i;
2520 	struct qla_hw_data *ha = vha->hw;
2521 	ms_iocb_entry_t	*ms_pkt;
2522 	struct ct_sns_req	*ct_req;
2523 	struct ct_sns_rsp	*ct_rsp;
2524 	struct ct_arg arg;
2525 
2526 	if (!IS_IIDMA_CAPABLE(ha))
2527 		return QLA_FUNCTION_FAILED;
2528 
2529 	arg.iocb = ha->ms_iocb;
2530 	arg.req_dma = ha->ct_sns_dma;
2531 	arg.rsp_dma = ha->ct_sns_dma;
2532 	arg.req_size = GFPN_ID_REQ_SIZE;
2533 	arg.rsp_size = GFPN_ID_RSP_SIZE;
2534 	arg.nport_handle = NPH_SNS;
2535 
2536 	for (i = 0; i < ha->max_fibre_devices; i++) {
2537 		/* Issue GFPN_ID */
2538 		/* Prepare common MS IOCB */
2539 		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
2540 
2541 		/* Prepare CT request */
2542 		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFPN_ID_CMD,
2543 		    GFPN_ID_RSP_SIZE);
2544 		ct_rsp = &ha->ct_sns->p.rsp;
2545 
2546 		/* Prepare CT arguments -- port_id */
2547 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
2548 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
2549 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
2550 
2551 		/* Execute MS IOCB */
2552 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2553 		    sizeof(ms_iocb_entry_t));
2554 		if (rval != QLA_SUCCESS) {
2555 			/*EMPTY*/
2556 			ql_dbg(ql_dbg_disc, vha, 0x2023,
2557 			    "GFPN_ID issue IOCB failed (%d).\n", rval);
2558 			break;
2559 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
2560 		    "GFPN_ID") != QLA_SUCCESS) {
2561 			rval = QLA_FUNCTION_FAILED;
2562 			break;
2563 		} else {
2564 			/* Save fabric portname */
2565 			memcpy(list[i].fabric_port_name,
2566 			    ct_rsp->rsp.gfpn_id.port_name, WWN_SIZE);
2567 		}
2568 
2569 		/* Last device exit. */
2570 		if (list[i].d_id.b.rsvd_1 != 0)
2571 			break;
2572 	}
2573 
2574 	return (rval);
2575 }
2576 
2577 
2578 static inline struct ct_sns_req *
2579 qla24xx_prep_ct_fm_req(struct ct_sns_pkt *p, uint16_t cmd,
2580     uint16_t rsp_size)
2581 {
2582 	memset(p, 0, sizeof(struct ct_sns_pkt));
2583 
2584 	p->p.req.header.revision = 0x01;
2585 	p->p.req.header.gs_type = 0xFA;
2586 	p->p.req.header.gs_subtype = 0x01;
2587 	p->p.req.command = cpu_to_be16(cmd);
2588 	p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
2589 
2590 	return &p->p.req;
2591 }
2592 
2593 /**
2594  * qla2x00_gpsc() - FCS Get Port Speed Capabilities (GPSC) query.
2595  * @ha: HA context
2596  * @list: switch info entries to populate
2597  *
2598  * Returns 0 on success.
2599  */
2600 int
2601 qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
2602 {
2603 	int		rval;
2604 	uint16_t	i;
2605 	struct qla_hw_data *ha = vha->hw;
2606 	ms_iocb_entry_t *ms_pkt;
2607 	struct ct_sns_req	*ct_req;
2608 	struct ct_sns_rsp	*ct_rsp;
2609 	struct ct_arg arg;
2610 
2611 	if (!IS_IIDMA_CAPABLE(ha))
2612 		return QLA_FUNCTION_FAILED;
2613 	if (!ha->flags.gpsc_supported)
2614 		return QLA_FUNCTION_FAILED;
2615 
2616 	rval = qla2x00_mgmt_svr_login(vha);
2617 	if (rval)
2618 		return rval;
2619 
2620 	arg.iocb = ha->ms_iocb;
2621 	arg.req_dma = ha->ct_sns_dma;
2622 	arg.rsp_dma = ha->ct_sns_dma;
2623 	arg.req_size = GPSC_REQ_SIZE;
2624 	arg.rsp_size = GPSC_RSP_SIZE;
2625 	arg.nport_handle = vha->mgmt_svr_loop_id;
2626 
2627 	for (i = 0; i < ha->max_fibre_devices; i++) {
2628 		/* Issue GFPN_ID */
2629 		/* Prepare common MS IOCB */
2630 		ms_pkt = qla24xx_prep_ms_iocb(vha, &arg);
2631 
2632 		/* Prepare CT request */
2633 		ct_req = qla24xx_prep_ct_fm_req(ha->ct_sns, GPSC_CMD,
2634 		    GPSC_RSP_SIZE);
2635 		ct_rsp = &ha->ct_sns->p.rsp;
2636 
2637 		/* Prepare CT arguments -- port_name */
2638 		memcpy(ct_req->req.gpsc.port_name, list[i].fabric_port_name,
2639 		    WWN_SIZE);
2640 
2641 		/* Execute MS IOCB */
2642 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2643 		    sizeof(ms_iocb_entry_t));
2644 		if (rval != QLA_SUCCESS) {
2645 			/*EMPTY*/
2646 			ql_dbg(ql_dbg_disc, vha, 0x2059,
2647 			    "GPSC issue IOCB failed (%d).\n", rval);
2648 		} else if ((rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
2649 		    "GPSC")) != QLA_SUCCESS) {
2650 			/* FM command unsupported? */
2651 			if (rval == QLA_INVALID_COMMAND &&
2652 			    (ct_rsp->header.reason_code ==
2653 				CT_REASON_INVALID_COMMAND_CODE ||
2654 			     ct_rsp->header.reason_code ==
2655 				CT_REASON_COMMAND_UNSUPPORTED)) {
2656 				ql_dbg(ql_dbg_disc, vha, 0x205a,
2657 				    "GPSC command unsupported, disabling "
2658 				    "query.\n");
2659 				ha->flags.gpsc_supported = 0;
2660 				rval = QLA_FUNCTION_FAILED;
2661 				break;
2662 			}
2663 			rval = QLA_FUNCTION_FAILED;
2664 		} else {
2665 			/* Save port-speed */
2666 			switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) {
2667 			case BIT_15:
2668 				list[i].fp_speed = PORT_SPEED_1GB;
2669 				break;
2670 			case BIT_14:
2671 				list[i].fp_speed = PORT_SPEED_2GB;
2672 				break;
2673 			case BIT_13:
2674 				list[i].fp_speed = PORT_SPEED_4GB;
2675 				break;
2676 			case BIT_12:
2677 				list[i].fp_speed = PORT_SPEED_10GB;
2678 				break;
2679 			case BIT_11:
2680 				list[i].fp_speed = PORT_SPEED_8GB;
2681 				break;
2682 			case BIT_10:
2683 				list[i].fp_speed = PORT_SPEED_16GB;
2684 				break;
2685 			case BIT_8:
2686 				list[i].fp_speed = PORT_SPEED_32GB;
2687 				break;
2688 			}
2689 
2690 			ql_dbg(ql_dbg_disc, vha, 0x205b,
2691 			    "GPSC ext entry - fpn "
2692 			    "%8phN speeds=%04x speed=%04x.\n",
2693 			    list[i].fabric_port_name,
2694 			    be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
2695 			    be16_to_cpu(ct_rsp->rsp.gpsc.speed));
2696 		}
2697 
2698 		/* Last device exit. */
2699 		if (list[i].d_id.b.rsvd_1 != 0)
2700 			break;
2701 	}
2702 
2703 	return (rval);
2704 }
2705 
2706 /**
2707  * qla2x00_gff_id() - SNS Get FC-4 Features (GFF_ID) query.
2708  *
2709  * @ha: HA context
2710  * @list: switch info entries to populate
2711  *
2712  */
2713 void
2714 qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
2715 {
2716 	int		rval;
2717 	uint16_t	i;
2718 
2719 	ms_iocb_entry_t	*ms_pkt;
2720 	struct ct_sns_req	*ct_req;
2721 	struct ct_sns_rsp	*ct_rsp;
2722 	struct qla_hw_data *ha = vha->hw;
2723 	uint8_t fcp_scsi_features = 0;
2724 	struct ct_arg arg;
2725 
2726 	for (i = 0; i < ha->max_fibre_devices; i++) {
2727 		/* Set default FC4 Type as UNKNOWN so the default is to
2728 		 * Process this port */
2729 		list[i].fc4_type = FC4_TYPE_UNKNOWN;
2730 
2731 		/* Do not attempt GFF_ID if we are not FWI_2 capable */
2732 		if (!IS_FWI2_CAPABLE(ha))
2733 			continue;
2734 
2735 		arg.iocb = ha->ms_iocb;
2736 		arg.req_dma = ha->ct_sns_dma;
2737 		arg.rsp_dma = ha->ct_sns_dma;
2738 		arg.req_size = GFF_ID_REQ_SIZE;
2739 		arg.rsp_size = GFF_ID_RSP_SIZE;
2740 		arg.nport_handle = NPH_SNS;
2741 
2742 		/* Prepare common MS IOCB */
2743 		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
2744 
2745 		/* Prepare CT request */
2746 		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFF_ID_CMD,
2747 		    GFF_ID_RSP_SIZE);
2748 		ct_rsp = &ha->ct_sns->p.rsp;
2749 
2750 		/* Prepare CT arguments -- port_id */
2751 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
2752 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
2753 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
2754 
2755 		/* Execute MS IOCB */
2756 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2757 		   sizeof(ms_iocb_entry_t));
2758 
2759 		if (rval != QLA_SUCCESS) {
2760 			ql_dbg(ql_dbg_disc, vha, 0x205c,
2761 			    "GFF_ID issue IOCB failed (%d).\n", rval);
2762 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
2763 			       "GFF_ID") != QLA_SUCCESS) {
2764 			ql_dbg(ql_dbg_disc, vha, 0x205d,
2765 			    "GFF_ID IOCB status had a failure status code.\n");
2766 		} else {
2767 			fcp_scsi_features =
2768 			   ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
2769 			fcp_scsi_features &= 0x0f;
2770 
2771 			if (fcp_scsi_features)
2772 				list[i].fc4_type = FC4_TYPE_FCP_SCSI;
2773 			else
2774 				list[i].fc4_type = FC4_TYPE_OTHER;
2775 
2776 			list[i].fc4f_nvme =
2777 			    ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];
2778 			list[i].fc4f_nvme &= 0xf;
2779 		}
2780 
2781 		/* Last device exit. */
2782 		if (list[i].d_id.b.rsvd_1 != 0)
2783 			break;
2784 	}
2785 }
2786 
2787 /* GID_PN completion processing. */
2788 void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
2789 {
2790 	fc_port_t *fcport = ea->fcport;
2791 
2792 	ql_dbg(ql_dbg_disc, vha, 0x201d,
2793 	    "%s %8phC login state %d\n",
2794 	    __func__, fcport->port_name, fcport->fw_login_state);
2795 
2796 	if (ea->sp->gen2 != fcport->login_gen) {
2797 		/* PLOGI/PRLI/LOGO came in while cmd was out.*/
2798 		ql_dbg(ql_dbg_disc, vha, 0x201e,
2799 		    "%s %8phC generation changed rscn %d|%d login %d|%d \n",
2800 		    __func__, fcport->port_name, fcport->last_rscn_gen,
2801 		    fcport->rscn_gen, fcport->last_login_gen, fcport->login_gen);
2802 		return;
2803 	}
2804 
2805 	if (!ea->rc) {
2806 		if (ea->sp->gen1 == fcport->rscn_gen) {
2807 			fcport->scan_state = QLA_FCPORT_FOUND;
2808 			fcport->flags |= FCF_FABRIC_DEVICE;
2809 
2810 			if (fcport->d_id.b24 == ea->id.b24) {
2811 				/* cable plugged into the same place */
2812 				switch (vha->host->active_mode) {
2813 				case MODE_TARGET:
2814 					/* NOOP. let the other guy login to us.*/
2815 					break;
2816 				case MODE_INITIATOR:
2817 				case MODE_DUAL:
2818 				default:
2819 					ql_dbg(ql_dbg_disc, vha, 0x201f,
2820 					    "%s %d %8phC post %s\n", __func__,
2821 					    __LINE__, fcport->port_name,
2822 					    (atomic_read(&fcport->state) ==
2823 					    FCS_ONLINE) ? "gpdb" : "gnl");
2824 
2825 					if (atomic_read(&fcport->state) ==
2826 					    FCS_ONLINE)
2827 						qla24xx_post_gpdb_work(vha,
2828 						    fcport, PDO_FORCE_ADISC);
2829 					else
2830 						qla24xx_post_gnl_work(vha,
2831 						    fcport);
2832 					break;
2833 				}
2834 			} else { /* fcport->d_id.b24 != ea->id.b24 */
2835 				fcport->d_id.b24 = ea->id.b24;
2836 				if (fcport->deleted == QLA_SESS_DELETED) {
2837 					ql_dbg(ql_dbg_disc, vha, 0x2021,
2838 					    "%s %d %8phC post del sess\n",
2839 					    __func__, __LINE__, fcport->port_name);
2840 					qlt_schedule_sess_for_deletion_lock(fcport);
2841 				}
2842 			}
2843 		} else { /* ea->sp->gen1 != fcport->rscn_gen */
2844 			ql_dbg(ql_dbg_disc, vha, 0x2022,
2845 			    "%s %d %8phC post gidpn\n",
2846 			    __func__, __LINE__, fcport->port_name);
2847 			/* rscn came in while cmd was out */
2848 			qla24xx_post_gidpn_work(vha, fcport);
2849 		}
2850 	} else { /* ea->rc */
2851 		/* cable pulled */
2852 		if (ea->sp->gen1 == fcport->rscn_gen) {
2853 			if (ea->sp->gen2 == fcport->login_gen) {
2854 				ql_dbg(ql_dbg_disc, vha, 0x2042,
2855 				    "%s %d %8phC post del sess\n", __func__,
2856 				    __LINE__, fcport->port_name);
2857 				qlt_schedule_sess_for_deletion_lock(fcport);
2858 			} else {
2859 				ql_dbg(ql_dbg_disc, vha, 0x2045,
2860 				    "%s %d %8phC login\n", __func__, __LINE__,
2861 				    fcport->port_name);
2862 				qla24xx_fcport_handle_login(vha, fcport);
2863 			}
2864 		} else {
2865 			ql_dbg(ql_dbg_disc, vha, 0x2049,
2866 			    "%s %d %8phC post gidpn\n", __func__, __LINE__,
2867 			    fcport->port_name);
2868 			qla24xx_post_gidpn_work(vha, fcport);
2869 		}
2870 	}
2871 } /* gidpn_event */
2872 
2873 static void qla2x00_async_gidpn_sp_done(void *s, int res)
2874 {
2875 	struct srb *sp = s;
2876 	struct scsi_qla_host *vha = sp->vha;
2877 	fc_port_t *fcport = sp->fcport;
2878 	u8 *id = fcport->ct_desc.ct_sns->p.rsp.rsp.gid_pn.port_id;
2879 	struct event_arg ea;
2880 
2881 	fcport->flags &= ~FCF_ASYNC_SENT;
2882 
2883 	memset(&ea, 0, sizeof(ea));
2884 	ea.fcport = fcport;
2885 	ea.id.b.domain = id[0];
2886 	ea.id.b.area = id[1];
2887 	ea.id.b.al_pa = id[2];
2888 	ea.sp = sp;
2889 	ea.rc = res;
2890 	ea.event = FCME_GIDPN_DONE;
2891 
2892 	ql_dbg(ql_dbg_disc, vha, 0x204f,
2893 	    "Async done-%s res %x, WWPN %8phC ID %3phC \n",
2894 	    sp->name, res, fcport->port_name, id);
2895 
2896 	qla2x00_fcport_event_handler(vha, &ea);
2897 
2898 	sp->free(sp);
2899 }
2900 
2901 int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t *fcport)
2902 {
2903 	int rval = QLA_FUNCTION_FAILED;
2904 	struct ct_sns_req       *ct_req;
2905 	srb_t *sp;
2906 
2907 	if (!vha->flags.online)
2908 		goto done;
2909 
2910 	fcport->flags |= FCF_ASYNC_SENT;
2911 	fcport->disc_state = DSC_GID_PN;
2912 	fcport->scan_state = QLA_FCPORT_SCAN;
2913 	sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
2914 	if (!sp)
2915 		goto done;
2916 
2917 	sp->type = SRB_CT_PTHRU_CMD;
2918 	sp->name = "gidpn";
2919 	sp->gen1 = fcport->rscn_gen;
2920 	sp->gen2 = fcport->login_gen;
2921 
2922 	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
2923 
2924 	/* CT_IU preamble  */
2925 	ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GID_PN_CMD,
2926 		GID_PN_RSP_SIZE);
2927 
2928 	/* GIDPN req */
2929 	memcpy(ct_req->req.gid_pn.port_name, fcport->port_name,
2930 		WWN_SIZE);
2931 
2932 	/* req & rsp use the same buffer */
2933 	sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
2934 	sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
2935 	sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
2936 	sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
2937 	sp->u.iocb_cmd.u.ctarg.req_size = GID_PN_REQ_SIZE;
2938 	sp->u.iocb_cmd.u.ctarg.rsp_size = GID_PN_RSP_SIZE;
2939 	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
2940 
2941 	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
2942 	sp->done = qla2x00_async_gidpn_sp_done;
2943 
2944 	rval = qla2x00_start_sp(sp);
2945 	if (rval != QLA_SUCCESS)
2946 		goto done_free_sp;
2947 
2948 	ql_dbg(ql_dbg_disc, vha, 0x20a4,
2949 	    "Async-%s - %8phC hdl=%x loopid=%x portid %02x%02x%02x.\n",
2950 	    sp->name, fcport->port_name,
2951 	    sp->handle, fcport->loop_id, fcport->d_id.b.domain,
2952 	    fcport->d_id.b.area, fcport->d_id.b.al_pa);
2953 	return rval;
2954 
2955 done_free_sp:
2956 	sp->free(sp);
2957 done:
2958 	fcport->flags &= ~FCF_ASYNC_SENT;
2959 	return rval;
2960 }
2961 
2962 int qla24xx_post_gidpn_work(struct scsi_qla_host *vha, fc_port_t *fcport)
2963 {
2964 	struct qla_work_evt *e;
2965 	int ls;
2966 
2967 	ls = atomic_read(&vha->loop_state);
2968 	if (((ls != LOOP_READY) && (ls != LOOP_UP)) ||
2969 		test_bit(UNLOADING, &vha->dpc_flags))
2970 		return 0;
2971 
2972 	e = qla2x00_alloc_work(vha, QLA_EVT_GIDPN);
2973 	if (!e)
2974 		return QLA_FUNCTION_FAILED;
2975 
2976 	e->u.fcport.fcport = fcport;
2977 	return qla2x00_post_work(vha, e);
2978 }
2979 
2980 int qla24xx_post_gpsc_work(struct scsi_qla_host *vha, fc_port_t *fcport)
2981 {
2982 	struct qla_work_evt *e;
2983 
2984 	e = qla2x00_alloc_work(vha, QLA_EVT_GPSC);
2985 	if (!e)
2986 		return QLA_FUNCTION_FAILED;
2987 
2988 	e->u.fcport.fcport = fcport;
2989 	return qla2x00_post_work(vha, e);
2990 }
2991 
2992 static void qla24xx_async_gpsc_sp_done(void *s, int res)
2993 {
2994 	struct srb *sp = s;
2995 	struct scsi_qla_host *vha = sp->vha;
2996 	struct qla_hw_data *ha = vha->hw;
2997 	fc_port_t *fcport = sp->fcport;
2998 	struct ct_sns_rsp       *ct_rsp;
2999 	struct event_arg ea;
3000 
3001 	ct_rsp = &fcport->ct_desc.ct_sns->p.rsp;
3002 
3003 	ql_dbg(ql_dbg_disc, vha, 0x2053,
3004 	    "Async done-%s res %x, WWPN %8phC \n",
3005 	    sp->name, res, fcport->port_name);
3006 
3007 	fcport->flags &= ~FCF_ASYNC_SENT;
3008 
3009 	if (res == (DID_ERROR << 16)) {
3010 		/* entry status error */
3011 		goto done;
3012 	} else if (res) {
3013 		if ((ct_rsp->header.reason_code ==
3014 			 CT_REASON_INVALID_COMMAND_CODE) ||
3015 			(ct_rsp->header.reason_code ==
3016 			CT_REASON_COMMAND_UNSUPPORTED)) {
3017 			ql_dbg(ql_dbg_disc, vha, 0x2019,
3018 			    "GPSC command unsupported, disabling query.\n");
3019 			ha->flags.gpsc_supported = 0;
3020 			res = QLA_SUCCESS;
3021 		}
3022 	} else {
3023 		switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) {
3024 		case BIT_15:
3025 			fcport->fp_speed = PORT_SPEED_1GB;
3026 			break;
3027 		case BIT_14:
3028 			fcport->fp_speed = PORT_SPEED_2GB;
3029 			break;
3030 		case BIT_13:
3031 			fcport->fp_speed = PORT_SPEED_4GB;
3032 			break;
3033 		case BIT_12:
3034 			fcport->fp_speed = PORT_SPEED_10GB;
3035 			break;
3036 		case BIT_11:
3037 			fcport->fp_speed = PORT_SPEED_8GB;
3038 			break;
3039 		case BIT_10:
3040 			fcport->fp_speed = PORT_SPEED_16GB;
3041 			break;
3042 		case BIT_8:
3043 			fcport->fp_speed = PORT_SPEED_32GB;
3044 			break;
3045 		}
3046 
3047 		ql_dbg(ql_dbg_disc, vha, 0x2054,
3048 		    "Async-%s OUT WWPN %8phC speeds=%04x speed=%04x.\n",
3049 		    sp->name, fcport->fabric_port_name,
3050 		    be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
3051 		    be16_to_cpu(ct_rsp->rsp.gpsc.speed));
3052 	}
3053 done:
3054 	memset(&ea, 0, sizeof(ea));
3055 	ea.event = FCME_GPSC_DONE;
3056 	ea.rc = res;
3057 	ea.fcport = fcport;
3058 	qla2x00_fcport_event_handler(vha, &ea);
3059 
3060 	sp->free(sp);
3061 }
3062 
3063 int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
3064 {
3065 	int rval = QLA_FUNCTION_FAILED;
3066 	struct ct_sns_req       *ct_req;
3067 	srb_t *sp;
3068 
3069 	if (!vha->flags.online)
3070 		goto done;
3071 
3072 	fcport->flags |= FCF_ASYNC_SENT;
3073 	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
3074 	if (!sp)
3075 		goto done;
3076 
3077 	sp->type = SRB_CT_PTHRU_CMD;
3078 	sp->name = "gpsc";
3079 	sp->gen1 = fcport->rscn_gen;
3080 	sp->gen2 = fcport->login_gen;
3081 
3082 	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
3083 
3084 	/* CT_IU preamble  */
3085 	ct_req = qla24xx_prep_ct_fm_req(fcport->ct_desc.ct_sns, GPSC_CMD,
3086 		GPSC_RSP_SIZE);
3087 
3088 	/* GPSC req */
3089 	memcpy(ct_req->req.gpsc.port_name, fcport->fabric_port_name,
3090 		WWN_SIZE);
3091 
3092 	sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
3093 	sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
3094 	sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
3095 	sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
3096 	sp->u.iocb_cmd.u.ctarg.req_size = GPSC_REQ_SIZE;
3097 	sp->u.iocb_cmd.u.ctarg.rsp_size = GPSC_RSP_SIZE;
3098 	sp->u.iocb_cmd.u.ctarg.nport_handle = vha->mgmt_svr_loop_id;
3099 
3100 	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
3101 	sp->done = qla24xx_async_gpsc_sp_done;
3102 
3103 	rval = qla2x00_start_sp(sp);
3104 	if (rval != QLA_SUCCESS)
3105 		goto done_free_sp;
3106 
3107 	ql_dbg(ql_dbg_disc, vha, 0x205e,
3108 	    "Async-%s %8phC hdl=%x loopid=%x portid=%02x%02x%02x.\n",
3109 	    sp->name, fcport->port_name, sp->handle,
3110 	    fcport->loop_id, fcport->d_id.b.domain,
3111 	    fcport->d_id.b.area, fcport->d_id.b.al_pa);
3112 	return rval;
3113 
3114 done_free_sp:
3115 	sp->free(sp);
3116 done:
3117 	fcport->flags &= ~FCF_ASYNC_SENT;
3118 	return rval;
3119 }
3120 
3121 int qla24xx_post_gpnid_work(struct scsi_qla_host *vha, port_id_t *id)
3122 {
3123 	struct qla_work_evt *e;
3124 
3125 	if (test_bit(UNLOADING, &vha->dpc_flags))
3126 		return 0;
3127 
3128 	e = qla2x00_alloc_work(vha, QLA_EVT_GPNID);
3129 	if (!e)
3130 		return QLA_FUNCTION_FAILED;
3131 
3132 	e->u.gpnid.id = *id;
3133 	return qla2x00_post_work(vha, e);
3134 }
3135 
3136 void qla24xx_async_gpnid_done(scsi_qla_host_t *vha, srb_t *sp)
3137 {
3138 	if (sp->u.iocb_cmd.u.ctarg.req) {
3139 		dma_free_coherent(&vha->hw->pdev->dev,
3140 			sizeof(struct ct_sns_pkt),
3141 			sp->u.iocb_cmd.u.ctarg.req,
3142 			sp->u.iocb_cmd.u.ctarg.req_dma);
3143 		sp->u.iocb_cmd.u.ctarg.req = NULL;
3144 	}
3145 	if (sp->u.iocb_cmd.u.ctarg.rsp) {
3146 		dma_free_coherent(&vha->hw->pdev->dev,
3147 			sizeof(struct ct_sns_pkt),
3148 			sp->u.iocb_cmd.u.ctarg.rsp,
3149 			sp->u.iocb_cmd.u.ctarg.rsp_dma);
3150 		sp->u.iocb_cmd.u.ctarg.rsp = NULL;
3151 	}
3152 
3153 	sp->free(sp);
3154 }
3155 
3156 void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
3157 {
3158 	fc_port_t *fcport;
3159 	unsigned long flags;
3160 
3161 	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
3162 	fcport = qla2x00_find_fcport_by_wwpn(vha, ea->port_name, 1);
3163 	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
3164 
3165 	if (fcport) {
3166 		/* cable moved. just plugged in */
3167 		fcport->rscn_gen++;
3168 		fcport->d_id = ea->id;
3169 		fcport->scan_state = QLA_FCPORT_FOUND;
3170 		fcport->flags |= FCF_FABRIC_DEVICE;
3171 
3172 		switch (fcport->disc_state) {
3173 		case DSC_DELETED:
3174 			ql_dbg(ql_dbg_disc, vha, 0x210d,
3175 			    "%s %d %8phC login\n", __func__, __LINE__,
3176 			    fcport->port_name);
3177 			qla24xx_fcport_handle_login(vha, fcport);
3178 			break;
3179 		case DSC_DELETE_PEND:
3180 			break;
3181 		default:
3182 			ql_dbg(ql_dbg_disc, vha, 0x2064,
3183 			    "%s %d %8phC post del sess\n",
3184 			    __func__, __LINE__, fcport->port_name);
3185 			qlt_schedule_sess_for_deletion_lock(fcport);
3186 			break;
3187 		}
3188 	} else {
3189 		/* create new fcport */
3190 		ql_dbg(ql_dbg_disc, vha, 0x2065,
3191 		    "%s %d %8phC post new sess\n",
3192 		    __func__, __LINE__, ea->port_name);
3193 
3194 		qla24xx_post_newsess_work(vha, &ea->id, ea->port_name, NULL);
3195 	}
3196 }
3197 
3198 static void qla2x00_async_gpnid_sp_done(void *s, int res)
3199 {
3200 	struct srb *sp = s;
3201 	struct scsi_qla_host *vha = sp->vha;
3202 	struct ct_sns_req *ct_req =
3203 	    (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
3204 	struct ct_sns_rsp *ct_rsp =
3205 	    (struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp;
3206 	struct event_arg ea;
3207 	struct qla_work_evt *e;
3208 
3209 	ql_dbg(ql_dbg_disc, vha, 0x2066,
3210 	    "Async done-%s res %x ID %3phC. %8phC\n",
3211 	    sp->name, res, ct_req->req.port_id.port_id,
3212 	    ct_rsp->rsp.gpn_id.port_name);
3213 
3214 	memset(&ea, 0, sizeof(ea));
3215 	memcpy(ea.port_name, ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);
3216 	ea.sp = sp;
3217 	ea.id.b.domain = ct_req->req.port_id.port_id[0];
3218 	ea.id.b.area = ct_req->req.port_id.port_id[1];
3219 	ea.id.b.al_pa = ct_req->req.port_id.port_id[2];
3220 	ea.rc = res;
3221 	ea.event = FCME_GPNID_DONE;
3222 
3223 	qla2x00_fcport_event_handler(vha, &ea);
3224 
3225 	e = qla2x00_alloc_work(vha, QLA_EVT_GPNID_DONE);
3226 	if (!e) {
3227 		/* please ignore kernel warning. otherwise, we have mem leak. */
3228 		if (sp->u.iocb_cmd.u.ctarg.req) {
3229 			dma_free_coherent(&vha->hw->pdev->dev,
3230 				sizeof(struct ct_sns_pkt),
3231 				sp->u.iocb_cmd.u.ctarg.req,
3232 				sp->u.iocb_cmd.u.ctarg.req_dma);
3233 			sp->u.iocb_cmd.u.ctarg.req = NULL;
3234 		}
3235 		if (sp->u.iocb_cmd.u.ctarg.rsp) {
3236 			dma_free_coherent(&vha->hw->pdev->dev,
3237 				sizeof(struct ct_sns_pkt),
3238 				sp->u.iocb_cmd.u.ctarg.rsp,
3239 				sp->u.iocb_cmd.u.ctarg.rsp_dma);
3240 			sp->u.iocb_cmd.u.ctarg.rsp = NULL;
3241 		}
3242 
3243 		sp->free(sp);
3244 		return;
3245 	}
3246 
3247 	e->u.iosb.sp = sp;
3248 	qla2x00_post_work(vha, e);
3249 }
3250 
3251 /* Get WWPN with Nport ID. */
3252 int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
3253 {
3254 	int rval = QLA_FUNCTION_FAILED;
3255 	struct ct_sns_req       *ct_req;
3256 	srb_t *sp;
3257 	struct ct_sns_pkt *ct_sns;
3258 
3259 	if (!vha->flags.online)
3260 		goto done;
3261 
3262 	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
3263 	if (!sp)
3264 		goto done;
3265 
3266 	sp->type = SRB_CT_PTHRU_CMD;
3267 	sp->name = "gpnid";
3268 	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
3269 
3270 	sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
3271 		sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
3272 		GFP_KERNEL);
3273 	if (!sp->u.iocb_cmd.u.ctarg.req) {
3274 		ql_log(ql_log_warn, vha, 0xd041,
3275 		    "Failed to allocate ct_sns request.\n");
3276 		goto done_free_sp;
3277 	}
3278 
3279 	sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
3280 		sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
3281 		GFP_KERNEL);
3282 	if (!sp->u.iocb_cmd.u.ctarg.rsp) {
3283 		ql_log(ql_log_warn, vha, 0xd042,
3284 		    "Failed to allocate ct_sns request.\n");
3285 		goto done_free_sp;
3286 	}
3287 
3288 	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
3289 	memset(ct_sns, 0, sizeof(*ct_sns));
3290 
3291 	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
3292 	/* CT_IU preamble  */
3293 	ct_req = qla2x00_prep_ct_req(ct_sns, GPN_ID_CMD, GPN_ID_RSP_SIZE);
3294 
3295 	/* GPN_ID req */
3296 	ct_req->req.port_id.port_id[0] = id->b.domain;
3297 	ct_req->req.port_id.port_id[1] = id->b.area;
3298 	ct_req->req.port_id.port_id[2] = id->b.al_pa;
3299 
3300 	sp->u.iocb_cmd.u.ctarg.req_size = GPN_ID_REQ_SIZE;
3301 	sp->u.iocb_cmd.u.ctarg.rsp_size = GPN_ID_RSP_SIZE;
3302 	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
3303 
3304 	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
3305 	sp->done = qla2x00_async_gpnid_sp_done;
3306 
3307 	rval = qla2x00_start_sp(sp);
3308 	if (rval != QLA_SUCCESS)
3309 		goto done_free_sp;
3310 
3311 	ql_dbg(ql_dbg_disc, vha, 0x2067,
3312 	    "Async-%s hdl=%x ID %3phC.\n", sp->name,
3313 	    sp->handle, ct_req->req.port_id.port_id);
3314 	return rval;
3315 
3316 done_free_sp:
3317 	if (sp->u.iocb_cmd.u.ctarg.req) {
3318 		dma_free_coherent(&vha->hw->pdev->dev,
3319 			sizeof(struct ct_sns_pkt),
3320 			sp->u.iocb_cmd.u.ctarg.req,
3321 			sp->u.iocb_cmd.u.ctarg.req_dma);
3322 		sp->u.iocb_cmd.u.ctarg.req = NULL;
3323 	}
3324 	if (sp->u.iocb_cmd.u.ctarg.rsp) {
3325 		dma_free_coherent(&vha->hw->pdev->dev,
3326 			sizeof(struct ct_sns_pkt),
3327 			sp->u.iocb_cmd.u.ctarg.rsp,
3328 			sp->u.iocb_cmd.u.ctarg.rsp_dma);
3329 		sp->u.iocb_cmd.u.ctarg.rsp = NULL;
3330 	}
3331 
3332 	sp->free(sp);
3333 done:
3334 	return rval;
3335 }
3336 
3337 void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea)
3338 {
3339        fc_port_t *fcport = ea->fcport;
3340 
3341        qla24xx_post_gnl_work(vha, fcport);
3342 }
3343 
3344 void qla24xx_async_gffid_sp_done(void *s, int res)
3345 {
3346        struct srb *sp = s;
3347        struct scsi_qla_host *vha = sp->vha;
3348        fc_port_t *fcport = sp->fcport;
3349        struct ct_sns_rsp *ct_rsp;
3350        struct event_arg ea;
3351 
3352        ql_dbg(ql_dbg_disc, vha, 0x2133,
3353 	   "Async done-%s res %x ID %x. %8phC\n",
3354 	   sp->name, res, fcport->d_id.b24, fcport->port_name);
3355 
3356        fcport->flags &= ~FCF_ASYNC_SENT;
3357        ct_rsp = &fcport->ct_desc.ct_sns->p.rsp;
3358        /*
3359 	* FC-GS-7, 5.2.3.12 FC-4 Features - format
3360 	* The format of the FC-4 Features object, as defined by the FC-4,
3361 	* Shall be an array of 4-bit values, one for each type code value
3362 	*/
3363        if (!res) {
3364 	       if (ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET] & 0xf) {
3365 		       /* w1 b00:03 */
3366 		       fcport->fc4_type =
3367 			   ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
3368 		       fcport->fc4_type &= 0xf;
3369 	       }
3370 
3371 	       if (ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET] & 0xf) {
3372 		       /* w5 [00:03]/28h */
3373 		       fcport->fc4f_nvme =
3374 			   ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];
3375 		       fcport->fc4f_nvme &= 0xf;
3376 	       }
3377        }
3378 
3379        memset(&ea, 0, sizeof(ea));
3380        ea.sp = sp;
3381        ea.fcport = sp->fcport;
3382        ea.rc = res;
3383        ea.event = FCME_GFFID_DONE;
3384 
3385        qla2x00_fcport_event_handler(vha, &ea);
3386        sp->free(sp);
3387 }
3388 
3389 /* Get FC4 Feature with Nport ID. */
3390 int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
3391 {
3392 	int rval = QLA_FUNCTION_FAILED;
3393 	struct ct_sns_req       *ct_req;
3394 	srb_t *sp;
3395 
3396 	if (!vha->flags.online)
3397 		return rval;
3398 
3399 	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
3400 	if (!sp)
3401 		return rval;
3402 
3403 	fcport->flags |= FCF_ASYNC_SENT;
3404 	sp->type = SRB_CT_PTHRU_CMD;
3405 	sp->name = "gffid";
3406 	sp->gen1 = fcport->rscn_gen;
3407 	sp->gen2 = fcport->login_gen;
3408 
3409 	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
3410 
3411 	/* CT_IU preamble  */
3412 	ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GFF_ID_CMD,
3413 	    GFF_ID_RSP_SIZE);
3414 
3415 	ct_req->req.gff_id.port_id[0] = fcport->d_id.b.domain;
3416 	ct_req->req.gff_id.port_id[1] = fcport->d_id.b.area;
3417 	ct_req->req.gff_id.port_id[2] = fcport->d_id.b.al_pa;
3418 
3419 	sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
3420 	sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
3421 	sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
3422 	sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
3423 	sp->u.iocb_cmd.u.ctarg.req_size = GFF_ID_REQ_SIZE;
3424 	sp->u.iocb_cmd.u.ctarg.rsp_size = GFF_ID_RSP_SIZE;
3425 	sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
3426 
3427 	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
3428 	sp->done = qla24xx_async_gffid_sp_done;
3429 
3430 	rval = qla2x00_start_sp(sp);
3431 	if (rval != QLA_SUCCESS)
3432 		goto done_free_sp;
3433 
3434 	ql_dbg(ql_dbg_disc, vha, 0x2132,
3435 	    "Async-%s hdl=%x  %8phC.\n", sp->name,
3436 	    sp->handle, fcport->port_name);
3437 
3438 	return rval;
3439 done_free_sp:
3440 	sp->free(sp);
3441 	fcport->flags &= ~FCF_ASYNC_SENT;
3442 	return rval;
3443 }
3444