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