qla_gs.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  1. /*
  2. * QLOGIC LINUX SOFTWARE
  3. *
  4. * QLogic ISP2x00 device driver for Linux 2.6.x
  5. * Copyright (C) 2003-2004 QLogic Corporation
  6. * (www.qlogic.com)
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the
  10. * Free Software Foundation; either version 2, or (at your option) any
  11. * later version.
  12. *
  13. * This program is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * General Public License for more details.
  17. *
  18. */
  19. #include "qla_def.h"
  20. static inline ms_iocb_entry_t *
  21. qla2x00_prep_ms_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
  22. static inline struct ct_sns_req *
  23. qla2x00_prep_ct_req(struct ct_sns_req *, uint16_t, uint16_t);
  24. static inline struct sns_cmd_pkt *
  25. qla2x00_prep_sns_cmd(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
  26. static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *);
  27. static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *);
  28. static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *);
  29. static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *);
  30. static int qla2x00_sns_rft_id(scsi_qla_host_t *);
  31. static int qla2x00_sns_rnn_id(scsi_qla_host_t *);
  32. /**
  33. * qla2x00_prep_ms_iocb() - Prepare common MS IOCB fields for SNS CT query.
  34. * @ha: HA context
  35. * @req_size: request size in bytes
  36. * @rsp_size: response size in bytes
  37. *
  38. * Returns a pointer to the @ha's ms_iocb.
  39. */
  40. static inline ms_iocb_entry_t *
  41. qla2x00_prep_ms_iocb(scsi_qla_host_t *ha, uint32_t req_size, uint32_t rsp_size)
  42. {
  43. ms_iocb_entry_t *ms_pkt;
  44. ms_pkt = ha->ms_iocb;
  45. memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
  46. ms_pkt->entry_type = MS_IOCB_TYPE;
  47. ms_pkt->entry_count = 1;
  48. SET_TARGET_ID(ha, ms_pkt->loop_id, SIMPLE_NAME_SERVER);
  49. ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG);
  50. ms_pkt->timeout = __constant_cpu_to_le16(25);
  51. ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
  52. ms_pkt->total_dsd_count = __constant_cpu_to_le16(2);
  53. ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
  54. ms_pkt->req_bytecount = cpu_to_le32(req_size);
  55. ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
  56. ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
  57. ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
  58. ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
  59. ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
  60. ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
  61. return (ms_pkt);
  62. }
  63. /**
  64. * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
  65. * @ct_req: CT request buffer
  66. * @cmd: GS command
  67. * @rsp_size: response size in bytes
  68. *
  69. * Returns a pointer to the intitialized @ct_req.
  70. */
  71. static inline struct ct_sns_req *
  72. qla2x00_prep_ct_req(struct ct_sns_req *ct_req, uint16_t cmd, uint16_t rsp_size)
  73. {
  74. memset(ct_req, 0, sizeof(struct ct_sns_pkt));
  75. ct_req->header.revision = 0x01;
  76. ct_req->header.gs_type = 0xFC;
  77. ct_req->header.gs_subtype = 0x02;
  78. ct_req->command = cpu_to_be16(cmd);
  79. ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
  80. return (ct_req);
  81. }
  82. /**
  83. * qla2x00_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
  84. * @ha: HA context
  85. * @fcport: fcport entry to updated
  86. *
  87. * Returns 0 on success.
  88. */
  89. int
  90. qla2x00_ga_nxt(scsi_qla_host_t *ha, fc_port_t *fcport)
  91. {
  92. int rval;
  93. ms_iocb_entry_t *ms_pkt;
  94. struct ct_sns_req *ct_req;
  95. struct ct_sns_rsp *ct_rsp;
  96. if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
  97. return (qla2x00_sns_ga_nxt(ha, fcport));
  98. }
  99. /* Issue GA_NXT */
  100. /* Prepare common MS IOCB */
  101. ms_pkt = qla2x00_prep_ms_iocb(ha, GA_NXT_REQ_SIZE, GA_NXT_RSP_SIZE);
  102. /* Prepare CT request */
  103. ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GA_NXT_CMD,
  104. GA_NXT_RSP_SIZE);
  105. ct_rsp = &ha->ct_sns->p.rsp;
  106. /* Prepare CT arguments -- port_id */
  107. ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain;
  108. ct_req->req.port_id.port_id[1] = fcport->d_id.b.area;
  109. ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa;
  110. /* Execute MS IOCB */
  111. rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
  112. sizeof(ms_iocb_entry_t));
  113. if (rval != QLA_SUCCESS) {
  114. /*EMPTY*/
  115. DEBUG2_3(printk("scsi(%ld): GA_NXT issue IOCB failed (%d).\n",
  116. ha->host_no, rval));
  117. } else if (ct_rsp->header.response !=
  118. __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
  119. DEBUG2_3(printk("scsi(%ld): GA_NXT failed, rejected request, "
  120. "ga_nxt_rsp:\n", ha->host_no));
  121. DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header,
  122. sizeof(struct ct_rsp_hdr)));
  123. rval = QLA_FUNCTION_FAILED;
  124. } else {
  125. /* Populate fc_port_t entry. */
  126. fcport->d_id.b.domain = ct_rsp->rsp.ga_nxt.port_id[0];
  127. fcport->d_id.b.area = ct_rsp->rsp.ga_nxt.port_id[1];
  128. fcport->d_id.b.al_pa = ct_rsp->rsp.ga_nxt.port_id[2];
  129. memcpy(fcport->node_name, ct_rsp->rsp.ga_nxt.node_name,
  130. WWN_SIZE);
  131. memcpy(fcport->port_name, ct_rsp->rsp.ga_nxt.port_name,
  132. WWN_SIZE);
  133. if (ct_rsp->rsp.ga_nxt.port_type != NS_N_PORT_TYPE &&
  134. ct_rsp->rsp.ga_nxt.port_type != NS_NL_PORT_TYPE)
  135. fcport->d_id.b.domain = 0xf0;
  136. DEBUG2_3(printk("scsi(%ld): GA_NXT entry - "
  137. "nn %02x%02x%02x%02x%02x%02x%02x%02x "
  138. "pn %02x%02x%02x%02x%02x%02x%02x%02x "
  139. "portid=%02x%02x%02x.\n",
  140. ha->host_no,
  141. fcport->node_name[0], fcport->node_name[1],
  142. fcport->node_name[2], fcport->node_name[3],
  143. fcport->node_name[4], fcport->node_name[5],
  144. fcport->node_name[6], fcport->node_name[7],
  145. fcport->port_name[0], fcport->port_name[1],
  146. fcport->port_name[2], fcport->port_name[3],
  147. fcport->port_name[4], fcport->port_name[5],
  148. fcport->port_name[6], fcport->port_name[7],
  149. fcport->d_id.b.domain, fcport->d_id.b.area,
  150. fcport->d_id.b.al_pa));
  151. }
  152. return (rval);
  153. }
  154. /**
  155. * qla2x00_gid_pt() - SNS scan for fabric devices via GID_PT command.
  156. * @ha: HA context
  157. * @list: switch info entries to populate
  158. *
  159. * NOTE: Non-Nx_Ports are not requested.
  160. *
  161. * Returns 0 on success.
  162. */
  163. int
  164. qla2x00_gid_pt(scsi_qla_host_t *ha, sw_info_t *list)
  165. {
  166. int rval;
  167. uint16_t i;
  168. ms_iocb_entry_t *ms_pkt;
  169. struct ct_sns_req *ct_req;
  170. struct ct_sns_rsp *ct_rsp;
  171. struct ct_sns_gid_pt_data *gid_data;
  172. if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
  173. return (qla2x00_sns_gid_pt(ha, list));
  174. }
  175. gid_data = NULL;
  176. /* Issue GID_PT */
  177. /* Prepare common MS IOCB */
  178. ms_pkt = qla2x00_prep_ms_iocb(ha, GID_PT_REQ_SIZE, GID_PT_RSP_SIZE);
  179. /* Prepare CT request */
  180. ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GID_PT_CMD,
  181. GID_PT_RSP_SIZE);
  182. ct_rsp = &ha->ct_sns->p.rsp;
  183. /* Prepare CT arguments -- port_type */
  184. ct_req->req.gid_pt.port_type = NS_NX_PORT_TYPE;
  185. /* Execute MS IOCB */
  186. rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
  187. sizeof(ms_iocb_entry_t));
  188. if (rval != QLA_SUCCESS) {
  189. /*EMPTY*/
  190. DEBUG2_3(printk("scsi(%ld): GID_PT issue IOCB failed (%d).\n",
  191. ha->host_no, rval));
  192. } else if (ct_rsp->header.response !=
  193. __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
  194. DEBUG2_3(printk("scsi(%ld): GID_PT failed, rejected request, "
  195. "gid_pt_rsp:\n", ha->host_no));
  196. DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header,
  197. sizeof(struct ct_rsp_hdr)));
  198. rval = QLA_FUNCTION_FAILED;
  199. } else {
  200. /* Set port IDs in switch info list. */
  201. for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
  202. gid_data = &ct_rsp->rsp.gid_pt.entries[i];
  203. list[i].d_id.b.domain = gid_data->port_id[0];
  204. list[i].d_id.b.area = gid_data->port_id[1];
  205. list[i].d_id.b.al_pa = gid_data->port_id[2];
  206. /* Last one exit. */
  207. if (gid_data->control_byte & BIT_7) {
  208. list[i].d_id.b.rsvd_1 = gid_data->control_byte;
  209. break;
  210. }
  211. }
  212. /*
  213. * If we've used all available slots, then the switch is
  214. * reporting back more devices than we can handle with this
  215. * single call. Return a failed status, and let GA_NXT handle
  216. * the overload.
  217. */
  218. if (i == MAX_FIBRE_DEVICES)
  219. rval = QLA_FUNCTION_FAILED;
  220. }
  221. return (rval);
  222. }
  223. /**
  224. * qla2x00_gpn_id() - SNS Get Port Name (GPN_ID) query.
  225. * @ha: HA context
  226. * @list: switch info entries to populate
  227. *
  228. * Returns 0 on success.
  229. */
  230. int
  231. qla2x00_gpn_id(scsi_qla_host_t *ha, sw_info_t *list)
  232. {
  233. int rval;
  234. uint16_t i;
  235. ms_iocb_entry_t *ms_pkt;
  236. struct ct_sns_req *ct_req;
  237. struct ct_sns_rsp *ct_rsp;
  238. if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
  239. return (qla2x00_sns_gpn_id(ha, list));
  240. }
  241. for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
  242. /* Issue GPN_ID */
  243. /* Prepare common MS IOCB */
  244. ms_pkt = qla2x00_prep_ms_iocb(ha, GPN_ID_REQ_SIZE,
  245. GPN_ID_RSP_SIZE);
  246. /* Prepare CT request */
  247. ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GPN_ID_CMD,
  248. GPN_ID_RSP_SIZE);
  249. ct_rsp = &ha->ct_sns->p.rsp;
  250. /* Prepare CT arguments -- port_id */
  251. ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
  252. ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
  253. ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
  254. /* Execute MS IOCB */
  255. rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
  256. sizeof(ms_iocb_entry_t));
  257. if (rval != QLA_SUCCESS) {
  258. /*EMPTY*/
  259. DEBUG2_3(printk("scsi(%ld): GPN_ID issue IOCB failed "
  260. "(%d).\n", ha->host_no, rval));
  261. } else if (ct_rsp->header.response !=
  262. __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
  263. DEBUG2_3(printk("scsi(%ld): GPN_ID failed, rejected "
  264. "request, gpn_id_rsp:\n", ha->host_no));
  265. DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header,
  266. sizeof(struct ct_rsp_hdr)));
  267. rval = QLA_FUNCTION_FAILED;
  268. } else {
  269. /* Save portname */
  270. memcpy(list[i].port_name,
  271. ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);
  272. }
  273. /* Last device exit. */
  274. if (list[i].d_id.b.rsvd_1 != 0)
  275. break;
  276. }
  277. return (rval);
  278. }
  279. /**
  280. * qla2x00_gnn_id() - SNS Get Node Name (GNN_ID) query.
  281. * @ha: HA context
  282. * @list: switch info entries to populate
  283. *
  284. * Returns 0 on success.
  285. */
  286. int
  287. qla2x00_gnn_id(scsi_qla_host_t *ha, sw_info_t *list)
  288. {
  289. int rval;
  290. uint16_t i;
  291. ms_iocb_entry_t *ms_pkt;
  292. struct ct_sns_req *ct_req;
  293. struct ct_sns_rsp *ct_rsp;
  294. if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
  295. return (qla2x00_sns_gnn_id(ha, list));
  296. }
  297. for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
  298. /* Issue GNN_ID */
  299. /* Prepare common MS IOCB */
  300. ms_pkt = qla2x00_prep_ms_iocb(ha, GNN_ID_REQ_SIZE,
  301. GNN_ID_RSP_SIZE);
  302. /* Prepare CT request */
  303. ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GNN_ID_CMD,
  304. GNN_ID_RSP_SIZE);
  305. ct_rsp = &ha->ct_sns->p.rsp;
  306. /* Prepare CT arguments -- port_id */
  307. ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
  308. ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
  309. ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
  310. /* Execute MS IOCB */
  311. rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
  312. sizeof(ms_iocb_entry_t));
  313. if (rval != QLA_SUCCESS) {
  314. /*EMPTY*/
  315. DEBUG2_3(printk("scsi(%ld): GNN_ID issue IOCB failed "
  316. "(%d).\n", ha->host_no, rval));
  317. } else if (ct_rsp->header.response !=
  318. __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
  319. DEBUG2_3(printk("scsi(%ld): GNN_ID failed, rejected "
  320. "request, gnn_id_rsp:\n", ha->host_no));
  321. DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header,
  322. sizeof(struct ct_rsp_hdr)));
  323. rval = QLA_FUNCTION_FAILED;
  324. } else {
  325. /* Save nodename */
  326. memcpy(list[i].node_name,
  327. ct_rsp->rsp.gnn_id.node_name, WWN_SIZE);
  328. DEBUG2_3(printk("scsi(%ld): GID_PT entry - "
  329. "nn %02x%02x%02x%02x%02x%02x%02x%02x "
  330. "pn %02x%02x%02x%02x%02x%02x%02x%02x "
  331. "portid=%02x%02x%02x.\n",
  332. ha->host_no,
  333. list[i].node_name[0], list[i].node_name[1],
  334. list[i].node_name[2], list[i].node_name[3],
  335. list[i].node_name[4], list[i].node_name[5],
  336. list[i].node_name[6], list[i].node_name[7],
  337. list[i].port_name[0], list[i].port_name[1],
  338. list[i].port_name[2], list[i].port_name[3],
  339. list[i].port_name[4], list[i].port_name[5],
  340. list[i].port_name[6], list[i].port_name[7],
  341. list[i].d_id.b.domain, list[i].d_id.b.area,
  342. list[i].d_id.b.al_pa));
  343. }
  344. /* Last device exit. */
  345. if (list[i].d_id.b.rsvd_1 != 0)
  346. break;
  347. }
  348. return (rval);
  349. }
  350. /**
  351. * qla2x00_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
  352. * @ha: HA context
  353. *
  354. * Returns 0 on success.
  355. */
  356. int
  357. qla2x00_rft_id(scsi_qla_host_t *ha)
  358. {
  359. int rval;
  360. ms_iocb_entry_t *ms_pkt;
  361. struct ct_sns_req *ct_req;
  362. struct ct_sns_rsp *ct_rsp;
  363. if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
  364. return (qla2x00_sns_rft_id(ha));
  365. }
  366. /* Issue RFT_ID */
  367. /* Prepare common MS IOCB */
  368. ms_pkt = qla2x00_prep_ms_iocb(ha, RFT_ID_REQ_SIZE, RFT_ID_RSP_SIZE);
  369. /* Prepare CT request */
  370. ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFT_ID_CMD,
  371. RFT_ID_RSP_SIZE);
  372. ct_rsp = &ha->ct_sns->p.rsp;
  373. /* Prepare CT arguments -- port_id, FC-4 types */
  374. ct_req->req.rft_id.port_id[0] = ha->d_id.b.domain;
  375. ct_req->req.rft_id.port_id[1] = ha->d_id.b.area;
  376. ct_req->req.rft_id.port_id[2] = ha->d_id.b.al_pa;
  377. ct_req->req.rft_id.fc4_types[2] = 0x01; /* FCP-3 */
  378. /* Execute MS IOCB */
  379. rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
  380. sizeof(ms_iocb_entry_t));
  381. if (rval != QLA_SUCCESS) {
  382. /*EMPTY*/
  383. DEBUG2_3(printk("scsi(%ld): RFT_ID issue IOCB failed (%d).\n",
  384. ha->host_no, rval));
  385. } else if (ct_rsp->header.response !=
  386. __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
  387. DEBUG2_3(printk("scsi(%ld): RFT_ID failed, rejected "
  388. "request, rft_id_rsp:\n", ha->host_no));
  389. DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header,
  390. sizeof(struct ct_rsp_hdr)));
  391. rval = QLA_FUNCTION_FAILED;
  392. } else {
  393. DEBUG2(printk("scsi(%ld): RFT_ID exiting normally.\n",
  394. ha->host_no));
  395. }
  396. return (rval);
  397. }
  398. /**
  399. * qla2x00_rff_id() - SNS Register FC-4 Features (RFF_ID) supported by the HBA.
  400. * @ha: HA context
  401. *
  402. * Returns 0 on success.
  403. */
  404. int
  405. qla2x00_rff_id(scsi_qla_host_t *ha)
  406. {
  407. int rval;
  408. ms_iocb_entry_t *ms_pkt;
  409. struct ct_sns_req *ct_req;
  410. struct ct_sns_rsp *ct_rsp;
  411. if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
  412. DEBUG2(printk("scsi(%ld): RFF_ID call unsupported on "
  413. "ISP2100/ISP2200.\n", ha->host_no));
  414. return (QLA_SUCCESS);
  415. }
  416. /* Issue RFF_ID */
  417. /* Prepare common MS IOCB */
  418. ms_pkt = qla2x00_prep_ms_iocb(ha, RFF_ID_REQ_SIZE, RFF_ID_RSP_SIZE);
  419. /* Prepare CT request */
  420. ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFF_ID_CMD,
  421. RFF_ID_RSP_SIZE);
  422. ct_rsp = &ha->ct_sns->p.rsp;
  423. /* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */
  424. ct_req->req.rff_id.port_id[0] = ha->d_id.b.domain;
  425. ct_req->req.rff_id.port_id[1] = ha->d_id.b.area;
  426. ct_req->req.rff_id.port_id[2] = ha->d_id.b.al_pa;
  427. ct_req->req.rff_id.fc4_type = 0x08; /* SCSI - FCP */
  428. /* Execute MS IOCB */
  429. rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
  430. sizeof(ms_iocb_entry_t));
  431. if (rval != QLA_SUCCESS) {
  432. /*EMPTY*/
  433. DEBUG2_3(printk("scsi(%ld): RFF_ID issue IOCB failed (%d).\n",
  434. ha->host_no, rval));
  435. } else if (ct_rsp->header.response !=
  436. __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
  437. DEBUG2_3(printk("scsi(%ld): RFF_ID failed, rejected "
  438. "request, rff_id_rsp:\n", ha->host_no));
  439. DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header,
  440. sizeof(struct ct_rsp_hdr)));
  441. rval = QLA_FUNCTION_FAILED;
  442. } else {
  443. DEBUG2(printk("scsi(%ld): RFF_ID exiting normally.\n",
  444. ha->host_no));
  445. }
  446. return (rval);
  447. }
  448. /**
  449. * qla2x00_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
  450. * @ha: HA context
  451. *
  452. * Returns 0 on success.
  453. */
  454. int
  455. qla2x00_rnn_id(scsi_qla_host_t *ha)
  456. {
  457. int rval;
  458. ms_iocb_entry_t *ms_pkt;
  459. struct ct_sns_req *ct_req;
  460. struct ct_sns_rsp *ct_rsp;
  461. if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
  462. return (qla2x00_sns_rnn_id(ha));
  463. }
  464. /* Issue RNN_ID */
  465. /* Prepare common MS IOCB */
  466. ms_pkt = qla2x00_prep_ms_iocb(ha, RNN_ID_REQ_SIZE, RNN_ID_RSP_SIZE);
  467. /* Prepare CT request */
  468. ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RNN_ID_CMD,
  469. RNN_ID_RSP_SIZE);
  470. ct_rsp = &ha->ct_sns->p.rsp;
  471. /* Prepare CT arguments -- port_id, node_name */
  472. ct_req->req.rnn_id.port_id[0] = ha->d_id.b.domain;
  473. ct_req->req.rnn_id.port_id[1] = ha->d_id.b.area;
  474. ct_req->req.rnn_id.port_id[2] = ha->d_id.b.al_pa;
  475. memcpy(ct_req->req.rnn_id.node_name, ha->init_cb->node_name, WWN_SIZE);
  476. /* Execute MS IOCB */
  477. rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
  478. sizeof(ms_iocb_entry_t));
  479. if (rval != QLA_SUCCESS) {
  480. /*EMPTY*/
  481. DEBUG2_3(printk("scsi(%ld): RNN_ID issue IOCB failed (%d).\n",
  482. ha->host_no, rval));
  483. } else if (ct_rsp->header.response !=
  484. __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
  485. DEBUG2_3(printk("scsi(%ld): RNN_ID failed, rejected "
  486. "request, rnn_id_rsp:\n", ha->host_no));
  487. DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header,
  488. sizeof(struct ct_rsp_hdr)));
  489. rval = QLA_FUNCTION_FAILED;
  490. } else {
  491. DEBUG2(printk("scsi(%ld): RNN_ID exiting normally.\n",
  492. ha->host_no));
  493. }
  494. return (rval);
  495. }
  496. /**
  497. * qla2x00_rsnn_nn() - SNS Register Symbolic Node Name (RSNN_NN) of the HBA.
  498. * @ha: HA context
  499. *
  500. * Returns 0 on success.
  501. */
  502. int
  503. qla2x00_rsnn_nn(scsi_qla_host_t *ha)
  504. {
  505. int rval;
  506. uint8_t *snn;
  507. uint8_t version[20];
  508. ms_iocb_entry_t *ms_pkt;
  509. struct ct_sns_req *ct_req;
  510. struct ct_sns_rsp *ct_rsp;
  511. if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
  512. DEBUG2(printk("scsi(%ld): RSNN_ID call unsupported on "
  513. "ISP2100/ISP2200.\n", ha->host_no));
  514. return (QLA_SUCCESS);
  515. }
  516. /* Issue RSNN_NN */
  517. /* Prepare common MS IOCB */
  518. /* Request size adjusted after CT preparation */
  519. ms_pkt = qla2x00_prep_ms_iocb(ha, 0, RSNN_NN_RSP_SIZE);
  520. /* Prepare CT request */
  521. ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RSNN_NN_CMD,
  522. RSNN_NN_RSP_SIZE);
  523. ct_rsp = &ha->ct_sns->p.rsp;
  524. /* Prepare CT arguments -- node_name, symbolic node_name, size */
  525. memcpy(ct_req->req.rsnn_nn.node_name, ha->init_cb->node_name, WWN_SIZE);
  526. /* Prepare the Symbolic Node Name */
  527. /* Board type */
  528. snn = ct_req->req.rsnn_nn.sym_node_name;
  529. strcpy(snn, ha->model_number);
  530. /* Firmware version */
  531. strcat(snn, " FW:v");
  532. sprintf(version, "%d.%02d.%02d", ha->fw_major_version,
  533. ha->fw_minor_version, ha->fw_subminor_version);
  534. strcat(snn, version);
  535. /* Driver version */
  536. strcat(snn, " DVR:v");
  537. strcat(snn, qla2x00_version_str);
  538. /* Calculate SNN length */
  539. ct_req->req.rsnn_nn.name_len = (uint8_t)strlen(snn);
  540. /* Update MS IOCB request */
  541. ms_pkt->req_bytecount =
  542. cpu_to_le32(24 + 1 + ct_req->req.rsnn_nn.name_len);
  543. ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
  544. /* Execute MS IOCB */
  545. rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
  546. sizeof(ms_iocb_entry_t));
  547. if (rval != QLA_SUCCESS) {
  548. /*EMPTY*/
  549. DEBUG2_3(printk("scsi(%ld): RSNN_NN issue IOCB failed (%d).\n",
  550. ha->host_no, rval));
  551. } else if (ct_rsp->header.response !=
  552. __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
  553. DEBUG2_3(printk("scsi(%ld): RSNN_NN failed, rejected "
  554. "request, rsnn_id_rsp:\n", ha->host_no));
  555. DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header,
  556. sizeof(struct ct_rsp_hdr)));
  557. rval = QLA_FUNCTION_FAILED;
  558. } else {
  559. DEBUG2(printk("scsi(%ld): RSNN_NN exiting normally.\n",
  560. ha->host_no));
  561. }
  562. return (rval);
  563. }
  564. /**
  565. * qla2x00_prep_sns_cmd() - Prepare common SNS command request fields for query.
  566. * @ha: HA context
  567. * @cmd: GS command
  568. * @scmd_len: Subcommand length
  569. * @data_size: response size in bytes
  570. *
  571. * Returns a pointer to the @ha's sns_cmd.
  572. */
  573. static inline struct sns_cmd_pkt *
  574. qla2x00_prep_sns_cmd(scsi_qla_host_t *ha, uint16_t cmd, uint16_t scmd_len,
  575. uint16_t data_size)
  576. {
  577. uint16_t wc;
  578. struct sns_cmd_pkt *sns_cmd;
  579. sns_cmd = ha->sns_cmd;
  580. memset(sns_cmd, 0, sizeof(struct sns_cmd_pkt));
  581. wc = data_size / 2; /* Size in 16bit words. */
  582. sns_cmd->p.cmd.buffer_length = cpu_to_le16(wc);
  583. sns_cmd->p.cmd.buffer_address[0] = cpu_to_le32(LSD(ha->sns_cmd_dma));
  584. sns_cmd->p.cmd.buffer_address[1] = cpu_to_le32(MSD(ha->sns_cmd_dma));
  585. sns_cmd->p.cmd.subcommand_length = cpu_to_le16(scmd_len);
  586. sns_cmd->p.cmd.subcommand = cpu_to_le16(cmd);
  587. wc = (data_size - 16) / 4; /* Size in 32bit words. */
  588. sns_cmd->p.cmd.size = cpu_to_le16(wc);
  589. return (sns_cmd);
  590. }
  591. /**
  592. * qla2x00_sns_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
  593. * @ha: HA context
  594. * @fcport: fcport entry to updated
  595. *
  596. * This command uses the old Exectute SNS Command mailbox routine.
  597. *
  598. * Returns 0 on success.
  599. */
  600. static int
  601. qla2x00_sns_ga_nxt(scsi_qla_host_t *ha, fc_port_t *fcport)
  602. {
  603. int rval;
  604. struct sns_cmd_pkt *sns_cmd;
  605. /* Issue GA_NXT. */
  606. /* Prepare SNS command request. */
  607. sns_cmd = qla2x00_prep_sns_cmd(ha, GA_NXT_CMD, GA_NXT_SNS_SCMD_LEN,
  608. GA_NXT_SNS_DATA_SIZE);
  609. /* Prepare SNS command arguments -- port_id. */
  610. sns_cmd->p.cmd.param[0] = fcport->d_id.b.al_pa;
  611. sns_cmd->p.cmd.param[1] = fcport->d_id.b.area;
  612. sns_cmd->p.cmd.param[2] = fcport->d_id.b.domain;
  613. /* Execute SNS command. */
  614. rval = qla2x00_send_sns(ha, ha->sns_cmd_dma, GA_NXT_SNS_CMD_SIZE / 2,
  615. sizeof(struct sns_cmd_pkt));
  616. if (rval != QLA_SUCCESS) {
  617. /*EMPTY*/
  618. DEBUG2_3(printk("scsi(%ld): GA_NXT Send SNS failed (%d).\n",
  619. ha->host_no, rval));
  620. } else if (sns_cmd->p.gan_data[8] != 0x80 ||
  621. sns_cmd->p.gan_data[9] != 0x02) {
  622. DEBUG2_3(printk("scsi(%ld): GA_NXT failed, rejected request, "
  623. "ga_nxt_rsp:\n", ha->host_no));
  624. DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gan_data, 16));
  625. rval = QLA_FUNCTION_FAILED;
  626. } else {
  627. /* Populate fc_port_t entry. */
  628. fcport->d_id.b.domain = sns_cmd->p.gan_data[17];
  629. fcport->d_id.b.area = sns_cmd->p.gan_data[18];
  630. fcport->d_id.b.al_pa = sns_cmd->p.gan_data[19];
  631. memcpy(fcport->node_name, &sns_cmd->p.gan_data[284], WWN_SIZE);
  632. memcpy(fcport->port_name, &sns_cmd->p.gan_data[20], WWN_SIZE);
  633. if (sns_cmd->p.gan_data[16] != NS_N_PORT_TYPE &&
  634. sns_cmd->p.gan_data[16] != NS_NL_PORT_TYPE)
  635. fcport->d_id.b.domain = 0xf0;
  636. DEBUG2_3(printk("scsi(%ld): GA_NXT entry - "
  637. "nn %02x%02x%02x%02x%02x%02x%02x%02x "
  638. "pn %02x%02x%02x%02x%02x%02x%02x%02x "
  639. "portid=%02x%02x%02x.\n",
  640. ha->host_no,
  641. fcport->node_name[0], fcport->node_name[1],
  642. fcport->node_name[2], fcport->node_name[3],
  643. fcport->node_name[4], fcport->node_name[5],
  644. fcport->node_name[6], fcport->node_name[7],
  645. fcport->port_name[0], fcport->port_name[1],
  646. fcport->port_name[2], fcport->port_name[3],
  647. fcport->port_name[4], fcport->port_name[5],
  648. fcport->port_name[6], fcport->port_name[7],
  649. fcport->d_id.b.domain, fcport->d_id.b.area,
  650. fcport->d_id.b.al_pa));
  651. }
  652. return (rval);
  653. }
  654. /**
  655. * qla2x00_sns_gid_pt() - SNS scan for fabric devices via GID_PT command.
  656. * @ha: HA context
  657. * @list: switch info entries to populate
  658. *
  659. * This command uses the old Exectute SNS Command mailbox routine.
  660. *
  661. * NOTE: Non-Nx_Ports are not requested.
  662. *
  663. * Returns 0 on success.
  664. */
  665. static int
  666. qla2x00_sns_gid_pt(scsi_qla_host_t *ha, sw_info_t *list)
  667. {
  668. int rval;
  669. uint16_t i;
  670. uint8_t *entry;
  671. struct sns_cmd_pkt *sns_cmd;
  672. /* Issue GID_PT. */
  673. /* Prepare SNS command request. */
  674. sns_cmd = qla2x00_prep_sns_cmd(ha, GID_PT_CMD, GID_PT_SNS_SCMD_LEN,
  675. GID_PT_SNS_DATA_SIZE);
  676. /* Prepare SNS command arguments -- port_type. */
  677. sns_cmd->p.cmd.param[0] = NS_NX_PORT_TYPE;
  678. /* Execute SNS command. */
  679. rval = qla2x00_send_sns(ha, ha->sns_cmd_dma, GID_PT_SNS_CMD_SIZE / 2,
  680. sizeof(struct sns_cmd_pkt));
  681. if (rval != QLA_SUCCESS) {
  682. /*EMPTY*/
  683. DEBUG2_3(printk("scsi(%ld): GID_PT Send SNS failed (%d).\n",
  684. ha->host_no, rval));
  685. } else if (sns_cmd->p.gid_data[8] != 0x80 ||
  686. sns_cmd->p.gid_data[9] != 0x02) {
  687. DEBUG2_3(printk("scsi(%ld): GID_PT failed, rejected request, "
  688. "gid_rsp:\n", ha->host_no));
  689. DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gid_data, 16));
  690. rval = QLA_FUNCTION_FAILED;
  691. } else {
  692. /* Set port IDs in switch info list. */
  693. for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
  694. entry = &sns_cmd->p.gid_data[(i * 4) + 16];
  695. list[i].d_id.b.domain = entry[1];
  696. list[i].d_id.b.area = entry[2];
  697. list[i].d_id.b.al_pa = entry[3];
  698. /* Last one exit. */
  699. if (entry[0] & BIT_7) {
  700. list[i].d_id.b.rsvd_1 = entry[0];
  701. break;
  702. }
  703. }
  704. /*
  705. * If we've used all available slots, then the switch is
  706. * reporting back more devices that we can handle with this
  707. * single call. Return a failed status, and let GA_NXT handle
  708. * the overload.
  709. */
  710. if (i == MAX_FIBRE_DEVICES)
  711. rval = QLA_FUNCTION_FAILED;
  712. }
  713. return (rval);
  714. }
  715. /**
  716. * qla2x00_sns_gpn_id() - SNS Get Port Name (GPN_ID) query.
  717. * @ha: HA context
  718. * @list: switch info entries to populate
  719. *
  720. * This command uses the old Exectute SNS Command mailbox routine.
  721. *
  722. * Returns 0 on success.
  723. */
  724. static int
  725. qla2x00_sns_gpn_id(scsi_qla_host_t *ha, sw_info_t *list)
  726. {
  727. int rval;
  728. uint16_t i;
  729. struct sns_cmd_pkt *sns_cmd;
  730. for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
  731. /* Issue GPN_ID */
  732. /* Prepare SNS command request. */
  733. sns_cmd = qla2x00_prep_sns_cmd(ha, GPN_ID_CMD,
  734. GPN_ID_SNS_SCMD_LEN, GPN_ID_SNS_DATA_SIZE);
  735. /* Prepare SNS command arguments -- port_id. */
  736. sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
  737. sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
  738. sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
  739. /* Execute SNS command. */
  740. rval = qla2x00_send_sns(ha, ha->sns_cmd_dma,
  741. GPN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
  742. if (rval != QLA_SUCCESS) {
  743. /*EMPTY*/
  744. DEBUG2_3(printk("scsi(%ld): GPN_ID Send SNS failed "
  745. "(%d).\n", ha->host_no, rval));
  746. } else if (sns_cmd->p.gpn_data[8] != 0x80 ||
  747. sns_cmd->p.gpn_data[9] != 0x02) {
  748. DEBUG2_3(printk("scsi(%ld): GPN_ID failed, rejected "
  749. "request, gpn_rsp:\n", ha->host_no));
  750. DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gpn_data, 16));
  751. rval = QLA_FUNCTION_FAILED;
  752. } else {
  753. /* Save portname */
  754. memcpy(list[i].port_name, &sns_cmd->p.gpn_data[16],
  755. WWN_SIZE);
  756. }
  757. /* Last device exit. */
  758. if (list[i].d_id.b.rsvd_1 != 0)
  759. break;
  760. }
  761. return (rval);
  762. }
  763. /**
  764. * qla2x00_sns_gnn_id() - SNS Get Node Name (GNN_ID) query.
  765. * @ha: HA context
  766. * @list: switch info entries to populate
  767. *
  768. * This command uses the old Exectute SNS Command mailbox routine.
  769. *
  770. * Returns 0 on success.
  771. */
  772. static int
  773. qla2x00_sns_gnn_id(scsi_qla_host_t *ha, sw_info_t *list)
  774. {
  775. int rval;
  776. uint16_t i;
  777. struct sns_cmd_pkt *sns_cmd;
  778. for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
  779. /* Issue GNN_ID */
  780. /* Prepare SNS command request. */
  781. sns_cmd = qla2x00_prep_sns_cmd(ha, GNN_ID_CMD,
  782. GNN_ID_SNS_SCMD_LEN, GNN_ID_SNS_DATA_SIZE);
  783. /* Prepare SNS command arguments -- port_id. */
  784. sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
  785. sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
  786. sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
  787. /* Execute SNS command. */
  788. rval = qla2x00_send_sns(ha, ha->sns_cmd_dma,
  789. GNN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
  790. if (rval != QLA_SUCCESS) {
  791. /*EMPTY*/
  792. DEBUG2_3(printk("scsi(%ld): GNN_ID Send SNS failed "
  793. "(%d).\n", ha->host_no, rval));
  794. } else if (sns_cmd->p.gnn_data[8] != 0x80 ||
  795. sns_cmd->p.gnn_data[9] != 0x02) {
  796. DEBUG2_3(printk("scsi(%ld): GNN_ID failed, rejected "
  797. "request, gnn_rsp:\n", ha->host_no));
  798. DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gnn_data, 16));
  799. rval = QLA_FUNCTION_FAILED;
  800. } else {
  801. /* Save nodename */
  802. memcpy(list[i].node_name, &sns_cmd->p.gnn_data[16],
  803. WWN_SIZE);
  804. DEBUG2_3(printk("scsi(%ld): GID_PT entry - "
  805. "nn %02x%02x%02x%02x%02x%02x%02x%02x "
  806. "pn %02x%02x%02x%02x%02x%02x%02x%02x "
  807. "portid=%02x%02x%02x.\n",
  808. ha->host_no,
  809. list[i].node_name[0], list[i].node_name[1],
  810. list[i].node_name[2], list[i].node_name[3],
  811. list[i].node_name[4], list[i].node_name[5],
  812. list[i].node_name[6], list[i].node_name[7],
  813. list[i].port_name[0], list[i].port_name[1],
  814. list[i].port_name[2], list[i].port_name[3],
  815. list[i].port_name[4], list[i].port_name[5],
  816. list[i].port_name[6], list[i].port_name[7],
  817. list[i].d_id.b.domain, list[i].d_id.b.area,
  818. list[i].d_id.b.al_pa));
  819. }
  820. /* Last device exit. */
  821. if (list[i].d_id.b.rsvd_1 != 0)
  822. break;
  823. }
  824. return (rval);
  825. }
  826. /**
  827. * qla2x00_snd_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
  828. * @ha: HA context
  829. *
  830. * This command uses the old Exectute SNS Command mailbox routine.
  831. *
  832. * Returns 0 on success.
  833. */
  834. static int
  835. qla2x00_sns_rft_id(scsi_qla_host_t *ha)
  836. {
  837. int rval;
  838. struct sns_cmd_pkt *sns_cmd;
  839. /* Issue RFT_ID. */
  840. /* Prepare SNS command request. */
  841. sns_cmd = qla2x00_prep_sns_cmd(ha, RFT_ID_CMD, RFT_ID_SNS_SCMD_LEN,
  842. RFT_ID_SNS_DATA_SIZE);
  843. /* Prepare SNS command arguments -- port_id, FC-4 types */
  844. sns_cmd->p.cmd.param[0] = ha->d_id.b.al_pa;
  845. sns_cmd->p.cmd.param[1] = ha->d_id.b.area;
  846. sns_cmd->p.cmd.param[2] = ha->d_id.b.domain;
  847. sns_cmd->p.cmd.param[5] = 0x01; /* FCP-3 */
  848. /* Execute SNS command. */
  849. rval = qla2x00_send_sns(ha, ha->sns_cmd_dma, RFT_ID_SNS_CMD_SIZE / 2,
  850. sizeof(struct sns_cmd_pkt));
  851. if (rval != QLA_SUCCESS) {
  852. /*EMPTY*/
  853. DEBUG2_3(printk("scsi(%ld): RFT_ID Send SNS failed (%d).\n",
  854. ha->host_no, rval));
  855. } else if (sns_cmd->p.rft_data[8] != 0x80 ||
  856. sns_cmd->p.rft_data[9] != 0x02) {
  857. DEBUG2_3(printk("scsi(%ld): RFT_ID failed, rejected request, "
  858. "rft_rsp:\n", ha->host_no));
  859. DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.rft_data, 16));
  860. rval = QLA_FUNCTION_FAILED;
  861. } else {
  862. DEBUG2(printk("scsi(%ld): RFT_ID exiting normally.\n",
  863. ha->host_no));
  864. }
  865. return (rval);
  866. }
  867. /**
  868. * qla2x00_sns_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
  869. * HBA.
  870. * @ha: HA context
  871. *
  872. * This command uses the old Exectute SNS Command mailbox routine.
  873. *
  874. * Returns 0 on success.
  875. */
  876. static int
  877. qla2x00_sns_rnn_id(scsi_qla_host_t *ha)
  878. {
  879. int rval;
  880. struct sns_cmd_pkt *sns_cmd;
  881. /* Issue RNN_ID. */
  882. /* Prepare SNS command request. */
  883. sns_cmd = qla2x00_prep_sns_cmd(ha, RNN_ID_CMD, RNN_ID_SNS_SCMD_LEN,
  884. RNN_ID_SNS_DATA_SIZE);
  885. /* Prepare SNS command arguments -- port_id, nodename. */
  886. sns_cmd->p.cmd.param[0] = ha->d_id.b.al_pa;
  887. sns_cmd->p.cmd.param[1] = ha->d_id.b.area;
  888. sns_cmd->p.cmd.param[2] = ha->d_id.b.domain;
  889. sns_cmd->p.cmd.param[4] = ha->init_cb->node_name[7];
  890. sns_cmd->p.cmd.param[5] = ha->init_cb->node_name[6];
  891. sns_cmd->p.cmd.param[6] = ha->init_cb->node_name[5];
  892. sns_cmd->p.cmd.param[7] = ha->init_cb->node_name[4];
  893. sns_cmd->p.cmd.param[8] = ha->init_cb->node_name[3];
  894. sns_cmd->p.cmd.param[9] = ha->init_cb->node_name[2];
  895. sns_cmd->p.cmd.param[10] = ha->init_cb->node_name[1];
  896. sns_cmd->p.cmd.param[11] = ha->init_cb->node_name[0];
  897. /* Execute SNS command. */
  898. rval = qla2x00_send_sns(ha, ha->sns_cmd_dma, RNN_ID_SNS_CMD_SIZE / 2,
  899. sizeof(struct sns_cmd_pkt));
  900. if (rval != QLA_SUCCESS) {
  901. /*EMPTY*/
  902. DEBUG2_3(printk("scsi(%ld): RNN_ID Send SNS failed (%d).\n",
  903. ha->host_no, rval));
  904. } else if (sns_cmd->p.rnn_data[8] != 0x80 ||
  905. sns_cmd->p.rnn_data[9] != 0x02) {
  906. DEBUG2_3(printk("scsi(%ld): RNN_ID failed, rejected request, "
  907. "rnn_rsp:\n", ha->host_no));
  908. DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.rnn_data, 16));
  909. rval = QLA_FUNCTION_FAILED;
  910. } else {
  911. DEBUG2(printk("scsi(%ld): RNN_ID exiting normally.\n",
  912. ha->host_no));
  913. }
  914. return (rval);
  915. }