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