• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * QLogic Fibre Channel HBA Driver
3  * Copyright (c)  2003-2011 QLogic Corporation
4  *
5  * See LICENSE.qla2xxx for copyright and licensing details.
6  */
7 #include "qla_def.h"
8 
9 static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *);
10 static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *);
11 static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *);
12 static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *);
13 static int qla2x00_sns_rft_id(scsi_qla_host_t *);
14 static int qla2x00_sns_rnn_id(scsi_qla_host_t *);
15 
16 /**
17  * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query.
18  * @ha: HA context
19  * @req_size: request size in bytes
20  * @rsp_size: response size in bytes
21  *
22  * Returns a pointer to the @ha's ms_iocb.
23  */
24 void *
qla2x00_prep_ms_iocb(scsi_qla_host_t * vha,uint32_t req_size,uint32_t rsp_size)25 qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
26 {
27 	struct qla_hw_data *ha = vha->hw;
28 	ms_iocb_entry_t *ms_pkt;
29 
30 	ms_pkt = ha->ms_iocb;
31 	memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
32 
33 	ms_pkt->entry_type = MS_IOCB_TYPE;
34 	ms_pkt->entry_count = 1;
35 	SET_TARGET_ID(ha, ms_pkt->loop_id, SIMPLE_NAME_SERVER);
36 	ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG);
37 	ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
38 	ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
39 	ms_pkt->total_dsd_count = __constant_cpu_to_le16(2);
40 	ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
41 	ms_pkt->req_bytecount = cpu_to_le32(req_size);
42 
43 	ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
44 	ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
45 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
46 
47 	ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
48 	ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
49 	ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
50 
51 	return (ms_pkt);
52 }
53 
54 /**
55  * qla24xx_prep_ms_iocb() - Prepare common CT IOCB fields for SNS CT query.
56  * @ha: HA context
57  * @req_size: request size in bytes
58  * @rsp_size: response size in bytes
59  *
60  * Returns a pointer to the @ha's ms_iocb.
61  */
62 void *
qla24xx_prep_ms_iocb(scsi_qla_host_t * vha,uint32_t req_size,uint32_t rsp_size)63 qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
64 {
65 	struct qla_hw_data *ha = vha->hw;
66 	struct ct_entry_24xx *ct_pkt;
67 
68 	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
69 	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
70 
71 	ct_pkt->entry_type = CT_IOCB_TYPE;
72 	ct_pkt->entry_count = 1;
73 	ct_pkt->nport_handle = __constant_cpu_to_le16(NPH_SNS);
74 	ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
75 	ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
76 	ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
77 	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
78 	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
79 
80 	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
81 	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
82 	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
83 
84 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
85 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
86 	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
87 	ct_pkt->vp_index = vha->vp_idx;
88 
89 	return (ct_pkt);
90 }
91 
92 /**
93  * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
94  * @ct_req: CT request buffer
95  * @cmd: GS command
96  * @rsp_size: response size in bytes
97  *
98  * Returns a pointer to the intitialized @ct_req.
99  */
100 static inline struct ct_sns_req *
qla2x00_prep_ct_req(struct ct_sns_req * ct_req,uint16_t cmd,uint16_t rsp_size)101 qla2x00_prep_ct_req(struct ct_sns_req *ct_req, uint16_t cmd, uint16_t rsp_size)
102 {
103 	memset(ct_req, 0, sizeof(struct ct_sns_pkt));
104 
105 	ct_req->header.revision = 0x01;
106 	ct_req->header.gs_type = 0xFC;
107 	ct_req->header.gs_subtype = 0x02;
108 	ct_req->command = cpu_to_be16(cmd);
109 	ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
110 
111 	return (ct_req);
112 }
113 
114 static int
qla2x00_chk_ms_status(scsi_qla_host_t * vha,ms_iocb_entry_t * ms_pkt,struct ct_sns_rsp * ct_rsp,const char * routine)115 qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
116     struct ct_sns_rsp *ct_rsp, const char *routine)
117 {
118 	int rval;
119 	uint16_t comp_status;
120 	struct qla_hw_data *ha = vha->hw;
121 
122 	rval = QLA_FUNCTION_FAILED;
123 	if (ms_pkt->entry_status != 0) {
124 		ql_dbg(ql_dbg_disc, vha, 0x2031,
125 		    "%s failed, error status (%x) on port_id: %02x%02x%02x.\n",
126 		    routine, ms_pkt->entry_status, vha->d_id.b.domain,
127 		    vha->d_id.b.area, vha->d_id.b.al_pa);
128 	} else {
129 		if (IS_FWI2_CAPABLE(ha))
130 			comp_status = le16_to_cpu(
131 			    ((struct ct_entry_24xx *)ms_pkt)->comp_status);
132 		else
133 			comp_status = le16_to_cpu(ms_pkt->status);
134 		switch (comp_status) {
135 		case CS_COMPLETE:
136 		case CS_DATA_UNDERRUN:
137 		case CS_DATA_OVERRUN:		/* Overrun? */
138 			if (ct_rsp->header.response !=
139 			    __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
140 				ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2077,
141 				    "%s failed rejected request on port_id: "
142 				    "%02x%02x%02x.\n", routine,
143 				    vha->d_id.b.domain, vha->d_id.b.area,
144 				    vha->d_id.b.al_pa);
145 				ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha,
146 				    0x2078, (uint8_t *)&ct_rsp->header,
147 				    sizeof(struct ct_rsp_hdr));
148 				rval = QLA_INVALID_COMMAND;
149 			} else
150 				rval = QLA_SUCCESS;
151 			break;
152 		default:
153 			ql_dbg(ql_dbg_disc, vha, 0x2033,
154 			    "%s failed, completion status (%x) on port_id: "
155 			    "%02x%02x%02x.\n", routine, comp_status,
156 			    vha->d_id.b.domain, vha->d_id.b.area,
157 			    vha->d_id.b.al_pa);
158 			break;
159 		}
160 	}
161 	return rval;
162 }
163 
164 /**
165  * qla2x00_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
166  * @ha: HA context
167  * @fcport: fcport entry to updated
168  *
169  * Returns 0 on success.
170  */
171 int
qla2x00_ga_nxt(scsi_qla_host_t * vha,fc_port_t * fcport)172 qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
173 {
174 	int		rval;
175 
176 	ms_iocb_entry_t	*ms_pkt;
177 	struct ct_sns_req	*ct_req;
178 	struct ct_sns_rsp	*ct_rsp;
179 	struct qla_hw_data *ha = vha->hw;
180 
181 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
182 		return qla2x00_sns_ga_nxt(vha, fcport);
183 
184 	/* Issue GA_NXT */
185 	/* Prepare common MS IOCB */
186 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GA_NXT_REQ_SIZE,
187 	    GA_NXT_RSP_SIZE);
188 
189 	/* Prepare CT request */
190 	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GA_NXT_CMD,
191 	    GA_NXT_RSP_SIZE);
192 	ct_rsp = &ha->ct_sns->p.rsp;
193 
194 	/* Prepare CT arguments -- port_id */
195 	ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain;
196 	ct_req->req.port_id.port_id[1] = fcport->d_id.b.area;
197 	ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa;
198 
199 	/* Execute MS IOCB */
200 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
201 	    sizeof(ms_iocb_entry_t));
202 	if (rval != QLA_SUCCESS) {
203 		/*EMPTY*/
204 		ql_dbg(ql_dbg_disc, vha, 0x2062,
205 		    "GA_NXT issue IOCB failed (%d).\n", rval);
206 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GA_NXT") !=
207 	    QLA_SUCCESS) {
208 		rval = QLA_FUNCTION_FAILED;
209 	} else {
210 		/* Populate fc_port_t entry. */
211 		fcport->d_id.b.domain = ct_rsp->rsp.ga_nxt.port_id[0];
212 		fcport->d_id.b.area = ct_rsp->rsp.ga_nxt.port_id[1];
213 		fcport->d_id.b.al_pa = ct_rsp->rsp.ga_nxt.port_id[2];
214 
215 		memcpy(fcport->node_name, ct_rsp->rsp.ga_nxt.node_name,
216 		    WWN_SIZE);
217 		memcpy(fcport->port_name, ct_rsp->rsp.ga_nxt.port_name,
218 		    WWN_SIZE);
219 
220 		if (ct_rsp->rsp.ga_nxt.port_type != NS_N_PORT_TYPE &&
221 		    ct_rsp->rsp.ga_nxt.port_type != NS_NL_PORT_TYPE)
222 			fcport->d_id.b.domain = 0xf0;
223 
224 		ql_dbg(ql_dbg_disc, vha, 0x2063,
225 		    "GA_NXT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
226 		    "pn %02x%02x%02x%02x%02x%02x%02x%02x "
227 		    "port_id=%02x%02x%02x.\n",
228 		    fcport->node_name[0], fcport->node_name[1],
229 		    fcport->node_name[2], fcport->node_name[3],
230 		    fcport->node_name[4], fcport->node_name[5],
231 		    fcport->node_name[6], fcport->node_name[7],
232 		    fcport->port_name[0], fcport->port_name[1],
233 		    fcport->port_name[2], fcport->port_name[3],
234 		    fcport->port_name[4], fcport->port_name[5],
235 		    fcport->port_name[6], fcport->port_name[7],
236 		    fcport->d_id.b.domain, fcport->d_id.b.area,
237 		    fcport->d_id.b.al_pa);
238 	}
239 
240 	return (rval);
241 }
242 
243 static inline int
qla2x00_gid_pt_rsp_size(scsi_qla_host_t * vha)244 qla2x00_gid_pt_rsp_size(scsi_qla_host_t *vha)
245 {
246 	return vha->hw->max_fibre_devices * 4 + 16;
247 }
248 
249 /**
250  * qla2x00_gid_pt() - SNS scan for fabric devices via GID_PT command.
251  * @ha: HA context
252  * @list: switch info entries to populate
253  *
254  * NOTE: Non-Nx_Ports are not requested.
255  *
256  * Returns 0 on success.
257  */
258 int
qla2x00_gid_pt(scsi_qla_host_t * vha,sw_info_t * list)259 qla2x00_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
260 {
261 	int		rval;
262 	uint16_t	i;
263 
264 	ms_iocb_entry_t	*ms_pkt;
265 	struct ct_sns_req	*ct_req;
266 	struct ct_sns_rsp	*ct_rsp;
267 
268 	struct ct_sns_gid_pt_data *gid_data;
269 	struct qla_hw_data *ha = vha->hw;
270 	uint16_t gid_pt_rsp_size;
271 
272 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
273 		return qla2x00_sns_gid_pt(vha, list);
274 
275 	gid_data = NULL;
276 	gid_pt_rsp_size = qla2x00_gid_pt_rsp_size(vha);
277 	/* Issue GID_PT */
278 	/* Prepare common MS IOCB */
279 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GID_PT_REQ_SIZE,
280 	    gid_pt_rsp_size);
281 
282 	/* Prepare CT request */
283 	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GID_PT_CMD,
284 	    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
qla2x00_gpn_id(scsi_qla_host_t * vha,sw_info_t * list)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->p.req, 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
qla2x00_gnn_id(scsi_qla_host_t * vha,sw_info_t * list)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->p.req, 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 %02x%02x%02x%02x%02x%02x%02X%02x "
448 			    "pn %02x%02x%02x%02x%02x%02x%02X%02x "
449 			    "portid=%02x%02x%02x.\n",
450 			    list[i].node_name[0], list[i].node_name[1],
451 			    list[i].node_name[2], list[i].node_name[3],
452 			    list[i].node_name[4], list[i].node_name[5],
453 			    list[i].node_name[6], list[i].node_name[7],
454 			    list[i].port_name[0], list[i].port_name[1],
455 			    list[i].port_name[2], list[i].port_name[3],
456 			    list[i].port_name[4], list[i].port_name[5],
457 			    list[i].port_name[6], list[i].port_name[7],
458 			    list[i].d_id.b.domain, list[i].d_id.b.area,
459 			    list[i].d_id.b.al_pa);
460 		}
461 
462 		/* Last device exit. */
463 		if (list[i].d_id.b.rsvd_1 != 0)
464 			break;
465 	}
466 
467 	return (rval);
468 }
469 
470 /**
471  * qla2x00_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
472  * @ha: HA context
473  *
474  * Returns 0 on success.
475  */
476 int
qla2x00_rft_id(scsi_qla_host_t * vha)477 qla2x00_rft_id(scsi_qla_host_t *vha)
478 {
479 	int		rval;
480 	struct qla_hw_data *ha = vha->hw;
481 	ms_iocb_entry_t	*ms_pkt;
482 	struct ct_sns_req	*ct_req;
483 	struct ct_sns_rsp	*ct_rsp;
484 
485 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
486 		return qla2x00_sns_rft_id(vha);
487 
488 	/* Issue RFT_ID */
489 	/* Prepare common MS IOCB */
490 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFT_ID_REQ_SIZE,
491 	    RFT_ID_RSP_SIZE);
492 
493 	/* Prepare CT request */
494 	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFT_ID_CMD,
495 	    RFT_ID_RSP_SIZE);
496 	ct_rsp = &ha->ct_sns->p.rsp;
497 
498 	/* Prepare CT arguments -- port_id, FC-4 types */
499 	ct_req->req.rft_id.port_id[0] = vha->d_id.b.domain;
500 	ct_req->req.rft_id.port_id[1] = vha->d_id.b.area;
501 	ct_req->req.rft_id.port_id[2] = vha->d_id.b.al_pa;
502 
503 	ct_req->req.rft_id.fc4_types[2] = 0x01;		/* FCP-3 */
504 
505 	/* Execute MS IOCB */
506 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
507 	    sizeof(ms_iocb_entry_t));
508 	if (rval != QLA_SUCCESS) {
509 		/*EMPTY*/
510 		ql_dbg(ql_dbg_disc, vha, 0x2043,
511 		    "RFT_ID issue IOCB failed (%d).\n", rval);
512 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFT_ID") !=
513 	    QLA_SUCCESS) {
514 		rval = QLA_FUNCTION_FAILED;
515 	} else {
516 		ql_dbg(ql_dbg_disc, vha, 0x2044,
517 		    "RFT_ID exiting normally.\n");
518 	}
519 
520 	return (rval);
521 }
522 
523 /**
524  * qla2x00_rff_id() - SNS Register FC-4 Features (RFF_ID) supported by the HBA.
525  * @ha: HA context
526  *
527  * Returns 0 on success.
528  */
529 int
qla2x00_rff_id(scsi_qla_host_t * vha)530 qla2x00_rff_id(scsi_qla_host_t *vha)
531 {
532 	int		rval;
533 	struct qla_hw_data *ha = vha->hw;
534 	ms_iocb_entry_t	*ms_pkt;
535 	struct ct_sns_req	*ct_req;
536 	struct ct_sns_rsp	*ct_rsp;
537 
538 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
539 		ql_dbg(ql_dbg_disc, vha, 0x2046,
540 		    "RFF_ID call not supported on ISP2100/ISP2200.\n");
541 		return (QLA_SUCCESS);
542 	}
543 
544 	/* Issue RFF_ID */
545 	/* Prepare common MS IOCB */
546 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFF_ID_REQ_SIZE,
547 	    RFF_ID_RSP_SIZE);
548 
549 	/* Prepare CT request */
550 	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFF_ID_CMD,
551 	    RFF_ID_RSP_SIZE);
552 	ct_rsp = &ha->ct_sns->p.rsp;
553 
554 	/* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */
555 	ct_req->req.rff_id.port_id[0] = vha->d_id.b.domain;
556 	ct_req->req.rff_id.port_id[1] = vha->d_id.b.area;
557 	ct_req->req.rff_id.port_id[2] = vha->d_id.b.al_pa;
558 
559 	ct_req->req.rff_id.fc4_feature = BIT_1;
560 	ct_req->req.rff_id.fc4_type = 0x08;		/* SCSI - FCP */
561 
562 	/* Execute MS IOCB */
563 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
564 	    sizeof(ms_iocb_entry_t));
565 	if (rval != QLA_SUCCESS) {
566 		/*EMPTY*/
567 		ql_dbg(ql_dbg_disc, vha, 0x2047,
568 		    "RFF_ID issue IOCB failed (%d).\n", rval);
569 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFF_ID") !=
570 	    QLA_SUCCESS) {
571 		rval = QLA_FUNCTION_FAILED;
572 	} else {
573 		ql_dbg(ql_dbg_disc, vha, 0x2048,
574 		    "RFF_ID exiting normally.\n");
575 	}
576 
577 	return (rval);
578 }
579 
580 /**
581  * qla2x00_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
582  * @ha: HA context
583  *
584  * Returns 0 on success.
585  */
586 int
qla2x00_rnn_id(scsi_qla_host_t * vha)587 qla2x00_rnn_id(scsi_qla_host_t *vha)
588 {
589 	int		rval;
590 	struct qla_hw_data *ha = vha->hw;
591 	ms_iocb_entry_t	*ms_pkt;
592 	struct ct_sns_req	*ct_req;
593 	struct ct_sns_rsp	*ct_rsp;
594 
595 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
596 		return qla2x00_sns_rnn_id(vha);
597 
598 	/* Issue RNN_ID */
599 	/* Prepare common MS IOCB */
600 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RNN_ID_REQ_SIZE,
601 	    RNN_ID_RSP_SIZE);
602 
603 	/* Prepare CT request */
604 	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RNN_ID_CMD,
605 	    RNN_ID_RSP_SIZE);
606 	ct_rsp = &ha->ct_sns->p.rsp;
607 
608 	/* Prepare CT arguments -- port_id, node_name */
609 	ct_req->req.rnn_id.port_id[0] = vha->d_id.b.domain;
610 	ct_req->req.rnn_id.port_id[1] = vha->d_id.b.area;
611 	ct_req->req.rnn_id.port_id[2] = vha->d_id.b.al_pa;
612 
613 	memcpy(ct_req->req.rnn_id.node_name, vha->node_name, WWN_SIZE);
614 
615 	/* Execute MS IOCB */
616 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
617 	    sizeof(ms_iocb_entry_t));
618 	if (rval != QLA_SUCCESS) {
619 		/*EMPTY*/
620 		ql_dbg(ql_dbg_disc, vha, 0x204d,
621 		    "RNN_ID issue IOCB failed (%d).\n", rval);
622 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RNN_ID") !=
623 	    QLA_SUCCESS) {
624 		rval = QLA_FUNCTION_FAILED;
625 	} else {
626 		ql_dbg(ql_dbg_disc, vha, 0x204e,
627 		    "RNN_ID exiting normally.\n");
628 	}
629 
630 	return (rval);
631 }
632 
633 void
qla2x00_get_sym_node_name(scsi_qla_host_t * vha,uint8_t * snn)634 qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn)
635 {
636 	struct qla_hw_data *ha = vha->hw;
637 	sprintf(snn, "%s FW:v%d.%02d.%02d DVR:v%s",ha->model_number,
638 	    ha->fw_major_version, ha->fw_minor_version,
639 	    ha->fw_subminor_version, qla2x00_version_str);
640 }
641 
642 /**
643  * qla2x00_rsnn_nn() - SNS Register Symbolic Node Name (RSNN_NN) of the HBA.
644  * @ha: HA context
645  *
646  * Returns 0 on success.
647  */
648 int
qla2x00_rsnn_nn(scsi_qla_host_t * vha)649 qla2x00_rsnn_nn(scsi_qla_host_t *vha)
650 {
651 	int		rval;
652 	struct qla_hw_data *ha = vha->hw;
653 	ms_iocb_entry_t	*ms_pkt;
654 	struct ct_sns_req	*ct_req;
655 	struct ct_sns_rsp	*ct_rsp;
656 
657 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
658 		ql_dbg(ql_dbg_disc, vha, 0x2050,
659 		    "RSNN_ID call unsupported on ISP2100/ISP2200.\n");
660 		return (QLA_SUCCESS);
661 	}
662 
663 	/* Issue RSNN_NN */
664 	/* Prepare common MS IOCB */
665 	/*   Request size adjusted after CT preparation */
666 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, 0, RSNN_NN_RSP_SIZE);
667 
668 	/* Prepare CT request */
669 	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RSNN_NN_CMD,
670 	    RSNN_NN_RSP_SIZE);
671 	ct_rsp = &ha->ct_sns->p.rsp;
672 
673 	/* Prepare CT arguments -- node_name, symbolic node_name, size */
674 	memcpy(ct_req->req.rsnn_nn.node_name, vha->node_name, WWN_SIZE);
675 
676 	/* Prepare the Symbolic Node Name */
677 	qla2x00_get_sym_node_name(vha, ct_req->req.rsnn_nn.sym_node_name);
678 
679 	/* Calculate SNN length */
680 	ct_req->req.rsnn_nn.name_len =
681 	    (uint8_t)strlen(ct_req->req.rsnn_nn.sym_node_name);
682 
683 	/* Update MS IOCB request */
684 	ms_pkt->req_bytecount =
685 	    cpu_to_le32(24 + 1 + ct_req->req.rsnn_nn.name_len);
686 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
687 
688 	/* Execute MS IOCB */
689 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
690 	    sizeof(ms_iocb_entry_t));
691 	if (rval != QLA_SUCCESS) {
692 		/*EMPTY*/
693 		ql_dbg(ql_dbg_disc, vha, 0x2051,
694 		    "RSNN_NN issue IOCB failed (%d).\n", rval);
695 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RSNN_NN") !=
696 	    QLA_SUCCESS) {
697 		rval = QLA_FUNCTION_FAILED;
698 	} else {
699 		ql_dbg(ql_dbg_disc, vha, 0x2052,
700 		    "RSNN_NN exiting normally.\n");
701 	}
702 
703 	return (rval);
704 }
705 
706 /**
707  * qla2x00_prep_sns_cmd() - Prepare common SNS command request fields for query.
708  * @ha: HA context
709  * @cmd: GS command
710  * @scmd_len: Subcommand length
711  * @data_size: response size in bytes
712  *
713  * Returns a pointer to the @ha's sns_cmd.
714  */
715 static inline struct sns_cmd_pkt *
qla2x00_prep_sns_cmd(scsi_qla_host_t * vha,uint16_t cmd,uint16_t scmd_len,uint16_t data_size)716 qla2x00_prep_sns_cmd(scsi_qla_host_t *vha, uint16_t cmd, uint16_t scmd_len,
717     uint16_t data_size)
718 {
719 	uint16_t		wc;
720 	struct sns_cmd_pkt	*sns_cmd;
721 	struct qla_hw_data *ha = vha->hw;
722 
723 	sns_cmd = ha->sns_cmd;
724 	memset(sns_cmd, 0, sizeof(struct sns_cmd_pkt));
725 	wc = data_size / 2;			/* Size in 16bit words. */
726 	sns_cmd->p.cmd.buffer_length = cpu_to_le16(wc);
727 	sns_cmd->p.cmd.buffer_address[0] = cpu_to_le32(LSD(ha->sns_cmd_dma));
728 	sns_cmd->p.cmd.buffer_address[1] = cpu_to_le32(MSD(ha->sns_cmd_dma));
729 	sns_cmd->p.cmd.subcommand_length = cpu_to_le16(scmd_len);
730 	sns_cmd->p.cmd.subcommand = cpu_to_le16(cmd);
731 	wc = (data_size - 16) / 4;		/* Size in 32bit words. */
732 	sns_cmd->p.cmd.size = cpu_to_le16(wc);
733 
734 	return (sns_cmd);
735 }
736 
737 /**
738  * qla2x00_sns_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
739  * @ha: HA context
740  * @fcport: fcport entry to updated
741  *
742  * This command uses the old Exectute SNS Command mailbox routine.
743  *
744  * Returns 0 on success.
745  */
746 static int
qla2x00_sns_ga_nxt(scsi_qla_host_t * vha,fc_port_t * fcport)747 qla2x00_sns_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
748 {
749 	int		rval = QLA_SUCCESS;
750 	struct qla_hw_data *ha = vha->hw;
751 	struct sns_cmd_pkt	*sns_cmd;
752 
753 	/* Issue GA_NXT. */
754 	/* Prepare SNS command request. */
755 	sns_cmd = qla2x00_prep_sns_cmd(vha, GA_NXT_CMD, GA_NXT_SNS_SCMD_LEN,
756 	    GA_NXT_SNS_DATA_SIZE);
757 
758 	/* Prepare SNS command arguments -- port_id. */
759 	sns_cmd->p.cmd.param[0] = fcport->d_id.b.al_pa;
760 	sns_cmd->p.cmd.param[1] = fcport->d_id.b.area;
761 	sns_cmd->p.cmd.param[2] = fcport->d_id.b.domain;
762 
763 	/* Execute SNS command. */
764 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GA_NXT_SNS_CMD_SIZE / 2,
765 	    sizeof(struct sns_cmd_pkt));
766 	if (rval != QLA_SUCCESS) {
767 		/*EMPTY*/
768 		ql_dbg(ql_dbg_disc, vha, 0x205f,
769 		    "GA_NXT Send SNS failed (%d).\n", rval);
770 	} else if (sns_cmd->p.gan_data[8] != 0x80 ||
771 	    sns_cmd->p.gan_data[9] != 0x02) {
772 		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2084,
773 		    "GA_NXT failed, rejected request ga_nxt_rsp:\n");
774 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2074,
775 		    sns_cmd->p.gan_data, 16);
776 		rval = QLA_FUNCTION_FAILED;
777 	} else {
778 		/* Populate fc_port_t entry. */
779 		fcport->d_id.b.domain = sns_cmd->p.gan_data[17];
780 		fcport->d_id.b.area = sns_cmd->p.gan_data[18];
781 		fcport->d_id.b.al_pa = sns_cmd->p.gan_data[19];
782 
783 		memcpy(fcport->node_name, &sns_cmd->p.gan_data[284], WWN_SIZE);
784 		memcpy(fcport->port_name, &sns_cmd->p.gan_data[20], WWN_SIZE);
785 
786 		if (sns_cmd->p.gan_data[16] != NS_N_PORT_TYPE &&
787 		    sns_cmd->p.gan_data[16] != NS_NL_PORT_TYPE)
788 			fcport->d_id.b.domain = 0xf0;
789 
790 		ql_dbg(ql_dbg_disc, vha, 0x2061,
791 		    "GA_NXT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
792 		    "pn %02x%02x%02x%02x%02x%02x%02x%02x "
793 		    "port_id=%02x%02x%02x.\n",
794 		    fcport->node_name[0], fcport->node_name[1],
795 		    fcport->node_name[2], fcport->node_name[3],
796 		    fcport->node_name[4], fcport->node_name[5],
797 		    fcport->node_name[6], fcport->node_name[7],
798 		    fcport->port_name[0], fcport->port_name[1],
799 		    fcport->port_name[2], fcport->port_name[3],
800 		    fcport->port_name[4], fcport->port_name[5],
801 		    fcport->port_name[6], fcport->port_name[7],
802 		    fcport->d_id.b.domain, fcport->d_id.b.area,
803 		    fcport->d_id.b.al_pa);
804 	}
805 
806 	return (rval);
807 }
808 
809 /**
810  * qla2x00_sns_gid_pt() - SNS scan for fabric devices via GID_PT command.
811  * @ha: HA context
812  * @list: switch info entries to populate
813  *
814  * This command uses the old Exectute SNS Command mailbox routine.
815  *
816  * NOTE: Non-Nx_Ports are not requested.
817  *
818  * Returns 0 on success.
819  */
820 static int
qla2x00_sns_gid_pt(scsi_qla_host_t * vha,sw_info_t * list)821 qla2x00_sns_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
822 {
823 	int		rval;
824 	struct qla_hw_data *ha = vha->hw;
825 	uint16_t	i;
826 	uint8_t		*entry;
827 	struct sns_cmd_pkt	*sns_cmd;
828 	uint16_t gid_pt_sns_data_size;
829 
830 	gid_pt_sns_data_size = qla2x00_gid_pt_rsp_size(vha);
831 
832 	/* Issue GID_PT. */
833 	/* Prepare SNS command request. */
834 	sns_cmd = qla2x00_prep_sns_cmd(vha, GID_PT_CMD, GID_PT_SNS_SCMD_LEN,
835 	    gid_pt_sns_data_size);
836 
837 	/* Prepare SNS command arguments -- port_type. */
838 	sns_cmd->p.cmd.param[0] = NS_NX_PORT_TYPE;
839 
840 	/* Execute SNS command. */
841 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GID_PT_SNS_CMD_SIZE / 2,
842 	    sizeof(struct sns_cmd_pkt));
843 	if (rval != QLA_SUCCESS) {
844 		/*EMPTY*/
845 		ql_dbg(ql_dbg_disc, vha, 0x206d,
846 		    "GID_PT Send SNS failed (%d).\n", rval);
847 	} else if (sns_cmd->p.gid_data[8] != 0x80 ||
848 	    sns_cmd->p.gid_data[9] != 0x02) {
849 		ql_dbg(ql_dbg_disc, vha, 0x202f,
850 		    "GID_PT failed, rejected request, gid_rsp:\n");
851 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2081,
852 		    sns_cmd->p.gid_data, 16);
853 		rval = QLA_FUNCTION_FAILED;
854 	} else {
855 		/* Set port IDs in switch info list. */
856 		for (i = 0; i < ha->max_fibre_devices; i++) {
857 			entry = &sns_cmd->p.gid_data[(i * 4) + 16];
858 			list[i].d_id.b.domain = entry[1];
859 			list[i].d_id.b.area = entry[2];
860 			list[i].d_id.b.al_pa = entry[3];
861 
862 			/* Last one exit. */
863 			if (entry[0] & BIT_7) {
864 				list[i].d_id.b.rsvd_1 = entry[0];
865 				break;
866 			}
867 		}
868 
869 		/*
870 		 * If we've used all available slots, then the switch is
871 		 * reporting back more devices that we can handle with this
872 		 * single call.  Return a failed status, and let GA_NXT handle
873 		 * the overload.
874 		 */
875 		if (i == ha->max_fibre_devices)
876 			rval = QLA_FUNCTION_FAILED;
877 	}
878 
879 	return (rval);
880 }
881 
882 /**
883  * qla2x00_sns_gpn_id() - SNS Get Port Name (GPN_ID) query.
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  * Returns 0 on success.
890  */
891 static int
qla2x00_sns_gpn_id(scsi_qla_host_t * vha,sw_info_t * list)892 qla2x00_sns_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
893 {
894 	int		rval = QLA_SUCCESS;
895 	struct qla_hw_data *ha = vha->hw;
896 	uint16_t	i;
897 	struct sns_cmd_pkt	*sns_cmd;
898 
899 	for (i = 0; i < ha->max_fibre_devices; i++) {
900 		/* Issue GPN_ID */
901 		/* Prepare SNS command request. */
902 		sns_cmd = qla2x00_prep_sns_cmd(vha, GPN_ID_CMD,
903 		    GPN_ID_SNS_SCMD_LEN, GPN_ID_SNS_DATA_SIZE);
904 
905 		/* Prepare SNS command arguments -- port_id. */
906 		sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
907 		sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
908 		sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
909 
910 		/* Execute SNS command. */
911 		rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,
912 		    GPN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
913 		if (rval != QLA_SUCCESS) {
914 			/*EMPTY*/
915 			ql_dbg(ql_dbg_disc, vha, 0x2032,
916 			    "GPN_ID Send SNS failed (%d).\n", rval);
917 		} else if (sns_cmd->p.gpn_data[8] != 0x80 ||
918 		    sns_cmd->p.gpn_data[9] != 0x02) {
919 			ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207e,
920 			    "GPN_ID failed, rejected request, gpn_rsp:\n");
921 			ql_dump_buffer(ql_dbg_disc, vha, 0x207f,
922 			    sns_cmd->p.gpn_data, 16);
923 			rval = QLA_FUNCTION_FAILED;
924 		} else {
925 			/* Save portname */
926 			memcpy(list[i].port_name, &sns_cmd->p.gpn_data[16],
927 			    WWN_SIZE);
928 		}
929 
930 		/* Last device exit. */
931 		if (list[i].d_id.b.rsvd_1 != 0)
932 			break;
933 	}
934 
935 	return (rval);
936 }
937 
938 /**
939  * qla2x00_sns_gnn_id() - SNS Get Node Name (GNN_ID) query.
940  * @ha: HA context
941  * @list: switch info entries to populate
942  *
943  * This command uses the old Exectute SNS Command mailbox routine.
944  *
945  * Returns 0 on success.
946  */
947 static int
qla2x00_sns_gnn_id(scsi_qla_host_t * vha,sw_info_t * list)948 qla2x00_sns_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
949 {
950 	int		rval = QLA_SUCCESS;
951 	struct qla_hw_data *ha = vha->hw;
952 	uint16_t	i;
953 	struct sns_cmd_pkt	*sns_cmd;
954 
955 	for (i = 0; i < ha->max_fibre_devices; i++) {
956 		/* Issue GNN_ID */
957 		/* Prepare SNS command request. */
958 		sns_cmd = qla2x00_prep_sns_cmd(vha, GNN_ID_CMD,
959 		    GNN_ID_SNS_SCMD_LEN, GNN_ID_SNS_DATA_SIZE);
960 
961 		/* Prepare SNS command arguments -- port_id. */
962 		sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
963 		sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
964 		sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
965 
966 		/* Execute SNS command. */
967 		rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,
968 		    GNN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
969 		if (rval != QLA_SUCCESS) {
970 			/*EMPTY*/
971 			ql_dbg(ql_dbg_disc, vha, 0x203f,
972 			    "GNN_ID Send SNS failed (%d).\n", rval);
973 		} else if (sns_cmd->p.gnn_data[8] != 0x80 ||
974 		    sns_cmd->p.gnn_data[9] != 0x02) {
975 			ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2082,
976 			    "GNN_ID failed, rejected request, gnn_rsp:\n");
977 			ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207a,
978 			    sns_cmd->p.gnn_data, 16);
979 			rval = QLA_FUNCTION_FAILED;
980 		} else {
981 			/* Save nodename */
982 			memcpy(list[i].node_name, &sns_cmd->p.gnn_data[16],
983 			    WWN_SIZE);
984 
985 			ql_dbg(ql_dbg_disc, vha, 0x206e,
986 			    "GID_PT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
987 			    "pn %02x%02x%02x%02x%02x%02x%02x%02x "
988 			    "port_id=%02x%02x%02x.\n",
989 			    list[i].node_name[0], list[i].node_name[1],
990 			    list[i].node_name[2], list[i].node_name[3],
991 			    list[i].node_name[4], list[i].node_name[5],
992 			    list[i].node_name[6], list[i].node_name[7],
993 			    list[i].port_name[0], list[i].port_name[1],
994 			    list[i].port_name[2], list[i].port_name[3],
995 			    list[i].port_name[4], list[i].port_name[5],
996 			    list[i].port_name[6], list[i].port_name[7],
997 			    list[i].d_id.b.domain, list[i].d_id.b.area,
998 			    list[i].d_id.b.al_pa);
999 		}
1000 
1001 		/* Last device exit. */
1002 		if (list[i].d_id.b.rsvd_1 != 0)
1003 			break;
1004 	}
1005 
1006 	return (rval);
1007 }
1008 
1009 /**
1010  * qla2x00_snd_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
1011  * @ha: HA context
1012  *
1013  * This command uses the old Exectute SNS Command mailbox routine.
1014  *
1015  * Returns 0 on success.
1016  */
1017 static int
qla2x00_sns_rft_id(scsi_qla_host_t * vha)1018 qla2x00_sns_rft_id(scsi_qla_host_t *vha)
1019 {
1020 	int		rval;
1021 	struct qla_hw_data *ha = vha->hw;
1022 	struct sns_cmd_pkt	*sns_cmd;
1023 
1024 	/* Issue RFT_ID. */
1025 	/* Prepare SNS command request. */
1026 	sns_cmd = qla2x00_prep_sns_cmd(vha, RFT_ID_CMD, RFT_ID_SNS_SCMD_LEN,
1027 	    RFT_ID_SNS_DATA_SIZE);
1028 
1029 	/* Prepare SNS command arguments -- port_id, FC-4 types */
1030 	sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;
1031 	sns_cmd->p.cmd.param[1] = vha->d_id.b.area;
1032 	sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;
1033 
1034 	sns_cmd->p.cmd.param[5] = 0x01;			/* FCP-3 */
1035 
1036 	/* Execute SNS command. */
1037 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RFT_ID_SNS_CMD_SIZE / 2,
1038 	    sizeof(struct sns_cmd_pkt));
1039 	if (rval != QLA_SUCCESS) {
1040 		/*EMPTY*/
1041 		ql_dbg(ql_dbg_disc, vha, 0x2060,
1042 		    "RFT_ID Send SNS failed (%d).\n", rval);
1043 	} else if (sns_cmd->p.rft_data[8] != 0x80 ||
1044 	    sns_cmd->p.rft_data[9] != 0x02) {
1045 		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2083,
1046 		    "RFT_ID failed, rejected request rft_rsp:\n");
1047 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2080,
1048 		    sns_cmd->p.rft_data, 16);
1049 		rval = QLA_FUNCTION_FAILED;
1050 	} else {
1051 		ql_dbg(ql_dbg_disc, vha, 0x2073,
1052 		    "RFT_ID exiting normally.\n");
1053 	}
1054 
1055 	return (rval);
1056 }
1057 
1058 /**
1059  * qla2x00_sns_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
1060  * HBA.
1061  * @ha: HA context
1062  *
1063  * This command uses the old Exectute SNS Command mailbox routine.
1064  *
1065  * Returns 0 on success.
1066  */
1067 static int
qla2x00_sns_rnn_id(scsi_qla_host_t * vha)1068 qla2x00_sns_rnn_id(scsi_qla_host_t *vha)
1069 {
1070 	int		rval;
1071 	struct qla_hw_data *ha = vha->hw;
1072 	struct sns_cmd_pkt	*sns_cmd;
1073 
1074 	/* Issue RNN_ID. */
1075 	/* Prepare SNS command request. */
1076 	sns_cmd = qla2x00_prep_sns_cmd(vha, RNN_ID_CMD, RNN_ID_SNS_SCMD_LEN,
1077 	    RNN_ID_SNS_DATA_SIZE);
1078 
1079 	/* Prepare SNS command arguments -- port_id, nodename. */
1080 	sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;
1081 	sns_cmd->p.cmd.param[1] = vha->d_id.b.area;
1082 	sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;
1083 
1084 	sns_cmd->p.cmd.param[4] = vha->node_name[7];
1085 	sns_cmd->p.cmd.param[5] = vha->node_name[6];
1086 	sns_cmd->p.cmd.param[6] = vha->node_name[5];
1087 	sns_cmd->p.cmd.param[7] = vha->node_name[4];
1088 	sns_cmd->p.cmd.param[8] = vha->node_name[3];
1089 	sns_cmd->p.cmd.param[9] = vha->node_name[2];
1090 	sns_cmd->p.cmd.param[10] = vha->node_name[1];
1091 	sns_cmd->p.cmd.param[11] = vha->node_name[0];
1092 
1093 	/* Execute SNS command. */
1094 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RNN_ID_SNS_CMD_SIZE / 2,
1095 	    sizeof(struct sns_cmd_pkt));
1096 	if (rval != QLA_SUCCESS) {
1097 		/*EMPTY*/
1098 		ql_dbg(ql_dbg_disc, vha, 0x204a,
1099 		    "RNN_ID Send SNS failed (%d).\n", rval);
1100 	} else if (sns_cmd->p.rnn_data[8] != 0x80 ||
1101 	    sns_cmd->p.rnn_data[9] != 0x02) {
1102 		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207b,
1103 		    "RNN_ID failed, rejected request, rnn_rsp:\n");
1104 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207c,
1105 		    sns_cmd->p.rnn_data, 16);
1106 		rval = QLA_FUNCTION_FAILED;
1107 	} else {
1108 		ql_dbg(ql_dbg_disc, vha, 0x204c,
1109 		    "RNN_ID exiting normally.\n");
1110 	}
1111 
1112 	return (rval);
1113 }
1114 
1115 /**
1116  * qla2x00_mgmt_svr_login() - Login to fabric Management Service.
1117  * @ha: HA context
1118  *
1119  * Returns 0 on success.
1120  */
1121 static int
qla2x00_mgmt_svr_login(scsi_qla_host_t * vha)1122 qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
1123 {
1124 	int ret, rval;
1125 	uint16_t mb[MAILBOX_REGISTER_COUNT];
1126 	struct qla_hw_data *ha = vha->hw;
1127 	ret = QLA_SUCCESS;
1128 	if (vha->flags.management_server_logged_in)
1129 		return ret;
1130 
1131 	rval = ha->isp_ops->fabric_login(vha, vha->mgmt_svr_loop_id, 0xff, 0xff,
1132 	    0xfa, mb, BIT_1|BIT_0);
1133 	if (rval != QLA_SUCCESS || mb[0] != MBS_COMMAND_COMPLETE) {
1134 		if (rval == QLA_MEMORY_ALLOC_FAILED)
1135 			ql_dbg(ql_dbg_disc, vha, 0x2085,
1136 			    "Failed management_server login: loopid=%x "
1137 			    "rval=%d\n", vha->mgmt_svr_loop_id, rval);
1138 		else
1139 			ql_dbg(ql_dbg_disc, vha, 0x2024,
1140 			    "Failed management_server login: loopid=%x "
1141 			    "mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x.\n",
1142 			    vha->mgmt_svr_loop_id, mb[0], mb[1], mb[2], mb[6],
1143 			    mb[7]);
1144 		ret = QLA_FUNCTION_FAILED;
1145 	} else
1146 		vha->flags.management_server_logged_in = 1;
1147 
1148 	return ret;
1149 }
1150 
1151 /**
1152  * qla2x00_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
1153  * @ha: HA context
1154  * @req_size: request size in bytes
1155  * @rsp_size: response size in bytes
1156  *
1157  * Returns a pointer to the @ha's ms_iocb.
1158  */
1159 void *
qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t * vha,uint32_t req_size,uint32_t rsp_size)1160 qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1161     uint32_t rsp_size)
1162 {
1163 	ms_iocb_entry_t *ms_pkt;
1164 	struct qla_hw_data *ha = vha->hw;
1165 	ms_pkt = ha->ms_iocb;
1166 	memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
1167 
1168 	ms_pkt->entry_type = MS_IOCB_TYPE;
1169 	ms_pkt->entry_count = 1;
1170 	SET_TARGET_ID(ha, ms_pkt->loop_id, vha->mgmt_svr_loop_id);
1171 	ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG);
1172 	ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1173 	ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
1174 	ms_pkt->total_dsd_count = __constant_cpu_to_le16(2);
1175 	ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
1176 	ms_pkt->req_bytecount = cpu_to_le32(req_size);
1177 
1178 	ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1179 	ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1180 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
1181 
1182 	ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1183 	ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1184 	ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
1185 
1186 	return ms_pkt;
1187 }
1188 
1189 /**
1190  * qla24xx_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
1191  * @ha: HA context
1192  * @req_size: request size in bytes
1193  * @rsp_size: response size in bytes
1194  *
1195  * Returns a pointer to the @ha's ms_iocb.
1196  */
1197 void *
qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t * vha,uint32_t req_size,uint32_t rsp_size)1198 qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1199     uint32_t rsp_size)
1200 {
1201 	struct ct_entry_24xx *ct_pkt;
1202 	struct qla_hw_data *ha = vha->hw;
1203 
1204 	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1205 	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
1206 
1207 	ct_pkt->entry_type = CT_IOCB_TYPE;
1208 	ct_pkt->entry_count = 1;
1209 	ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);
1210 	ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1211 	ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
1212 	ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
1213 	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
1214 	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1215 
1216 	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1217 	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1218 	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1219 
1220 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1221 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1222 	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
1223 	ct_pkt->vp_index = vha->vp_idx;
1224 
1225 	return ct_pkt;
1226 }
1227 
1228 static inline ms_iocb_entry_t *
qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t * vha,uint32_t req_size)1229 qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size)
1230 {
1231 	struct qla_hw_data *ha = vha->hw;
1232 	ms_iocb_entry_t *ms_pkt = ha->ms_iocb;
1233 	struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1234 
1235 	if (IS_FWI2_CAPABLE(ha)) {
1236 		ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1237 		ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1238 	} else {
1239 		ms_pkt->req_bytecount = cpu_to_le32(req_size);
1240 		ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
1241 	}
1242 
1243 	return ms_pkt;
1244 }
1245 
1246 /**
1247  * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
1248  * @ct_req: CT request buffer
1249  * @cmd: GS command
1250  * @rsp_size: response size in bytes
1251  *
1252  * Returns a pointer to the intitialized @ct_req.
1253  */
1254 static inline struct ct_sns_req *
qla2x00_prep_ct_fdmi_req(struct ct_sns_req * ct_req,uint16_t cmd,uint16_t rsp_size)1255 qla2x00_prep_ct_fdmi_req(struct ct_sns_req *ct_req, uint16_t cmd,
1256     uint16_t rsp_size)
1257 {
1258 	memset(ct_req, 0, sizeof(struct ct_sns_pkt));
1259 
1260 	ct_req->header.revision = 0x01;
1261 	ct_req->header.gs_type = 0xFA;
1262 	ct_req->header.gs_subtype = 0x10;
1263 	ct_req->command = cpu_to_be16(cmd);
1264 	ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
1265 
1266 	return ct_req;
1267 }
1268 
1269 /**
1270  * qla2x00_fdmi_rhba() -
1271  * @ha: HA context
1272  *
1273  * Returns 0 on success.
1274  */
1275 static int
qla2x00_fdmi_rhba(scsi_qla_host_t * vha)1276 qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
1277 {
1278 	int rval, alen;
1279 	uint32_t size, sn;
1280 
1281 	ms_iocb_entry_t *ms_pkt;
1282 	struct ct_sns_req *ct_req;
1283 	struct ct_sns_rsp *ct_rsp;
1284 	uint8_t *entries;
1285 	struct ct_fdmi_hba_attr *eiter;
1286 	struct qla_hw_data *ha = vha->hw;
1287 
1288 	/* Issue RHBA */
1289 	/* Prepare common MS IOCB */
1290 	/*   Request size adjusted after CT preparation */
1291 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE);
1292 
1293 	/* Prepare CT request */
1294 	ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RHBA_CMD,
1295 	    RHBA_RSP_SIZE);
1296 	ct_rsp = &ha->ct_sns->p.rsp;
1297 
1298 	/* Prepare FDMI command arguments -- attribute block, attributes. */
1299 	memcpy(ct_req->req.rhba.hba_identifier, vha->port_name, WWN_SIZE);
1300 	ct_req->req.rhba.entry_count = __constant_cpu_to_be32(1);
1301 	memcpy(ct_req->req.rhba.port_name, vha->port_name, WWN_SIZE);
1302 	size = 2 * WWN_SIZE + 4 + 4;
1303 
1304 	/* Attributes */
1305 	ct_req->req.rhba.attrs.count =
1306 	    __constant_cpu_to_be32(FDMI_HBA_ATTR_COUNT);
1307 	entries = ct_req->req.rhba.hba_identifier;
1308 
1309 	/* Nodename. */
1310 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1311 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_NODE_NAME);
1312 	eiter->len = __constant_cpu_to_be16(4 + WWN_SIZE);
1313 	memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
1314 	size += 4 + WWN_SIZE;
1315 
1316 	ql_dbg(ql_dbg_disc, vha, 0x2025,
1317 	    "NodeName = %02x%02x%02x%02x%02x%02x%02x%02x.\n",
1318 	    eiter->a.node_name[0], eiter->a.node_name[1],
1319 	    eiter->a.node_name[2], eiter->a.node_name[3],
1320 	    eiter->a.node_name[4], eiter->a.node_name[5],
1321 	    eiter->a.node_name[6], eiter->a.node_name[7]);
1322 
1323 	/* Manufacturer. */
1324 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1325 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_MANUFACTURER);
1326 	strcpy(eiter->a.manufacturer, "QLogic Corporation");
1327 	alen = strlen(eiter->a.manufacturer);
1328 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1329 	eiter->len = cpu_to_be16(4 + alen);
1330 	size += 4 + alen;
1331 
1332 	ql_dbg(ql_dbg_disc, vha, 0x2026,
1333 	    "Manufacturer = %s.\n", eiter->a.manufacturer);
1334 
1335 	/* Serial number. */
1336 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1337 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
1338 	sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
1339 	sprintf(eiter->a.serial_num, "%c%05d", 'A' + sn / 100000, sn % 100000);
1340 	alen = strlen(eiter->a.serial_num);
1341 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1342 	eiter->len = cpu_to_be16(4 + alen);
1343 	size += 4 + alen;
1344 
1345 	ql_dbg(ql_dbg_disc, vha, 0x2027,
1346 	    "Serial no. = %s.\n", eiter->a.serial_num);
1347 
1348 	/* Model name. */
1349 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1350 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL);
1351 	strcpy(eiter->a.model, ha->model_number);
1352 	alen = strlen(eiter->a.model);
1353 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1354 	eiter->len = cpu_to_be16(4 + alen);
1355 	size += 4 + alen;
1356 
1357 	ql_dbg(ql_dbg_disc, vha, 0x2028,
1358 	    "Model Name = %s.\n", eiter->a.model);
1359 
1360 	/* Model description. */
1361 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1362 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
1363 	if (ha->model_desc)
1364 		strncpy(eiter->a.model_desc, ha->model_desc, 80);
1365 	alen = strlen(eiter->a.model_desc);
1366 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1367 	eiter->len = cpu_to_be16(4 + alen);
1368 	size += 4 + alen;
1369 
1370 	ql_dbg(ql_dbg_disc, vha, 0x2029,
1371 	    "Model Desc = %s.\n", eiter->a.model_desc);
1372 
1373 	/* Hardware version. */
1374 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1375 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
1376 	strcpy(eiter->a.hw_version, ha->adapter_id);
1377 	alen = strlen(eiter->a.hw_version);
1378 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1379 	eiter->len = cpu_to_be16(4 + alen);
1380 	size += 4 + alen;
1381 
1382 	ql_dbg(ql_dbg_disc, vha, 0x202a,
1383 	    "Hardware ver = %s.\n", eiter->a.hw_version);
1384 
1385 	/* Driver version. */
1386 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1387 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
1388 	strcpy(eiter->a.driver_version, qla2x00_version_str);
1389 	alen = strlen(eiter->a.driver_version);
1390 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1391 	eiter->len = cpu_to_be16(4 + alen);
1392 	size += 4 + alen;
1393 
1394 	ql_dbg(ql_dbg_disc, vha, 0x202b,
1395 	    "Driver ver = %s.\n", eiter->a.driver_version);
1396 
1397 	/* Option ROM version. */
1398 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1399 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
1400 	strcpy(eiter->a.orom_version, "0.00");
1401 	alen = strlen(eiter->a.orom_version);
1402 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1403 	eiter->len = cpu_to_be16(4 + alen);
1404 	size += 4 + alen;
1405 
1406 	ql_dbg(ql_dbg_disc, vha , 0x202c,
1407 	    "Optrom vers = %s.\n", eiter->a.orom_version);
1408 
1409 	/* Firmware version */
1410 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1411 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
1412 	ha->isp_ops->fw_version_str(vha, eiter->a.fw_version);
1413 	alen = strlen(eiter->a.fw_version);
1414 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1415 	eiter->len = cpu_to_be16(4 + alen);
1416 	size += 4 + alen;
1417 
1418 	ql_dbg(ql_dbg_disc, vha, 0x202d,
1419 	    "Firmware vers = %s.\n", eiter->a.fw_version);
1420 
1421 	/* Update MS request size. */
1422 	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
1423 
1424 	ql_dbg(ql_dbg_disc, vha, 0x202e,
1425 	    "RHBA identifier = "
1426 	    "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n",
1427 	    ct_req->req.rhba.hba_identifier[0],
1428 	    ct_req->req.rhba.hba_identifier[1],
1429 	    ct_req->req.rhba.hba_identifier[2],
1430 	    ct_req->req.rhba.hba_identifier[3],
1431 	    ct_req->req.rhba.hba_identifier[4],
1432 	    ct_req->req.rhba.hba_identifier[5],
1433 	    ct_req->req.rhba.hba_identifier[6],
1434 	    ct_req->req.rhba.hba_identifier[7], size);
1435 	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2076,
1436 	    entries, size);
1437 
1438 	/* Execute MS IOCB */
1439 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1440 	    sizeof(ms_iocb_entry_t));
1441 	if (rval != QLA_SUCCESS) {
1442 		/*EMPTY*/
1443 		ql_dbg(ql_dbg_disc, vha, 0x2030,
1444 		    "RHBA issue IOCB failed (%d).\n", rval);
1445 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") !=
1446 	    QLA_SUCCESS) {
1447 		rval = QLA_FUNCTION_FAILED;
1448 		if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
1449 		    ct_rsp->header.explanation_code ==
1450 		    CT_EXPL_ALREADY_REGISTERED) {
1451 			ql_dbg(ql_dbg_disc, vha, 0x2034,
1452 			    "HBA already registered.\n");
1453 			rval = QLA_ALREADY_REGISTERED;
1454 		}
1455 	} else {
1456 		ql_dbg(ql_dbg_disc, vha, 0x2035,
1457 		    "RHBA exiting normally.\n");
1458 	}
1459 
1460 	return rval;
1461 }
1462 
1463 /**
1464  * qla2x00_fdmi_dhba() -
1465  * @ha: HA context
1466  *
1467  * Returns 0 on success.
1468  */
1469 static int
qla2x00_fdmi_dhba(scsi_qla_host_t * vha)1470 qla2x00_fdmi_dhba(scsi_qla_host_t *vha)
1471 {
1472 	int rval;
1473 	struct qla_hw_data *ha = vha->hw;
1474 	ms_iocb_entry_t *ms_pkt;
1475 	struct ct_sns_req *ct_req;
1476 	struct ct_sns_rsp *ct_rsp;
1477 
1478 	/* Issue RPA */
1479 	/* Prepare common MS IOCB */
1480 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, DHBA_REQ_SIZE,
1481 	    DHBA_RSP_SIZE);
1482 
1483 	/* Prepare CT request */
1484 	ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, DHBA_CMD,
1485 	    DHBA_RSP_SIZE);
1486 	ct_rsp = &ha->ct_sns->p.rsp;
1487 
1488 	/* Prepare FDMI command arguments -- portname. */
1489 	memcpy(ct_req->req.dhba.port_name, vha->port_name, WWN_SIZE);
1490 
1491 	ql_dbg(ql_dbg_disc, vha, 0x2036,
1492 	    "DHBA portname = %02x%02x%02x%02x%02x%02x%02x%02x.\n",
1493 	    ct_req->req.dhba.port_name[0], ct_req->req.dhba.port_name[1],
1494 	    ct_req->req.dhba.port_name[2], ct_req->req.dhba.port_name[3],
1495 	    ct_req->req.dhba.port_name[4], ct_req->req.dhba.port_name[5],
1496 	    ct_req->req.dhba.port_name[6], ct_req->req.dhba.port_name[7]);
1497 
1498 	/* Execute MS IOCB */
1499 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1500 	    sizeof(ms_iocb_entry_t));
1501 	if (rval != QLA_SUCCESS) {
1502 		/*EMPTY*/
1503 		ql_dbg(ql_dbg_disc, vha, 0x2037,
1504 		    "DHBA issue IOCB failed (%d).\n", rval);
1505 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "DHBA") !=
1506 	    QLA_SUCCESS) {
1507 		rval = QLA_FUNCTION_FAILED;
1508 	} else {
1509 		ql_dbg(ql_dbg_disc, vha, 0x2038,
1510 		    "DHBA exiting normally.\n");
1511 	}
1512 
1513 	return rval;
1514 }
1515 
1516 /**
1517  * qla2x00_fdmi_rpa() -
1518  * @ha: HA context
1519  *
1520  * Returns 0 on success.
1521  */
1522 static int
qla2x00_fdmi_rpa(scsi_qla_host_t * vha)1523 qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
1524 {
1525 	int rval, alen;
1526 	uint32_t size, max_frame_size;
1527 	struct qla_hw_data *ha = vha->hw;
1528 	ms_iocb_entry_t *ms_pkt;
1529 	struct ct_sns_req *ct_req;
1530 	struct ct_sns_rsp *ct_rsp;
1531 	uint8_t *entries;
1532 	struct ct_fdmi_port_attr *eiter;
1533 	struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
1534 
1535 	/* Issue RPA */
1536 	/* Prepare common MS IOCB */
1537 	/*   Request size adjusted after CT preparation */
1538 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE);
1539 
1540 	/* Prepare CT request */
1541 	ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RPA_CMD,
1542 	    RPA_RSP_SIZE);
1543 	ct_rsp = &ha->ct_sns->p.rsp;
1544 
1545 	/* Prepare FDMI command arguments -- attribute block, attributes. */
1546 	memcpy(ct_req->req.rpa.port_name, vha->port_name, WWN_SIZE);
1547 	size = WWN_SIZE + 4;
1548 
1549 	/* Attributes */
1550 	ct_req->req.rpa.attrs.count =
1551 	    __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT - 1);
1552 	entries = ct_req->req.rpa.port_name;
1553 
1554 	/* FC4 types. */
1555 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1556 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_FC4_TYPES);
1557 	eiter->len = __constant_cpu_to_be16(4 + 32);
1558 	eiter->a.fc4_types[2] = 0x01;
1559 	size += 4 + 32;
1560 
1561 	ql_dbg(ql_dbg_disc, vha, 0x2039,
1562 	    "FC4_TYPES=%02x %02x.\n",
1563 	    eiter->a.fc4_types[2],
1564 	    eiter->a.fc4_types[1]);
1565 
1566 	/* Supported speed. */
1567 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1568 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
1569 	eiter->len = __constant_cpu_to_be16(4 + 4);
1570 	if (IS_CNA_CAPABLE(ha))
1571 		eiter->a.sup_speed = __constant_cpu_to_be32(
1572 		    FDMI_PORT_SPEED_10GB);
1573 	else if (IS_QLA25XX(ha))
1574 		eiter->a.sup_speed = __constant_cpu_to_be32(
1575 		    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
1576 		    FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_8GB);
1577 	else if (IS_QLA24XX_TYPE(ha))
1578 		eiter->a.sup_speed = __constant_cpu_to_be32(
1579 		    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
1580 		    FDMI_PORT_SPEED_4GB);
1581 	else if (IS_QLA23XX(ha))
1582 		eiter->a.sup_speed =__constant_cpu_to_be32(
1583 		    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB);
1584 	else
1585 		eiter->a.sup_speed = __constant_cpu_to_be32(
1586 		    FDMI_PORT_SPEED_1GB);
1587 	size += 4 + 4;
1588 
1589 	ql_dbg(ql_dbg_disc, vha, 0x203a,
1590 	    "Supported_Speed=%x.\n", eiter->a.sup_speed);
1591 
1592 	/* Current speed. */
1593 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1594 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
1595 	eiter->len = __constant_cpu_to_be16(4 + 4);
1596 	switch (ha->link_data_rate) {
1597 	case PORT_SPEED_1GB:
1598 		eiter->a.cur_speed =
1599 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_1GB);
1600 		break;
1601 	case PORT_SPEED_2GB:
1602 		eiter->a.cur_speed =
1603 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_2GB);
1604 		break;
1605 	case PORT_SPEED_4GB:
1606 		eiter->a.cur_speed =
1607 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_4GB);
1608 		break;
1609 	case PORT_SPEED_8GB:
1610 		eiter->a.cur_speed =
1611 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_8GB);
1612 		break;
1613 	case PORT_SPEED_10GB:
1614 		eiter->a.cur_speed =
1615 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_10GB);
1616 		break;
1617 	case PORT_SPEED_16GB:
1618 		eiter->a.cur_speed =
1619 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_16GB);
1620 		break;
1621 	default:
1622 		eiter->a.cur_speed =
1623 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN);
1624 		break;
1625 	}
1626 	size += 4 + 4;
1627 
1628 	ql_dbg(ql_dbg_disc, vha, 0x203b,
1629 	    "Current_Speed=%x.\n", eiter->a.cur_speed);
1630 
1631 	/* Max frame size. */
1632 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1633 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
1634 	eiter->len = __constant_cpu_to_be16(4 + 4);
1635 	max_frame_size = IS_FWI2_CAPABLE(ha) ?
1636 	    le16_to_cpu(icb24->frame_payload_size):
1637 	    le16_to_cpu(ha->init_cb->frame_payload_size);
1638 	eiter->a.max_frame_size = cpu_to_be32(max_frame_size);
1639 	size += 4 + 4;
1640 
1641 	ql_dbg(ql_dbg_disc, vha, 0x203c,
1642 	    "Max_Frame_Size=%x.\n", eiter->a.max_frame_size);
1643 
1644 	/* OS device name. */
1645 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1646 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
1647 	strcpy(eiter->a.os_dev_name, QLA2XXX_DRIVER_NAME);
1648 	alen = strlen(eiter->a.os_dev_name);
1649 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1650 	eiter->len = cpu_to_be16(4 + alen);
1651 	size += 4 + alen;
1652 
1653 	ql_dbg(ql_dbg_disc, vha, 0x204b,
1654 	    "OS_Device_Name=%s.\n", eiter->a.os_dev_name);
1655 
1656 	/* Hostname. */
1657 	if (strlen(fc_host_system_hostname(vha->host))) {
1658 		ct_req->req.rpa.attrs.count =
1659 		    __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT);
1660 		eiter = (struct ct_fdmi_port_attr *) (entries + size);
1661 		eiter->type = __constant_cpu_to_be16(FDMI_PORT_HOST_NAME);
1662 		snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
1663 		    "%s", fc_host_system_hostname(vha->host));
1664 		alen = strlen(eiter->a.host_name);
1665 		alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1666 		eiter->len = cpu_to_be16(4 + alen);
1667 		size += 4 + alen;
1668 
1669 		ql_dbg(ql_dbg_disc, vha, 0x203d,
1670 		    "HostName=%s.\n", eiter->a.host_name);
1671 	}
1672 
1673 	/* Update MS request size. */
1674 	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
1675 
1676 	ql_dbg(ql_dbg_disc, vha, 0x203e,
1677 	    "RPA portname= %02x%02x%02x%02x%02X%02x%02x%02x size=%d.\n",
1678 	    ct_req->req.rpa.port_name[0], ct_req->req.rpa.port_name[1],
1679 	    ct_req->req.rpa.port_name[2], ct_req->req.rpa.port_name[3],
1680 	    ct_req->req.rpa.port_name[4], ct_req->req.rpa.port_name[5],
1681 	    ct_req->req.rpa.port_name[6], ct_req->req.rpa.port_name[7],
1682 	    size);
1683 	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2079,
1684 	    entries, size);
1685 
1686 	/* Execute MS IOCB */
1687 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1688 	    sizeof(ms_iocb_entry_t));
1689 	if (rval != QLA_SUCCESS) {
1690 		/*EMPTY*/
1691 		ql_dbg(ql_dbg_disc, vha, 0x2040,
1692 		    "RPA issue IOCB failed (%d).\n", rval);
1693 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") !=
1694 	    QLA_SUCCESS) {
1695 		rval = QLA_FUNCTION_FAILED;
1696 	} else {
1697 		ql_dbg(ql_dbg_disc, vha, 0x2041,
1698 		    "RPA exiting nornally.\n");
1699 	}
1700 
1701 	return rval;
1702 }
1703 
1704 /**
1705  * qla2x00_fdmi_register() -
1706  * @ha: HA context
1707  *
1708  * Returns 0 on success.
1709  */
1710 int
qla2x00_fdmi_register(scsi_qla_host_t * vha)1711 qla2x00_fdmi_register(scsi_qla_host_t *vha)
1712 {
1713 	int rval;
1714        struct qla_hw_data *ha = vha->hw;
1715 
1716 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
1717 		return QLA_FUNCTION_FAILED;
1718 
1719 	rval = qla2x00_mgmt_svr_login(vha);
1720 	if (rval)
1721 		return rval;
1722 
1723 	rval = qla2x00_fdmi_rhba(vha);
1724 	if (rval) {
1725 		if (rval != QLA_ALREADY_REGISTERED)
1726 			return rval;
1727 
1728 		rval = qla2x00_fdmi_dhba(vha);
1729 		if (rval)
1730 			return rval;
1731 
1732 		rval = qla2x00_fdmi_rhba(vha);
1733 		if (rval)
1734 			return rval;
1735 	}
1736 	rval = qla2x00_fdmi_rpa(vha);
1737 
1738 	return rval;
1739 }
1740 
1741 /**
1742  * qla2x00_gfpn_id() - SNS Get Fabric Port Name (GFPN_ID) query.
1743  * @ha: HA context
1744  * @list: switch info entries to populate
1745  *
1746  * Returns 0 on success.
1747  */
1748 int
qla2x00_gfpn_id(scsi_qla_host_t * vha,sw_info_t * list)1749 qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)
1750 {
1751 	int		rval = QLA_SUCCESS;
1752 	uint16_t	i;
1753 	struct qla_hw_data *ha = vha->hw;
1754 	ms_iocb_entry_t	*ms_pkt;
1755 	struct ct_sns_req	*ct_req;
1756 	struct ct_sns_rsp	*ct_rsp;
1757 
1758 	if (!IS_IIDMA_CAPABLE(ha))
1759 		return QLA_FUNCTION_FAILED;
1760 
1761 	for (i = 0; i < ha->max_fibre_devices; i++) {
1762 		/* Issue GFPN_ID */
1763 		/* Prepare common MS IOCB */
1764 		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFPN_ID_REQ_SIZE,
1765 		    GFPN_ID_RSP_SIZE);
1766 
1767 		/* Prepare CT request */
1768 		ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GFPN_ID_CMD,
1769 		    GFPN_ID_RSP_SIZE);
1770 		ct_rsp = &ha->ct_sns->p.rsp;
1771 
1772 		/* Prepare CT arguments -- port_id */
1773 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
1774 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
1775 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
1776 
1777 		/* Execute MS IOCB */
1778 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1779 		    sizeof(ms_iocb_entry_t));
1780 		if (rval != QLA_SUCCESS) {
1781 			/*EMPTY*/
1782 			ql_dbg(ql_dbg_disc, vha, 0x2023,
1783 			    "GFPN_ID issue IOCB failed (%d).\n", rval);
1784 			break;
1785 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
1786 		    "GFPN_ID") != QLA_SUCCESS) {
1787 			rval = QLA_FUNCTION_FAILED;
1788 			break;
1789 		} else {
1790 			/* Save fabric portname */
1791 			memcpy(list[i].fabric_port_name,
1792 			    ct_rsp->rsp.gfpn_id.port_name, WWN_SIZE);
1793 		}
1794 
1795 		/* Last device exit. */
1796 		if (list[i].d_id.b.rsvd_1 != 0)
1797 			break;
1798 	}
1799 
1800 	return (rval);
1801 }
1802 
1803 static inline void *
qla24xx_prep_ms_fm_iocb(scsi_qla_host_t * vha,uint32_t req_size,uint32_t rsp_size)1804 qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1805     uint32_t rsp_size)
1806 {
1807 	struct ct_entry_24xx *ct_pkt;
1808 	struct qla_hw_data *ha = vha->hw;
1809 	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1810 	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
1811 
1812 	ct_pkt->entry_type = CT_IOCB_TYPE;
1813 	ct_pkt->entry_count = 1;
1814 	ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);
1815 	ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1816 	ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
1817 	ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
1818 	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
1819 	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1820 
1821 	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1822 	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1823 	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1824 
1825 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1826 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1827 	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
1828 	ct_pkt->vp_index = vha->vp_idx;
1829 
1830 	return ct_pkt;
1831 }
1832 
1833 
1834 static inline struct ct_sns_req *
qla24xx_prep_ct_fm_req(struct ct_sns_req * ct_req,uint16_t cmd,uint16_t rsp_size)1835 qla24xx_prep_ct_fm_req(struct ct_sns_req *ct_req, uint16_t cmd,
1836     uint16_t rsp_size)
1837 {
1838 	memset(ct_req, 0, sizeof(struct ct_sns_pkt));
1839 
1840 	ct_req->header.revision = 0x01;
1841 	ct_req->header.gs_type = 0xFA;
1842 	ct_req->header.gs_subtype = 0x01;
1843 	ct_req->command = cpu_to_be16(cmd);
1844 	ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
1845 
1846 	return ct_req;
1847 }
1848 
1849 /**
1850  * qla2x00_gpsc() - FCS Get Port Speed Capabilities (GPSC) query.
1851  * @ha: HA context
1852  * @list: switch info entries to populate
1853  *
1854  * Returns 0 on success.
1855  */
1856 int
qla2x00_gpsc(scsi_qla_host_t * vha,sw_info_t * list)1857 qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
1858 {
1859 	int		rval;
1860 	uint16_t	i;
1861 	struct qla_hw_data *ha = vha->hw;
1862 	ms_iocb_entry_t	*ms_pkt;
1863 	struct ct_sns_req	*ct_req;
1864 	struct ct_sns_rsp	*ct_rsp;
1865 
1866 	if (!IS_IIDMA_CAPABLE(ha))
1867 		return QLA_FUNCTION_FAILED;
1868 	if (!ha->flags.gpsc_supported)
1869 		return QLA_FUNCTION_FAILED;
1870 
1871 	rval = qla2x00_mgmt_svr_login(vha);
1872 	if (rval)
1873 		return rval;
1874 
1875 	for (i = 0; i < ha->max_fibre_devices; i++) {
1876 		/* Issue GFPN_ID */
1877 		/* Prepare common MS IOCB */
1878 		ms_pkt = qla24xx_prep_ms_fm_iocb(vha, GPSC_REQ_SIZE,
1879 		    GPSC_RSP_SIZE);
1880 
1881 		/* Prepare CT request */
1882 		ct_req = qla24xx_prep_ct_fm_req(&ha->ct_sns->p.req,
1883 		    GPSC_CMD, GPSC_RSP_SIZE);
1884 		ct_rsp = &ha->ct_sns->p.rsp;
1885 
1886 		/* Prepare CT arguments -- port_name */
1887 		memcpy(ct_req->req.gpsc.port_name, list[i].fabric_port_name,
1888 		    WWN_SIZE);
1889 
1890 		/* Execute MS IOCB */
1891 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1892 		    sizeof(ms_iocb_entry_t));
1893 		if (rval != QLA_SUCCESS) {
1894 			/*EMPTY*/
1895 			ql_dbg(ql_dbg_disc, vha, 0x2059,
1896 			    "GPSC issue IOCB failed (%d).\n", rval);
1897 		} else if ((rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
1898 		    "GPSC")) != QLA_SUCCESS) {
1899 			/* FM command unsupported? */
1900 			if (rval == QLA_INVALID_COMMAND &&
1901 			    (ct_rsp->header.reason_code ==
1902 				CT_REASON_INVALID_COMMAND_CODE ||
1903 			     ct_rsp->header.reason_code ==
1904 				CT_REASON_COMMAND_UNSUPPORTED)) {
1905 				ql_dbg(ql_dbg_disc, vha, 0x205a,
1906 				    "GPSC command unsupported, disabling "
1907 				    "query.\n");
1908 				ha->flags.gpsc_supported = 0;
1909 				rval = QLA_FUNCTION_FAILED;
1910 				break;
1911 			}
1912 			rval = QLA_FUNCTION_FAILED;
1913 		} else {
1914 			/* Save port-speed */
1915 			switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) {
1916 			case BIT_15:
1917 				list[i].fp_speed = PORT_SPEED_1GB;
1918 				break;
1919 			case BIT_14:
1920 				list[i].fp_speed = PORT_SPEED_2GB;
1921 				break;
1922 			case BIT_13:
1923 				list[i].fp_speed = PORT_SPEED_4GB;
1924 				break;
1925 			case BIT_12:
1926 				list[i].fp_speed = PORT_SPEED_10GB;
1927 				break;
1928 			case BIT_11:
1929 				list[i].fp_speed = PORT_SPEED_8GB;
1930 				break;
1931 			}
1932 
1933 			ql_dbg(ql_dbg_disc, vha, 0x205b,
1934 			    "GPSC ext entry - fpn "
1935 			    "%02x%02x%02x%02x%02x%02x%02x%02x speeds=%04x "
1936 			    "speed=%04x.\n",
1937 			    list[i].fabric_port_name[0],
1938 			    list[i].fabric_port_name[1],
1939 			    list[i].fabric_port_name[2],
1940 			    list[i].fabric_port_name[3],
1941 			    list[i].fabric_port_name[4],
1942 			    list[i].fabric_port_name[5],
1943 			    list[i].fabric_port_name[6],
1944 			    list[i].fabric_port_name[7],
1945 			    be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
1946 			    be16_to_cpu(ct_rsp->rsp.gpsc.speed));
1947 		}
1948 
1949 		/* Last device exit. */
1950 		if (list[i].d_id.b.rsvd_1 != 0)
1951 			break;
1952 	}
1953 
1954 	return (rval);
1955 }
1956 
1957 /**
1958  * qla2x00_gff_id() - SNS Get FC-4 Features (GFF_ID) query.
1959  *
1960  * @ha: HA context
1961  * @list: switch info entries to populate
1962  *
1963  */
1964 void
qla2x00_gff_id(scsi_qla_host_t * vha,sw_info_t * list)1965 qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
1966 {
1967 	int		rval;
1968 	uint16_t	i;
1969 
1970 	ms_iocb_entry_t	*ms_pkt;
1971 	struct ct_sns_req	*ct_req;
1972 	struct ct_sns_rsp	*ct_rsp;
1973 	struct qla_hw_data *ha = vha->hw;
1974 	uint8_t fcp_scsi_features = 0;
1975 
1976 	for (i = 0; i < ha->max_fibre_devices; i++) {
1977 		/* Set default FC4 Type as UNKNOWN so the default is to
1978 		 * Process this port */
1979 		list[i].fc4_type = FC4_TYPE_UNKNOWN;
1980 
1981 		/* Do not attempt GFF_ID if we are not FWI_2 capable */
1982 		if (!IS_FWI2_CAPABLE(ha))
1983 			continue;
1984 
1985 		/* Prepare common MS IOCB */
1986 		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFF_ID_REQ_SIZE,
1987 		    GFF_ID_RSP_SIZE);
1988 
1989 		/* Prepare CT request */
1990 		ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GFF_ID_CMD,
1991 		    GFF_ID_RSP_SIZE);
1992 		ct_rsp = &ha->ct_sns->p.rsp;
1993 
1994 		/* Prepare CT arguments -- port_id */
1995 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
1996 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
1997 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
1998 
1999 		/* Execute MS IOCB */
2000 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2001 		   sizeof(ms_iocb_entry_t));
2002 
2003 		if (rval != QLA_SUCCESS) {
2004 			ql_dbg(ql_dbg_disc, vha, 0x205c,
2005 			    "GFF_ID issue IOCB failed (%d).\n", rval);
2006 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
2007 			       "GFF_ID") != QLA_SUCCESS) {
2008 			ql_dbg(ql_dbg_disc, vha, 0x205d,
2009 			    "GFF_ID IOCB status had a failure status code.\n");
2010 		} else {
2011 			fcp_scsi_features =
2012 			   ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
2013 			fcp_scsi_features &= 0x0f;
2014 
2015 			if (fcp_scsi_features)
2016 				list[i].fc4_type = FC4_TYPE_FCP_SCSI;
2017 			else
2018 				list[i].fc4_type = FC4_TYPE_OTHER;
2019 		}
2020 
2021 		/* Last device exit. */
2022 		if (list[i].d_id.b.rsvd_1 != 0)
2023 			break;
2024 	}
2025 }
2026