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