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