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