fc_encode.h 29 KB

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