qla_gs.c 55 KB

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