xref: /linux/drivers/scsi/qla2xxx/qla_gs.c (revision ca55b2fef3a9373fcfc30f82fd26bc7fccbda732)
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, uint32_t req_size, uint32_t rsp_size)
28 {
29 	struct qla_hw_data *ha = vha->hw;
30 	ms_iocb_entry_t *ms_pkt;
31 
32 	ms_pkt = ha->ms_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(rsp_size);
43 	ms_pkt->req_bytecount = cpu_to_le32(req_size);
44 
45 	ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
46 	ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
47 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
48 
49 	ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
50 	ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_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, uint32_t req_size, uint32_t rsp_size)
68 {
69 	struct qla_hw_data *ha = vha->hw;
70 	struct ct_entry_24xx *ct_pkt;
71 
72 	ct_pkt = (struct ct_entry_24xx *)ha->ms_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(NPH_SNS);
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(rsp_size);
82 	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
83 
84 	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
85 	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
86 	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
87 
88 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
89 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_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 static 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 
128 	rval = QLA_FUNCTION_FAILED;
129 	if (ms_pkt->entry_status != 0) {
130 		ql_dbg(ql_dbg_disc, vha, 0x2031,
131 		    "%s failed, error status (%x) on port_id: %02x%02x%02x.\n",
132 		    routine, ms_pkt->entry_status, vha->d_id.b.domain,
133 		    vha->d_id.b.area, vha->d_id.b.al_pa);
134 	} else {
135 		if (IS_FWI2_CAPABLE(ha))
136 			comp_status = le16_to_cpu(
137 			    ((struct ct_entry_24xx *)ms_pkt)->comp_status);
138 		else
139 			comp_status = le16_to_cpu(ms_pkt->status);
140 		switch (comp_status) {
141 		case CS_COMPLETE:
142 		case CS_DATA_UNDERRUN:
143 		case CS_DATA_OVERRUN:		/* Overrun? */
144 			if (ct_rsp->header.response !=
145 			    cpu_to_be16(CT_ACCEPT_RESPONSE)) {
146 				ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2077,
147 				    "%s failed rejected request on port_id: %02x%02x%02x Compeltion status 0x%x, response 0x%x\n",
148 				    routine, vha->d_id.b.domain,
149 				    vha->d_id.b.area, vha->d_id.b.al_pa,
150 				    comp_status, ct_rsp->header.response);
151 				ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha,
152 				    0x2078, (uint8_t *)&ct_rsp->header,
153 				    sizeof(struct ct_rsp_hdr));
154 				rval = QLA_INVALID_COMMAND;
155 			} else
156 				rval = QLA_SUCCESS;
157 			break;
158 		default:
159 			ql_dbg(ql_dbg_disc, vha, 0x2033,
160 			    "%s failed, completion status (%x) on port_id: "
161 			    "%02x%02x%02x.\n", routine, comp_status,
162 			    vha->d_id.b.domain, vha->d_id.b.area,
163 			    vha->d_id.b.al_pa);
164 			break;
165 		}
166 	}
167 	return rval;
168 }
169 
170 /**
171  * qla2x00_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
172  * @ha: HA context
173  * @fcport: fcport entry to updated
174  *
175  * Returns 0 on success.
176  */
177 int
178 qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
179 {
180 	int		rval;
181 
182 	ms_iocb_entry_t	*ms_pkt;
183 	struct ct_sns_req	*ct_req;
184 	struct ct_sns_rsp	*ct_rsp;
185 	struct qla_hw_data *ha = vha->hw;
186 
187 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
188 		return qla2x00_sns_ga_nxt(vha, fcport);
189 
190 	/* Issue GA_NXT */
191 	/* Prepare common MS IOCB */
192 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GA_NXT_REQ_SIZE,
193 	    GA_NXT_RSP_SIZE);
194 
195 	/* Prepare CT request */
196 	ct_req = qla2x00_prep_ct_req(ha->ct_sns, GA_NXT_CMD,
197 	    GA_NXT_RSP_SIZE);
198 	ct_rsp = &ha->ct_sns->p.rsp;
199 
200 	/* Prepare CT arguments -- port_id */
201 	ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain;
202 	ct_req->req.port_id.port_id[1] = fcport->d_id.b.area;
203 	ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa;
204 
205 	/* Execute MS IOCB */
206 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
207 	    sizeof(ms_iocb_entry_t));
208 	if (rval != QLA_SUCCESS) {
209 		/*EMPTY*/
210 		ql_dbg(ql_dbg_disc, vha, 0x2062,
211 		    "GA_NXT issue IOCB failed (%d).\n", rval);
212 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GA_NXT") !=
213 	    QLA_SUCCESS) {
214 		rval = QLA_FUNCTION_FAILED;
215 	} else {
216 		/* Populate fc_port_t entry. */
217 		fcport->d_id.b.domain = ct_rsp->rsp.ga_nxt.port_id[0];
218 		fcport->d_id.b.area = ct_rsp->rsp.ga_nxt.port_id[1];
219 		fcport->d_id.b.al_pa = ct_rsp->rsp.ga_nxt.port_id[2];
220 
221 		memcpy(fcport->node_name, ct_rsp->rsp.ga_nxt.node_name,
222 		    WWN_SIZE);
223 		memcpy(fcport->port_name, ct_rsp->rsp.ga_nxt.port_name,
224 		    WWN_SIZE);
225 
226 		fcport->fc4_type = (ct_rsp->rsp.ga_nxt.fc4_types[2] & BIT_0) ?
227 		    FC4_TYPE_FCP_SCSI : FC4_TYPE_OTHER;
228 
229 		if (ct_rsp->rsp.ga_nxt.port_type != NS_N_PORT_TYPE &&
230 		    ct_rsp->rsp.ga_nxt.port_type != NS_NL_PORT_TYPE)
231 			fcport->d_id.b.domain = 0xf0;
232 
233 		ql_dbg(ql_dbg_disc, vha, 0x2063,
234 		    "GA_NXT entry - nn %8phN pn %8phN "
235 		    "port_id=%02x%02x%02x.\n",
236 		    fcport->node_name, fcport->port_name,
237 		    fcport->d_id.b.domain, fcport->d_id.b.area,
238 		    fcport->d_id.b.al_pa);
239 	}
240 
241 	return (rval);
242 }
243 
244 static inline int
245 qla2x00_gid_pt_rsp_size(scsi_qla_host_t *vha)
246 {
247 	return vha->hw->max_fibre_devices * 4 + 16;
248 }
249 
250 /**
251  * qla2x00_gid_pt() - SNS scan for fabric devices via GID_PT command.
252  * @ha: HA context
253  * @list: switch info entries to populate
254  *
255  * NOTE: Non-Nx_Ports are not requested.
256  *
257  * Returns 0 on success.
258  */
259 int
260 qla2x00_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
261 {
262 	int		rval;
263 	uint16_t	i;
264 
265 	ms_iocb_entry_t	*ms_pkt;
266 	struct ct_sns_req	*ct_req;
267 	struct ct_sns_rsp	*ct_rsp;
268 
269 	struct ct_sns_gid_pt_data *gid_data;
270 	struct qla_hw_data *ha = vha->hw;
271 	uint16_t gid_pt_rsp_size;
272 
273 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
274 		return qla2x00_sns_gid_pt(vha, list);
275 
276 	gid_data = NULL;
277 	gid_pt_rsp_size = qla2x00_gid_pt_rsp_size(vha);
278 	/* Issue GID_PT */
279 	/* Prepare common MS IOCB */
280 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GID_PT_REQ_SIZE,
281 	    gid_pt_rsp_size);
282 
283 	/* Prepare CT request */
284 	ct_req = qla2x00_prep_ct_req(ha->ct_sns, GID_PT_CMD, gid_pt_rsp_size);
285 	ct_rsp = &ha->ct_sns->p.rsp;
286 
287 	/* Prepare CT arguments -- port_type */
288 	ct_req->req.gid_pt.port_type = NS_NX_PORT_TYPE;
289 
290 	/* Execute MS IOCB */
291 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
292 	    sizeof(ms_iocb_entry_t));
293 	if (rval != QLA_SUCCESS) {
294 		/*EMPTY*/
295 		ql_dbg(ql_dbg_disc, vha, 0x2055,
296 		    "GID_PT issue IOCB failed (%d).\n", rval);
297 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GID_PT") !=
298 	    QLA_SUCCESS) {
299 		rval = QLA_FUNCTION_FAILED;
300 	} else {
301 		/* Set port IDs in switch info list. */
302 		for (i = 0; i < ha->max_fibre_devices; i++) {
303 			gid_data = &ct_rsp->rsp.gid_pt.entries[i];
304 			list[i].d_id.b.domain = gid_data->port_id[0];
305 			list[i].d_id.b.area = gid_data->port_id[1];
306 			list[i].d_id.b.al_pa = gid_data->port_id[2];
307 			memset(list[i].fabric_port_name, 0, WWN_SIZE);
308 			list[i].fp_speed = PORT_SPEED_UNKNOWN;
309 
310 			/* Last one exit. */
311 			if (gid_data->control_byte & BIT_7) {
312 				list[i].d_id.b.rsvd_1 = gid_data->control_byte;
313 				break;
314 			}
315 		}
316 
317 		/*
318 		 * If we've used all available slots, then the switch is
319 		 * reporting back more devices than we can handle with this
320 		 * single call.  Return a failed status, and let GA_NXT handle
321 		 * the overload.
322 		 */
323 		if (i == ha->max_fibre_devices)
324 			rval = QLA_FUNCTION_FAILED;
325 	}
326 
327 	return (rval);
328 }
329 
330 /**
331  * qla2x00_gpn_id() - SNS Get Port Name (GPN_ID) query.
332  * @ha: HA context
333  * @list: switch info entries to populate
334  *
335  * Returns 0 on success.
336  */
337 int
338 qla2x00_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
339 {
340 	int		rval = QLA_SUCCESS;
341 	uint16_t	i;
342 
343 	ms_iocb_entry_t	*ms_pkt;
344 	struct ct_sns_req	*ct_req;
345 	struct ct_sns_rsp	*ct_rsp;
346 	struct qla_hw_data *ha = vha->hw;
347 
348 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
349 		return qla2x00_sns_gpn_id(vha, list);
350 
351 	for (i = 0; i < ha->max_fibre_devices; i++) {
352 		/* Issue GPN_ID */
353 		/* Prepare common MS IOCB */
354 		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GPN_ID_REQ_SIZE,
355 		    GPN_ID_RSP_SIZE);
356 
357 		/* Prepare CT request */
358 		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GPN_ID_CMD,
359 		    GPN_ID_RSP_SIZE);
360 		ct_rsp = &ha->ct_sns->p.rsp;
361 
362 		/* Prepare CT arguments -- port_id */
363 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
364 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
365 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
366 
367 		/* Execute MS IOCB */
368 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
369 		    sizeof(ms_iocb_entry_t));
370 		if (rval != QLA_SUCCESS) {
371 			/*EMPTY*/
372 			ql_dbg(ql_dbg_disc, vha, 0x2056,
373 			    "GPN_ID issue IOCB failed (%d).\n", rval);
374 			break;
375 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
376 		    "GPN_ID") != QLA_SUCCESS) {
377 			rval = QLA_FUNCTION_FAILED;
378 			break;
379 		} else {
380 			/* Save portname */
381 			memcpy(list[i].port_name,
382 			    ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);
383 		}
384 
385 		/* Last device exit. */
386 		if (list[i].d_id.b.rsvd_1 != 0)
387 			break;
388 	}
389 
390 	return (rval);
391 }
392 
393 /**
394  * qla2x00_gnn_id() - SNS Get Node Name (GNN_ID) query.
395  * @ha: HA context
396  * @list: switch info entries to populate
397  *
398  * Returns 0 on success.
399  */
400 int
401 qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
402 {
403 	int		rval = QLA_SUCCESS;
404 	uint16_t	i;
405 	struct qla_hw_data *ha = vha->hw;
406 	ms_iocb_entry_t	*ms_pkt;
407 	struct ct_sns_req	*ct_req;
408 	struct ct_sns_rsp	*ct_rsp;
409 
410 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
411 		return qla2x00_sns_gnn_id(vha, list);
412 
413 	for (i = 0; i < ha->max_fibre_devices; i++) {
414 		/* Issue GNN_ID */
415 		/* Prepare common MS IOCB */
416 		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GNN_ID_REQ_SIZE,
417 		    GNN_ID_RSP_SIZE);
418 
419 		/* Prepare CT request */
420 		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GNN_ID_CMD,
421 		    GNN_ID_RSP_SIZE);
422 		ct_rsp = &ha->ct_sns->p.rsp;
423 
424 		/* Prepare CT arguments -- port_id */
425 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
426 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
427 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
428 
429 		/* Execute MS IOCB */
430 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
431 		    sizeof(ms_iocb_entry_t));
432 		if (rval != QLA_SUCCESS) {
433 			/*EMPTY*/
434 			ql_dbg(ql_dbg_disc, vha, 0x2057,
435 			    "GNN_ID issue IOCB failed (%d).\n", rval);
436 			break;
437 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
438 		    "GNN_ID") != QLA_SUCCESS) {
439 			rval = QLA_FUNCTION_FAILED;
440 			break;
441 		} else {
442 			/* Save nodename */
443 			memcpy(list[i].node_name,
444 			    ct_rsp->rsp.gnn_id.node_name, WWN_SIZE);
445 
446 			ql_dbg(ql_dbg_disc, vha, 0x2058,
447 			    "GID_PT entry - nn %8phN pn %8phN "
448 			    "portid=%02x%02x%02x.\n",
449 			    list[i].node_name, list[i].port_name,
450 			    list[i].d_id.b.domain, list[i].d_id.b.area,
451 			    list[i].d_id.b.al_pa);
452 		}
453 
454 		/* Last device exit. */
455 		if (list[i].d_id.b.rsvd_1 != 0)
456 			break;
457 	}
458 
459 	return (rval);
460 }
461 
462 /**
463  * qla2x00_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
464  * @ha: HA context
465  *
466  * Returns 0 on success.
467  */
468 int
469 qla2x00_rft_id(scsi_qla_host_t *vha)
470 {
471 	int		rval;
472 	struct qla_hw_data *ha = vha->hw;
473 	ms_iocb_entry_t	*ms_pkt;
474 	struct ct_sns_req	*ct_req;
475 	struct ct_sns_rsp	*ct_rsp;
476 
477 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
478 		return qla2x00_sns_rft_id(vha);
479 
480 	/* Issue RFT_ID */
481 	/* Prepare common MS IOCB */
482 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFT_ID_REQ_SIZE,
483 	    RFT_ID_RSP_SIZE);
484 
485 	/* Prepare CT request */
486 	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFT_ID_CMD,
487 	    RFT_ID_RSP_SIZE);
488 	ct_rsp = &ha->ct_sns->p.rsp;
489 
490 	/* Prepare CT arguments -- port_id, FC-4 types */
491 	ct_req->req.rft_id.port_id[0] = vha->d_id.b.domain;
492 	ct_req->req.rft_id.port_id[1] = vha->d_id.b.area;
493 	ct_req->req.rft_id.port_id[2] = vha->d_id.b.al_pa;
494 
495 	ct_req->req.rft_id.fc4_types[2] = 0x01;		/* FCP-3 */
496 
497 	/* Execute MS IOCB */
498 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
499 	    sizeof(ms_iocb_entry_t));
500 	if (rval != QLA_SUCCESS) {
501 		/*EMPTY*/
502 		ql_dbg(ql_dbg_disc, vha, 0x2043,
503 		    "RFT_ID issue IOCB failed (%d).\n", rval);
504 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFT_ID") !=
505 	    QLA_SUCCESS) {
506 		rval = QLA_FUNCTION_FAILED;
507 	} else {
508 		ql_dbg(ql_dbg_disc, vha, 0x2044,
509 		    "RFT_ID exiting normally.\n");
510 	}
511 
512 	return (rval);
513 }
514 
515 /**
516  * qla2x00_rff_id() - SNS Register FC-4 Features (RFF_ID) supported by the HBA.
517  * @ha: HA context
518  *
519  * Returns 0 on success.
520  */
521 int
522 qla2x00_rff_id(scsi_qla_host_t *vha)
523 {
524 	int		rval;
525 	struct qla_hw_data *ha = vha->hw;
526 	ms_iocb_entry_t	*ms_pkt;
527 	struct ct_sns_req	*ct_req;
528 	struct ct_sns_rsp	*ct_rsp;
529 
530 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
531 		ql_dbg(ql_dbg_disc, vha, 0x2046,
532 		    "RFF_ID call not supported on ISP2100/ISP2200.\n");
533 		return (QLA_SUCCESS);
534 	}
535 
536 	/* Issue RFF_ID */
537 	/* Prepare common MS IOCB */
538 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFF_ID_REQ_SIZE,
539 	    RFF_ID_RSP_SIZE);
540 
541 	/* Prepare CT request */
542 	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFF_ID_CMD,
543 	    RFF_ID_RSP_SIZE);
544 	ct_rsp = &ha->ct_sns->p.rsp;
545 
546 	/* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */
547 	ct_req->req.rff_id.port_id[0] = vha->d_id.b.domain;
548 	ct_req->req.rff_id.port_id[1] = vha->d_id.b.area;
549 	ct_req->req.rff_id.port_id[2] = vha->d_id.b.al_pa;
550 
551 	qlt_rff_id(vha, ct_req);
552 
553 	ct_req->req.rff_id.fc4_type = 0x08;		/* SCSI - FCP */
554 
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, 0x2047,
561 		    "RFF_ID issue IOCB failed (%d).\n", rval);
562 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFF_ID") !=
563 	    QLA_SUCCESS) {
564 		rval = QLA_FUNCTION_FAILED;
565 	} else {
566 		ql_dbg(ql_dbg_disc, vha, 0x2048,
567 		    "RFF_ID exiting normally.\n");
568 	}
569 
570 	return (rval);
571 }
572 
573 /**
574  * qla2x00_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
575  * @ha: HA context
576  *
577  * Returns 0 on success.
578  */
579 int
580 qla2x00_rnn_id(scsi_qla_host_t *vha)
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 
588 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
589 		return qla2x00_sns_rnn_id(vha);
590 
591 	/* Issue RNN_ID */
592 	/* Prepare common MS IOCB */
593 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RNN_ID_REQ_SIZE,
594 	    RNN_ID_RSP_SIZE);
595 
596 	/* Prepare CT request */
597 	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE);
598 	ct_rsp = &ha->ct_sns->p.rsp;
599 
600 	/* Prepare CT arguments -- port_id, node_name */
601 	ct_req->req.rnn_id.port_id[0] = vha->d_id.b.domain;
602 	ct_req->req.rnn_id.port_id[1] = vha->d_id.b.area;
603 	ct_req->req.rnn_id.port_id[2] = vha->d_id.b.al_pa;
604 
605 	memcpy(ct_req->req.rnn_id.node_name, vha->node_name, WWN_SIZE);
606 
607 	/* Execute MS IOCB */
608 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
609 	    sizeof(ms_iocb_entry_t));
610 	if (rval != QLA_SUCCESS) {
611 		/*EMPTY*/
612 		ql_dbg(ql_dbg_disc, vha, 0x204d,
613 		    "RNN_ID issue IOCB failed (%d).\n", rval);
614 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RNN_ID") !=
615 	    QLA_SUCCESS) {
616 		rval = QLA_FUNCTION_FAILED;
617 	} else {
618 		ql_dbg(ql_dbg_disc, vha, 0x204e,
619 		    "RNN_ID exiting normally.\n");
620 	}
621 
622 	return (rval);
623 }
624 
625 void
626 qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn, size_t size)
627 {
628 	struct qla_hw_data *ha = vha->hw;
629 
630 	if (IS_QLAFX00(ha))
631 		snprintf(snn, size, "%s FW:v%s DVR:v%s", ha->model_number,
632 		    ha->mr.fw_version, qla2x00_version_str);
633 	else
634 		snprintf(snn, size,
635 		    "%s FW:v%d.%02d.%02d DVR:v%s", ha->model_number,
636 		    ha->fw_major_version, ha->fw_minor_version,
637 		    ha->fw_subminor_version, qla2x00_version_str);
638 }
639 
640 /**
641  * qla2x00_rsnn_nn() - SNS Register Symbolic Node Name (RSNN_NN) of the HBA.
642  * @ha: HA context
643  *
644  * Returns 0 on success.
645  */
646 int
647 qla2x00_rsnn_nn(scsi_qla_host_t *vha)
648 {
649 	int		rval;
650 	struct qla_hw_data *ha = vha->hw;
651 	ms_iocb_entry_t	*ms_pkt;
652 	struct ct_sns_req	*ct_req;
653 	struct ct_sns_rsp	*ct_rsp;
654 
655 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
656 		ql_dbg(ql_dbg_disc, vha, 0x2050,
657 		    "RSNN_ID call unsupported on ISP2100/ISP2200.\n");
658 		return (QLA_SUCCESS);
659 	}
660 
661 	/* Issue RSNN_NN */
662 	/* Prepare common MS IOCB */
663 	/*   Request size adjusted after CT preparation */
664 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, 0, RSNN_NN_RSP_SIZE);
665 
666 	/* Prepare CT request */
667 	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RSNN_NN_CMD,
668 	    RSNN_NN_RSP_SIZE);
669 	ct_rsp = &ha->ct_sns->p.rsp;
670 
671 	/* Prepare CT arguments -- node_name, symbolic node_name, size */
672 	memcpy(ct_req->req.rsnn_nn.node_name, vha->node_name, WWN_SIZE);
673 
674 	/* Prepare the Symbolic Node Name */
675 	qla2x00_get_sym_node_name(vha, ct_req->req.rsnn_nn.sym_node_name,
676 	    sizeof(ct_req->req.rsnn_nn.sym_node_name));
677 
678 	/* Calculate SNN length */
679 	ct_req->req.rsnn_nn.name_len =
680 	    (uint8_t)strlen(ct_req->req.rsnn_nn.sym_node_name);
681 
682 	/* Update MS IOCB request */
683 	ms_pkt->req_bytecount =
684 	    cpu_to_le32(24 + 1 + ct_req->req.rsnn_nn.name_len);
685 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
686 
687 	/* Execute MS IOCB */
688 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
689 	    sizeof(ms_iocb_entry_t));
690 	if (rval != QLA_SUCCESS) {
691 		/*EMPTY*/
692 		ql_dbg(ql_dbg_disc, vha, 0x2051,
693 		    "RSNN_NN issue IOCB failed (%d).\n", rval);
694 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RSNN_NN") !=
695 	    QLA_SUCCESS) {
696 		rval = QLA_FUNCTION_FAILED;
697 	} else {
698 		ql_dbg(ql_dbg_disc, vha, 0x2052,
699 		    "RSNN_NN exiting normally.\n");
700 	}
701 
702 	return (rval);
703 }
704 
705 /**
706  * qla2x00_prep_sns_cmd() - Prepare common SNS command request fields for query.
707  * @ha: HA context
708  * @cmd: GS command
709  * @scmd_len: Subcommand length
710  * @data_size: response size in bytes
711  *
712  * Returns a pointer to the @ha's sns_cmd.
713  */
714 static inline struct sns_cmd_pkt *
715 qla2x00_prep_sns_cmd(scsi_qla_host_t *vha, uint16_t cmd, uint16_t scmd_len,
716     uint16_t data_size)
717 {
718 	uint16_t		wc;
719 	struct sns_cmd_pkt	*sns_cmd;
720 	struct qla_hw_data *ha = vha->hw;
721 
722 	sns_cmd = ha->sns_cmd;
723 	memset(sns_cmd, 0, sizeof(struct sns_cmd_pkt));
724 	wc = data_size / 2;			/* Size in 16bit words. */
725 	sns_cmd->p.cmd.buffer_length = cpu_to_le16(wc);
726 	sns_cmd->p.cmd.buffer_address[0] = cpu_to_le32(LSD(ha->sns_cmd_dma));
727 	sns_cmd->p.cmd.buffer_address[1] = cpu_to_le32(MSD(ha->sns_cmd_dma));
728 	sns_cmd->p.cmd.subcommand_length = cpu_to_le16(scmd_len);
729 	sns_cmd->p.cmd.subcommand = cpu_to_le16(cmd);
730 	wc = (data_size - 16) / 4;		/* Size in 32bit words. */
731 	sns_cmd->p.cmd.size = cpu_to_le16(wc);
732 
733 	vha->qla_stats.control_requests++;
734 
735 	return (sns_cmd);
736 }
737 
738 /**
739  * qla2x00_sns_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
740  * @ha: HA context
741  * @fcport: fcport entry to updated
742  *
743  * This command uses the old Exectute SNS Command mailbox routine.
744  *
745  * Returns 0 on success.
746  */
747 static int
748 qla2x00_sns_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
749 {
750 	int		rval = QLA_SUCCESS;
751 	struct qla_hw_data *ha = vha->hw;
752 	struct sns_cmd_pkt	*sns_cmd;
753 
754 	/* Issue GA_NXT. */
755 	/* Prepare SNS command request. */
756 	sns_cmd = qla2x00_prep_sns_cmd(vha, GA_NXT_CMD, GA_NXT_SNS_SCMD_LEN,
757 	    GA_NXT_SNS_DATA_SIZE);
758 
759 	/* Prepare SNS command arguments -- port_id. */
760 	sns_cmd->p.cmd.param[0] = fcport->d_id.b.al_pa;
761 	sns_cmd->p.cmd.param[1] = fcport->d_id.b.area;
762 	sns_cmd->p.cmd.param[2] = fcport->d_id.b.domain;
763 
764 	/* Execute SNS command. */
765 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GA_NXT_SNS_CMD_SIZE / 2,
766 	    sizeof(struct sns_cmd_pkt));
767 	if (rval != QLA_SUCCESS) {
768 		/*EMPTY*/
769 		ql_dbg(ql_dbg_disc, vha, 0x205f,
770 		    "GA_NXT Send SNS failed (%d).\n", rval);
771 	} else if (sns_cmd->p.gan_data[8] != 0x80 ||
772 	    sns_cmd->p.gan_data[9] != 0x02) {
773 		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2084,
774 		    "GA_NXT failed, rejected request ga_nxt_rsp:\n");
775 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2074,
776 		    sns_cmd->p.gan_data, 16);
777 		rval = QLA_FUNCTION_FAILED;
778 	} else {
779 		/* Populate fc_port_t entry. */
780 		fcport->d_id.b.domain = sns_cmd->p.gan_data[17];
781 		fcport->d_id.b.area = sns_cmd->p.gan_data[18];
782 		fcport->d_id.b.al_pa = sns_cmd->p.gan_data[19];
783 
784 		memcpy(fcport->node_name, &sns_cmd->p.gan_data[284], WWN_SIZE);
785 		memcpy(fcport->port_name, &sns_cmd->p.gan_data[20], WWN_SIZE);
786 
787 		if (sns_cmd->p.gan_data[16] != NS_N_PORT_TYPE &&
788 		    sns_cmd->p.gan_data[16] != NS_NL_PORT_TYPE)
789 			fcport->d_id.b.domain = 0xf0;
790 
791 		ql_dbg(ql_dbg_disc, vha, 0x2061,
792 		    "GA_NXT entry - nn %8phN pn %8phN "
793 		    "port_id=%02x%02x%02x.\n",
794 		    fcport->node_name, fcport->port_name,
795 		    fcport->d_id.b.domain, fcport->d_id.b.area,
796 		    fcport->d_id.b.al_pa);
797 	}
798 
799 	return (rval);
800 }
801 
802 /**
803  * qla2x00_sns_gid_pt() - SNS scan for fabric devices via GID_PT command.
804  * @ha: HA context
805  * @list: switch info entries to populate
806  *
807  * This command uses the old Exectute SNS Command mailbox routine.
808  *
809  * NOTE: Non-Nx_Ports are not requested.
810  *
811  * Returns 0 on success.
812  */
813 static int
814 qla2x00_sns_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
815 {
816 	int		rval;
817 	struct qla_hw_data *ha = vha->hw;
818 	uint16_t	i;
819 	uint8_t		*entry;
820 	struct sns_cmd_pkt	*sns_cmd;
821 	uint16_t gid_pt_sns_data_size;
822 
823 	gid_pt_sns_data_size = qla2x00_gid_pt_rsp_size(vha);
824 
825 	/* Issue GID_PT. */
826 	/* Prepare SNS command request. */
827 	sns_cmd = qla2x00_prep_sns_cmd(vha, GID_PT_CMD, GID_PT_SNS_SCMD_LEN,
828 	    gid_pt_sns_data_size);
829 
830 	/* Prepare SNS command arguments -- port_type. */
831 	sns_cmd->p.cmd.param[0] = NS_NX_PORT_TYPE;
832 
833 	/* Execute SNS command. */
834 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GID_PT_SNS_CMD_SIZE / 2,
835 	    sizeof(struct sns_cmd_pkt));
836 	if (rval != QLA_SUCCESS) {
837 		/*EMPTY*/
838 		ql_dbg(ql_dbg_disc, vha, 0x206d,
839 		    "GID_PT Send SNS failed (%d).\n", rval);
840 	} else if (sns_cmd->p.gid_data[8] != 0x80 ||
841 	    sns_cmd->p.gid_data[9] != 0x02) {
842 		ql_dbg(ql_dbg_disc, vha, 0x202f,
843 		    "GID_PT failed, rejected request, gid_rsp:\n");
844 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2081,
845 		    sns_cmd->p.gid_data, 16);
846 		rval = QLA_FUNCTION_FAILED;
847 	} else {
848 		/* Set port IDs in switch info list. */
849 		for (i = 0; i < ha->max_fibre_devices; i++) {
850 			entry = &sns_cmd->p.gid_data[(i * 4) + 16];
851 			list[i].d_id.b.domain = entry[1];
852 			list[i].d_id.b.area = entry[2];
853 			list[i].d_id.b.al_pa = entry[3];
854 
855 			/* Last one exit. */
856 			if (entry[0] & BIT_7) {
857 				list[i].d_id.b.rsvd_1 = entry[0];
858 				break;
859 			}
860 		}
861 
862 		/*
863 		 * If we've used all available slots, then the switch is
864 		 * reporting back more devices that we can handle with this
865 		 * single call.  Return a failed status, and let GA_NXT handle
866 		 * the overload.
867 		 */
868 		if (i == ha->max_fibre_devices)
869 			rval = QLA_FUNCTION_FAILED;
870 	}
871 
872 	return (rval);
873 }
874 
875 /**
876  * qla2x00_sns_gpn_id() - SNS Get Port Name (GPN_ID) query.
877  * @ha: HA context
878  * @list: switch info entries to populate
879  *
880  * This command uses the old Exectute SNS Command mailbox routine.
881  *
882  * Returns 0 on success.
883  */
884 static int
885 qla2x00_sns_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
886 {
887 	int		rval = QLA_SUCCESS;
888 	struct qla_hw_data *ha = vha->hw;
889 	uint16_t	i;
890 	struct sns_cmd_pkt	*sns_cmd;
891 
892 	for (i = 0; i < ha->max_fibre_devices; i++) {
893 		/* Issue GPN_ID */
894 		/* Prepare SNS command request. */
895 		sns_cmd = qla2x00_prep_sns_cmd(vha, GPN_ID_CMD,
896 		    GPN_ID_SNS_SCMD_LEN, GPN_ID_SNS_DATA_SIZE);
897 
898 		/* Prepare SNS command arguments -- port_id. */
899 		sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
900 		sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
901 		sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
902 
903 		/* Execute SNS command. */
904 		rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,
905 		    GPN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
906 		if (rval != QLA_SUCCESS) {
907 			/*EMPTY*/
908 			ql_dbg(ql_dbg_disc, vha, 0x2032,
909 			    "GPN_ID Send SNS failed (%d).\n", rval);
910 		} else if (sns_cmd->p.gpn_data[8] != 0x80 ||
911 		    sns_cmd->p.gpn_data[9] != 0x02) {
912 			ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207e,
913 			    "GPN_ID failed, rejected request, gpn_rsp:\n");
914 			ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207f,
915 			    sns_cmd->p.gpn_data, 16);
916 			rval = QLA_FUNCTION_FAILED;
917 		} else {
918 			/* Save portname */
919 			memcpy(list[i].port_name, &sns_cmd->p.gpn_data[16],
920 			    WWN_SIZE);
921 		}
922 
923 		/* Last device exit. */
924 		if (list[i].d_id.b.rsvd_1 != 0)
925 			break;
926 	}
927 
928 	return (rval);
929 }
930 
931 /**
932  * qla2x00_sns_gnn_id() - SNS Get Node Name (GNN_ID) query.
933  * @ha: HA context
934  * @list: switch info entries to populate
935  *
936  * This command uses the old Exectute SNS Command mailbox routine.
937  *
938  * Returns 0 on success.
939  */
940 static int
941 qla2x00_sns_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
942 {
943 	int		rval = QLA_SUCCESS;
944 	struct qla_hw_data *ha = vha->hw;
945 	uint16_t	i;
946 	struct sns_cmd_pkt	*sns_cmd;
947 
948 	for (i = 0; i < ha->max_fibre_devices; i++) {
949 		/* Issue GNN_ID */
950 		/* Prepare SNS command request. */
951 		sns_cmd = qla2x00_prep_sns_cmd(vha, GNN_ID_CMD,
952 		    GNN_ID_SNS_SCMD_LEN, GNN_ID_SNS_DATA_SIZE);
953 
954 		/* Prepare SNS command arguments -- port_id. */
955 		sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
956 		sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
957 		sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
958 
959 		/* Execute SNS command. */
960 		rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,
961 		    GNN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
962 		if (rval != QLA_SUCCESS) {
963 			/*EMPTY*/
964 			ql_dbg(ql_dbg_disc, vha, 0x203f,
965 			    "GNN_ID Send SNS failed (%d).\n", rval);
966 		} else if (sns_cmd->p.gnn_data[8] != 0x80 ||
967 		    sns_cmd->p.gnn_data[9] != 0x02) {
968 			ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2082,
969 			    "GNN_ID failed, rejected request, gnn_rsp:\n");
970 			ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207a,
971 			    sns_cmd->p.gnn_data, 16);
972 			rval = QLA_FUNCTION_FAILED;
973 		} else {
974 			/* Save nodename */
975 			memcpy(list[i].node_name, &sns_cmd->p.gnn_data[16],
976 			    WWN_SIZE);
977 
978 			ql_dbg(ql_dbg_disc, vha, 0x206e,
979 			    "GID_PT entry - nn %8phN pn %8phN "
980 			    "port_id=%02x%02x%02x.\n",
981 			    list[i].node_name, list[i].port_name,
982 			    list[i].d_id.b.domain, list[i].d_id.b.area,
983 			    list[i].d_id.b.al_pa);
984 		}
985 
986 		/* Last device exit. */
987 		if (list[i].d_id.b.rsvd_1 != 0)
988 			break;
989 	}
990 
991 	return (rval);
992 }
993 
994 /**
995  * qla2x00_snd_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
996  * @ha: HA context
997  *
998  * This command uses the old Exectute SNS Command mailbox routine.
999  *
1000  * Returns 0 on success.
1001  */
1002 static int
1003 qla2x00_sns_rft_id(scsi_qla_host_t *vha)
1004 {
1005 	int		rval;
1006 	struct qla_hw_data *ha = vha->hw;
1007 	struct sns_cmd_pkt	*sns_cmd;
1008 
1009 	/* Issue RFT_ID. */
1010 	/* Prepare SNS command request. */
1011 	sns_cmd = qla2x00_prep_sns_cmd(vha, RFT_ID_CMD, RFT_ID_SNS_SCMD_LEN,
1012 	    RFT_ID_SNS_DATA_SIZE);
1013 
1014 	/* Prepare SNS command arguments -- port_id, FC-4 types */
1015 	sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;
1016 	sns_cmd->p.cmd.param[1] = vha->d_id.b.area;
1017 	sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;
1018 
1019 	sns_cmd->p.cmd.param[5] = 0x01;			/* FCP-3 */
1020 
1021 	/* Execute SNS command. */
1022 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RFT_ID_SNS_CMD_SIZE / 2,
1023 	    sizeof(struct sns_cmd_pkt));
1024 	if (rval != QLA_SUCCESS) {
1025 		/*EMPTY*/
1026 		ql_dbg(ql_dbg_disc, vha, 0x2060,
1027 		    "RFT_ID Send SNS failed (%d).\n", rval);
1028 	} else if (sns_cmd->p.rft_data[8] != 0x80 ||
1029 	    sns_cmd->p.rft_data[9] != 0x02) {
1030 		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2083,
1031 		    "RFT_ID failed, rejected request rft_rsp:\n");
1032 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2080,
1033 		    sns_cmd->p.rft_data, 16);
1034 		rval = QLA_FUNCTION_FAILED;
1035 	} else {
1036 		ql_dbg(ql_dbg_disc, vha, 0x2073,
1037 		    "RFT_ID exiting normally.\n");
1038 	}
1039 
1040 	return (rval);
1041 }
1042 
1043 /**
1044  * qla2x00_sns_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
1045  * HBA.
1046  * @ha: HA context
1047  *
1048  * This command uses the old Exectute SNS Command mailbox routine.
1049  *
1050  * Returns 0 on success.
1051  */
1052 static int
1053 qla2x00_sns_rnn_id(scsi_qla_host_t *vha)
1054 {
1055 	int		rval;
1056 	struct qla_hw_data *ha = vha->hw;
1057 	struct sns_cmd_pkt	*sns_cmd;
1058 
1059 	/* Issue RNN_ID. */
1060 	/* Prepare SNS command request. */
1061 	sns_cmd = qla2x00_prep_sns_cmd(vha, RNN_ID_CMD, RNN_ID_SNS_SCMD_LEN,
1062 	    RNN_ID_SNS_DATA_SIZE);
1063 
1064 	/* Prepare SNS command arguments -- port_id, nodename. */
1065 	sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;
1066 	sns_cmd->p.cmd.param[1] = vha->d_id.b.area;
1067 	sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;
1068 
1069 	sns_cmd->p.cmd.param[4] = vha->node_name[7];
1070 	sns_cmd->p.cmd.param[5] = vha->node_name[6];
1071 	sns_cmd->p.cmd.param[6] = vha->node_name[5];
1072 	sns_cmd->p.cmd.param[7] = vha->node_name[4];
1073 	sns_cmd->p.cmd.param[8] = vha->node_name[3];
1074 	sns_cmd->p.cmd.param[9] = vha->node_name[2];
1075 	sns_cmd->p.cmd.param[10] = vha->node_name[1];
1076 	sns_cmd->p.cmd.param[11] = vha->node_name[0];
1077 
1078 	/* Execute SNS command. */
1079 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RNN_ID_SNS_CMD_SIZE / 2,
1080 	    sizeof(struct sns_cmd_pkt));
1081 	if (rval != QLA_SUCCESS) {
1082 		/*EMPTY*/
1083 		ql_dbg(ql_dbg_disc, vha, 0x204a,
1084 		    "RNN_ID Send SNS failed (%d).\n", rval);
1085 	} else if (sns_cmd->p.rnn_data[8] != 0x80 ||
1086 	    sns_cmd->p.rnn_data[9] != 0x02) {
1087 		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207b,
1088 		    "RNN_ID failed, rejected request, rnn_rsp:\n");
1089 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207c,
1090 		    sns_cmd->p.rnn_data, 16);
1091 		rval = QLA_FUNCTION_FAILED;
1092 	} else {
1093 		ql_dbg(ql_dbg_disc, vha, 0x204c,
1094 		    "RNN_ID exiting normally.\n");
1095 	}
1096 
1097 	return (rval);
1098 }
1099 
1100 /**
1101  * qla2x00_mgmt_svr_login() - Login to fabric Management Service.
1102  * @ha: HA context
1103  *
1104  * Returns 0 on success.
1105  */
1106 static int
1107 qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
1108 {
1109 	int ret, rval;
1110 	uint16_t mb[MAILBOX_REGISTER_COUNT];
1111 	struct qla_hw_data *ha = vha->hw;
1112 	ret = QLA_SUCCESS;
1113 	if (vha->flags.management_server_logged_in)
1114 		return ret;
1115 
1116 	rval = ha->isp_ops->fabric_login(vha, vha->mgmt_svr_loop_id, 0xff, 0xff,
1117 	    0xfa, mb, BIT_1);
1118 	if (rval != QLA_SUCCESS || mb[0] != MBS_COMMAND_COMPLETE) {
1119 		if (rval == QLA_MEMORY_ALLOC_FAILED)
1120 			ql_dbg(ql_dbg_disc, vha, 0x2085,
1121 			    "Failed management_server login: loopid=%x "
1122 			    "rval=%d\n", vha->mgmt_svr_loop_id, rval);
1123 		else
1124 			ql_dbg(ql_dbg_disc, vha, 0x2024,
1125 			    "Failed management_server login: loopid=%x "
1126 			    "mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x.\n",
1127 			    vha->mgmt_svr_loop_id, mb[0], mb[1], mb[2], mb[6],
1128 			    mb[7]);
1129 		ret = QLA_FUNCTION_FAILED;
1130 	} else
1131 		vha->flags.management_server_logged_in = 1;
1132 
1133 	return ret;
1134 }
1135 
1136 /**
1137  * qla2x00_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
1138  * @ha: HA context
1139  * @req_size: request size in bytes
1140  * @rsp_size: response size in bytes
1141  *
1142  * Returns a pointer to the @ha's ms_iocb.
1143  */
1144 void *
1145 qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1146     uint32_t rsp_size)
1147 {
1148 	ms_iocb_entry_t *ms_pkt;
1149 	struct qla_hw_data *ha = vha->hw;
1150 	ms_pkt = ha->ms_iocb;
1151 	memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
1152 
1153 	ms_pkt->entry_type = MS_IOCB_TYPE;
1154 	ms_pkt->entry_count = 1;
1155 	SET_TARGET_ID(ha, ms_pkt->loop_id, vha->mgmt_svr_loop_id);
1156 	ms_pkt->control_flags = cpu_to_le16(CF_READ | CF_HEAD_TAG);
1157 	ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1158 	ms_pkt->cmd_dsd_count = cpu_to_le16(1);
1159 	ms_pkt->total_dsd_count = cpu_to_le16(2);
1160 	ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
1161 	ms_pkt->req_bytecount = cpu_to_le32(req_size);
1162 
1163 	ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1164 	ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1165 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
1166 
1167 	ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1168 	ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1169 	ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
1170 
1171 	return ms_pkt;
1172 }
1173 
1174 /**
1175  * qla24xx_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
1176  * @ha: HA context
1177  * @req_size: request size in bytes
1178  * @rsp_size: response size in bytes
1179  *
1180  * Returns a pointer to the @ha's ms_iocb.
1181  */
1182 void *
1183 qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1184     uint32_t rsp_size)
1185 {
1186 	struct ct_entry_24xx *ct_pkt;
1187 	struct qla_hw_data *ha = vha->hw;
1188 
1189 	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1190 	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
1191 
1192 	ct_pkt->entry_type = CT_IOCB_TYPE;
1193 	ct_pkt->entry_count = 1;
1194 	ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);
1195 	ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1196 	ct_pkt->cmd_dsd_count = cpu_to_le16(1);
1197 	ct_pkt->rsp_dsd_count = cpu_to_le16(1);
1198 	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
1199 	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1200 
1201 	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1202 	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1203 	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1204 
1205 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1206 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1207 	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
1208 	ct_pkt->vp_index = vha->vp_idx;
1209 
1210 	return ct_pkt;
1211 }
1212 
1213 static inline ms_iocb_entry_t *
1214 qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size)
1215 {
1216 	struct qla_hw_data *ha = vha->hw;
1217 	ms_iocb_entry_t *ms_pkt = ha->ms_iocb;
1218 	struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1219 
1220 	if (IS_FWI2_CAPABLE(ha)) {
1221 		ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1222 		ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1223 	} else {
1224 		ms_pkt->req_bytecount = cpu_to_le32(req_size);
1225 		ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
1226 	}
1227 
1228 	return ms_pkt;
1229 }
1230 
1231 /**
1232  * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
1233  * @ct_req: CT request buffer
1234  * @cmd: GS command
1235  * @rsp_size: response size in bytes
1236  *
1237  * Returns a pointer to the intitialized @ct_req.
1238  */
1239 static inline struct ct_sns_req *
1240 qla2x00_prep_ct_fdmi_req(struct ct_sns_pkt *p, uint16_t cmd,
1241     uint16_t rsp_size)
1242 {
1243 	memset(p, 0, sizeof(struct ct_sns_pkt));
1244 
1245 	p->p.req.header.revision = 0x01;
1246 	p->p.req.header.gs_type = 0xFA;
1247 	p->p.req.header.gs_subtype = 0x10;
1248 	p->p.req.command = cpu_to_be16(cmd);
1249 	p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
1250 
1251 	return &p->p.req;
1252 }
1253 
1254 /**
1255  * qla2x00_fdmi_rhba() -
1256  * @ha: HA context
1257  *
1258  * Returns 0 on success.
1259  */
1260 static int
1261 qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
1262 {
1263 	int rval, alen;
1264 	uint32_t size, sn;
1265 
1266 	ms_iocb_entry_t *ms_pkt;
1267 	struct ct_sns_req *ct_req;
1268 	struct ct_sns_rsp *ct_rsp;
1269 	void *entries;
1270 	struct ct_fdmi_hba_attr *eiter;
1271 	struct qla_hw_data *ha = vha->hw;
1272 
1273 	/* Issue RHBA */
1274 	/* Prepare common MS IOCB */
1275 	/*   Request size adjusted after CT preparation */
1276 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE);
1277 
1278 	/* Prepare CT request */
1279 	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, RHBA_RSP_SIZE);
1280 	ct_rsp = &ha->ct_sns->p.rsp;
1281 
1282 	/* Prepare FDMI command arguments -- attribute block, attributes. */
1283 	memcpy(ct_req->req.rhba.hba_identifier, vha->port_name, WWN_SIZE);
1284 	ct_req->req.rhba.entry_count = cpu_to_be32(1);
1285 	memcpy(ct_req->req.rhba.port_name, vha->port_name, WWN_SIZE);
1286 	size = 2 * WWN_SIZE + 4 + 4;
1287 
1288 	/* Attributes */
1289 	ct_req->req.rhba.attrs.count =
1290 	    cpu_to_be32(FDMI_HBA_ATTR_COUNT);
1291 	entries = ct_req->req.rhba.hba_identifier;
1292 
1293 	/* Nodename. */
1294 	eiter = entries + size;
1295 	eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME);
1296 	eiter->len = cpu_to_be16(4 + WWN_SIZE);
1297 	memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
1298 	size += 4 + WWN_SIZE;
1299 
1300 	ql_dbg(ql_dbg_disc, vha, 0x2025,
1301 	    "NodeName = %8phN.\n", eiter->a.node_name);
1302 
1303 	/* Manufacturer. */
1304 	eiter = entries + size;
1305 	eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER);
1306 	alen = strlen(QLA2XXX_MANUFACTURER);
1307 	snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer),
1308 	    "%s", "QLogic Corporation");
1309 	alen += 4 - (alen & 3);
1310 	eiter->len = cpu_to_be16(4 + alen);
1311 	size += 4 + alen;
1312 
1313 	ql_dbg(ql_dbg_disc, vha, 0x2026,
1314 	    "Manufacturer = %s.\n", eiter->a.manufacturer);
1315 
1316 	/* Serial number. */
1317 	eiter = entries + size;
1318 	eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
1319 	if (IS_FWI2_CAPABLE(ha))
1320 		qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num,
1321 		    sizeof(eiter->a.serial_num));
1322 	else {
1323 		sn = ((ha->serial0 & 0x1f) << 16) |
1324 			(ha->serial2 << 8) | ha->serial1;
1325 		snprintf(eiter->a.serial_num, sizeof(eiter->a.serial_num),
1326 		    "%c%05d", 'A' + sn / 100000, sn % 100000);
1327 	}
1328 	alen = strlen(eiter->a.serial_num);
1329 	alen += 4 - (alen & 3);
1330 	eiter->len = cpu_to_be16(4 + alen);
1331 	size += 4 + alen;
1332 
1333 	ql_dbg(ql_dbg_disc, vha, 0x2027,
1334 	    "Serial no. = %s.\n", eiter->a.serial_num);
1335 
1336 	/* Model name. */
1337 	eiter = entries + size;
1338 	eiter->type = cpu_to_be16(FDMI_HBA_MODEL);
1339 	snprintf(eiter->a.model, sizeof(eiter->a.model),
1340 	    "%s", ha->model_number);
1341 	alen = strlen(eiter->a.model);
1342 	alen += 4 - (alen & 3);
1343 	eiter->len = cpu_to_be16(4 + alen);
1344 	size += 4 + alen;
1345 
1346 	ql_dbg(ql_dbg_disc, vha, 0x2028,
1347 	    "Model Name = %s.\n", eiter->a.model);
1348 
1349 	/* Model description. */
1350 	eiter = entries + size;
1351 	eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
1352 	snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc),
1353 	    "%s", ha->model_desc);
1354 	alen = strlen(eiter->a.model_desc);
1355 	alen += 4 - (alen & 3);
1356 	eiter->len = cpu_to_be16(4 + alen);
1357 	size += 4 + alen;
1358 
1359 	ql_dbg(ql_dbg_disc, vha, 0x2029,
1360 	    "Model Desc = %s.\n", eiter->a.model_desc);
1361 
1362 	/* Hardware version. */
1363 	eiter = entries + size;
1364 	eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
1365 	if (!IS_FWI2_CAPABLE(ha)) {
1366 		snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
1367 		    "HW:%s", ha->adapter_id);
1368 	} else if (qla2xxx_get_vpd_field(vha, "MN", eiter->a.hw_version,
1369 		    sizeof(eiter->a.hw_version))) {
1370 		;
1371 	} else if (qla2xxx_get_vpd_field(vha, "EC", eiter->a.hw_version,
1372 		    sizeof(eiter->a.hw_version))) {
1373 		;
1374 	} else {
1375 		snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
1376 		    "HW:%s", ha->adapter_id);
1377 	}
1378 	alen = strlen(eiter->a.hw_version);
1379 	alen += 4 - (alen & 3);
1380 	eiter->len = cpu_to_be16(4 + alen);
1381 	size += 4 + alen;
1382 
1383 	ql_dbg(ql_dbg_disc, vha, 0x202a,
1384 	    "Hardware ver = %s.\n", eiter->a.hw_version);
1385 
1386 	/* Driver version. */
1387 	eiter = entries + size;
1388 	eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
1389 	snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version),
1390 	    "%s", qla2x00_version_str);
1391 	alen = strlen(eiter->a.driver_version);
1392 	alen += 4 - (alen & 3);
1393 	eiter->len = cpu_to_be16(4 + alen);
1394 	size += 4 + alen;
1395 
1396 	ql_dbg(ql_dbg_disc, vha, 0x202b,
1397 	    "Driver ver = %s.\n", eiter->a.driver_version);
1398 
1399 	/* Option ROM version. */
1400 	eiter = entries + size;
1401 	eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
1402 	snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version),
1403 	    "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
1404 	alen = strlen(eiter->a.orom_version);
1405 	alen += 4 - (alen & 3);
1406 	eiter->len = cpu_to_be16(4 + alen);
1407 	size += 4 + alen;
1408 
1409 	ql_dbg(ql_dbg_disc, vha , 0x202c,
1410 	    "Optrom vers = %s.\n", eiter->a.orom_version);
1411 
1412 	/* Firmware version */
1413 	eiter = entries + size;
1414 	eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
1415 	ha->isp_ops->fw_version_str(vha, eiter->a.fw_version,
1416 	    sizeof(eiter->a.fw_version));
1417 	alen = strlen(eiter->a.fw_version);
1418 	alen += 4 - (alen & 3);
1419 	eiter->len = cpu_to_be16(4 + alen);
1420 	size += 4 + alen;
1421 
1422 	ql_dbg(ql_dbg_disc, vha, 0x202d,
1423 	    "Firmware vers = %s.\n", eiter->a.fw_version);
1424 
1425 	/* Update MS request size. */
1426 	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
1427 
1428 	ql_dbg(ql_dbg_disc, vha, 0x202e,
1429 	    "RHBA identifier = %8phN size=%d.\n",
1430 	    ct_req->req.rhba.hba_identifier, size);
1431 	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2076,
1432 	    entries, size);
1433 
1434 	/* Execute MS IOCB */
1435 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1436 	    sizeof(ms_iocb_entry_t));
1437 	if (rval != QLA_SUCCESS) {
1438 		/*EMPTY*/
1439 		ql_dbg(ql_dbg_disc, vha, 0x2030,
1440 		    "RHBA issue IOCB failed (%d).\n", rval);
1441 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") !=
1442 	    QLA_SUCCESS) {
1443 		rval = QLA_FUNCTION_FAILED;
1444 		if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
1445 		    ct_rsp->header.explanation_code ==
1446 		    CT_EXPL_ALREADY_REGISTERED) {
1447 			ql_dbg(ql_dbg_disc, vha, 0x2034,
1448 			    "HBA already registered.\n");
1449 			rval = QLA_ALREADY_REGISTERED;
1450 		} else {
1451 			ql_dbg(ql_dbg_disc, vha, 0x20ad,
1452 			    "RHBA FDMI registration failed, CT Reason code: 0x%x, CT Explanation 0x%x\n",
1453 			    ct_rsp->header.reason_code,
1454 			    ct_rsp->header.explanation_code);
1455 		}
1456 	} else {
1457 		ql_dbg(ql_dbg_disc, vha, 0x2035,
1458 		    "RHBA exiting normally.\n");
1459 	}
1460 
1461 	return rval;
1462 }
1463 
1464 /**
1465  * qla2x00_fdmi_rpa() -
1466  * @ha: HA context
1467  *
1468  * Returns 0 on success.
1469  */
1470 static int
1471 qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
1472 {
1473 	int rval, alen;
1474 	uint32_t size;
1475 	struct qla_hw_data *ha = vha->hw;
1476 	ms_iocb_entry_t *ms_pkt;
1477 	struct ct_sns_req *ct_req;
1478 	struct ct_sns_rsp *ct_rsp;
1479 	void *entries;
1480 	struct ct_fdmi_port_attr *eiter;
1481 	struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
1482 	struct new_utsname *p_sysid = NULL;
1483 
1484 	/* Issue RPA */
1485 	/* Prepare common MS IOCB */
1486 	/*   Request size adjusted after CT preparation */
1487 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE);
1488 
1489 	/* Prepare CT request */
1490 	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD,
1491 	    RPA_RSP_SIZE);
1492 	ct_rsp = &ha->ct_sns->p.rsp;
1493 
1494 	/* Prepare FDMI command arguments -- attribute block, attributes. */
1495 	memcpy(ct_req->req.rpa.port_name, vha->port_name, WWN_SIZE);
1496 	size = WWN_SIZE + 4;
1497 
1498 	/* Attributes */
1499 	ct_req->req.rpa.attrs.count = cpu_to_be32(FDMI_PORT_ATTR_COUNT);
1500 	entries = ct_req->req.rpa.port_name;
1501 
1502 	/* FC4 types. */
1503 	eiter = entries + size;
1504 	eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES);
1505 	eiter->len = cpu_to_be16(4 + 32);
1506 	eiter->a.fc4_types[2] = 0x01;
1507 	size += 4 + 32;
1508 
1509 	ql_dbg(ql_dbg_disc, vha, 0x2039,
1510 	    "FC4_TYPES=%02x %02x.\n",
1511 	    eiter->a.fc4_types[2],
1512 	    eiter->a.fc4_types[1]);
1513 
1514 	/* Supported speed. */
1515 	eiter = entries + size;
1516 	eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
1517 	eiter->len = cpu_to_be16(4 + 4);
1518 	if (IS_CNA_CAPABLE(ha))
1519 		eiter->a.sup_speed = cpu_to_be32(
1520 		    FDMI_PORT_SPEED_10GB);
1521 	else if (IS_QLA27XX(ha))
1522 		eiter->a.sup_speed = cpu_to_be32(
1523 		    FDMI_PORT_SPEED_32GB|
1524 		    FDMI_PORT_SPEED_16GB|
1525 		    FDMI_PORT_SPEED_8GB);
1526 	else if (IS_QLA2031(ha))
1527 		eiter->a.sup_speed = cpu_to_be32(
1528 		    FDMI_PORT_SPEED_16GB|
1529 		    FDMI_PORT_SPEED_8GB|
1530 		    FDMI_PORT_SPEED_4GB);
1531 	else if (IS_QLA25XX(ha))
1532 		eiter->a.sup_speed = cpu_to_be32(
1533 		    FDMI_PORT_SPEED_8GB|
1534 		    FDMI_PORT_SPEED_4GB|
1535 		    FDMI_PORT_SPEED_2GB|
1536 		    FDMI_PORT_SPEED_1GB);
1537 	else if (IS_QLA24XX_TYPE(ha))
1538 		eiter->a.sup_speed = cpu_to_be32(
1539 		    FDMI_PORT_SPEED_4GB|
1540 		    FDMI_PORT_SPEED_2GB|
1541 		    FDMI_PORT_SPEED_1GB);
1542 	else if (IS_QLA23XX(ha))
1543 		eiter->a.sup_speed = cpu_to_be32(
1544 		    FDMI_PORT_SPEED_2GB|
1545 		    FDMI_PORT_SPEED_1GB);
1546 	else
1547 		eiter->a.sup_speed = cpu_to_be32(
1548 		    FDMI_PORT_SPEED_1GB);
1549 	size += 4 + 4;
1550 
1551 	ql_dbg(ql_dbg_disc, vha, 0x203a,
1552 	    "Supported_Speed=%x.\n", eiter->a.sup_speed);
1553 
1554 	/* Current speed. */
1555 	eiter = entries + size;
1556 	eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
1557 	eiter->len = cpu_to_be16(4 + 4);
1558 	switch (ha->link_data_rate) {
1559 	case PORT_SPEED_1GB:
1560 		eiter->a.cur_speed =
1561 		    cpu_to_be32(FDMI_PORT_SPEED_1GB);
1562 		break;
1563 	case PORT_SPEED_2GB:
1564 		eiter->a.cur_speed =
1565 		    cpu_to_be32(FDMI_PORT_SPEED_2GB);
1566 		break;
1567 	case PORT_SPEED_4GB:
1568 		eiter->a.cur_speed =
1569 		    cpu_to_be32(FDMI_PORT_SPEED_4GB);
1570 		break;
1571 	case PORT_SPEED_8GB:
1572 		eiter->a.cur_speed =
1573 		    cpu_to_be32(FDMI_PORT_SPEED_8GB);
1574 		break;
1575 	case PORT_SPEED_10GB:
1576 		eiter->a.cur_speed =
1577 		    cpu_to_be32(FDMI_PORT_SPEED_10GB);
1578 		break;
1579 	case PORT_SPEED_16GB:
1580 		eiter->a.cur_speed =
1581 		    cpu_to_be32(FDMI_PORT_SPEED_16GB);
1582 		break;
1583 	case PORT_SPEED_32GB:
1584 		eiter->a.cur_speed =
1585 		    cpu_to_be32(FDMI_PORT_SPEED_32GB);
1586 		break;
1587 	default:
1588 		eiter->a.cur_speed =
1589 		    cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN);
1590 		break;
1591 	}
1592 	size += 4 + 4;
1593 
1594 	ql_dbg(ql_dbg_disc, vha, 0x203b,
1595 	    "Current_Speed=%x.\n", eiter->a.cur_speed);
1596 
1597 	/* Max frame size. */
1598 	eiter = entries + size;
1599 	eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
1600 	eiter->len = cpu_to_be16(4 + 4);
1601 	eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ?
1602 	    le16_to_cpu(icb24->frame_payload_size) :
1603 	    le16_to_cpu(ha->init_cb->frame_payload_size);
1604 	eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size);
1605 	size += 4 + 4;
1606 
1607 	ql_dbg(ql_dbg_disc, vha, 0x203c,
1608 	    "Max_Frame_Size=%x.\n", eiter->a.max_frame_size);
1609 
1610 	/* OS device name. */
1611 	eiter = entries + size;
1612 	eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
1613 	snprintf(eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name),
1614 	    "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no);
1615 	alen = strlen(eiter->a.os_dev_name);
1616 	alen += 4 - (alen & 3);
1617 	eiter->len = cpu_to_be16(4 + alen);
1618 	size += 4 + alen;
1619 
1620 	ql_dbg(ql_dbg_disc, vha, 0x204b,
1621 	    "OS_Device_Name=%s.\n", eiter->a.os_dev_name);
1622 
1623 	/* Hostname. */
1624 	eiter = entries + size;
1625 	eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME);
1626 	p_sysid = utsname();
1627 	if (p_sysid) {
1628 		snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
1629 		    "%s", p_sysid->nodename);
1630 	} else {
1631 		snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
1632 		    "%s", fc_host_system_hostname(vha->host));
1633 	}
1634 	alen = strlen(eiter->a.host_name);
1635 	alen += 4 - (alen & 3);
1636 	eiter->len = cpu_to_be16(4 + alen);
1637 	size += 4 + alen;
1638 
1639 	ql_dbg(ql_dbg_disc, vha, 0x203d, "HostName=%s.\n", eiter->a.host_name);
1640 
1641 	/* Update MS request size. */
1642 	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
1643 
1644 	ql_dbg(ql_dbg_disc, vha, 0x203e,
1645 	    "RPA portname  %016llx, size = %d.\n",
1646 	    wwn_to_u64(ct_req->req.rpa.port_name), size);
1647 	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2079,
1648 	    entries, size);
1649 
1650 	/* Execute MS IOCB */
1651 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1652 	    sizeof(ms_iocb_entry_t));
1653 	if (rval != QLA_SUCCESS) {
1654 		/*EMPTY*/
1655 		ql_dbg(ql_dbg_disc, vha, 0x2040,
1656 		    "RPA issue IOCB failed (%d).\n", rval);
1657 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") !=
1658 	    QLA_SUCCESS) {
1659 		rval = QLA_FUNCTION_FAILED;
1660 		if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
1661 		    ct_rsp->header.explanation_code ==
1662 		    CT_EXPL_ALREADY_REGISTERED) {
1663 			ql_dbg(ql_dbg_disc, vha, 0x20cd,
1664 			    "RPA already registered.\n");
1665 			rval = QLA_ALREADY_REGISTERED;
1666 		}
1667 
1668 	} else {
1669 		ql_dbg(ql_dbg_disc, vha, 0x2041,
1670 		    "RPA exiting normally.\n");
1671 	}
1672 
1673 	return rval;
1674 }
1675 
1676 /**
1677  * qla2x00_fdmiv2_rhba() -
1678  * @ha: HA context
1679  *
1680  * Returns 0 on success.
1681  */
1682 static int
1683 qla2x00_fdmiv2_rhba(scsi_qla_host_t *vha)
1684 {
1685 	int rval, alen;
1686 	uint32_t size, sn;
1687 	ms_iocb_entry_t *ms_pkt;
1688 	struct ct_sns_req *ct_req;
1689 	struct ct_sns_rsp *ct_rsp;
1690 	void *entries;
1691 	struct ct_fdmiv2_hba_attr *eiter;
1692 	struct qla_hw_data *ha = vha->hw;
1693 	struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
1694 	struct new_utsname *p_sysid = NULL;
1695 
1696 	/* Issue RHBA */
1697 	/* Prepare common MS IOCB */
1698 	/*   Request size adjusted after CT preparation */
1699 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE);
1700 
1701 	/* Prepare CT request */
1702 	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD,
1703 	    RHBA_RSP_SIZE);
1704 	ct_rsp = &ha->ct_sns->p.rsp;
1705 
1706 	/* Prepare FDMI command arguments -- attribute block, attributes. */
1707 	memcpy(ct_req->req.rhba2.hba_identifier, vha->port_name, WWN_SIZE);
1708 	ct_req->req.rhba2.entry_count = cpu_to_be32(1);
1709 	memcpy(ct_req->req.rhba2.port_name, vha->port_name, WWN_SIZE);
1710 	size = 2 * WWN_SIZE + 4 + 4;
1711 
1712 	/* Attributes */
1713 	ct_req->req.rhba2.attrs.count = cpu_to_be32(FDMIV2_HBA_ATTR_COUNT);
1714 	entries = ct_req->req.rhba2.hba_identifier;
1715 
1716 	/* Nodename. */
1717 	eiter = entries + size;
1718 	eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME);
1719 	eiter->len = cpu_to_be16(4 + WWN_SIZE);
1720 	memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
1721 	size += 4 + WWN_SIZE;
1722 
1723 	ql_dbg(ql_dbg_disc, vha, 0x207d,
1724 	    "NodeName = %016llx.\n", wwn_to_u64(eiter->a.node_name));
1725 
1726 	/* Manufacturer. */
1727 	eiter = entries + size;
1728 	eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER);
1729 	snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer),
1730 	    "%s", "QLogic Corporation");
1731 	eiter->a.manufacturer[strlen("QLogic Corporation")] = '\0';
1732 	alen = strlen(eiter->a.manufacturer);
1733 	alen += 4 - (alen & 3);
1734 	eiter->len = cpu_to_be16(4 + alen);
1735 	size += 4 + alen;
1736 
1737 	ql_dbg(ql_dbg_disc, vha, 0x20a5,
1738 	    "Manufacturer = %s.\n", eiter->a.manufacturer);
1739 
1740 	/* Serial number. */
1741 	eiter = entries + size;
1742 	eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
1743 	if (IS_FWI2_CAPABLE(ha))
1744 		qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num,
1745 		    sizeof(eiter->a.serial_num));
1746 	else {
1747 		sn = ((ha->serial0 & 0x1f) << 16) |
1748 			(ha->serial2 << 8) | ha->serial1;
1749 		snprintf(eiter->a.serial_num, sizeof(eiter->a.serial_num),
1750 		    "%c%05d", 'A' + sn / 100000, sn % 100000);
1751 	}
1752 	alen = strlen(eiter->a.serial_num);
1753 	alen += 4 - (alen & 3);
1754 	eiter->len = cpu_to_be16(4 + alen);
1755 	size += 4 + alen;
1756 
1757 	ql_dbg(ql_dbg_disc, vha, 0x20a6,
1758 	    "Serial no. = %s.\n", eiter->a.serial_num);
1759 
1760 	/* Model name. */
1761 	eiter = entries + size;
1762 	eiter->type = cpu_to_be16(FDMI_HBA_MODEL);
1763 	snprintf(eiter->a.model, sizeof(eiter->a.model),
1764 	    "%s", ha->model_number);
1765 	alen = strlen(eiter->a.model);
1766 	alen += 4 - (alen & 3);
1767 	eiter->len = cpu_to_be16(4 + alen);
1768 	size += 4 + alen;
1769 
1770 	ql_dbg(ql_dbg_disc, vha, 0x20a7,
1771 	    "Model Name = %s.\n", eiter->a.model);
1772 
1773 	/* Model description. */
1774 	eiter = entries + size;
1775 	eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
1776 	snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc),
1777 	    "%s", ha->model_desc);
1778 	alen = strlen(eiter->a.model_desc);
1779 	alen += 4 - (alen & 3);
1780 	eiter->len = cpu_to_be16(4 + alen);
1781 	size += 4 + alen;
1782 
1783 	ql_dbg(ql_dbg_disc, vha, 0x20a8,
1784 	    "Model Desc = %s.\n", eiter->a.model_desc);
1785 
1786 	/* Hardware version. */
1787 	eiter = entries + size;
1788 	eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
1789 	if (!IS_FWI2_CAPABLE(ha)) {
1790 		snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
1791 		    "HW:%s", ha->adapter_id);
1792 	} else if (qla2xxx_get_vpd_field(vha, "MN", eiter->a.hw_version,
1793 		    sizeof(eiter->a.hw_version))) {
1794 		;
1795 	} else if (qla2xxx_get_vpd_field(vha, "EC", eiter->a.hw_version,
1796 		    sizeof(eiter->a.hw_version))) {
1797 		;
1798 	} else {
1799 		snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
1800 		    "HW:%s", ha->adapter_id);
1801 	}
1802 	alen = strlen(eiter->a.hw_version);
1803 	alen += 4 - (alen & 3);
1804 	eiter->len = cpu_to_be16(4 + alen);
1805 	size += 4 + alen;
1806 
1807 	ql_dbg(ql_dbg_disc, vha, 0x20a9,
1808 	    "Hardware ver = %s.\n", eiter->a.hw_version);
1809 
1810 	/* Driver version. */
1811 	eiter = entries + size;
1812 	eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
1813 	snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version),
1814 	    "%s", qla2x00_version_str);
1815 	alen = strlen(eiter->a.driver_version);
1816 	alen += 4 - (alen & 3);
1817 	eiter->len = cpu_to_be16(4 + alen);
1818 	size += 4 + alen;
1819 
1820 	ql_dbg(ql_dbg_disc, vha, 0x20aa,
1821 	    "Driver ver = %s.\n", eiter->a.driver_version);
1822 
1823 	/* Option ROM version. */
1824 	eiter = entries + size;
1825 	eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
1826 	snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version),
1827 	    "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
1828 	alen = strlen(eiter->a.orom_version);
1829 	alen += 4 - (alen & 3);
1830 	eiter->len = cpu_to_be16(4 + alen);
1831 	size += 4 + alen;
1832 
1833 	ql_dbg(ql_dbg_disc, vha , 0x20ab,
1834 	    "Optrom version = %d.%02d.\n", eiter->a.orom_version[1],
1835 	    eiter->a.orom_version[0]);
1836 
1837 	/* Firmware version */
1838 	eiter = entries + size;
1839 	eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
1840 	ha->isp_ops->fw_version_str(vha, eiter->a.fw_version,
1841 	    sizeof(eiter->a.fw_version));
1842 	alen = strlen(eiter->a.fw_version);
1843 	alen += 4 - (alen & 3);
1844 	eiter->len = cpu_to_be16(4 + alen);
1845 	size += 4 + alen;
1846 
1847 	ql_dbg(ql_dbg_disc, vha, 0x20ac,
1848 	    "Firmware vers = %s.\n", eiter->a.fw_version);
1849 
1850 	/* OS Name and Version */
1851 	eiter = entries + size;
1852 	eiter->type = cpu_to_be16(FDMI_HBA_OS_NAME_AND_VERSION);
1853 	p_sysid = utsname();
1854 	if (p_sysid) {
1855 		snprintf(eiter->a.os_version, sizeof(eiter->a.os_version),
1856 		    "%s %s %s",
1857 		    p_sysid->sysname, p_sysid->release, p_sysid->version);
1858 	} else {
1859 		snprintf(eiter->a.os_version, sizeof(eiter->a.os_version),
1860 		    "%s %s", "Linux", fc_host_system_hostname(vha->host));
1861 	}
1862 	alen = strlen(eiter->a.os_version);
1863 	alen += 4 - (alen & 3);
1864 	eiter->len = cpu_to_be16(4 + alen);
1865 	size += 4 + alen;
1866 
1867 	ql_dbg(ql_dbg_disc, vha, 0x20ae,
1868 	    "OS Name and Version = %s.\n", eiter->a.os_version);
1869 
1870 	/* MAX CT Payload Length */
1871 	eiter = entries + size;
1872 	eiter->type = cpu_to_be16(FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH);
1873 	eiter->a.max_ct_len = IS_FWI2_CAPABLE(ha) ?
1874 	    le16_to_cpu(icb24->frame_payload_size) :
1875 	    le16_to_cpu(ha->init_cb->frame_payload_size);
1876 	eiter->a.max_ct_len = cpu_to_be32(eiter->a.max_ct_len);
1877 	eiter->len = cpu_to_be16(4 + 4);
1878 	size += 4 + 4;
1879 
1880 	ql_dbg(ql_dbg_disc, vha, 0x20af,
1881 	    "CT Payload Length = 0x%x.\n", eiter->a.max_ct_len);
1882 
1883 	/* Node Sybolic Name */
1884 	eiter = entries + size;
1885 	eiter->type = cpu_to_be16(FDMI_HBA_NODE_SYMBOLIC_NAME);
1886 	qla2x00_get_sym_node_name(vha, eiter->a.sym_name,
1887 	    sizeof(eiter->a.sym_name));
1888 	alen = strlen(eiter->a.sym_name);
1889 	alen += 4 - (alen & 3);
1890 	eiter->len = cpu_to_be16(4 + alen);
1891 	size += 4 + alen;
1892 
1893 	ql_dbg(ql_dbg_disc, vha, 0x20b0,
1894 	    "Symbolic Name = %s.\n", eiter->a.sym_name);
1895 
1896 	/* Vendor Id */
1897 	eiter = entries + size;
1898 	eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_ID);
1899 	eiter->a.vendor_id = cpu_to_be32(0x1077);
1900 	eiter->len = cpu_to_be16(4 + 4);
1901 	size += 4 + 4;
1902 
1903 	ql_dbg(ql_dbg_disc, vha, 0x20b1,
1904 	    "Vendor Id = %x.\n", eiter->a.vendor_id);
1905 
1906 	/* Num Ports */
1907 	eiter = entries + size;
1908 	eiter->type = cpu_to_be16(FDMI_HBA_NUM_PORTS);
1909 	eiter->a.num_ports = cpu_to_be32(1);
1910 	eiter->len = cpu_to_be16(4 + 4);
1911 	size += 4 + 4;
1912 
1913 	ql_dbg(ql_dbg_disc, vha, 0x20b2,
1914 	    "Port Num = %x.\n", eiter->a.num_ports);
1915 
1916 	/* Fabric Name */
1917 	eiter = entries + size;
1918 	eiter->type = cpu_to_be16(FDMI_HBA_FABRIC_NAME);
1919 	memcpy(eiter->a.fabric_name, vha->fabric_node_name, WWN_SIZE);
1920 	eiter->len = cpu_to_be16(4 + WWN_SIZE);
1921 	size += 4 + WWN_SIZE;
1922 
1923 	ql_dbg(ql_dbg_disc, vha, 0x20b3,
1924 	    "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name));
1925 
1926 	/* BIOS Version */
1927 	eiter = entries + size;
1928 	eiter->type = cpu_to_be16(FDMI_HBA_BOOT_BIOS_NAME);
1929 	snprintf(eiter->a.bios_name, sizeof(eiter->a.bios_name),
1930 	    "BIOS %d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
1931 	alen = strlen(eiter->a.bios_name);
1932 	alen += 4 - (alen & 3);
1933 	eiter->len = cpu_to_be16(4 + alen);
1934 	size += 4 + alen;
1935 
1936 	ql_dbg(ql_dbg_disc, vha, 0x20b4,
1937 	    "BIOS Name = %s\n", eiter->a.bios_name);
1938 
1939 	/* Vendor Identifier */
1940 	eiter = entries + size;
1941 	eiter->type = cpu_to_be16(FDMI_HBA_TYPE_VENDOR_IDENTIFIER);
1942 	snprintf(eiter->a.vendor_indentifer, sizeof(eiter->a.vendor_indentifer),
1943 	    "%s", "QLGC");
1944 	alen = strlen(eiter->a.vendor_indentifer);
1945 	alen += 4 - (alen & 3);
1946 	eiter->len = cpu_to_be16(4 + alen);
1947 	size += 4 + alen;
1948 
1949 	ql_dbg(ql_dbg_disc, vha, 0x20b1,
1950 	    "Vendor Identifier = %s.\n", eiter->a.vendor_indentifer);
1951 
1952 	/* Update MS request size. */
1953 	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
1954 
1955 	ql_dbg(ql_dbg_disc, vha, 0x20b5,
1956 	    "RHBA identifier = %016llx.\n",
1957 	    wwn_to_u64(ct_req->req.rhba2.hba_identifier));
1958 	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20b6,
1959 	    entries, size);
1960 
1961 	/* Execute MS IOCB */
1962 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1963 	    sizeof(ms_iocb_entry_t));
1964 	if (rval != QLA_SUCCESS) {
1965 		/*EMPTY*/
1966 		ql_dbg(ql_dbg_disc, vha, 0x20b7,
1967 		    "RHBA issue IOCB failed (%d).\n", rval);
1968 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") !=
1969 	    QLA_SUCCESS) {
1970 		rval = QLA_FUNCTION_FAILED;
1971 
1972 		if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
1973 		    ct_rsp->header.explanation_code ==
1974 		    CT_EXPL_ALREADY_REGISTERED) {
1975 			ql_dbg(ql_dbg_disc, vha, 0x20b8,
1976 			    "HBA already registered.\n");
1977 			rval = QLA_ALREADY_REGISTERED;
1978 		} else {
1979 			ql_dbg(ql_dbg_disc, vha, 0x2016,
1980 			    "RHBA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x\n",
1981 			    ct_rsp->header.reason_code,
1982 			    ct_rsp->header.explanation_code);
1983 		}
1984 	} else {
1985 		ql_dbg(ql_dbg_disc, vha, 0x20b9,
1986 		    "RHBA FDMI V2 exiting normally.\n");
1987 	}
1988 
1989 	return rval;
1990 }
1991 
1992 /**
1993  * qla2x00_fdmi_dhba() -
1994  * @ha: HA context
1995  *
1996  * Returns 0 on success.
1997  */
1998 static int
1999 qla2x00_fdmi_dhba(scsi_qla_host_t *vha)
2000 {
2001 	int rval;
2002 	struct qla_hw_data *ha = vha->hw;
2003 	ms_iocb_entry_t *ms_pkt;
2004 	struct ct_sns_req *ct_req;
2005 	struct ct_sns_rsp *ct_rsp;
2006 
2007 	/* Issue RPA */
2008 	/* Prepare common MS IOCB */
2009 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, DHBA_REQ_SIZE,
2010 	    DHBA_RSP_SIZE);
2011 
2012 	/* Prepare CT request */
2013 	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, DHBA_CMD, DHBA_RSP_SIZE);
2014 	ct_rsp = &ha->ct_sns->p.rsp;
2015 
2016 	/* Prepare FDMI command arguments -- portname. */
2017 	memcpy(ct_req->req.dhba.port_name, vha->port_name, WWN_SIZE);
2018 
2019 	ql_dbg(ql_dbg_disc, vha, 0x2036,
2020 	    "DHBA portname = %8phN.\n", ct_req->req.dhba.port_name);
2021 
2022 	/* Execute MS IOCB */
2023 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2024 	    sizeof(ms_iocb_entry_t));
2025 	if (rval != QLA_SUCCESS) {
2026 		/*EMPTY*/
2027 		ql_dbg(ql_dbg_disc, vha, 0x2037,
2028 		    "DHBA issue IOCB failed (%d).\n", rval);
2029 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "DHBA") !=
2030 	    QLA_SUCCESS) {
2031 		rval = QLA_FUNCTION_FAILED;
2032 	} else {
2033 		ql_dbg(ql_dbg_disc, vha, 0x2038,
2034 		    "DHBA exiting normally.\n");
2035 	}
2036 
2037 	return rval;
2038 }
2039 
2040 /**
2041  * qla2x00_fdmiv2_rpa() -
2042  * @ha: HA context
2043  *
2044  * Returns 0 on success.
2045  */
2046 static int
2047 qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha)
2048 {
2049 	int rval, alen;
2050 	uint32_t size;
2051 	struct qla_hw_data *ha = vha->hw;
2052 	ms_iocb_entry_t *ms_pkt;
2053 	struct ct_sns_req *ct_req;
2054 	struct ct_sns_rsp *ct_rsp;
2055 	void *entries;
2056 	struct ct_fdmiv2_port_attr *eiter;
2057 	struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
2058 	struct new_utsname *p_sysid = NULL;
2059 
2060 	/* Issue RPA */
2061 	/* Prepare common MS IOCB */
2062 	/*   Request size adjusted after CT preparation */
2063 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE);
2064 
2065 	/* Prepare CT request */
2066 	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, RPA_RSP_SIZE);
2067 	ct_rsp = &ha->ct_sns->p.rsp;
2068 
2069 	/* Prepare FDMI command arguments -- attribute block, attributes. */
2070 	memcpy(ct_req->req.rpa2.port_name, vha->port_name, WWN_SIZE);
2071 	size = WWN_SIZE + 4;
2072 
2073 	/* Attributes */
2074 	ct_req->req.rpa2.attrs.count = cpu_to_be32(FDMIV2_PORT_ATTR_COUNT);
2075 	entries = ct_req->req.rpa2.port_name;
2076 
2077 	/* FC4 types. */
2078 	eiter = entries + size;
2079 	eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES);
2080 	eiter->len = cpu_to_be16(4 + 32);
2081 	eiter->a.fc4_types[2] = 0x01;
2082 	size += 4 + 32;
2083 
2084 	ql_dbg(ql_dbg_disc, vha, 0x20ba,
2085 	    "FC4_TYPES=%02x %02x.\n",
2086 	    eiter->a.fc4_types[2],
2087 	    eiter->a.fc4_types[1]);
2088 
2089 	/* Supported speed. */
2090 	eiter = entries + size;
2091 	eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
2092 	eiter->len = cpu_to_be16(4 + 4);
2093 	if (IS_CNA_CAPABLE(ha))
2094 		eiter->a.sup_speed = cpu_to_be32(
2095 		    FDMI_PORT_SPEED_10GB);
2096 	else if (IS_QLA27XX(ha))
2097 		eiter->a.sup_speed = cpu_to_be32(
2098 		    FDMI_PORT_SPEED_32GB|
2099 		    FDMI_PORT_SPEED_16GB|
2100 		    FDMI_PORT_SPEED_8GB);
2101 	else if (IS_QLA2031(ha))
2102 		eiter->a.sup_speed = cpu_to_be32(
2103 		    FDMI_PORT_SPEED_16GB|
2104 		    FDMI_PORT_SPEED_8GB|
2105 		    FDMI_PORT_SPEED_4GB);
2106 	else if (IS_QLA25XX(ha))
2107 		eiter->a.sup_speed = cpu_to_be32(
2108 		    FDMI_PORT_SPEED_8GB|
2109 		    FDMI_PORT_SPEED_4GB|
2110 		    FDMI_PORT_SPEED_2GB|
2111 		    FDMI_PORT_SPEED_1GB);
2112 	else if (IS_QLA24XX_TYPE(ha))
2113 		eiter->a.sup_speed = cpu_to_be32(
2114 		    FDMI_PORT_SPEED_4GB|
2115 		    FDMI_PORT_SPEED_2GB|
2116 		    FDMI_PORT_SPEED_1GB);
2117 	else if (IS_QLA23XX(ha))
2118 		eiter->a.sup_speed = cpu_to_be32(
2119 		    FDMI_PORT_SPEED_2GB|
2120 		    FDMI_PORT_SPEED_1GB);
2121 	else
2122 		eiter->a.sup_speed = cpu_to_be32(
2123 		    FDMI_PORT_SPEED_1GB);
2124 	size += 4 + 4;
2125 
2126 	ql_dbg(ql_dbg_disc, vha, 0x20bb,
2127 	    "Supported Port Speed = %x.\n", eiter->a.sup_speed);
2128 
2129 	/* Current speed. */
2130 	eiter = entries + size;
2131 	eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
2132 	eiter->len = cpu_to_be16(4 + 4);
2133 	switch (ha->link_data_rate) {
2134 	case PORT_SPEED_1GB:
2135 		eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_1GB);
2136 		break;
2137 	case PORT_SPEED_2GB:
2138 		eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_2GB);
2139 		break;
2140 	case PORT_SPEED_4GB:
2141 		eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_4GB);
2142 		break;
2143 	case PORT_SPEED_8GB:
2144 		eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_8GB);
2145 		break;
2146 	case PORT_SPEED_10GB:
2147 		eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_10GB);
2148 		break;
2149 	case PORT_SPEED_16GB:
2150 		eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_16GB);
2151 		break;
2152 	case PORT_SPEED_32GB:
2153 		eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_32GB);
2154 		break;
2155 	default:
2156 		eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN);
2157 		break;
2158 	}
2159 	size += 4 + 4;
2160 
2161 	ql_dbg(ql_dbg_disc, vha, 0x20bc,
2162 	    "Current_Speed = %x.\n", eiter->a.cur_speed);
2163 
2164 	/* Max frame size. */
2165 	eiter = entries + size;
2166 	eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
2167 	eiter->len = cpu_to_be16(4 + 4);
2168 	eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ?
2169 	    le16_to_cpu(icb24->frame_payload_size):
2170 	    le16_to_cpu(ha->init_cb->frame_payload_size);
2171 	eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size);
2172 	size += 4 + 4;
2173 
2174 	ql_dbg(ql_dbg_disc, vha, 0x20bc,
2175 	    "Max_Frame_Size = %x.\n", eiter->a.max_frame_size);
2176 
2177 	/* OS device name. */
2178 	eiter = entries + size;
2179 	eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
2180 	alen = strlen(QLA2XXX_DRIVER_NAME);
2181 	snprintf(eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name),
2182 	    "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no);
2183 	alen += 4 - (alen & 3);
2184 	eiter->len = cpu_to_be16(4 + alen);
2185 	size += 4 + alen;
2186 
2187 	ql_dbg(ql_dbg_disc, vha, 0x20be,
2188 	    "OS_Device_Name = %s.\n", eiter->a.os_dev_name);
2189 
2190 	/* Hostname. */
2191 	eiter = entries + size;
2192 	eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME);
2193 	p_sysid = utsname();
2194 	if (p_sysid) {
2195 		snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
2196 		    "%s", p_sysid->nodename);
2197 	} else {
2198 		snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
2199 		    "%s", fc_host_system_hostname(vha->host));
2200 	}
2201 	alen = strlen(eiter->a.host_name);
2202 	alen += 4 - (alen & 3);
2203 	eiter->len = cpu_to_be16(4 + alen);
2204 	size += 4 + alen;
2205 
2206 	ql_dbg(ql_dbg_disc, vha, 0x203d,
2207 	    "HostName=%s.\n", eiter->a.host_name);
2208 
2209 	/* Node Name */
2210 	eiter = entries + size;
2211 	eiter->type = cpu_to_be16(FDMI_PORT_NODE_NAME);
2212 	memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
2213 	eiter->len = cpu_to_be16(4 + WWN_SIZE);
2214 	size += 4 + WWN_SIZE;
2215 
2216 	ql_dbg(ql_dbg_disc, vha, 0x20c0,
2217 	    "Node Name = %016llx.\n", wwn_to_u64(eiter->a.node_name));
2218 
2219 	/* Port Name */
2220 	eiter = entries + size;
2221 	eiter->type = cpu_to_be16(FDMI_PORT_NAME);
2222 	memcpy(eiter->a.port_name, vha->port_name, WWN_SIZE);
2223 	eiter->len = cpu_to_be16(4 + WWN_SIZE);
2224 	size += 4 + WWN_SIZE;
2225 
2226 	ql_dbg(ql_dbg_disc, vha, 0x20c1,
2227 	    "Port Name = %016llx.\n", wwn_to_u64(eiter->a.port_name));
2228 
2229 	/* Port Symbolic Name */
2230 	eiter = entries + size;
2231 	eiter->type = cpu_to_be16(FDMI_PORT_SYM_NAME);
2232 	qla2x00_get_sym_node_name(vha, eiter->a.port_sym_name,
2233 	    sizeof(eiter->a.port_sym_name));
2234 	alen = strlen(eiter->a.port_sym_name);
2235 	alen += 4 - (alen & 3);
2236 	eiter->len = cpu_to_be16(4 + alen);
2237 	size += 4 + alen;
2238 
2239 	ql_dbg(ql_dbg_disc, vha, 0x20c2,
2240 	    "port symbolic name = %s\n", eiter->a.port_sym_name);
2241 
2242 	/* Port Type */
2243 	eiter = entries + size;
2244 	eiter->type = cpu_to_be16(FDMI_PORT_TYPE);
2245 	eiter->a.port_type = cpu_to_be32(NS_NX_PORT_TYPE);
2246 	eiter->len = cpu_to_be16(4 + 4);
2247 	size += 4 + 4;
2248 
2249 	ql_dbg(ql_dbg_disc, vha, 0x20c3,
2250 	    "Port Type = %x.\n", eiter->a.port_type);
2251 
2252 	/* Class of Service  */
2253 	eiter = entries + size;
2254 	eiter->type = cpu_to_be16(FDMI_PORT_SUPP_COS);
2255 	eiter->a.port_supported_cos = cpu_to_be32(FC_CLASS_3);
2256 	eiter->len = cpu_to_be16(4 + 4);
2257 	size += 4 + 4;
2258 
2259 	ql_dbg(ql_dbg_disc, vha, 0x20c4,
2260 	    "Supported COS = %08x\n", eiter->a.port_supported_cos);
2261 
2262 	/* Port Fabric Name */
2263 	eiter = entries + size;
2264 	eiter->type = cpu_to_be16(FDMI_PORT_FABRIC_NAME);
2265 	memcpy(eiter->a.fabric_name, vha->fabric_node_name, WWN_SIZE);
2266 	eiter->len = cpu_to_be16(4 + WWN_SIZE);
2267 	size += 4 + WWN_SIZE;
2268 
2269 	ql_dbg(ql_dbg_disc, vha, 0x20c5,
2270 	    "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name));
2271 
2272 	/* FC4_type */
2273 	eiter = entries + size;
2274 	eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPE);
2275 	eiter->a.port_fc4_type[0] = 0;
2276 	eiter->a.port_fc4_type[1] = 0;
2277 	eiter->a.port_fc4_type[2] = 1;
2278 	eiter->a.port_fc4_type[3] = 0;
2279 	eiter->len = cpu_to_be16(4 + 32);
2280 	size += 4 + 32;
2281 
2282 	ql_dbg(ql_dbg_disc, vha, 0x20c6,
2283 	    "Port Active FC4 Type = %02x %02x.\n",
2284 	    eiter->a.port_fc4_type[2], eiter->a.port_fc4_type[1]);
2285 
2286 	/* Port State */
2287 	eiter = entries + size;
2288 	eiter->type = cpu_to_be16(FDMI_PORT_STATE);
2289 	eiter->a.port_state = cpu_to_be32(1);
2290 	eiter->len = cpu_to_be16(4 + 4);
2291 	size += 4 + 4;
2292 
2293 	ql_dbg(ql_dbg_disc, vha, 0x20c7,
2294 	    "Port State = %x.\n", eiter->a.port_state);
2295 
2296 	/* Number of Ports */
2297 	eiter = entries + size;
2298 	eiter->type = cpu_to_be16(FDMI_PORT_COUNT);
2299 	eiter->a.num_ports = cpu_to_be32(1);
2300 	eiter->len = cpu_to_be16(4 + 4);
2301 	size += 4 + 4;
2302 
2303 	ql_dbg(ql_dbg_disc, vha, 0x20c8,
2304 	    "Number of ports = %x.\n", eiter->a.num_ports);
2305 
2306 	/* Port Id */
2307 	eiter = entries + size;
2308 	eiter->type = cpu_to_be16(FDMI_PORT_ID);
2309 	eiter->a.port_id = cpu_to_be32(vha->d_id.b24);
2310 	eiter->len = cpu_to_be16(4 + 4);
2311 	size += 4 + 4;
2312 
2313 	ql_dbg(ql_dbg_disc, vha, 0x20c8,
2314 	    "Port Id = %x.\n", eiter->a.port_id);
2315 
2316 	/* Update MS request size. */
2317 	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
2318 
2319 	ql_dbg(ql_dbg_disc, vha, 0x203e,
2320 	    "RPA portname= %8phN size=%d.\n", ct_req->req.rpa.port_name, size);
2321 	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20ca,
2322 	    entries, size);
2323 
2324 	/* Execute MS IOCB */
2325 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2326 	    sizeof(ms_iocb_entry_t));
2327 	if (rval != QLA_SUCCESS) {
2328 		/*EMPTY*/
2329 		ql_dbg(ql_dbg_disc, vha, 0x20cb,
2330 		    "RPA FDMI v2 issue IOCB failed (%d).\n", rval);
2331 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") !=
2332 	    QLA_SUCCESS) {
2333 		rval = QLA_FUNCTION_FAILED;
2334 		if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
2335 		    ct_rsp->header.explanation_code ==
2336 		    CT_EXPL_ALREADY_REGISTERED) {
2337 			ql_dbg(ql_dbg_disc, vha, 0x20ce,
2338 			    "RPA FDMI v2 already registered\n");
2339 			rval = QLA_ALREADY_REGISTERED;
2340 		} else {
2341 			ql_dbg(ql_dbg_disc, vha, 0x2020,
2342 			    "RPA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x\n",
2343 			    ct_rsp->header.reason_code,
2344 			    ct_rsp->header.explanation_code);
2345 		}
2346 	} else {
2347 		ql_dbg(ql_dbg_disc, vha, 0x20cc,
2348 		    "RPA FDMI V2 exiting normally.\n");
2349 	}
2350 
2351 	return rval;
2352 }
2353 
2354 /**
2355  * qla2x00_fdmi_register() -
2356  * @ha: HA context
2357  *
2358  * Returns 0 on success.
2359  */
2360 int
2361 qla2x00_fdmi_register(scsi_qla_host_t *vha)
2362 {
2363 	int rval = QLA_FUNCTION_FAILED;
2364 	struct qla_hw_data *ha = vha->hw;
2365 
2366 	if (IS_QLA2100(ha) || IS_QLA2200(ha) ||
2367 	    IS_QLAFX00(ha))
2368 		return QLA_FUNCTION_FAILED;
2369 
2370 	rval = qla2x00_mgmt_svr_login(vha);
2371 	if (rval)
2372 		return rval;
2373 
2374 	rval = qla2x00_fdmiv2_rhba(vha);
2375 	if (rval) {
2376 		if (rval != QLA_ALREADY_REGISTERED)
2377 			goto try_fdmi;
2378 
2379 		rval = qla2x00_fdmi_dhba(vha);
2380 		if (rval)
2381 			goto try_fdmi;
2382 
2383 		rval = qla2x00_fdmiv2_rhba(vha);
2384 		if (rval)
2385 			goto try_fdmi;
2386 	}
2387 	rval = qla2x00_fdmiv2_rpa(vha);
2388 	if (rval)
2389 		goto try_fdmi;
2390 
2391 	goto out;
2392 
2393 try_fdmi:
2394 	rval = qla2x00_fdmi_rhba(vha);
2395 	if (rval) {
2396 		if (rval != QLA_ALREADY_REGISTERED)
2397 			return rval;
2398 
2399 		rval = qla2x00_fdmi_dhba(vha);
2400 		if (rval)
2401 			return rval;
2402 
2403 		rval = qla2x00_fdmi_rhba(vha);
2404 		if (rval)
2405 			return rval;
2406 	}
2407 	rval = qla2x00_fdmi_rpa(vha);
2408 out:
2409 	return rval;
2410 }
2411 
2412 /**
2413  * qla2x00_gfpn_id() - SNS Get Fabric Port Name (GFPN_ID) query.
2414  * @ha: HA context
2415  * @list: switch info entries to populate
2416  *
2417  * Returns 0 on success.
2418  */
2419 int
2420 qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)
2421 {
2422 	int		rval = QLA_SUCCESS;
2423 	uint16_t	i;
2424 	struct qla_hw_data *ha = vha->hw;
2425 	ms_iocb_entry_t	*ms_pkt;
2426 	struct ct_sns_req	*ct_req;
2427 	struct ct_sns_rsp	*ct_rsp;
2428 
2429 	if (!IS_IIDMA_CAPABLE(ha))
2430 		return QLA_FUNCTION_FAILED;
2431 
2432 	for (i = 0; i < ha->max_fibre_devices; i++) {
2433 		/* Issue GFPN_ID */
2434 		/* Prepare common MS IOCB */
2435 		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFPN_ID_REQ_SIZE,
2436 		    GFPN_ID_RSP_SIZE);
2437 
2438 		/* Prepare CT request */
2439 		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFPN_ID_CMD,
2440 		    GFPN_ID_RSP_SIZE);
2441 		ct_rsp = &ha->ct_sns->p.rsp;
2442 
2443 		/* Prepare CT arguments -- port_id */
2444 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
2445 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
2446 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
2447 
2448 		/* Execute MS IOCB */
2449 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2450 		    sizeof(ms_iocb_entry_t));
2451 		if (rval != QLA_SUCCESS) {
2452 			/*EMPTY*/
2453 			ql_dbg(ql_dbg_disc, vha, 0x2023,
2454 			    "GFPN_ID issue IOCB failed (%d).\n", rval);
2455 			break;
2456 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
2457 		    "GFPN_ID") != QLA_SUCCESS) {
2458 			rval = QLA_FUNCTION_FAILED;
2459 			break;
2460 		} else {
2461 			/* Save fabric portname */
2462 			memcpy(list[i].fabric_port_name,
2463 			    ct_rsp->rsp.gfpn_id.port_name, WWN_SIZE);
2464 		}
2465 
2466 		/* Last device exit. */
2467 		if (list[i].d_id.b.rsvd_1 != 0)
2468 			break;
2469 	}
2470 
2471 	return (rval);
2472 }
2473 
2474 static inline void *
2475 qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *vha, uint32_t req_size,
2476     uint32_t rsp_size)
2477 {
2478 	struct ct_entry_24xx *ct_pkt;
2479 	struct qla_hw_data *ha = vha->hw;
2480 	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
2481 	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
2482 
2483 	ct_pkt->entry_type = CT_IOCB_TYPE;
2484 	ct_pkt->entry_count = 1;
2485 	ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);
2486 	ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
2487 	ct_pkt->cmd_dsd_count = cpu_to_le16(1);
2488 	ct_pkt->rsp_dsd_count = cpu_to_le16(1);
2489 	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
2490 	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
2491 
2492 	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
2493 	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
2494 	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
2495 
2496 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
2497 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
2498 	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
2499 	ct_pkt->vp_index = vha->vp_idx;
2500 
2501 	return ct_pkt;
2502 }
2503 
2504 
2505 static inline struct ct_sns_req *
2506 qla24xx_prep_ct_fm_req(struct ct_sns_pkt *p, uint16_t cmd,
2507     uint16_t rsp_size)
2508 {
2509 	memset(p, 0, sizeof(struct ct_sns_pkt));
2510 
2511 	p->p.req.header.revision = 0x01;
2512 	p->p.req.header.gs_type = 0xFA;
2513 	p->p.req.header.gs_subtype = 0x01;
2514 	p->p.req.command = cpu_to_be16(cmd);
2515 	p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
2516 
2517 	return &p->p.req;
2518 }
2519 
2520 /**
2521  * qla2x00_gpsc() - FCS Get Port Speed Capabilities (GPSC) query.
2522  * @ha: HA context
2523  * @list: switch info entries to populate
2524  *
2525  * Returns 0 on success.
2526  */
2527 int
2528 qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
2529 {
2530 	int		rval;
2531 	uint16_t	i;
2532 	struct qla_hw_data *ha = vha->hw;
2533 	ms_iocb_entry_t	*ms_pkt;
2534 	struct ct_sns_req	*ct_req;
2535 	struct ct_sns_rsp	*ct_rsp;
2536 
2537 	if (!IS_IIDMA_CAPABLE(ha))
2538 		return QLA_FUNCTION_FAILED;
2539 	if (!ha->flags.gpsc_supported)
2540 		return QLA_FUNCTION_FAILED;
2541 
2542 	rval = qla2x00_mgmt_svr_login(vha);
2543 	if (rval)
2544 		return rval;
2545 
2546 	for (i = 0; i < ha->max_fibre_devices; i++) {
2547 		/* Issue GFPN_ID */
2548 		/* Prepare common MS IOCB */
2549 		ms_pkt = qla24xx_prep_ms_fm_iocb(vha, GPSC_REQ_SIZE,
2550 		    GPSC_RSP_SIZE);
2551 
2552 		/* Prepare CT request */
2553 		ct_req = qla24xx_prep_ct_fm_req(ha->ct_sns, GPSC_CMD,
2554 		    GPSC_RSP_SIZE);
2555 		ct_rsp = &ha->ct_sns->p.rsp;
2556 
2557 		/* Prepare CT arguments -- port_name */
2558 		memcpy(ct_req->req.gpsc.port_name, list[i].fabric_port_name,
2559 		    WWN_SIZE);
2560 
2561 		/* Execute MS IOCB */
2562 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2563 		    sizeof(ms_iocb_entry_t));
2564 		if (rval != QLA_SUCCESS) {
2565 			/*EMPTY*/
2566 			ql_dbg(ql_dbg_disc, vha, 0x2059,
2567 			    "GPSC issue IOCB failed (%d).\n", rval);
2568 		} else if ((rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
2569 		    "GPSC")) != QLA_SUCCESS) {
2570 			/* FM command unsupported? */
2571 			if (rval == QLA_INVALID_COMMAND &&
2572 			    (ct_rsp->header.reason_code ==
2573 				CT_REASON_INVALID_COMMAND_CODE ||
2574 			     ct_rsp->header.reason_code ==
2575 				CT_REASON_COMMAND_UNSUPPORTED)) {
2576 				ql_dbg(ql_dbg_disc, vha, 0x205a,
2577 				    "GPSC command unsupported, disabling "
2578 				    "query.\n");
2579 				ha->flags.gpsc_supported = 0;
2580 				rval = QLA_FUNCTION_FAILED;
2581 				break;
2582 			}
2583 			rval = QLA_FUNCTION_FAILED;
2584 		} else {
2585 			/* Save port-speed */
2586 			switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) {
2587 			case BIT_15:
2588 				list[i].fp_speed = PORT_SPEED_1GB;
2589 				break;
2590 			case BIT_14:
2591 				list[i].fp_speed = PORT_SPEED_2GB;
2592 				break;
2593 			case BIT_13:
2594 				list[i].fp_speed = PORT_SPEED_4GB;
2595 				break;
2596 			case BIT_12:
2597 				list[i].fp_speed = PORT_SPEED_10GB;
2598 				break;
2599 			case BIT_11:
2600 				list[i].fp_speed = PORT_SPEED_8GB;
2601 				break;
2602 			case BIT_10:
2603 				list[i].fp_speed = PORT_SPEED_16GB;
2604 				break;
2605 			case BIT_8:
2606 				list[i].fp_speed = PORT_SPEED_32GB;
2607 				break;
2608 			}
2609 
2610 			ql_dbg(ql_dbg_disc, vha, 0x205b,
2611 			    "GPSC ext entry - fpn "
2612 			    "%8phN speeds=%04x speed=%04x.\n",
2613 			    list[i].fabric_port_name,
2614 			    be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
2615 			    be16_to_cpu(ct_rsp->rsp.gpsc.speed));
2616 		}
2617 
2618 		/* Last device exit. */
2619 		if (list[i].d_id.b.rsvd_1 != 0)
2620 			break;
2621 	}
2622 
2623 	return (rval);
2624 }
2625 
2626 /**
2627  * qla2x00_gff_id() - SNS Get FC-4 Features (GFF_ID) query.
2628  *
2629  * @ha: HA context
2630  * @list: switch info entries to populate
2631  *
2632  */
2633 void
2634 qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
2635 {
2636 	int		rval;
2637 	uint16_t	i;
2638 
2639 	ms_iocb_entry_t	*ms_pkt;
2640 	struct ct_sns_req	*ct_req;
2641 	struct ct_sns_rsp	*ct_rsp;
2642 	struct qla_hw_data *ha = vha->hw;
2643 	uint8_t fcp_scsi_features = 0;
2644 
2645 	for (i = 0; i < ha->max_fibre_devices; i++) {
2646 		/* Set default FC4 Type as UNKNOWN so the default is to
2647 		 * Process this port */
2648 		list[i].fc4_type = FC4_TYPE_UNKNOWN;
2649 
2650 		/* Do not attempt GFF_ID if we are not FWI_2 capable */
2651 		if (!IS_FWI2_CAPABLE(ha))
2652 			continue;
2653 
2654 		/* Prepare common MS IOCB */
2655 		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFF_ID_REQ_SIZE,
2656 		    GFF_ID_RSP_SIZE);
2657 
2658 		/* Prepare CT request */
2659 		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFF_ID_CMD,
2660 		    GFF_ID_RSP_SIZE);
2661 		ct_rsp = &ha->ct_sns->p.rsp;
2662 
2663 		/* Prepare CT arguments -- port_id */
2664 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
2665 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
2666 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
2667 
2668 		/* Execute MS IOCB */
2669 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2670 		   sizeof(ms_iocb_entry_t));
2671 
2672 		if (rval != QLA_SUCCESS) {
2673 			ql_dbg(ql_dbg_disc, vha, 0x205c,
2674 			    "GFF_ID issue IOCB failed (%d).\n", rval);
2675 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
2676 			       "GFF_ID") != QLA_SUCCESS) {
2677 			ql_dbg(ql_dbg_disc, vha, 0x205d,
2678 			    "GFF_ID IOCB status had a failure status code.\n");
2679 		} else {
2680 			fcp_scsi_features =
2681 			   ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
2682 			fcp_scsi_features &= 0x0f;
2683 
2684 			if (fcp_scsi_features)
2685 				list[i].fc4_type = FC4_TYPE_FCP_SCSI;
2686 			else
2687 				list[i].fc4_type = FC4_TYPE_OTHER;
2688 		}
2689 
2690 		/* Last device exit. */
2691 		if (list[i].d_id.b.rsvd_1 != 0)
2692 			break;
2693 	}
2694 }
2695