fc_encode.h 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright(c) 2008 Intel Corporation. All rights reserved.
  4. *
  5. * Maintained at www.Open-FCoE.org
  6. */
  7. #ifndef _FC_ENCODE_H_
  8. #define _FC_ENCODE_H_
  9. #include <asm/unaligned.h>
  10. #include <linux/utsname.h>
  11. #include <scsi/fc/fc_ms.h>
  12. /*
  13. * F_CTL values for simple requests and responses.
  14. */
  15. #define FC_FCTL_REQ (FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT)
  16. #define FC_FCTL_RESP (FC_FC_EX_CTX | FC_FC_LAST_SEQ | \
  17. FC_FC_END_SEQ | FC_FC_SEQ_INIT)
  18. struct fc_ns_rft {
  19. struct fc_ns_fid fid; /* port ID object */
  20. struct fc_ns_fts fts; /* FC4-types object */
  21. };
  22. struct fc_ct_req {
  23. struct fc_ct_hdr hdr;
  24. union {
  25. struct fc_ns_gid_ft gid;
  26. struct fc_ns_rn_id rn;
  27. struct fc_ns_rft rft;
  28. struct fc_ns_rff_id rff;
  29. struct fc_ns_fid fid;
  30. struct fc_ns_rsnn snn;
  31. struct fc_ns_rspn spn;
  32. struct fc_fdmi_rhba rhba;
  33. struct fc_fdmi_rpa rpa;
  34. struct fc_fdmi_dprt dprt;
  35. struct fc_fdmi_dhba dhba;
  36. } payload;
  37. };
  38. /**
  39. * fc_adisc_fill() - Fill in adisc request frame
  40. * @lport: local port.
  41. * @fp: fc frame where payload will be placed.
  42. */
  43. static inline void fc_adisc_fill(struct fc_lport *lport, struct fc_frame *fp)
  44. {
  45. struct fc_els_adisc *adisc;
  46. adisc = fc_frame_payload_get(fp, sizeof(*adisc));
  47. memset(adisc, 0, sizeof(*adisc));
  48. adisc->adisc_cmd = ELS_ADISC;
  49. put_unaligned_be64(lport->wwpn, &adisc->adisc_wwpn);
  50. put_unaligned_be64(lport->wwnn, &adisc->adisc_wwnn);
  51. hton24(adisc->adisc_port_id, lport->port_id);
  52. }
  53. /**
  54. * fc_ct_hdr_fill- fills ct header and reset ct payload
  55. * returns pointer to ct request.
  56. */
  57. static inline struct fc_ct_req *fc_ct_hdr_fill(const struct fc_frame *fp,
  58. unsigned int op, size_t req_size,
  59. enum fc_ct_fs_type fs_type,
  60. u8 subtype)
  61. {
  62. struct fc_ct_req *ct;
  63. size_t ct_plen;
  64. ct_plen = sizeof(struct fc_ct_hdr) + req_size;
  65. ct = fc_frame_payload_get(fp, ct_plen);
  66. memset(ct, 0, ct_plen);
  67. ct->hdr.ct_rev = FC_CT_REV;
  68. ct->hdr.ct_fs_type = fs_type;
  69. ct->hdr.ct_fs_subtype = subtype;
  70. ct->hdr.ct_cmd = htons((u16) op);
  71. return ct;
  72. }
  73. /**
  74. * fc_ct_ns_fill() - Fill in a name service request frame
  75. * @lport: local port.
  76. * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
  77. * @fp: frame to contain payload.
  78. * @op: CT opcode.
  79. * @r_ctl: pointer to FC header R_CTL.
  80. * @fh_type: pointer to FC-4 type.
  81. */
  82. static inline int fc_ct_ns_fill(struct fc_lport *lport,
  83. u32 fc_id, struct fc_frame *fp,
  84. unsigned int op, enum fc_rctl *r_ctl,
  85. enum fc_fh_type *fh_type)
  86. {
  87. struct fc_ct_req *ct;
  88. size_t len;
  89. switch (op) {
  90. case FC_NS_GPN_FT:
  91. ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_gid_ft),
  92. FC_FST_DIR, FC_NS_SUBTYPE);
  93. ct->payload.gid.fn_fc4_type = FC_TYPE_FCP;
  94. break;
  95. case FC_NS_GPN_ID:
  96. ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_fid),
  97. FC_FST_DIR, FC_NS_SUBTYPE);
  98. ct->payload.gid.fn_fc4_type = FC_TYPE_FCP;
  99. hton24(ct->payload.fid.fp_fid, fc_id);
  100. break;
  101. case FC_NS_RFT_ID:
  102. ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rft),
  103. FC_FST_DIR, FC_NS_SUBTYPE);
  104. hton24(ct->payload.rft.fid.fp_fid, lport->port_id);
  105. ct->payload.rft.fts = lport->fcts;
  106. break;
  107. case FC_NS_RFF_ID:
  108. ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rff_id),
  109. FC_FST_DIR, FC_NS_SUBTYPE);
  110. hton24(ct->payload.rff.fr_fid.fp_fid, lport->port_id);
  111. ct->payload.rff.fr_type = FC_TYPE_FCP;
  112. if (lport->service_params & FCP_SPPF_INIT_FCN)
  113. ct->payload.rff.fr_feat = FCP_FEAT_INIT;
  114. if (lport->service_params & FCP_SPPF_TARG_FCN)
  115. ct->payload.rff.fr_feat |= FCP_FEAT_TARG;
  116. break;
  117. case FC_NS_RNN_ID:
  118. ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rn_id),
  119. FC_FST_DIR, FC_NS_SUBTYPE);
  120. hton24(ct->payload.rn.fr_fid.fp_fid, lport->port_id);
  121. put_unaligned_be64(lport->wwnn, &ct->payload.rn.fr_wwn);
  122. break;
  123. case FC_NS_RSPN_ID:
  124. len = strnlen(fc_host_symbolic_name(lport->host), 255);
  125. ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rspn) + len,
  126. FC_FST_DIR, FC_NS_SUBTYPE);
  127. hton24(ct->payload.spn.fr_fid.fp_fid, lport->port_id);
  128. strncpy(ct->payload.spn.fr_name,
  129. fc_host_symbolic_name(lport->host), len);
  130. ct->payload.spn.fr_name_len = len;
  131. break;
  132. case FC_NS_RSNN_NN:
  133. len = strnlen(fc_host_symbolic_name(lport->host), 255);
  134. ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rsnn) + len,
  135. FC_FST_DIR, FC_NS_SUBTYPE);
  136. put_unaligned_be64(lport->wwnn, &ct->payload.snn.fr_wwn);
  137. strncpy(ct->payload.snn.fr_name,
  138. fc_host_symbolic_name(lport->host), len);
  139. ct->payload.snn.fr_name_len = len;
  140. break;
  141. default:
  142. return -EINVAL;
  143. }
  144. *r_ctl = FC_RCTL_DD_UNSOL_CTL;
  145. *fh_type = FC_TYPE_CT;
  146. return 0;
  147. }
  148. static inline void fc_ct_ms_fill_attr(struct fc_fdmi_attr_entry *entry,
  149. const char *in, size_t len)
  150. {
  151. int copied;
  152. copied = strscpy(entry->value, in, len);
  153. if (copied > 0 && copied + 1 < len)
  154. memset(entry->value + copied + 1, 0, len - copied - 1);
  155. }
  156. /**
  157. * fc_ct_ms_fill() - Fill in a mgmt service request frame
  158. * @lport: local port.
  159. * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
  160. * @fp: frame to contain payload.
  161. * @op: CT opcode.
  162. * @r_ctl: pointer to FC header R_CTL.
  163. * @fh_type: pointer to FC-4 type.
  164. */
  165. static inline int fc_ct_ms_fill(struct fc_lport *lport,
  166. u32 fc_id, struct fc_frame *fp,
  167. unsigned int op, enum fc_rctl *r_ctl,
  168. enum fc_fh_type *fh_type)
  169. {
  170. struct fc_ct_req *ct;
  171. size_t len;
  172. struct fc_fdmi_attr_entry *entry;
  173. struct fs_fdmi_attrs *hba_attrs;
  174. int numattrs = 0;
  175. struct fc_host_attrs *fc_host = shost_to_fc_host(lport->host);
  176. switch (op) {
  177. case FC_FDMI_RHBA:
  178. numattrs = 11;
  179. len = sizeof(struct fc_fdmi_rhba);
  180. len -= sizeof(struct fc_fdmi_attr_entry);
  181. len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN);
  182. len += FC_FDMI_HBA_ATTR_NODENAME_LEN;
  183. len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN;
  184. len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN;
  185. len += FC_FDMI_HBA_ATTR_MODEL_LEN;
  186. len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN;
  187. len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN;
  188. len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN;
  189. len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN;
  190. len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN;
  191. len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN;
  192. len += FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN;
  193. if (fc_host->fdmi_version == FDMI_V2) {
  194. numattrs += 7;
  195. len += FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN;
  196. len += FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN;
  197. len += FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN;
  198. len += FC_FDMI_HBA_ATTR_FABRICNAME_LEN;
  199. len += FC_FDMI_HBA_ATTR_BIOSVERSION_LEN;
  200. len += FC_FDMI_HBA_ATTR_BIOSSTATE_LEN;
  201. len += FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN;
  202. }
  203. ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
  204. FC_FDMI_SUBTYPE);
  205. /* HBA Identifier */
  206. put_unaligned_be64(lport->wwpn, &ct->payload.rhba.hbaid.id);
  207. /* Number of Ports - always 1 */
  208. put_unaligned_be32(1, &ct->payload.rhba.port.numport);
  209. /* Port Name */
  210. put_unaligned_be64(lport->wwpn,
  211. &ct->payload.rhba.port.port[0].portname);
  212. /* HBA Attributes */
  213. put_unaligned_be32(numattrs,
  214. &ct->payload.rhba.hba_attrs.numattrs);
  215. hba_attrs = &ct->payload.rhba.hba_attrs;
  216. entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr;
  217. /* NodeName*/
  218. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  219. len += FC_FDMI_HBA_ATTR_NODENAME_LEN;
  220. put_unaligned_be16(FC_FDMI_HBA_ATTR_NODENAME,
  221. &entry->type);
  222. put_unaligned_be16(len, &entry->len);
  223. put_unaligned_be64(lport->wwnn,
  224. (__be64 *)&entry->value);
  225. /* Manufacturer */
  226. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  227. FC_FDMI_HBA_ATTR_NODENAME_LEN);
  228. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  229. len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN;
  230. put_unaligned_be16(FC_FDMI_HBA_ATTR_MANUFACTURER,
  231. &entry->type);
  232. put_unaligned_be16(len, &entry->len);
  233. fc_ct_ms_fill_attr(entry,
  234. fc_host_manufacturer(lport->host),
  235. FC_FDMI_HBA_ATTR_MANUFACTURER_LEN);
  236. /* SerialNumber */
  237. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  238. FC_FDMI_HBA_ATTR_MANUFACTURER_LEN);
  239. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  240. len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN;
  241. put_unaligned_be16(FC_FDMI_HBA_ATTR_SERIALNUMBER,
  242. &entry->type);
  243. put_unaligned_be16(len, &entry->len);
  244. fc_ct_ms_fill_attr(entry,
  245. fc_host_serial_number(lport->host),
  246. FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN);
  247. /* Model */
  248. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  249. FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN);
  250. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  251. len += FC_FDMI_HBA_ATTR_MODEL_LEN;
  252. put_unaligned_be16(FC_FDMI_HBA_ATTR_MODEL,
  253. &entry->type);
  254. put_unaligned_be16(len, &entry->len);
  255. fc_ct_ms_fill_attr(entry,
  256. fc_host_model(lport->host),
  257. FC_FDMI_HBA_ATTR_MODEL_LEN);
  258. /* Model Description */
  259. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  260. FC_FDMI_HBA_ATTR_MODEL_LEN);
  261. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  262. len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN;
  263. put_unaligned_be16(FC_FDMI_HBA_ATTR_MODELDESCRIPTION,
  264. &entry->type);
  265. put_unaligned_be16(len, &entry->len);
  266. fc_ct_ms_fill_attr(entry,
  267. fc_host_model_description(lport->host),
  268. FC_FDMI_HBA_ATTR_MODELDESCR_LEN);
  269. /* Hardware Version */
  270. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  271. FC_FDMI_HBA_ATTR_MODELDESCR_LEN);
  272. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  273. len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN;
  274. put_unaligned_be16(FC_FDMI_HBA_ATTR_HARDWAREVERSION,
  275. &entry->type);
  276. put_unaligned_be16(len, &entry->len);
  277. fc_ct_ms_fill_attr(entry,
  278. fc_host_hardware_version(lport->host),
  279. FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN);
  280. /* Driver Version */
  281. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  282. FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN);
  283. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  284. len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN;
  285. put_unaligned_be16(FC_FDMI_HBA_ATTR_DRIVERVERSION,
  286. &entry->type);
  287. put_unaligned_be16(len, &entry->len);
  288. fc_ct_ms_fill_attr(entry,
  289. fc_host_driver_version(lport->host),
  290. FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN);
  291. /* OptionROM Version */
  292. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  293. FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN);
  294. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  295. len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN;
  296. put_unaligned_be16(FC_FDMI_HBA_ATTR_OPTIONROMVERSION,
  297. &entry->type);
  298. put_unaligned_be16(len, &entry->len);
  299. fc_ct_ms_fill_attr(entry,
  300. "unknown",
  301. FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN);
  302. /* Firmware Version */
  303. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  304. FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN);
  305. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  306. len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN;
  307. put_unaligned_be16(FC_FDMI_HBA_ATTR_FIRMWAREVERSION,
  308. &entry->type);
  309. put_unaligned_be16(len, &entry->len);
  310. fc_ct_ms_fill_attr(entry,
  311. fc_host_firmware_version(lport->host),
  312. FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN);
  313. /* OS Name and Version */
  314. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  315. FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN);
  316. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  317. len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN;
  318. put_unaligned_be16(FC_FDMI_HBA_ATTR_OSNAMEVERSION,
  319. &entry->type);
  320. put_unaligned_be16(len, &entry->len);
  321. snprintf((char *)&entry->value,
  322. FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN,
  323. "%s v%s",
  324. init_utsname()->sysname,
  325. init_utsname()->release);
  326. /* Max CT payload */
  327. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  328. FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN);
  329. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  330. len += FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN;
  331. put_unaligned_be16(FC_FDMI_HBA_ATTR_MAXCTPAYLOAD,
  332. &entry->type);
  333. put_unaligned_be16(len, &entry->len);
  334. put_unaligned_be32(fc_host_max_ct_payload(lport->host),
  335. &entry->value);
  336. if (fc_host->fdmi_version == FDMI_V2) {
  337. /* Node symbolic name */
  338. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  339. FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN);
  340. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  341. len += FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN;
  342. put_unaligned_be16(FC_FDMI_HBA_ATTR_NODESYMBLNAME,
  343. &entry->type);
  344. put_unaligned_be16(len, &entry->len);
  345. fc_ct_ms_fill_attr(entry,
  346. fc_host_symbolic_name(lport->host),
  347. FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN);
  348. /* Vendor specific info */
  349. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  350. FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN);
  351. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  352. len += FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN;
  353. put_unaligned_be16(FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO,
  354. &entry->type);
  355. put_unaligned_be16(len, &entry->len);
  356. put_unaligned_be32(0,
  357. &entry->value);
  358. /* Number of ports */
  359. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  360. FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN);
  361. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  362. len += FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN;
  363. put_unaligned_be16(FC_FDMI_HBA_ATTR_NUMBEROFPORTS,
  364. &entry->type);
  365. put_unaligned_be16(len, &entry->len);
  366. put_unaligned_be32(fc_host_num_ports(lport->host),
  367. &entry->value);
  368. /* Fabric name */
  369. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  370. FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN);
  371. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  372. len += FC_FDMI_HBA_ATTR_FABRICNAME_LEN;
  373. put_unaligned_be16(FC_FDMI_HBA_ATTR_FABRICNAME,
  374. &entry->type);
  375. put_unaligned_be16(len, &entry->len);
  376. put_unaligned_be64(fc_host_fabric_name(lport->host),
  377. &entry->value);
  378. /* BIOS version */
  379. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  380. FC_FDMI_HBA_ATTR_FABRICNAME_LEN);
  381. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  382. len += FC_FDMI_HBA_ATTR_BIOSVERSION_LEN;
  383. put_unaligned_be16(FC_FDMI_HBA_ATTR_BIOSVERSION,
  384. &entry->type);
  385. put_unaligned_be16(len, &entry->len);
  386. fc_ct_ms_fill_attr(entry,
  387. fc_host_bootbios_version(lport->host),
  388. FC_FDMI_HBA_ATTR_BIOSVERSION_LEN);
  389. /* BIOS state */
  390. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  391. FC_FDMI_HBA_ATTR_BIOSVERSION_LEN);
  392. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  393. len += FC_FDMI_HBA_ATTR_BIOSSTATE_LEN;
  394. put_unaligned_be16(FC_FDMI_HBA_ATTR_BIOSSTATE,
  395. &entry->type);
  396. put_unaligned_be16(len, &entry->len);
  397. put_unaligned_be32(fc_host_bootbios_state(lport->host),
  398. &entry->value);
  399. /* Vendor identifier */
  400. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  401. FC_FDMI_HBA_ATTR_BIOSSTATE_LEN);
  402. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  403. len += FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN;
  404. put_unaligned_be16(FC_FDMI_HBA_ATTR_VENDORIDENTIFIER,
  405. &entry->type);
  406. put_unaligned_be16(len, &entry->len);
  407. fc_ct_ms_fill_attr(entry,
  408. fc_host_vendor_identifier(lport->host),
  409. FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN);
  410. }
  411. break;
  412. case FC_FDMI_RPA:
  413. numattrs = 6;
  414. len = sizeof(struct fc_fdmi_rpa);
  415. len -= sizeof(struct fc_fdmi_attr_entry);
  416. len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN);
  417. len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN;
  418. len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN;
  419. len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN;
  420. len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN;
  421. len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN;
  422. len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN;
  423. if (fc_host->fdmi_version == FDMI_V2) {
  424. numattrs += 10;
  425. len += FC_FDMI_PORT_ATTR_NODENAME_LEN;
  426. len += FC_FDMI_PORT_ATTR_PORTNAME_LEN;
  427. len += FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN;
  428. len += FC_FDMI_PORT_ATTR_PORTTYPE_LEN;
  429. len += FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN;
  430. len += FC_FDMI_PORT_ATTR_FABRICNAME_LEN;
  431. len += FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN;
  432. len += FC_FDMI_PORT_ATTR_PORTSTATE_LEN;
  433. len += FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN;
  434. len += FC_FDMI_PORT_ATTR_PORTID_LEN;
  435. }
  436. ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
  437. FC_FDMI_SUBTYPE);
  438. /* Port Name */
  439. put_unaligned_be64(lport->wwpn,
  440. &ct->payload.rpa.port.portname);
  441. /* Port Attributes */
  442. put_unaligned_be32(numattrs,
  443. &ct->payload.rpa.hba_attrs.numattrs);
  444. hba_attrs = &ct->payload.rpa.hba_attrs;
  445. entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr;
  446. /* FC4 types */
  447. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  448. len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN;
  449. put_unaligned_be16(FC_FDMI_PORT_ATTR_FC4TYPES,
  450. &entry->type);
  451. put_unaligned_be16(len, &entry->len);
  452. memcpy(&entry->value, fc_host_supported_fc4s(lport->host),
  453. FC_FDMI_PORT_ATTR_FC4TYPES_LEN);
  454. /* Supported Speed */
  455. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  456. FC_FDMI_PORT_ATTR_FC4TYPES_LEN);
  457. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  458. len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN;
  459. put_unaligned_be16(FC_FDMI_PORT_ATTR_SUPPORTEDSPEED,
  460. &entry->type);
  461. put_unaligned_be16(len, &entry->len);
  462. put_unaligned_be32(fc_host_supported_speeds(lport->host),
  463. &entry->value);
  464. /* Current Port Speed */
  465. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  466. FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN);
  467. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  468. len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN;
  469. put_unaligned_be16(FC_FDMI_PORT_ATTR_CURRENTPORTSPEED,
  470. &entry->type);
  471. put_unaligned_be16(len, &entry->len);
  472. put_unaligned_be32(lport->link_speed,
  473. &entry->value);
  474. /* Max Frame Size */
  475. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  476. FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN);
  477. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  478. len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN;
  479. put_unaligned_be16(FC_FDMI_PORT_ATTR_MAXFRAMESIZE,
  480. &entry->type);
  481. put_unaligned_be16(len, &entry->len);
  482. put_unaligned_be32(fc_host_maxframe_size(lport->host),
  483. &entry->value);
  484. /* OS Device Name */
  485. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  486. FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN);
  487. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  488. len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN;
  489. put_unaligned_be16(FC_FDMI_PORT_ATTR_OSDEVICENAME,
  490. &entry->type);
  491. put_unaligned_be16(len, &entry->len);
  492. /* Use the sysfs device name */
  493. fc_ct_ms_fill_attr(entry,
  494. dev_name(&lport->host->shost_gendev),
  495. strnlen(dev_name(&lport->host->shost_gendev),
  496. FC_FDMI_PORT_ATTR_HOSTNAME_LEN));
  497. /* Host Name */
  498. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  499. FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN);
  500. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  501. len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN;
  502. put_unaligned_be16(FC_FDMI_PORT_ATTR_HOSTNAME,
  503. &entry->type);
  504. put_unaligned_be16(len, &entry->len);
  505. if (strlen(fc_host_system_hostname(lport->host)))
  506. fc_ct_ms_fill_attr(entry,
  507. fc_host_system_hostname(lport->host),
  508. strnlen(fc_host_system_hostname(lport->host),
  509. FC_FDMI_PORT_ATTR_HOSTNAME_LEN));
  510. else
  511. fc_ct_ms_fill_attr(entry,
  512. init_utsname()->nodename,
  513. FC_FDMI_PORT_ATTR_HOSTNAME_LEN);
  514. if (fc_host->fdmi_version == FDMI_V2) {
  515. /* Node name */
  516. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  517. FC_FDMI_PORT_ATTR_HOSTNAME_LEN);
  518. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  519. len += FC_FDMI_PORT_ATTR_NODENAME_LEN;
  520. put_unaligned_be16(FC_FDMI_PORT_ATTR_NODENAME,
  521. &entry->type);
  522. put_unaligned_be16(len, &entry->len);
  523. put_unaligned_be64(fc_host_node_name(lport->host),
  524. &entry->value);
  525. /* Port name */
  526. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  527. FC_FDMI_PORT_ATTR_NODENAME_LEN);
  528. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  529. len += FC_FDMI_PORT_ATTR_PORTNAME_LEN;
  530. put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTNAME,
  531. &entry->type);
  532. put_unaligned_be16(len, &entry->len);
  533. put_unaligned_be64(lport->wwpn,
  534. &entry->value);
  535. /* Port symbolic name */
  536. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  537. FC_FDMI_PORT_ATTR_PORTNAME_LEN);
  538. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  539. len += FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN;
  540. put_unaligned_be16(FC_FDMI_PORT_ATTR_SYMBOLICNAME,
  541. &entry->type);
  542. put_unaligned_be16(len, &entry->len);
  543. fc_ct_ms_fill_attr(entry,
  544. fc_host_symbolic_name(lport->host),
  545. FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN);
  546. /* Port type */
  547. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  548. FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN);
  549. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  550. len += FC_FDMI_PORT_ATTR_PORTTYPE_LEN;
  551. put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTTYPE,
  552. &entry->type);
  553. put_unaligned_be16(len, &entry->len);
  554. put_unaligned_be32(fc_host_port_type(lport->host),
  555. &entry->value);
  556. /* Supported class of service */
  557. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  558. FC_FDMI_PORT_ATTR_PORTTYPE_LEN);
  559. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  560. len += FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN;
  561. put_unaligned_be16(FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC,
  562. &entry->type);
  563. put_unaligned_be16(len, &entry->len);
  564. put_unaligned_be32(fc_host_supported_classes(lport->host),
  565. &entry->value);
  566. /* Port Fabric name */
  567. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  568. FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN);
  569. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  570. len += FC_FDMI_PORT_ATTR_FABRICNAME_LEN;
  571. put_unaligned_be16(FC_FDMI_PORT_ATTR_FABRICNAME,
  572. &entry->type);
  573. put_unaligned_be16(len, &entry->len);
  574. put_unaligned_be64(fc_host_fabric_name(lport->host),
  575. &entry->value);
  576. /* Port active FC-4 */
  577. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  578. FC_FDMI_PORT_ATTR_FABRICNAME_LEN);
  579. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  580. len += FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN;
  581. put_unaligned_be16(FC_FDMI_PORT_ATTR_CURRENTFC4TYPE,
  582. &entry->type);
  583. put_unaligned_be16(len, &entry->len);
  584. memcpy(&entry->value, fc_host_active_fc4s(lport->host),
  585. FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN);
  586. /* Port state */
  587. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  588. FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN);
  589. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  590. len += FC_FDMI_PORT_ATTR_PORTSTATE_LEN;
  591. put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTSTATE,
  592. &entry->type);
  593. put_unaligned_be16(len, &entry->len);
  594. put_unaligned_be32(fc_host_port_state(lport->host),
  595. &entry->value);
  596. /* Discovered ports */
  597. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  598. FC_FDMI_PORT_ATTR_PORTSTATE_LEN);
  599. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  600. len += FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN;
  601. put_unaligned_be16(FC_FDMI_PORT_ATTR_DISCOVEREDPORTS,
  602. &entry->type);
  603. put_unaligned_be16(len, &entry->len);
  604. put_unaligned_be32(fc_host_num_discovered_ports(lport->host),
  605. &entry->value);
  606. /* Port ID */
  607. entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
  608. FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN);
  609. len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
  610. len += FC_FDMI_PORT_ATTR_PORTID_LEN;
  611. put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTID,
  612. &entry->type);
  613. put_unaligned_be16(len, &entry->len);
  614. put_unaligned_be32(fc_host_port_id(lport->host),
  615. &entry->value);
  616. }
  617. break;
  618. case FC_FDMI_DPRT:
  619. len = sizeof(struct fc_fdmi_dprt);
  620. ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
  621. FC_FDMI_SUBTYPE);
  622. /* Port Name */
  623. put_unaligned_be64(lport->wwpn,
  624. &ct->payload.dprt.port.portname);
  625. break;
  626. case FC_FDMI_DHBA:
  627. len = sizeof(struct fc_fdmi_dhba);
  628. ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
  629. FC_FDMI_SUBTYPE);
  630. /* HBA Identifier */
  631. put_unaligned_be64(lport->wwpn, &ct->payload.dhba.hbaid.id);
  632. break;
  633. default:
  634. return -EINVAL;
  635. }
  636. *r_ctl = FC_RCTL_DD_UNSOL_CTL;
  637. *fh_type = FC_TYPE_CT;
  638. return 0;
  639. }
  640. /**
  641. * fc_ct_fill() - Fill in a common transport service request frame
  642. * @lport: local port.
  643. * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
  644. * @fp: frame to contain payload.
  645. * @op: CT opcode.
  646. * @r_ctl: pointer to FC header R_CTL.
  647. * @fh_type: pointer to FC-4 type.
  648. */
  649. static inline int fc_ct_fill(struct fc_lport *lport,
  650. u32 fc_id, struct fc_frame *fp,
  651. unsigned int op, enum fc_rctl *r_ctl,
  652. enum fc_fh_type *fh_type, u32 *did)
  653. {
  654. int rc = -EINVAL;
  655. switch (fc_id) {
  656. case FC_FID_MGMT_SERV:
  657. rc = fc_ct_ms_fill(lport, fc_id, fp, op, r_ctl, fh_type);
  658. *did = FC_FID_MGMT_SERV;
  659. break;
  660. case FC_FID_DIR_SERV:
  661. default:
  662. rc = fc_ct_ns_fill(lport, fc_id, fp, op, r_ctl, fh_type);
  663. *did = FC_FID_DIR_SERV;
  664. break;
  665. }
  666. return rc;
  667. }
  668. /**
  669. * fc_plogi_fill - Fill in plogi request frame
  670. */
  671. static inline void fc_plogi_fill(struct fc_lport *lport, struct fc_frame *fp,
  672. unsigned int op)
  673. {
  674. struct fc_els_flogi *plogi;
  675. struct fc_els_csp *csp;
  676. struct fc_els_cssp *cp;
  677. plogi = fc_frame_payload_get(fp, sizeof(*plogi));
  678. memset(plogi, 0, sizeof(*plogi));
  679. plogi->fl_cmd = (u8) op;
  680. put_unaligned_be64(lport->wwpn, &plogi->fl_wwpn);
  681. put_unaligned_be64(lport->wwnn, &plogi->fl_wwnn);
  682. csp = &plogi->fl_csp;
  683. csp->sp_hi_ver = 0x20;
  684. csp->sp_lo_ver = 0x20;
  685. csp->sp_bb_cred = htons(10); /* this gets set by gateway */
  686. csp->sp_bb_data = htons((u16) lport->mfs);
  687. cp = &plogi->fl_cssp[3 - 1]; /* class 3 parameters */
  688. cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
  689. csp->sp_features = htons(FC_SP_FT_CIRO);
  690. csp->sp_tot_seq = htons(255); /* seq. we accept */
  691. csp->sp_rel_off = htons(0x1f);
  692. csp->sp_e_d_tov = htonl(lport->e_d_tov);
  693. cp->cp_rdfs = htons((u16) lport->mfs);
  694. cp->cp_con_seq = htons(255);
  695. cp->cp_open_seq = 1;
  696. }
  697. /**
  698. * fc_flogi_fill - Fill in a flogi request frame.
  699. */
  700. static inline void fc_flogi_fill(struct fc_lport *lport, struct fc_frame *fp)
  701. {
  702. struct fc_els_csp *sp;
  703. struct fc_els_cssp *cp;
  704. struct fc_els_flogi *flogi;
  705. flogi = fc_frame_payload_get(fp, sizeof(*flogi));
  706. memset(flogi, 0, sizeof(*flogi));
  707. flogi->fl_cmd = (u8) ELS_FLOGI;
  708. put_unaligned_be64(lport->wwpn, &flogi->fl_wwpn);
  709. put_unaligned_be64(lport->wwnn, &flogi->fl_wwnn);
  710. sp = &flogi->fl_csp;
  711. sp->sp_hi_ver = 0x20;
  712. sp->sp_lo_ver = 0x20;
  713. sp->sp_bb_cred = htons(10); /* this gets set by gateway */
  714. sp->sp_bb_data = htons((u16) lport->mfs);
  715. cp = &flogi->fl_cssp[3 - 1]; /* class 3 parameters */
  716. cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
  717. if (lport->does_npiv)
  718. sp->sp_features = htons(FC_SP_FT_NPIV);
  719. }
  720. /**
  721. * fc_fdisc_fill - Fill in a fdisc request frame.
  722. */
  723. static inline void fc_fdisc_fill(struct fc_lport *lport, struct fc_frame *fp)
  724. {
  725. struct fc_els_csp *sp;
  726. struct fc_els_cssp *cp;
  727. struct fc_els_flogi *fdisc;
  728. fdisc = fc_frame_payload_get(fp, sizeof(*fdisc));
  729. memset(fdisc, 0, sizeof(*fdisc));
  730. fdisc->fl_cmd = (u8) ELS_FDISC;
  731. put_unaligned_be64(lport->wwpn, &fdisc->fl_wwpn);
  732. put_unaligned_be64(lport->wwnn, &fdisc->fl_wwnn);
  733. sp = &fdisc->fl_csp;
  734. sp->sp_hi_ver = 0x20;
  735. sp->sp_lo_ver = 0x20;
  736. sp->sp_bb_cred = htons(10); /* this gets set by gateway */
  737. sp->sp_bb_data = htons((u16) lport->mfs);
  738. cp = &fdisc->fl_cssp[3 - 1]; /* class 3 parameters */
  739. cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
  740. }
  741. /**
  742. * fc_logo_fill - Fill in a logo request frame.
  743. */
  744. static inline void fc_logo_fill(struct fc_lport *lport, struct fc_frame *fp)
  745. {
  746. struct fc_els_logo *logo;
  747. logo = fc_frame_payload_get(fp, sizeof(*logo));
  748. memset(logo, 0, sizeof(*logo));
  749. logo->fl_cmd = ELS_LOGO;
  750. hton24(logo->fl_n_port_id, lport->port_id);
  751. logo->fl_n_port_wwn = htonll(lport->wwpn);
  752. }
  753. /**
  754. * fc_rtv_fill - Fill in RTV (read timeout value) request frame.
  755. */
  756. static inline void fc_rtv_fill(struct fc_lport *lport, struct fc_frame *fp)
  757. {
  758. struct fc_els_rtv *rtv;
  759. rtv = fc_frame_payload_get(fp, sizeof(*rtv));
  760. memset(rtv, 0, sizeof(*rtv));
  761. rtv->rtv_cmd = ELS_RTV;
  762. }
  763. /**
  764. * fc_rec_fill - Fill in rec request frame
  765. */
  766. static inline void fc_rec_fill(struct fc_lport *lport, struct fc_frame *fp)
  767. {
  768. struct fc_els_rec *rec;
  769. struct fc_exch *ep = fc_seq_exch(fr_seq(fp));
  770. rec = fc_frame_payload_get(fp, sizeof(*rec));
  771. memset(rec, 0, sizeof(*rec));
  772. rec->rec_cmd = ELS_REC;
  773. hton24(rec->rec_s_id, lport->port_id);
  774. rec->rec_ox_id = htons(ep->oxid);
  775. rec->rec_rx_id = htons(ep->rxid);
  776. }
  777. /**
  778. * fc_prli_fill - Fill in prli request frame
  779. */
  780. static inline void fc_prli_fill(struct fc_lport *lport, struct fc_frame *fp)
  781. {
  782. struct {
  783. struct fc_els_prli prli;
  784. struct fc_els_spp spp;
  785. } *pp;
  786. pp = fc_frame_payload_get(fp, sizeof(*pp));
  787. memset(pp, 0, sizeof(*pp));
  788. pp->prli.prli_cmd = ELS_PRLI;
  789. pp->prli.prli_spp_len = sizeof(struct fc_els_spp);
  790. pp->prli.prli_len = htons(sizeof(*pp));
  791. pp->spp.spp_type = FC_TYPE_FCP;
  792. pp->spp.spp_flags = FC_SPP_EST_IMG_PAIR;
  793. pp->spp.spp_params = htonl(lport->service_params);
  794. }
  795. /**
  796. * fc_scr_fill - Fill in a scr request frame.
  797. */
  798. static inline void fc_scr_fill(struct fc_lport *lport, struct fc_frame *fp)
  799. {
  800. struct fc_els_scr *scr;
  801. scr = fc_frame_payload_get(fp, sizeof(*scr));
  802. memset(scr, 0, sizeof(*scr));
  803. scr->scr_cmd = ELS_SCR;
  804. scr->scr_reg_func = ELS_SCRF_FULL;
  805. }
  806. /**
  807. * fc_els_fill - Fill in an ELS request frame
  808. */
  809. static inline int fc_els_fill(struct fc_lport *lport,
  810. u32 did,
  811. struct fc_frame *fp, unsigned int op,
  812. enum fc_rctl *r_ctl, enum fc_fh_type *fh_type)
  813. {
  814. switch (op) {
  815. case ELS_ADISC:
  816. fc_adisc_fill(lport, fp);
  817. break;
  818. case ELS_PLOGI:
  819. fc_plogi_fill(lport, fp, ELS_PLOGI);
  820. break;
  821. case ELS_FLOGI:
  822. fc_flogi_fill(lport, fp);
  823. break;
  824. case ELS_FDISC:
  825. fc_fdisc_fill(lport, fp);
  826. break;
  827. case ELS_LOGO:
  828. fc_logo_fill(lport, fp);
  829. break;
  830. case ELS_RTV:
  831. fc_rtv_fill(lport, fp);
  832. break;
  833. case ELS_REC:
  834. fc_rec_fill(lport, fp);
  835. break;
  836. case ELS_PRLI:
  837. fc_prli_fill(lport, fp);
  838. break;
  839. case ELS_SCR:
  840. fc_scr_fill(lport, fp);
  841. break;
  842. default:
  843. return -EINVAL;
  844. }
  845. *r_ctl = FC_RCTL_ELS_REQ;
  846. *fh_type = FC_TYPE_ELS;
  847. return 0;
  848. }
  849. #endif /* _FC_ENCODE_H_ */