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