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