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