bfa_fcbuild.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465
  1. /*
  2. * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
  3. * Copyright (c) 2014- QLogic Corporation.
  4. * All rights reserved
  5. * www.qlogic.com
  6. *
  7. * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
  8. *
  9. * This program is free software; you can redistribute it and/or modify it
  10. * under the terms of the GNU General Public License (GPL) Version 2 as
  11. * published by the Free Software Foundation
  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. * fcbuild.c - FC link service frame building and parsing routines
  20. */
  21. #include "bfad_drv.h"
  22. #include "bfa_fcbuild.h"
  23. /*
  24. * static build functions
  25. */
  26. static void fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
  27. __be16 ox_id);
  28. static void fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
  29. __be16 ox_id);
  30. static struct fchs_s fc_els_req_tmpl;
  31. static struct fchs_s fc_els_rsp_tmpl;
  32. static struct fchs_s fc_bls_req_tmpl;
  33. static struct fchs_s fc_bls_rsp_tmpl;
  34. static struct fc_ba_acc_s ba_acc_tmpl;
  35. static struct fc_logi_s plogi_tmpl;
  36. static struct fc_prli_s prli_tmpl;
  37. static struct fc_rrq_s rrq_tmpl;
  38. static struct fchs_s fcp_fchs_tmpl;
  39. void
  40. fcbuild_init(void)
  41. {
  42. /*
  43. * fc_els_req_tmpl
  44. */
  45. fc_els_req_tmpl.routing = FC_RTG_EXT_LINK;
  46. fc_els_req_tmpl.cat_info = FC_CAT_LD_REQUEST;
  47. fc_els_req_tmpl.type = FC_TYPE_ELS;
  48. fc_els_req_tmpl.f_ctl =
  49. bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
  50. FCTL_SI_XFER);
  51. fc_els_req_tmpl.rx_id = FC_RXID_ANY;
  52. /*
  53. * fc_els_rsp_tmpl
  54. */
  55. fc_els_rsp_tmpl.routing = FC_RTG_EXT_LINK;
  56. fc_els_rsp_tmpl.cat_info = FC_CAT_LD_REPLY;
  57. fc_els_rsp_tmpl.type = FC_TYPE_ELS;
  58. fc_els_rsp_tmpl.f_ctl =
  59. bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
  60. FCTL_END_SEQ | FCTL_SI_XFER);
  61. fc_els_rsp_tmpl.rx_id = FC_RXID_ANY;
  62. /*
  63. * fc_bls_req_tmpl
  64. */
  65. fc_bls_req_tmpl.routing = FC_RTG_BASIC_LINK;
  66. fc_bls_req_tmpl.type = FC_TYPE_BLS;
  67. fc_bls_req_tmpl.f_ctl = bfa_hton3b(FCTL_END_SEQ | FCTL_SI_XFER);
  68. fc_bls_req_tmpl.rx_id = FC_RXID_ANY;
  69. /*
  70. * fc_bls_rsp_tmpl
  71. */
  72. fc_bls_rsp_tmpl.routing = FC_RTG_BASIC_LINK;
  73. fc_bls_rsp_tmpl.cat_info = FC_CAT_BA_ACC;
  74. fc_bls_rsp_tmpl.type = FC_TYPE_BLS;
  75. fc_bls_rsp_tmpl.f_ctl =
  76. bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
  77. FCTL_END_SEQ | FCTL_SI_XFER);
  78. fc_bls_rsp_tmpl.rx_id = FC_RXID_ANY;
  79. /*
  80. * ba_acc_tmpl
  81. */
  82. ba_acc_tmpl.seq_id_valid = 0;
  83. ba_acc_tmpl.low_seq_cnt = 0;
  84. ba_acc_tmpl.high_seq_cnt = 0xFFFF;
  85. /*
  86. * plogi_tmpl
  87. */
  88. plogi_tmpl.csp.verhi = FC_PH_VER_PH_3;
  89. plogi_tmpl.csp.verlo = FC_PH_VER_4_3;
  90. plogi_tmpl.csp.ciro = 0x1;
  91. plogi_tmpl.csp.cisc = 0x0;
  92. plogi_tmpl.csp.altbbcred = 0x0;
  93. plogi_tmpl.csp.conseq = cpu_to_be16(0x00FF);
  94. plogi_tmpl.csp.ro_bitmap = cpu_to_be16(0x0002);
  95. plogi_tmpl.csp.e_d_tov = cpu_to_be32(2000);
  96. plogi_tmpl.class3.class_valid = 1;
  97. plogi_tmpl.class3.sequential = 1;
  98. plogi_tmpl.class3.conseq = 0xFF;
  99. plogi_tmpl.class3.ospx = 1;
  100. /*
  101. * prli_tmpl
  102. */
  103. prli_tmpl.command = FC_ELS_PRLI;
  104. prli_tmpl.pglen = 0x10;
  105. prli_tmpl.pagebytes = cpu_to_be16(0x0014);
  106. prli_tmpl.parampage.type = FC_TYPE_FCP;
  107. prli_tmpl.parampage.imagepair = 1;
  108. prli_tmpl.parampage.servparams.rxrdisab = 1;
  109. /*
  110. * rrq_tmpl
  111. */
  112. rrq_tmpl.els_cmd.els_code = FC_ELS_RRQ;
  113. /*
  114. * fcp_struct fchs_s mpl
  115. */
  116. fcp_fchs_tmpl.routing = FC_RTG_FC4_DEV_DATA;
  117. fcp_fchs_tmpl.cat_info = FC_CAT_UNSOLICIT_CMD;
  118. fcp_fchs_tmpl.type = FC_TYPE_FCP;
  119. fcp_fchs_tmpl.f_ctl =
  120. bfa_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER);
  121. fcp_fchs_tmpl.seq_id = 1;
  122. fcp_fchs_tmpl.rx_id = FC_RXID_ANY;
  123. }
  124. static void
  125. fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id)
  126. {
  127. memset(fchs, 0, sizeof(struct fchs_s));
  128. fchs->routing = FC_RTG_FC4_DEV_DATA;
  129. fchs->cat_info = FC_CAT_UNSOLICIT_CTRL;
  130. fchs->type = FC_TYPE_SERVICES;
  131. fchs->f_ctl =
  132. bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
  133. FCTL_SI_XFER);
  134. fchs->rx_id = FC_RXID_ANY;
  135. fchs->d_id = (d_id);
  136. fchs->s_id = (s_id);
  137. fchs->ox_id = cpu_to_be16(ox_id);
  138. /*
  139. * @todo no need to set ox_id for request
  140. * no need to set rx_id for response
  141. */
  142. }
  143. static void
  144. fc_gsresp_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
  145. {
  146. memset(fchs, 0, sizeof(struct fchs_s));
  147. fchs->routing = FC_RTG_FC4_DEV_DATA;
  148. fchs->cat_info = FC_CAT_SOLICIT_CTRL;
  149. fchs->type = FC_TYPE_SERVICES;
  150. fchs->f_ctl =
  151. bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
  152. FCTL_END_SEQ | FCTL_SI_XFER);
  153. fchs->d_id = d_id;
  154. fchs->s_id = s_id;
  155. fchs->ox_id = ox_id;
  156. }
  157. void
  158. fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
  159. {
  160. memcpy(fchs, &fc_els_req_tmpl, sizeof(struct fchs_s));
  161. fchs->d_id = (d_id);
  162. fchs->s_id = (s_id);
  163. fchs->ox_id = cpu_to_be16(ox_id);
  164. }
  165. static void
  166. fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
  167. {
  168. memcpy(fchs, &fc_els_rsp_tmpl, sizeof(struct fchs_s));
  169. fchs->d_id = d_id;
  170. fchs->s_id = s_id;
  171. fchs->ox_id = ox_id;
  172. }
  173. enum fc_parse_status
  174. fc_els_rsp_parse(struct fchs_s *fchs, int len)
  175. {
  176. struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
  177. struct fc_ls_rjt_s *ls_rjt = (struct fc_ls_rjt_s *) els_cmd;
  178. len = len;
  179. switch (els_cmd->els_code) {
  180. case FC_ELS_LS_RJT:
  181. if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY)
  182. return FC_PARSE_BUSY;
  183. else
  184. return FC_PARSE_FAILURE;
  185. case FC_ELS_ACC:
  186. return FC_PARSE_OK;
  187. }
  188. return FC_PARSE_OK;
  189. }
  190. static void
  191. fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
  192. {
  193. memcpy(fchs, &fc_bls_rsp_tmpl, sizeof(struct fchs_s));
  194. fchs->d_id = d_id;
  195. fchs->s_id = s_id;
  196. fchs->ox_id = ox_id;
  197. }
  198. static u16
  199. fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
  200. __be16 ox_id, wwn_t port_name, wwn_t node_name,
  201. u16 pdu_size, u16 bb_cr, u8 els_code)
  202. {
  203. struct fc_logi_s *plogi = (struct fc_logi_s *) (pld);
  204. memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s));
  205. /* For FC AL bb_cr is 0 and altbbcred is 1 */
  206. if (!bb_cr)
  207. plogi->csp.altbbcred = 1;
  208. plogi->els_cmd.els_code = els_code;
  209. if (els_code == FC_ELS_PLOGI)
  210. fc_els_req_build(fchs, d_id, s_id, ox_id);
  211. else
  212. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  213. plogi->csp.rxsz = plogi->class3.rxsz = cpu_to_be16(pdu_size);
  214. plogi->csp.bbcred = cpu_to_be16(bb_cr);
  215. memcpy(&plogi->port_name, &port_name, sizeof(wwn_t));
  216. memcpy(&plogi->node_name, &node_name, sizeof(wwn_t));
  217. return sizeof(struct fc_logi_s);
  218. }
  219. u16
  220. fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
  221. u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size,
  222. u8 set_npiv, u8 set_auth, u16 local_bb_credits)
  223. {
  224. u32 d_id = bfa_hton3b(FC_FABRIC_PORT);
  225. __be32 *vvl_info;
  226. memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
  227. flogi->els_cmd.els_code = FC_ELS_FLOGI;
  228. fc_els_req_build(fchs, d_id, s_id, ox_id);
  229. flogi->csp.rxsz = flogi->class3.rxsz = cpu_to_be16(pdu_size);
  230. flogi->port_name = port_name;
  231. flogi->node_name = node_name;
  232. /*
  233. * Set the NPIV Capability Bit ( word 1, bit 31) of Common
  234. * Service Parameters.
  235. */
  236. flogi->csp.ciro = set_npiv;
  237. /* set AUTH capability */
  238. flogi->csp.security = set_auth;
  239. flogi->csp.bbcred = cpu_to_be16(local_bb_credits);
  240. /* Set brcd token in VVL */
  241. vvl_info = (u32 *)&flogi->vvl[0];
  242. /* set the flag to indicate the presence of VVL */
  243. flogi->csp.npiv_supp = 1; /* @todo. field name is not correct */
  244. vvl_info[0] = cpu_to_be32(FLOGI_VVL_BRCD);
  245. return sizeof(struct fc_logi_s);
  246. }
  247. u16
  248. fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
  249. __be16 ox_id, wwn_t port_name, wwn_t node_name,
  250. u16 pdu_size, u16 local_bb_credits, u8 bb_scn)
  251. {
  252. u32 d_id = 0;
  253. u16 bbscn_rxsz = (bb_scn << 12) | pdu_size;
  254. memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
  255. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  256. flogi->els_cmd.els_code = FC_ELS_ACC;
  257. flogi->class3.rxsz = cpu_to_be16(pdu_size);
  258. flogi->csp.rxsz = cpu_to_be16(bbscn_rxsz); /* bb_scn/rxsz */
  259. flogi->port_name = port_name;
  260. flogi->node_name = node_name;
  261. flogi->csp.bbcred = cpu_to_be16(local_bb_credits);
  262. return sizeof(struct fc_logi_s);
  263. }
  264. u16
  265. fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
  266. u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size)
  267. {
  268. u32 d_id = bfa_hton3b(FC_FABRIC_PORT);
  269. memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
  270. flogi->els_cmd.els_code = FC_ELS_FDISC;
  271. fc_els_req_build(fchs, d_id, s_id, ox_id);
  272. flogi->csp.rxsz = flogi->class3.rxsz = cpu_to_be16(pdu_size);
  273. flogi->port_name = port_name;
  274. flogi->node_name = node_name;
  275. return sizeof(struct fc_logi_s);
  276. }
  277. u16
  278. fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
  279. u16 ox_id, wwn_t port_name, wwn_t node_name,
  280. u16 pdu_size, u16 bb_cr)
  281. {
  282. return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
  283. node_name, pdu_size, bb_cr, FC_ELS_PLOGI);
  284. }
  285. u16
  286. fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
  287. u16 ox_id, wwn_t port_name, wwn_t node_name,
  288. u16 pdu_size, u16 bb_cr)
  289. {
  290. return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
  291. node_name, pdu_size, bb_cr, FC_ELS_ACC);
  292. }
  293. enum fc_parse_status
  294. fc_plogi_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
  295. {
  296. struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
  297. struct fc_logi_s *plogi;
  298. struct fc_ls_rjt_s *ls_rjt;
  299. switch (els_cmd->els_code) {
  300. case FC_ELS_LS_RJT:
  301. ls_rjt = (struct fc_ls_rjt_s *) (fchs + 1);
  302. if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY)
  303. return FC_PARSE_BUSY;
  304. else
  305. return FC_PARSE_FAILURE;
  306. case FC_ELS_ACC:
  307. plogi = (struct fc_logi_s *) (fchs + 1);
  308. if (len < sizeof(struct fc_logi_s))
  309. return FC_PARSE_FAILURE;
  310. if (!wwn_is_equal(plogi->port_name, port_name))
  311. return FC_PARSE_FAILURE;
  312. if (!plogi->class3.class_valid)
  313. return FC_PARSE_FAILURE;
  314. if (be16_to_cpu(plogi->class3.rxsz) < (FC_MIN_PDUSZ))
  315. return FC_PARSE_FAILURE;
  316. return FC_PARSE_OK;
  317. default:
  318. return FC_PARSE_FAILURE;
  319. }
  320. }
  321. enum fc_parse_status
  322. fc_plogi_parse(struct fchs_s *fchs)
  323. {
  324. struct fc_logi_s *plogi = (struct fc_logi_s *) (fchs + 1);
  325. if (plogi->class3.class_valid != 1)
  326. return FC_PARSE_FAILURE;
  327. if ((be16_to_cpu(plogi->class3.rxsz) < FC_MIN_PDUSZ)
  328. || (be16_to_cpu(plogi->class3.rxsz) > FC_MAX_PDUSZ)
  329. || (plogi->class3.rxsz == 0))
  330. return FC_PARSE_FAILURE;
  331. return FC_PARSE_OK;
  332. }
  333. u16
  334. fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
  335. u16 ox_id)
  336. {
  337. struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
  338. fc_els_req_build(fchs, d_id, s_id, ox_id);
  339. memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
  340. prli->command = FC_ELS_PRLI;
  341. prli->parampage.servparams.initiator = 1;
  342. prli->parampage.servparams.retry = 1;
  343. prli->parampage.servparams.rec_support = 1;
  344. prli->parampage.servparams.task_retry_id = 0;
  345. prli->parampage.servparams.confirm = 1;
  346. return sizeof(struct fc_prli_s);
  347. }
  348. u16
  349. fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
  350. __be16 ox_id, enum bfa_lport_role role)
  351. {
  352. struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
  353. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  354. memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
  355. prli->command = FC_ELS_ACC;
  356. prli->parampage.servparams.initiator = 1;
  357. prli->parampage.rspcode = FC_PRLI_ACC_XQTD;
  358. return sizeof(struct fc_prli_s);
  359. }
  360. enum fc_parse_status
  361. fc_prli_rsp_parse(struct fc_prli_s *prli, int len)
  362. {
  363. if (len < sizeof(struct fc_prli_s))
  364. return FC_PARSE_FAILURE;
  365. if (prli->command != FC_ELS_ACC)
  366. return FC_PARSE_FAILURE;
  367. if ((prli->parampage.rspcode != FC_PRLI_ACC_XQTD)
  368. && (prli->parampage.rspcode != FC_PRLI_ACC_PREDEF_IMG))
  369. return FC_PARSE_FAILURE;
  370. if (prli->parampage.servparams.target != 1)
  371. return FC_PARSE_FAILURE;
  372. return FC_PARSE_OK;
  373. }
  374. enum fc_parse_status
  375. fc_prli_parse(struct fc_prli_s *prli)
  376. {
  377. if (prli->parampage.type != FC_TYPE_FCP)
  378. return FC_PARSE_FAILURE;
  379. if (!prli->parampage.imagepair)
  380. return FC_PARSE_FAILURE;
  381. if (!prli->parampage.servparams.initiator)
  382. return FC_PARSE_FAILURE;
  383. return FC_PARSE_OK;
  384. }
  385. u16
  386. fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id, u32 s_id,
  387. u16 ox_id, wwn_t port_name)
  388. {
  389. fc_els_req_build(fchs, d_id, s_id, ox_id);
  390. memset(logo, '\0', sizeof(struct fc_logo_s));
  391. logo->els_cmd.els_code = FC_ELS_LOGO;
  392. logo->nport_id = (s_id);
  393. logo->orig_port_name = port_name;
  394. return sizeof(struct fc_logo_s);
  395. }
  396. static u16
  397. fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
  398. u32 s_id, __be16 ox_id, wwn_t port_name,
  399. wwn_t node_name, u8 els_code)
  400. {
  401. memset(adisc, '\0', sizeof(struct fc_adisc_s));
  402. adisc->els_cmd.els_code = els_code;
  403. if (els_code == FC_ELS_ADISC)
  404. fc_els_req_build(fchs, d_id, s_id, ox_id);
  405. else
  406. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  407. adisc->orig_HA = 0;
  408. adisc->orig_port_name = port_name;
  409. adisc->orig_node_name = node_name;
  410. adisc->nport_id = (s_id);
  411. return sizeof(struct fc_adisc_s);
  412. }
  413. u16
  414. fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
  415. u32 s_id, __be16 ox_id, wwn_t port_name, wwn_t node_name)
  416. {
  417. return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
  418. node_name, FC_ELS_ADISC);
  419. }
  420. u16
  421. fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
  422. u32 s_id, __be16 ox_id, wwn_t port_name,
  423. wwn_t node_name)
  424. {
  425. return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
  426. node_name, FC_ELS_ACC);
  427. }
  428. enum fc_parse_status
  429. fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len, wwn_t port_name,
  430. wwn_t node_name)
  431. {
  432. if (len < sizeof(struct fc_adisc_s))
  433. return FC_PARSE_FAILURE;
  434. if (adisc->els_cmd.els_code != FC_ELS_ACC)
  435. return FC_PARSE_FAILURE;
  436. if (!wwn_is_equal(adisc->orig_port_name, port_name))
  437. return FC_PARSE_FAILURE;
  438. return FC_PARSE_OK;
  439. }
  440. enum fc_parse_status
  441. fc_adisc_parse(struct fchs_s *fchs, void *pld, u32 host_dap, wwn_t node_name,
  442. wwn_t port_name)
  443. {
  444. struct fc_adisc_s *adisc = (struct fc_adisc_s *) pld;
  445. if (adisc->els_cmd.els_code != FC_ELS_ACC)
  446. return FC_PARSE_FAILURE;
  447. if ((adisc->nport_id == (host_dap))
  448. && wwn_is_equal(adisc->orig_port_name, port_name)
  449. && wwn_is_equal(adisc->orig_node_name, node_name))
  450. return FC_PARSE_OK;
  451. return FC_PARSE_FAILURE;
  452. }
  453. enum fc_parse_status
  454. fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name, wwn_t port_name)
  455. {
  456. struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
  457. if (pdisc->class3.class_valid != 1)
  458. return FC_PARSE_FAILURE;
  459. if ((be16_to_cpu(pdisc->class3.rxsz) <
  460. (FC_MIN_PDUSZ - sizeof(struct fchs_s)))
  461. || (pdisc->class3.rxsz == 0))
  462. return FC_PARSE_FAILURE;
  463. if (!wwn_is_equal(pdisc->port_name, port_name))
  464. return FC_PARSE_FAILURE;
  465. if (!wwn_is_equal(pdisc->node_name, node_name))
  466. return FC_PARSE_FAILURE;
  467. return FC_PARSE_OK;
  468. }
  469. u16
  470. fc_abts_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
  471. {
  472. memcpy(fchs, &fc_bls_req_tmpl, sizeof(struct fchs_s));
  473. fchs->cat_info = FC_CAT_ABTS;
  474. fchs->d_id = (d_id);
  475. fchs->s_id = (s_id);
  476. fchs->ox_id = cpu_to_be16(ox_id);
  477. return sizeof(struct fchs_s);
  478. }
  479. enum fc_parse_status
  480. fc_abts_rsp_parse(struct fchs_s *fchs, int len)
  481. {
  482. if ((fchs->cat_info == FC_CAT_BA_ACC)
  483. || (fchs->cat_info == FC_CAT_BA_RJT))
  484. return FC_PARSE_OK;
  485. return FC_PARSE_FAILURE;
  486. }
  487. u16
  488. fc_rrq_build(struct fchs_s *fchs, struct fc_rrq_s *rrq, u32 d_id, u32 s_id,
  489. u16 ox_id, u16 rrq_oxid)
  490. {
  491. fc_els_req_build(fchs, d_id, s_id, ox_id);
  492. /*
  493. * build rrq payload
  494. */
  495. memcpy(rrq, &rrq_tmpl, sizeof(struct fc_rrq_s));
  496. rrq->s_id = (s_id);
  497. rrq->ox_id = cpu_to_be16(rrq_oxid);
  498. rrq->rx_id = FC_RXID_ANY;
  499. return sizeof(struct fc_rrq_s);
  500. }
  501. u16
  502. fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
  503. __be16 ox_id)
  504. {
  505. struct fc_els_cmd_s *acc = pld;
  506. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  507. memset(acc, 0, sizeof(struct fc_els_cmd_s));
  508. acc->els_code = FC_ELS_ACC;
  509. return sizeof(struct fc_els_cmd_s);
  510. }
  511. u16
  512. fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id,
  513. u32 s_id, __be16 ox_id, u8 reason_code,
  514. u8 reason_code_expl)
  515. {
  516. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  517. memset(ls_rjt, 0, sizeof(struct fc_ls_rjt_s));
  518. ls_rjt->els_cmd.els_code = FC_ELS_LS_RJT;
  519. ls_rjt->reason_code = reason_code;
  520. ls_rjt->reason_code_expl = reason_code_expl;
  521. ls_rjt->vendor_unique = 0x00;
  522. return sizeof(struct fc_ls_rjt_s);
  523. }
  524. u16
  525. fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
  526. u32 s_id, __be16 ox_id, u16 rx_id)
  527. {
  528. fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
  529. memcpy(ba_acc, &ba_acc_tmpl, sizeof(struct fc_ba_acc_s));
  530. fchs->rx_id = rx_id;
  531. ba_acc->ox_id = fchs->ox_id;
  532. ba_acc->rx_id = fchs->rx_id;
  533. return sizeof(struct fc_ba_acc_s);
  534. }
  535. u16
  536. fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, u32 d_id,
  537. u32 s_id, __be16 ox_id)
  538. {
  539. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  540. memset(els_cmd, 0, sizeof(struct fc_els_cmd_s));
  541. els_cmd->els_code = FC_ELS_ACC;
  542. return sizeof(struct fc_els_cmd_s);
  543. }
  544. int
  545. fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code)
  546. {
  547. int num_pages = 0;
  548. struct fc_prlo_s *prlo;
  549. struct fc_tprlo_s *tprlo;
  550. if (els_code == FC_ELS_PRLO) {
  551. prlo = (struct fc_prlo_s *) (fc_frame + 1);
  552. num_pages = (be16_to_cpu(prlo->payload_len) - 4) / 16;
  553. } else {
  554. tprlo = (struct fc_tprlo_s *) (fc_frame + 1);
  555. num_pages = (be16_to_cpu(tprlo->payload_len) - 4) / 16;
  556. }
  557. return num_pages;
  558. }
  559. u16
  560. fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
  561. u32 d_id, u32 s_id, __be16 ox_id, int num_pages)
  562. {
  563. int page;
  564. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  565. memset(tprlo_acc, 0, (num_pages * 16) + 4);
  566. tprlo_acc->command = FC_ELS_ACC;
  567. tprlo_acc->page_len = 0x10;
  568. tprlo_acc->payload_len = cpu_to_be16((num_pages * 16) + 4);
  569. for (page = 0; page < num_pages; page++) {
  570. tprlo_acc->tprlo_acc_params[page].opa_valid = 0;
  571. tprlo_acc->tprlo_acc_params[page].rpa_valid = 0;
  572. tprlo_acc->tprlo_acc_params[page].fc4type_csp = FC_TYPE_FCP;
  573. tprlo_acc->tprlo_acc_params[page].orig_process_assc = 0;
  574. tprlo_acc->tprlo_acc_params[page].resp_process_assc = 0;
  575. }
  576. return be16_to_cpu(tprlo_acc->payload_len);
  577. }
  578. u16
  579. fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, u32 d_id,
  580. u32 s_id, __be16 ox_id, int num_pages)
  581. {
  582. int page;
  583. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  584. memset(prlo_acc, 0, (num_pages * 16) + 4);
  585. prlo_acc->command = FC_ELS_ACC;
  586. prlo_acc->page_len = 0x10;
  587. prlo_acc->payload_len = cpu_to_be16((num_pages * 16) + 4);
  588. for (page = 0; page < num_pages; page++) {
  589. prlo_acc->prlo_acc_params[page].opa_valid = 0;
  590. prlo_acc->prlo_acc_params[page].rpa_valid = 0;
  591. prlo_acc->prlo_acc_params[page].fc4type_csp = FC_TYPE_FCP;
  592. prlo_acc->prlo_acc_params[page].orig_process_assc = 0;
  593. prlo_acc->prlo_acc_params[page].resp_process_assc = 0;
  594. }
  595. return be16_to_cpu(prlo_acc->payload_len);
  596. }
  597. u16
  598. fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u32 d_id,
  599. u32 s_id, u16 ox_id, u32 data_format)
  600. {
  601. fc_els_req_build(fchs, d_id, s_id, ox_id);
  602. memset(rnid, 0, sizeof(struct fc_rnid_cmd_s));
  603. rnid->els_cmd.els_code = FC_ELS_RNID;
  604. rnid->node_id_data_format = data_format;
  605. return sizeof(struct fc_rnid_cmd_s);
  606. }
  607. u16
  608. fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, u32 d_id,
  609. u32 s_id, __be16 ox_id, u32 data_format,
  610. struct fc_rnid_common_id_data_s *common_id_data,
  611. struct fc_rnid_general_topology_data_s *gen_topo_data)
  612. {
  613. memset(rnid_acc, 0, sizeof(struct fc_rnid_acc_s));
  614. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  615. rnid_acc->els_cmd.els_code = FC_ELS_ACC;
  616. rnid_acc->node_id_data_format = data_format;
  617. rnid_acc->common_id_data_length =
  618. sizeof(struct fc_rnid_common_id_data_s);
  619. rnid_acc->common_id_data = *common_id_data;
  620. if (data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
  621. rnid_acc->specific_id_data_length =
  622. sizeof(struct fc_rnid_general_topology_data_s);
  623. rnid_acc->gen_topology_data = *gen_topo_data;
  624. return sizeof(struct fc_rnid_acc_s);
  625. } else {
  626. return sizeof(struct fc_rnid_acc_s) -
  627. sizeof(struct fc_rnid_general_topology_data_s);
  628. }
  629. }
  630. u16
  631. fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc, u32 d_id,
  632. u32 s_id, u16 ox_id)
  633. {
  634. fc_els_req_build(fchs, d_id, s_id, ox_id);
  635. memset(rpsc, 0, sizeof(struct fc_rpsc_cmd_s));
  636. rpsc->els_cmd.els_code = FC_ELS_RPSC;
  637. return sizeof(struct fc_rpsc_cmd_s);
  638. }
  639. u16
  640. fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, u32 d_id,
  641. u32 s_id, u32 *pid_list, u16 npids)
  642. {
  643. u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_hton3b(d_id));
  644. int i = 0;
  645. fc_els_req_build(fchs, bfa_hton3b(dctlr_id), s_id, 0);
  646. memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s));
  647. rpsc2->els_cmd.els_code = FC_ELS_RPSC;
  648. rpsc2->token = cpu_to_be32(FC_BRCD_TOKEN);
  649. rpsc2->num_pids = cpu_to_be16(npids);
  650. for (i = 0; i < npids; i++)
  651. rpsc2->pid_list[i].pid = pid_list[i];
  652. return sizeof(struct fc_rpsc2_cmd_s) + ((npids - 1) * (sizeof(u32)));
  653. }
  654. u16
  655. fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
  656. u32 d_id, u32 s_id, __be16 ox_id,
  657. struct fc_rpsc_speed_info_s *oper_speed)
  658. {
  659. memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s));
  660. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  661. rpsc_acc->command = FC_ELS_ACC;
  662. rpsc_acc->num_entries = cpu_to_be16(1);
  663. rpsc_acc->speed_info[0].port_speed_cap =
  664. cpu_to_be16(oper_speed->port_speed_cap);
  665. rpsc_acc->speed_info[0].port_op_speed =
  666. cpu_to_be16(oper_speed->port_op_speed);
  667. return sizeof(struct fc_rpsc_acc_s);
  668. }
  669. u16
  670. fc_logo_rsp_parse(struct fchs_s *fchs, int len)
  671. {
  672. struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
  673. len = len;
  674. if (els_cmd->els_code != FC_ELS_ACC)
  675. return FC_PARSE_FAILURE;
  676. return FC_PARSE_OK;
  677. }
  678. u16
  679. fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
  680. wwn_t port_name, wwn_t node_name, u16 pdu_size)
  681. {
  682. struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
  683. memcpy(pdisc, &plogi_tmpl, sizeof(struct fc_logi_s));
  684. pdisc->els_cmd.els_code = FC_ELS_PDISC;
  685. fc_els_req_build(fchs, d_id, s_id, ox_id);
  686. pdisc->csp.rxsz = pdisc->class3.rxsz = cpu_to_be16(pdu_size);
  687. pdisc->port_name = port_name;
  688. pdisc->node_name = node_name;
  689. return sizeof(struct fc_logi_s);
  690. }
  691. u16
  692. fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
  693. {
  694. struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
  695. if (len < sizeof(struct fc_logi_s))
  696. return FC_PARSE_LEN_INVAL;
  697. if (pdisc->els_cmd.els_code != FC_ELS_ACC)
  698. return FC_PARSE_ACC_INVAL;
  699. if (!wwn_is_equal(pdisc->port_name, port_name))
  700. return FC_PARSE_PWWN_NOT_EQUAL;
  701. if (!pdisc->class3.class_valid)
  702. return FC_PARSE_NWWN_NOT_EQUAL;
  703. if (be16_to_cpu(pdisc->class3.rxsz) < (FC_MIN_PDUSZ))
  704. return FC_PARSE_RXSZ_INVAL;
  705. return FC_PARSE_OK;
  706. }
  707. u16
  708. fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
  709. int num_pages)
  710. {
  711. struct fc_prlo_s *prlo = (struct fc_prlo_s *) (fchs + 1);
  712. int page;
  713. fc_els_req_build(fchs, d_id, s_id, ox_id);
  714. memset(prlo, 0, (num_pages * 16) + 4);
  715. prlo->command = FC_ELS_PRLO;
  716. prlo->page_len = 0x10;
  717. prlo->payload_len = cpu_to_be16((num_pages * 16) + 4);
  718. for (page = 0; page < num_pages; page++) {
  719. prlo->prlo_params[page].type = FC_TYPE_FCP;
  720. prlo->prlo_params[page].opa_valid = 0;
  721. prlo->prlo_params[page].rpa_valid = 0;
  722. prlo->prlo_params[page].orig_process_assc = 0;
  723. prlo->prlo_params[page].resp_process_assc = 0;
  724. }
  725. return be16_to_cpu(prlo->payload_len);
  726. }
  727. u16
  728. fc_prlo_rsp_parse(struct fchs_s *fchs, int len)
  729. {
  730. struct fc_prlo_acc_s *prlo = (struct fc_prlo_acc_s *) (fchs + 1);
  731. int num_pages = 0;
  732. int page = 0;
  733. len = len;
  734. if (prlo->command != FC_ELS_ACC)
  735. return FC_PARSE_FAILURE;
  736. num_pages = ((be16_to_cpu(prlo->payload_len)) - 4) / 16;
  737. for (page = 0; page < num_pages; page++) {
  738. if (prlo->prlo_acc_params[page].type != FC_TYPE_FCP)
  739. return FC_PARSE_FAILURE;
  740. if (prlo->prlo_acc_params[page].opa_valid != 0)
  741. return FC_PARSE_FAILURE;
  742. if (prlo->prlo_acc_params[page].rpa_valid != 0)
  743. return FC_PARSE_FAILURE;
  744. if (prlo->prlo_acc_params[page].orig_process_assc != 0)
  745. return FC_PARSE_FAILURE;
  746. if (prlo->prlo_acc_params[page].resp_process_assc != 0)
  747. return FC_PARSE_FAILURE;
  748. }
  749. return FC_PARSE_OK;
  750. }
  751. u16
  752. fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
  753. int num_pages, enum fc_tprlo_type tprlo_type, u32 tpr_id)
  754. {
  755. struct fc_tprlo_s *tprlo = (struct fc_tprlo_s *) (fchs + 1);
  756. int page;
  757. fc_els_req_build(fchs, d_id, s_id, ox_id);
  758. memset(tprlo, 0, (num_pages * 16) + 4);
  759. tprlo->command = FC_ELS_TPRLO;
  760. tprlo->page_len = 0x10;
  761. tprlo->payload_len = cpu_to_be16((num_pages * 16) + 4);
  762. for (page = 0; page < num_pages; page++) {
  763. tprlo->tprlo_params[page].type = FC_TYPE_FCP;
  764. tprlo->tprlo_params[page].opa_valid = 0;
  765. tprlo->tprlo_params[page].rpa_valid = 0;
  766. tprlo->tprlo_params[page].orig_process_assc = 0;
  767. tprlo->tprlo_params[page].resp_process_assc = 0;
  768. if (tprlo_type == FC_GLOBAL_LOGO) {
  769. tprlo->tprlo_params[page].global_process_logout = 1;
  770. } else if (tprlo_type == FC_TPR_LOGO) {
  771. tprlo->tprlo_params[page].tpo_nport_valid = 1;
  772. tprlo->tprlo_params[page].tpo_nport_id = (tpr_id);
  773. }
  774. }
  775. return be16_to_cpu(tprlo->payload_len);
  776. }
  777. u16
  778. fc_tprlo_rsp_parse(struct fchs_s *fchs, int len)
  779. {
  780. struct fc_tprlo_acc_s *tprlo = (struct fc_tprlo_acc_s *) (fchs + 1);
  781. int num_pages = 0;
  782. int page = 0;
  783. len = len;
  784. if (tprlo->command != FC_ELS_ACC)
  785. return FC_PARSE_ACC_INVAL;
  786. num_pages = (be16_to_cpu(tprlo->payload_len) - 4) / 16;
  787. for (page = 0; page < num_pages; page++) {
  788. if (tprlo->tprlo_acc_params[page].type != FC_TYPE_FCP)
  789. return FC_PARSE_NOT_FCP;
  790. if (tprlo->tprlo_acc_params[page].opa_valid != 0)
  791. return FC_PARSE_OPAFLAG_INVAL;
  792. if (tprlo->tprlo_acc_params[page].rpa_valid != 0)
  793. return FC_PARSE_RPAFLAG_INVAL;
  794. if (tprlo->tprlo_acc_params[page].orig_process_assc != 0)
  795. return FC_PARSE_OPA_INVAL;
  796. if (tprlo->tprlo_acc_params[page].resp_process_assc != 0)
  797. return FC_PARSE_RPA_INVAL;
  798. }
  799. return FC_PARSE_OK;
  800. }
  801. enum fc_parse_status
  802. fc_rrq_rsp_parse(struct fchs_s *fchs, int len)
  803. {
  804. struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
  805. len = len;
  806. if (els_cmd->els_code != FC_ELS_ACC)
  807. return FC_PARSE_FAILURE;
  808. return FC_PARSE_OK;
  809. }
  810. u16
  811. fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id,
  812. u32 reason_code, u32 reason_expl)
  813. {
  814. struct fc_ba_rjt_s *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1);
  815. fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
  816. fchs->cat_info = FC_CAT_BA_RJT;
  817. ba_rjt->reason_code = reason_code;
  818. ba_rjt->reason_expl = reason_expl;
  819. return sizeof(struct fc_ba_rjt_s);
  820. }
  821. static void
  822. fc_gs_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code)
  823. {
  824. memset(cthdr, 0, sizeof(struct ct_hdr_s));
  825. cthdr->rev_id = CT_GS3_REVISION;
  826. cthdr->gs_type = CT_GSTYPE_DIRSERVICE;
  827. cthdr->gs_sub_type = CT_GSSUBTYPE_NAMESERVER;
  828. cthdr->cmd_rsp_code = cpu_to_be16(cmd_code);
  829. }
  830. static void
  831. fc_gs_fdmi_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code)
  832. {
  833. memset(cthdr, 0, sizeof(struct ct_hdr_s));
  834. cthdr->rev_id = CT_GS3_REVISION;
  835. cthdr->gs_type = CT_GSTYPE_MGMTSERVICE;
  836. cthdr->gs_sub_type = CT_GSSUBTYPE_HBA_MGMTSERVER;
  837. cthdr->cmd_rsp_code = cpu_to_be16(cmd_code);
  838. }
  839. static void
  840. fc_gs_ms_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code,
  841. u8 sub_type)
  842. {
  843. memset(cthdr, 0, sizeof(struct ct_hdr_s));
  844. cthdr->rev_id = CT_GS3_REVISION;
  845. cthdr->gs_type = CT_GSTYPE_MGMTSERVICE;
  846. cthdr->gs_sub_type = sub_type;
  847. cthdr->cmd_rsp_code = cpu_to_be16(cmd_code);
  848. }
  849. u16
  850. fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
  851. wwn_t port_name)
  852. {
  853. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  854. struct fcgs_gidpn_req_s *gidpn = (struct fcgs_gidpn_req_s *)(cthdr + 1);
  855. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  856. fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
  857. fc_gs_cthdr_build(cthdr, s_id, GS_GID_PN);
  858. memset(gidpn, 0, sizeof(struct fcgs_gidpn_req_s));
  859. gidpn->port_name = port_name;
  860. return sizeof(struct fcgs_gidpn_req_s) + sizeof(struct ct_hdr_s);
  861. }
  862. u16
  863. fc_gpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
  864. u32 port_id)
  865. {
  866. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  867. fcgs_gpnid_req_t *gpnid = (fcgs_gpnid_req_t *) (cthdr + 1);
  868. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  869. fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
  870. fc_gs_cthdr_build(cthdr, s_id, GS_GPN_ID);
  871. memset(gpnid, 0, sizeof(fcgs_gpnid_req_t));
  872. gpnid->dap = port_id;
  873. return sizeof(fcgs_gpnid_req_t) + sizeof(struct ct_hdr_s);
  874. }
  875. u16
  876. fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
  877. u32 port_id)
  878. {
  879. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  880. fcgs_gnnid_req_t *gnnid = (fcgs_gnnid_req_t *) (cthdr + 1);
  881. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  882. fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
  883. fc_gs_cthdr_build(cthdr, s_id, GS_GNN_ID);
  884. memset(gnnid, 0, sizeof(fcgs_gnnid_req_t));
  885. gnnid->dap = port_id;
  886. return sizeof(fcgs_gnnid_req_t) + sizeof(struct ct_hdr_s);
  887. }
  888. u16
  889. fc_ct_rsp_parse(struct ct_hdr_s *cthdr)
  890. {
  891. if (be16_to_cpu(cthdr->cmd_rsp_code) != CT_RSP_ACCEPT) {
  892. if (cthdr->reason_code == CT_RSN_LOGICAL_BUSY)
  893. return FC_PARSE_BUSY;
  894. else
  895. return FC_PARSE_FAILURE;
  896. }
  897. return FC_PARSE_OK;
  898. }
  899. u16
  900. fc_gs_rjt_build(struct fchs_s *fchs, struct ct_hdr_s *cthdr,
  901. u32 d_id, u32 s_id, u16 ox_id, u8 reason_code,
  902. u8 reason_code_expl)
  903. {
  904. fc_gsresp_fchdr_build(fchs, d_id, s_id, ox_id);
  905. cthdr->cmd_rsp_code = cpu_to_be16(CT_RSP_REJECT);
  906. cthdr->rev_id = CT_GS3_REVISION;
  907. cthdr->reason_code = reason_code;
  908. cthdr->exp_code = reason_code_expl;
  909. return sizeof(struct ct_hdr_s);
  910. }
  911. u16
  912. fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
  913. u8 set_br_reg, u32 s_id, u16 ox_id)
  914. {
  915. u32 d_id = bfa_hton3b(FC_FABRIC_CONTROLLER);
  916. fc_els_req_build(fchs, d_id, s_id, ox_id);
  917. memset(scr, 0, sizeof(struct fc_scr_s));
  918. scr->command = FC_ELS_SCR;
  919. scr->reg_func = FC_SCR_REG_FUNC_FULL;
  920. if (set_br_reg)
  921. scr->vu_reg_func = FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE;
  922. return sizeof(struct fc_scr_s);
  923. }
  924. u16
  925. fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn,
  926. u32 s_id, u16 ox_id)
  927. {
  928. u32 d_id = bfa_hton3b(FC_FABRIC_CONTROLLER);
  929. u16 payldlen;
  930. fc_els_req_build(fchs, d_id, s_id, ox_id);
  931. rscn->command = FC_ELS_RSCN;
  932. rscn->pagelen = sizeof(rscn->event[0]);
  933. payldlen = sizeof(u32) + rscn->pagelen;
  934. rscn->payldlen = cpu_to_be16(payldlen);
  935. rscn->event[0].format = FC_RSCN_FORMAT_PORTID;
  936. rscn->event[0].portid = s_id;
  937. return sizeof(struct fc_rscn_pl_s);
  938. }
  939. u16
  940. fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
  941. enum bfa_lport_role roles)
  942. {
  943. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  944. struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1);
  945. u32 type_value, d_id = bfa_hton3b(FC_NAME_SERVER);
  946. u8 index;
  947. fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
  948. fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID);
  949. memset(rftid, 0, sizeof(struct fcgs_rftid_req_s));
  950. rftid->dap = s_id;
  951. /* By default, FCP FC4 Type is registered */
  952. index = FC_TYPE_FCP >> 5;
  953. type_value = 1 << (FC_TYPE_FCP % 32);
  954. rftid->fc4_type[index] = cpu_to_be32(type_value);
  955. return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
  956. }
  957. u16
  958. fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
  959. u8 *fc4_bitmap, u32 bitmap_size)
  960. {
  961. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  962. struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1);
  963. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  964. fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
  965. fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID);
  966. memset(rftid, 0, sizeof(struct fcgs_rftid_req_s));
  967. rftid->dap = s_id;
  968. memcpy((void *)rftid->fc4_type, (void *)fc4_bitmap,
  969. (bitmap_size < 32 ? bitmap_size : 32));
  970. return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
  971. }
  972. u16
  973. fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
  974. u8 fc4_type, u8 fc4_ftrs)
  975. {
  976. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  977. struct fcgs_rffid_req_s *rffid = (struct fcgs_rffid_req_s *)(cthdr + 1);
  978. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  979. fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
  980. fc_gs_cthdr_build(cthdr, s_id, GS_RFF_ID);
  981. memset(rffid, 0, sizeof(struct fcgs_rffid_req_s));
  982. rffid->dap = s_id;
  983. rffid->fc4ftr_bits = fc4_ftrs;
  984. rffid->fc4_type = fc4_type;
  985. return sizeof(struct fcgs_rffid_req_s) + sizeof(struct ct_hdr_s);
  986. }
  987. u16
  988. fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
  989. u8 *name)
  990. {
  991. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  992. struct fcgs_rspnid_req_s *rspnid =
  993. (struct fcgs_rspnid_req_s *)(cthdr + 1);
  994. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  995. fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
  996. fc_gs_cthdr_build(cthdr, s_id, GS_RSPN_ID);
  997. memset(rspnid, 0, sizeof(struct fcgs_rspnid_req_s));
  998. rspnid->dap = s_id;
  999. rspnid->spn_len = (u8) strlen((char *)name);
  1000. strncpy((char *)rspnid->spn, (char *)name, rspnid->spn_len);
  1001. return sizeof(struct fcgs_rspnid_req_s) + sizeof(struct ct_hdr_s);
  1002. }
  1003. u16
  1004. fc_rsnn_nn_build(struct fchs_s *fchs, void *pyld, u32 s_id,
  1005. wwn_t node_name, u8 *name)
  1006. {
  1007. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1008. struct fcgs_rsnn_nn_req_s *rsnn_nn =
  1009. (struct fcgs_rsnn_nn_req_s *) (cthdr + 1);
  1010. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  1011. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1012. fc_gs_cthdr_build(cthdr, s_id, GS_RSNN_NN);
  1013. memset(rsnn_nn, 0, sizeof(struct fcgs_rsnn_nn_req_s));
  1014. rsnn_nn->node_name = node_name;
  1015. rsnn_nn->snn_len = (u8) strlen((char *)name);
  1016. strncpy((char *)rsnn_nn->snn, (char *)name, rsnn_nn->snn_len);
  1017. return sizeof(struct fcgs_rsnn_nn_req_s) + sizeof(struct ct_hdr_s);
  1018. }
  1019. u16
  1020. fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, u8 fc4_type)
  1021. {
  1022. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1023. struct fcgs_gidft_req_s *gidft = (struct fcgs_gidft_req_s *)(cthdr + 1);
  1024. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  1025. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1026. fc_gs_cthdr_build(cthdr, s_id, GS_GID_FT);
  1027. memset(gidft, 0, sizeof(struct fcgs_gidft_req_s));
  1028. gidft->fc4_type = fc4_type;
  1029. gidft->domain_id = 0;
  1030. gidft->area_id = 0;
  1031. return sizeof(struct fcgs_gidft_req_s) + sizeof(struct ct_hdr_s);
  1032. }
  1033. u16
  1034. fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
  1035. wwn_t port_name)
  1036. {
  1037. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1038. struct fcgs_rpnid_req_s *rpnid = (struct fcgs_rpnid_req_s *)(cthdr + 1);
  1039. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  1040. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1041. fc_gs_cthdr_build(cthdr, s_id, GS_RPN_ID);
  1042. memset(rpnid, 0, sizeof(struct fcgs_rpnid_req_s));
  1043. rpnid->port_id = port_id;
  1044. rpnid->port_name = port_name;
  1045. return sizeof(struct fcgs_rpnid_req_s) + sizeof(struct ct_hdr_s);
  1046. }
  1047. u16
  1048. fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
  1049. wwn_t node_name)
  1050. {
  1051. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1052. struct fcgs_rnnid_req_s *rnnid = (struct fcgs_rnnid_req_s *)(cthdr + 1);
  1053. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  1054. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1055. fc_gs_cthdr_build(cthdr, s_id, GS_RNN_ID);
  1056. memset(rnnid, 0, sizeof(struct fcgs_rnnid_req_s));
  1057. rnnid->port_id = port_id;
  1058. rnnid->node_name = node_name;
  1059. return sizeof(struct fcgs_rnnid_req_s) + sizeof(struct ct_hdr_s);
  1060. }
  1061. u16
  1062. fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
  1063. u32 cos)
  1064. {
  1065. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1066. struct fcgs_rcsid_req_s *rcsid =
  1067. (struct fcgs_rcsid_req_s *) (cthdr + 1);
  1068. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  1069. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1070. fc_gs_cthdr_build(cthdr, s_id, GS_RCS_ID);
  1071. memset(rcsid, 0, sizeof(struct fcgs_rcsid_req_s));
  1072. rcsid->port_id = port_id;
  1073. rcsid->cos = cos;
  1074. return sizeof(struct fcgs_rcsid_req_s) + sizeof(struct ct_hdr_s);
  1075. }
  1076. u16
  1077. fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
  1078. u8 port_type)
  1079. {
  1080. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1081. struct fcgs_rptid_req_s *rptid = (struct fcgs_rptid_req_s *)(cthdr + 1);
  1082. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  1083. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1084. fc_gs_cthdr_build(cthdr, s_id, GS_RPT_ID);
  1085. memset(rptid, 0, sizeof(struct fcgs_rptid_req_s));
  1086. rptid->port_id = port_id;
  1087. rptid->port_type = port_type;
  1088. return sizeof(struct fcgs_rptid_req_s) + sizeof(struct ct_hdr_s);
  1089. }
  1090. u16
  1091. fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id)
  1092. {
  1093. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1094. struct fcgs_ganxt_req_s *ganxt = (struct fcgs_ganxt_req_s *)(cthdr + 1);
  1095. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  1096. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1097. fc_gs_cthdr_build(cthdr, s_id, GS_GA_NXT);
  1098. memset(ganxt, 0, sizeof(struct fcgs_ganxt_req_s));
  1099. ganxt->port_id = port_id;
  1100. return sizeof(struct ct_hdr_s) + sizeof(struct fcgs_ganxt_req_s);
  1101. }
  1102. /*
  1103. * Builds fc hdr and ct hdr for FDMI requests.
  1104. */
  1105. u16
  1106. fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
  1107. u16 cmd_code)
  1108. {
  1109. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1110. u32 d_id = bfa_hton3b(FC_MGMT_SERVER);
  1111. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1112. fc_gs_fdmi_cthdr_build(cthdr, s_id, cmd_code);
  1113. return sizeof(struct ct_hdr_s);
  1114. }
  1115. /*
  1116. * Given a FC4 Type, this function returns a fc4 type bitmask
  1117. */
  1118. void
  1119. fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask)
  1120. {
  1121. u8 index;
  1122. __be32 *ptr = (__be32 *) bit_mask;
  1123. u32 type_value;
  1124. /*
  1125. * @todo : Check for bitmask size
  1126. */
  1127. index = fc4_type >> 5;
  1128. type_value = 1 << (fc4_type % 32);
  1129. ptr[index] = cpu_to_be32(type_value);
  1130. }
  1131. /*
  1132. * GMAL Request
  1133. */
  1134. u16
  1135. fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
  1136. {
  1137. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1138. fcgs_gmal_req_t *gmal = (fcgs_gmal_req_t *) (cthdr + 1);
  1139. u32 d_id = bfa_hton3b(FC_MGMT_SERVER);
  1140. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1141. fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GMAL_CMD,
  1142. CT_GSSUBTYPE_CFGSERVER);
  1143. memset(gmal, 0, sizeof(fcgs_gmal_req_t));
  1144. gmal->wwn = wwn;
  1145. return sizeof(struct ct_hdr_s) + sizeof(fcgs_gmal_req_t);
  1146. }
  1147. /*
  1148. * GFN (Get Fabric Name) Request
  1149. */
  1150. u16
  1151. fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
  1152. {
  1153. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1154. fcgs_gfn_req_t *gfn = (fcgs_gfn_req_t *) (cthdr + 1);
  1155. u32 d_id = bfa_hton3b(FC_MGMT_SERVER);
  1156. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1157. fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GFN_CMD,
  1158. CT_GSSUBTYPE_CFGSERVER);
  1159. memset(gfn, 0, sizeof(fcgs_gfn_req_t));
  1160. gfn->wwn = wwn;
  1161. return sizeof(struct ct_hdr_s) + sizeof(fcgs_gfn_req_t);
  1162. }