qla_gs.c 30 KB

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