Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
qla_gs.c
Go to the documentation of this file.
1 /*
2  * QLogic Fibre Channel HBA Driver
3  * Copyright (c) 2003-2012 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 
25 void *
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;
38  ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 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 
63 void *
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;
75  ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
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 
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 !=
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);
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 
172 int
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,
189 
190  /* Prepare CT request */
191  ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GA_NXT_CMD,
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 
259 int
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 
338 int
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,
357 
358  /* Prepare CT request */
359  ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GPN_ID_CMD,
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 
401 int
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,
419 
420  /* Prepare CT request */
421  ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GNN_ID_CMD,
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 
477 int
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,
493 
494  /* Prepare CT request */
495  ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFT_ID_CMD,
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 
530 int
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,
549 
550  /* Prepare CT request */
551  ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFF_ID_CMD,
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 
588 int
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,
604 
605  /* Prepare CT request */
606  ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RNN_ID_CMD,
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
637 {
638  struct qla_hw_data *ha = vha->hw;
639  sprintf(snn, "%s FW:v%d.%02d.%02d DVR:v%s",ha->model_number,
642 }
643 
650 int
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,
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 
717 static inline struct sns_cmd_pkt *
718 qla2x00_prep_sns_cmd(scsi_qla_host_t *vha, uint16_t cmd, uint16_t scmd_len,
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 
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,
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");
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 
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");
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 
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,
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 
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,
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");
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 
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,
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 
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,
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 
1123 static int
1124 qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
1125 {
1126  int ret, rval;
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);
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 
1161 void *
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);
1174  ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 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 
1199 void *
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);
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 
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 
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 =
1309  entries = ct_req->req.rhba.hba_identifier;
1310 
1311  /* Nodename. */
1312  eiter = (struct ct_fdmi_hba_attr *) (entries + size);
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);
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);
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);
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);
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);
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);
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);
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);
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 ==
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 
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 
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 =
1554  entries = ct_req->req.rpa.port_name;
1555 
1556  /* FC4 types. */
1557  eiter = (struct ct_fdmi_port_attr *) (entries + size);
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);
1571  eiter->len = __constant_cpu_to_be16(4 + 4);
1572  if (IS_CNA_CAPABLE(ha))
1575  else if (IS_QLA25XX(ha))
1579  else if (IS_QLA24XX_TYPE(ha))
1583  else if (IS_QLA23XX(ha))
1586  else
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);
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 =
1602  break;
1603  case PORT_SPEED_2GB:
1604  eiter->a.cur_speed =
1606  break;
1607  case PORT_SPEED_4GB:
1608  eiter->a.cur_speed =
1610  break;
1611  case PORT_SPEED_8GB:
1612  eiter->a.cur_speed =
1614  break;
1615  case PORT_SPEED_10GB:
1616  eiter->a.cur_speed =
1618  break;
1619  case PORT_SPEED_16GB:
1620  eiter->a.cur_speed =
1622  break;
1623  default:
1624  eiter->a.cur_speed =
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);
1636  eiter->len = __constant_cpu_to_be16(4 + 4);
1637  max_frame_size = IS_FWI2_CAPABLE(ha) ?
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);
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 =
1662  eiter = (struct ct_fdmi_port_attr *) (entries + size);
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 
1712 int
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 
1750 int
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,
1768 
1769  /* Prepare CT request */
1770  ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GFPN_ID_CMD,
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);
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 
1858 int
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,
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 ==
1905  ct_rsp->header.reason_code ==
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 
1966 void
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 }