blob: 94e8a8592f6904be9b4bbe408f705b0e28a342f8 [file] [log] [blame]
Kyle Swenson8d8f6542021-03-15 11:02:55 -06001/*
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
11static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *);
12static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *);
13static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *);
14static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *);
15static int qla2x00_sns_rft_id(scsi_qla_host_t *);
16static 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 */
26void *
27qla2x00_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 */
66void *
67qla24xx_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 */
106static inline struct ct_sns_req *
107qla2x00_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
120static int
121qla2x00_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 */
177int
178qla2x00_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
244static inline int
245qla2x00_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 */
259int
260qla2x00_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 */
337int
338qla2x00_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 */
400int
401qla2x00_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 */
468int
469qla2x00_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 */
521int
522qla2x00_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 */
579int
580qla2x00_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
625void
626qla2x00_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 */
646int
647qla2x00_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 */
714static inline struct sns_cmd_pkt *
715qla2x00_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 */
747static int
748qla2x00_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 */
813static int
814qla2x00_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 */
884static int
885qla2x00_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 */
940static int
941qla2x00_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 */
1002static int
1003qla2x00_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 */
1052static int
1053qla2x00_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 */
1106static int
1107qla2x00_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 */
1144void *
1145qla2x00_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 */
1182void *
1183qla24xx_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
1213static inline ms_iocb_entry_t *
1214qla2x00_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 */
1239static inline struct ct_sns_req *
1240qla2x00_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 */
1260static int
1261qla2x00_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 */
1470static int
1471qla2x00_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 */
1682static int
1683qla2x00_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 */
1998static int
1999qla2x00_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 */
2046static int
2047qla2x00_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 */
2360int
2361qla2x00_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
2393try_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);
2408out:
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 */
2419int
2420qla2x00_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
2474static inline void *
2475qla24xx_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
2505static inline struct ct_sns_req *
2506qla24xx_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 */
2527int
2528qla2x00_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 */
2633void
2634qla2x00_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}