18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright(c) 2008 Intel Corporation. All rights reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Maintained at www.Open-FCoE.org 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#ifndef _FC_ENCODE_H_ 98c2ecf20Sopenharmony_ci#define _FC_ENCODE_H_ 108c2ecf20Sopenharmony_ci#include <asm/unaligned.h> 118c2ecf20Sopenharmony_ci#include <linux/utsname.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* 148c2ecf20Sopenharmony_ci * F_CTL values for simple requests and responses. 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci#define FC_FCTL_REQ (FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT) 178c2ecf20Sopenharmony_ci#define FC_FCTL_RESP (FC_FC_EX_CTX | FC_FC_LAST_SEQ | \ 188c2ecf20Sopenharmony_ci FC_FC_END_SEQ | FC_FC_SEQ_INIT) 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistruct fc_ns_rft { 218c2ecf20Sopenharmony_ci struct fc_ns_fid fid; /* port ID object */ 228c2ecf20Sopenharmony_ci struct fc_ns_fts fts; /* FC4-types object */ 238c2ecf20Sopenharmony_ci}; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistruct fc_ct_req { 268c2ecf20Sopenharmony_ci struct fc_ct_hdr hdr; 278c2ecf20Sopenharmony_ci union { 288c2ecf20Sopenharmony_ci struct fc_ns_gid_ft gid; 298c2ecf20Sopenharmony_ci struct fc_ns_rn_id rn; 308c2ecf20Sopenharmony_ci struct fc_ns_rft rft; 318c2ecf20Sopenharmony_ci struct fc_ns_rff_id rff; 328c2ecf20Sopenharmony_ci struct fc_ns_fid fid; 338c2ecf20Sopenharmony_ci struct fc_ns_rsnn snn; 348c2ecf20Sopenharmony_ci struct fc_ns_rspn spn; 358c2ecf20Sopenharmony_ci struct fc_fdmi_rhba rhba; 368c2ecf20Sopenharmony_ci struct fc_fdmi_rpa rpa; 378c2ecf20Sopenharmony_ci struct fc_fdmi_dprt dprt; 388c2ecf20Sopenharmony_ci struct fc_fdmi_dhba dhba; 398c2ecf20Sopenharmony_ci } payload; 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic inline void __fc_fill_fc_hdr(struct fc_frame_header *fh, 438c2ecf20Sopenharmony_ci enum fc_rctl r_ctl, 448c2ecf20Sopenharmony_ci u32 did, u32 sid, enum fc_fh_type type, 458c2ecf20Sopenharmony_ci u32 f_ctl, u32 parm_offset) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci WARN_ON(r_ctl == 0); 488c2ecf20Sopenharmony_ci fh->fh_r_ctl = r_ctl; 498c2ecf20Sopenharmony_ci hton24(fh->fh_d_id, did); 508c2ecf20Sopenharmony_ci hton24(fh->fh_s_id, sid); 518c2ecf20Sopenharmony_ci fh->fh_type = type; 528c2ecf20Sopenharmony_ci hton24(fh->fh_f_ctl, f_ctl); 538c2ecf20Sopenharmony_ci fh->fh_cs_ctl = 0; 548c2ecf20Sopenharmony_ci fh->fh_df_ctl = 0; 558c2ecf20Sopenharmony_ci fh->fh_parm_offset = htonl(parm_offset); 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/** 598c2ecf20Sopenharmony_ci * fill FC header fields in specified fc_frame 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_cistatic inline void fc_fill_fc_hdr(struct fc_frame *fp, enum fc_rctl r_ctl, 628c2ecf20Sopenharmony_ci u32 did, u32 sid, enum fc_fh_type type, 638c2ecf20Sopenharmony_ci u32 f_ctl, u32 parm_offset) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci struct fc_frame_header *fh; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci fh = fc_frame_header_get(fp); 688c2ecf20Sopenharmony_ci __fc_fill_fc_hdr(fh, r_ctl, did, sid, type, f_ctl, parm_offset); 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci/** 728c2ecf20Sopenharmony_ci * fc_adisc_fill() - Fill in adisc request frame 738c2ecf20Sopenharmony_ci * @lport: local port. 748c2ecf20Sopenharmony_ci * @fp: fc frame where payload will be placed. 758c2ecf20Sopenharmony_ci */ 768c2ecf20Sopenharmony_cistatic inline void fc_adisc_fill(struct fc_lport *lport, struct fc_frame *fp) 778c2ecf20Sopenharmony_ci{ 788c2ecf20Sopenharmony_ci struct fc_els_adisc *adisc; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci adisc = fc_frame_payload_get(fp, sizeof(*adisc)); 818c2ecf20Sopenharmony_ci memset(adisc, 0, sizeof(*adisc)); 828c2ecf20Sopenharmony_ci adisc->adisc_cmd = ELS_ADISC; 838c2ecf20Sopenharmony_ci put_unaligned_be64(lport->wwpn, &adisc->adisc_wwpn); 848c2ecf20Sopenharmony_ci put_unaligned_be64(lport->wwnn, &adisc->adisc_wwnn); 858c2ecf20Sopenharmony_ci hton24(adisc->adisc_port_id, lport->port_id); 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci/** 898c2ecf20Sopenharmony_ci * fc_ct_hdr_fill- fills ct header and reset ct payload 908c2ecf20Sopenharmony_ci * returns pointer to ct request. 918c2ecf20Sopenharmony_ci */ 928c2ecf20Sopenharmony_cistatic inline struct fc_ct_req *fc_ct_hdr_fill(const struct fc_frame *fp, 938c2ecf20Sopenharmony_ci unsigned int op, size_t req_size, 948c2ecf20Sopenharmony_ci enum fc_ct_fs_type fs_type, 958c2ecf20Sopenharmony_ci u8 subtype) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci struct fc_ct_req *ct; 988c2ecf20Sopenharmony_ci size_t ct_plen; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci ct_plen = sizeof(struct fc_ct_hdr) + req_size; 1018c2ecf20Sopenharmony_ci ct = fc_frame_payload_get(fp, ct_plen); 1028c2ecf20Sopenharmony_ci memset(ct, 0, ct_plen); 1038c2ecf20Sopenharmony_ci ct->hdr.ct_rev = FC_CT_REV; 1048c2ecf20Sopenharmony_ci ct->hdr.ct_fs_type = fs_type; 1058c2ecf20Sopenharmony_ci ct->hdr.ct_fs_subtype = subtype; 1068c2ecf20Sopenharmony_ci ct->hdr.ct_cmd = htons((u16) op); 1078c2ecf20Sopenharmony_ci return ct; 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci/** 1118c2ecf20Sopenharmony_ci * fc_ct_ns_fill() - Fill in a name service request frame 1128c2ecf20Sopenharmony_ci * @lport: local port. 1138c2ecf20Sopenharmony_ci * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries. 1148c2ecf20Sopenharmony_ci * @fp: frame to contain payload. 1158c2ecf20Sopenharmony_ci * @op: CT opcode. 1168c2ecf20Sopenharmony_ci * @r_ctl: pointer to FC header R_CTL. 1178c2ecf20Sopenharmony_ci * @fh_type: pointer to FC-4 type. 1188c2ecf20Sopenharmony_ci */ 1198c2ecf20Sopenharmony_cistatic inline int fc_ct_ns_fill(struct fc_lport *lport, 1208c2ecf20Sopenharmony_ci u32 fc_id, struct fc_frame *fp, 1218c2ecf20Sopenharmony_ci unsigned int op, enum fc_rctl *r_ctl, 1228c2ecf20Sopenharmony_ci enum fc_fh_type *fh_type) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci struct fc_ct_req *ct; 1258c2ecf20Sopenharmony_ci size_t len; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci switch (op) { 1288c2ecf20Sopenharmony_ci case FC_NS_GPN_FT: 1298c2ecf20Sopenharmony_ci ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_gid_ft), 1308c2ecf20Sopenharmony_ci FC_FST_DIR, FC_NS_SUBTYPE); 1318c2ecf20Sopenharmony_ci ct->payload.gid.fn_fc4_type = FC_TYPE_FCP; 1328c2ecf20Sopenharmony_ci break; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci case FC_NS_GPN_ID: 1358c2ecf20Sopenharmony_ci ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_fid), 1368c2ecf20Sopenharmony_ci FC_FST_DIR, FC_NS_SUBTYPE); 1378c2ecf20Sopenharmony_ci ct->payload.gid.fn_fc4_type = FC_TYPE_FCP; 1388c2ecf20Sopenharmony_ci hton24(ct->payload.fid.fp_fid, fc_id); 1398c2ecf20Sopenharmony_ci break; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci case FC_NS_RFT_ID: 1428c2ecf20Sopenharmony_ci ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rft), 1438c2ecf20Sopenharmony_ci FC_FST_DIR, FC_NS_SUBTYPE); 1448c2ecf20Sopenharmony_ci hton24(ct->payload.rft.fid.fp_fid, lport->port_id); 1458c2ecf20Sopenharmony_ci ct->payload.rft.fts = lport->fcts; 1468c2ecf20Sopenharmony_ci break; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci case FC_NS_RFF_ID: 1498c2ecf20Sopenharmony_ci ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rff_id), 1508c2ecf20Sopenharmony_ci FC_FST_DIR, FC_NS_SUBTYPE); 1518c2ecf20Sopenharmony_ci hton24(ct->payload.rff.fr_fid.fp_fid, lport->port_id); 1528c2ecf20Sopenharmony_ci ct->payload.rff.fr_type = FC_TYPE_FCP; 1538c2ecf20Sopenharmony_ci if (lport->service_params & FCP_SPPF_INIT_FCN) 1548c2ecf20Sopenharmony_ci ct->payload.rff.fr_feat = FCP_FEAT_INIT; 1558c2ecf20Sopenharmony_ci if (lport->service_params & FCP_SPPF_TARG_FCN) 1568c2ecf20Sopenharmony_ci ct->payload.rff.fr_feat |= FCP_FEAT_TARG; 1578c2ecf20Sopenharmony_ci break; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci case FC_NS_RNN_ID: 1608c2ecf20Sopenharmony_ci ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rn_id), 1618c2ecf20Sopenharmony_ci FC_FST_DIR, FC_NS_SUBTYPE); 1628c2ecf20Sopenharmony_ci hton24(ct->payload.rn.fr_fid.fp_fid, lport->port_id); 1638c2ecf20Sopenharmony_ci put_unaligned_be64(lport->wwnn, &ct->payload.rn.fr_wwn); 1648c2ecf20Sopenharmony_ci break; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci case FC_NS_RSPN_ID: 1678c2ecf20Sopenharmony_ci len = strnlen(fc_host_symbolic_name(lport->host), 255); 1688c2ecf20Sopenharmony_ci ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rspn) + len, 1698c2ecf20Sopenharmony_ci FC_FST_DIR, FC_NS_SUBTYPE); 1708c2ecf20Sopenharmony_ci hton24(ct->payload.spn.fr_fid.fp_fid, lport->port_id); 1718c2ecf20Sopenharmony_ci strncpy(ct->payload.spn.fr_name, 1728c2ecf20Sopenharmony_ci fc_host_symbolic_name(lport->host), len); 1738c2ecf20Sopenharmony_ci ct->payload.spn.fr_name_len = len; 1748c2ecf20Sopenharmony_ci break; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci case FC_NS_RSNN_NN: 1778c2ecf20Sopenharmony_ci len = strnlen(fc_host_symbolic_name(lport->host), 255); 1788c2ecf20Sopenharmony_ci ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rsnn) + len, 1798c2ecf20Sopenharmony_ci FC_FST_DIR, FC_NS_SUBTYPE); 1808c2ecf20Sopenharmony_ci put_unaligned_be64(lport->wwnn, &ct->payload.snn.fr_wwn); 1818c2ecf20Sopenharmony_ci strncpy(ct->payload.snn.fr_name, 1828c2ecf20Sopenharmony_ci fc_host_symbolic_name(lport->host), len); 1838c2ecf20Sopenharmony_ci ct->payload.snn.fr_name_len = len; 1848c2ecf20Sopenharmony_ci break; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci default: 1878c2ecf20Sopenharmony_ci return -EINVAL; 1888c2ecf20Sopenharmony_ci } 1898c2ecf20Sopenharmony_ci *r_ctl = FC_RCTL_DD_UNSOL_CTL; 1908c2ecf20Sopenharmony_ci *fh_type = FC_TYPE_CT; 1918c2ecf20Sopenharmony_ci return 0; 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci/** 1958c2ecf20Sopenharmony_ci * fc_ct_ms_fill() - Fill in a mgmt service request frame 1968c2ecf20Sopenharmony_ci * @lport: local port. 1978c2ecf20Sopenharmony_ci * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries. 1988c2ecf20Sopenharmony_ci * @fp: frame to contain payload. 1998c2ecf20Sopenharmony_ci * @op: CT opcode. 2008c2ecf20Sopenharmony_ci * @r_ctl: pointer to FC header R_CTL. 2018c2ecf20Sopenharmony_ci * @fh_type: pointer to FC-4 type. 2028c2ecf20Sopenharmony_ci */ 2038c2ecf20Sopenharmony_cistatic inline int fc_ct_ms_fill(struct fc_lport *lport, 2048c2ecf20Sopenharmony_ci u32 fc_id, struct fc_frame *fp, 2058c2ecf20Sopenharmony_ci unsigned int op, enum fc_rctl *r_ctl, 2068c2ecf20Sopenharmony_ci enum fc_fh_type *fh_type) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci struct fc_ct_req *ct; 2098c2ecf20Sopenharmony_ci size_t len; 2108c2ecf20Sopenharmony_ci struct fc_fdmi_attr_entry *entry; 2118c2ecf20Sopenharmony_ci struct fs_fdmi_attrs *hba_attrs; 2128c2ecf20Sopenharmony_ci int numattrs = 0; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci switch (op) { 2158c2ecf20Sopenharmony_ci case FC_FDMI_RHBA: 2168c2ecf20Sopenharmony_ci numattrs = 10; 2178c2ecf20Sopenharmony_ci len = sizeof(struct fc_fdmi_rhba); 2188c2ecf20Sopenharmony_ci len -= sizeof(struct fc_fdmi_attr_entry); 2198c2ecf20Sopenharmony_ci len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN); 2208c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_NODENAME_LEN; 2218c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN; 2228c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN; 2238c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_MODEL_LEN; 2248c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN; 2258c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN; 2268c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN; 2278c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN; 2288c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN; 2298c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN; 2308c2ecf20Sopenharmony_ci ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT, 2318c2ecf20Sopenharmony_ci FC_FDMI_SUBTYPE); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci /* HBA Identifier */ 2348c2ecf20Sopenharmony_ci put_unaligned_be64(lport->wwpn, &ct->payload.rhba.hbaid.id); 2358c2ecf20Sopenharmony_ci /* Number of Ports - always 1 */ 2368c2ecf20Sopenharmony_ci put_unaligned_be32(1, &ct->payload.rhba.port.numport); 2378c2ecf20Sopenharmony_ci /* Port Name */ 2388c2ecf20Sopenharmony_ci put_unaligned_be64(lport->wwpn, 2398c2ecf20Sopenharmony_ci &ct->payload.rhba.port.port[0].portname); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci /* HBA Attributes */ 2428c2ecf20Sopenharmony_ci put_unaligned_be32(numattrs, 2438c2ecf20Sopenharmony_ci &ct->payload.rhba.hba_attrs.numattrs); 2448c2ecf20Sopenharmony_ci hba_attrs = &ct->payload.rhba.hba_attrs; 2458c2ecf20Sopenharmony_ci entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr; 2468c2ecf20Sopenharmony_ci /* NodeName*/ 2478c2ecf20Sopenharmony_ci len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 2488c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_NODENAME_LEN; 2498c2ecf20Sopenharmony_ci put_unaligned_be16(FC_FDMI_HBA_ATTR_NODENAME, 2508c2ecf20Sopenharmony_ci &entry->type); 2518c2ecf20Sopenharmony_ci put_unaligned_be16(len, &entry->len); 2528c2ecf20Sopenharmony_ci put_unaligned_be64(lport->wwnn, 2538c2ecf20Sopenharmony_ci (__be64 *)&entry->value[0]); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci /* Manufacturer */ 2568c2ecf20Sopenharmony_ci entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 2578c2ecf20Sopenharmony_ci FC_FDMI_HBA_ATTR_NODENAME_LEN); 2588c2ecf20Sopenharmony_ci len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 2598c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN; 2608c2ecf20Sopenharmony_ci put_unaligned_be16(FC_FDMI_HBA_ATTR_MANUFACTURER, 2618c2ecf20Sopenharmony_ci &entry->type); 2628c2ecf20Sopenharmony_ci put_unaligned_be16(len, &entry->len); 2638c2ecf20Sopenharmony_ci strncpy((char *)&entry->value, 2648c2ecf20Sopenharmony_ci fc_host_manufacturer(lport->host), 2658c2ecf20Sopenharmony_ci FC_FDMI_HBA_ATTR_MANUFACTURER_LEN); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci /* SerialNumber */ 2688c2ecf20Sopenharmony_ci entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 2698c2ecf20Sopenharmony_ci FC_FDMI_HBA_ATTR_MANUFACTURER_LEN); 2708c2ecf20Sopenharmony_ci len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 2718c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN; 2728c2ecf20Sopenharmony_ci put_unaligned_be16(FC_FDMI_HBA_ATTR_SERIALNUMBER, 2738c2ecf20Sopenharmony_ci &entry->type); 2748c2ecf20Sopenharmony_ci put_unaligned_be16(len, &entry->len); 2758c2ecf20Sopenharmony_ci strncpy((char *)&entry->value, 2768c2ecf20Sopenharmony_ci fc_host_serial_number(lport->host), 2778c2ecf20Sopenharmony_ci FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci /* Model */ 2808c2ecf20Sopenharmony_ci entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 2818c2ecf20Sopenharmony_ci FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN); 2828c2ecf20Sopenharmony_ci len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 2838c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_MODEL_LEN; 2848c2ecf20Sopenharmony_ci put_unaligned_be16(FC_FDMI_HBA_ATTR_MODEL, 2858c2ecf20Sopenharmony_ci &entry->type); 2868c2ecf20Sopenharmony_ci put_unaligned_be16(len, &entry->len); 2878c2ecf20Sopenharmony_ci strncpy((char *)&entry->value, 2888c2ecf20Sopenharmony_ci fc_host_model(lport->host), 2898c2ecf20Sopenharmony_ci FC_FDMI_HBA_ATTR_MODEL_LEN); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci /* Model Description */ 2928c2ecf20Sopenharmony_ci entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 2938c2ecf20Sopenharmony_ci FC_FDMI_HBA_ATTR_MODEL_LEN); 2948c2ecf20Sopenharmony_ci len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 2958c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN; 2968c2ecf20Sopenharmony_ci put_unaligned_be16(FC_FDMI_HBA_ATTR_MODELDESCRIPTION, 2978c2ecf20Sopenharmony_ci &entry->type); 2988c2ecf20Sopenharmony_ci put_unaligned_be16(len, &entry->len); 2998c2ecf20Sopenharmony_ci strncpy((char *)&entry->value, 3008c2ecf20Sopenharmony_ci fc_host_model_description(lport->host), 3018c2ecf20Sopenharmony_ci FC_FDMI_HBA_ATTR_MODELDESCR_LEN); 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci /* Hardware Version */ 3048c2ecf20Sopenharmony_ci entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 3058c2ecf20Sopenharmony_ci FC_FDMI_HBA_ATTR_MODELDESCR_LEN); 3068c2ecf20Sopenharmony_ci len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 3078c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN; 3088c2ecf20Sopenharmony_ci put_unaligned_be16(FC_FDMI_HBA_ATTR_HARDWAREVERSION, 3098c2ecf20Sopenharmony_ci &entry->type); 3108c2ecf20Sopenharmony_ci put_unaligned_be16(len, &entry->len); 3118c2ecf20Sopenharmony_ci strncpy((char *)&entry->value, 3128c2ecf20Sopenharmony_ci fc_host_hardware_version(lport->host), 3138c2ecf20Sopenharmony_ci FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci /* Driver Version */ 3168c2ecf20Sopenharmony_ci entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 3178c2ecf20Sopenharmony_ci FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN); 3188c2ecf20Sopenharmony_ci len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 3198c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN; 3208c2ecf20Sopenharmony_ci put_unaligned_be16(FC_FDMI_HBA_ATTR_DRIVERVERSION, 3218c2ecf20Sopenharmony_ci &entry->type); 3228c2ecf20Sopenharmony_ci put_unaligned_be16(len, &entry->len); 3238c2ecf20Sopenharmony_ci strncpy((char *)&entry->value, 3248c2ecf20Sopenharmony_ci fc_host_driver_version(lport->host), 3258c2ecf20Sopenharmony_ci FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN); 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci /* OptionROM Version */ 3288c2ecf20Sopenharmony_ci entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 3298c2ecf20Sopenharmony_ci FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN); 3308c2ecf20Sopenharmony_ci len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 3318c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN; 3328c2ecf20Sopenharmony_ci put_unaligned_be16(FC_FDMI_HBA_ATTR_OPTIONROMVERSION, 3338c2ecf20Sopenharmony_ci &entry->type); 3348c2ecf20Sopenharmony_ci put_unaligned_be16(len, &entry->len); 3358c2ecf20Sopenharmony_ci strncpy((char *)&entry->value, 3368c2ecf20Sopenharmony_ci fc_host_optionrom_version(lport->host), 3378c2ecf20Sopenharmony_ci FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci /* Firmware Version */ 3408c2ecf20Sopenharmony_ci entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 3418c2ecf20Sopenharmony_ci FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN); 3428c2ecf20Sopenharmony_ci len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 3438c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN; 3448c2ecf20Sopenharmony_ci put_unaligned_be16(FC_FDMI_HBA_ATTR_FIRMWAREVERSION, 3458c2ecf20Sopenharmony_ci &entry->type); 3468c2ecf20Sopenharmony_ci put_unaligned_be16(len, &entry->len); 3478c2ecf20Sopenharmony_ci strncpy((char *)&entry->value, 3488c2ecf20Sopenharmony_ci fc_host_firmware_version(lport->host), 3498c2ecf20Sopenharmony_ci FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN); 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci /* OS Name and Version */ 3528c2ecf20Sopenharmony_ci entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 3538c2ecf20Sopenharmony_ci FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN); 3548c2ecf20Sopenharmony_ci len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 3558c2ecf20Sopenharmony_ci len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN; 3568c2ecf20Sopenharmony_ci put_unaligned_be16(FC_FDMI_HBA_ATTR_OSNAMEVERSION, 3578c2ecf20Sopenharmony_ci &entry->type); 3588c2ecf20Sopenharmony_ci put_unaligned_be16(len, &entry->len); 3598c2ecf20Sopenharmony_ci snprintf((char *)&entry->value, 3608c2ecf20Sopenharmony_ci FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN, 3618c2ecf20Sopenharmony_ci "%s v%s", 3628c2ecf20Sopenharmony_ci init_utsname()->sysname, 3638c2ecf20Sopenharmony_ci init_utsname()->release); 3648c2ecf20Sopenharmony_ci break; 3658c2ecf20Sopenharmony_ci case FC_FDMI_RPA: 3668c2ecf20Sopenharmony_ci numattrs = 6; 3678c2ecf20Sopenharmony_ci len = sizeof(struct fc_fdmi_rpa); 3688c2ecf20Sopenharmony_ci len -= sizeof(struct fc_fdmi_attr_entry); 3698c2ecf20Sopenharmony_ci len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN); 3708c2ecf20Sopenharmony_ci len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN; 3718c2ecf20Sopenharmony_ci len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN; 3728c2ecf20Sopenharmony_ci len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN; 3738c2ecf20Sopenharmony_ci len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN; 3748c2ecf20Sopenharmony_ci len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN; 3758c2ecf20Sopenharmony_ci len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN; 3768c2ecf20Sopenharmony_ci ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT, 3778c2ecf20Sopenharmony_ci FC_FDMI_SUBTYPE); 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci /* Port Name */ 3808c2ecf20Sopenharmony_ci put_unaligned_be64(lport->wwpn, 3818c2ecf20Sopenharmony_ci &ct->payload.rpa.port.portname); 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci /* Port Attributes */ 3848c2ecf20Sopenharmony_ci put_unaligned_be32(numattrs, 3858c2ecf20Sopenharmony_ci &ct->payload.rpa.hba_attrs.numattrs); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci hba_attrs = &ct->payload.rpa.hba_attrs; 3888c2ecf20Sopenharmony_ci entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci /* FC4 types */ 3918c2ecf20Sopenharmony_ci len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 3928c2ecf20Sopenharmony_ci len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN; 3938c2ecf20Sopenharmony_ci put_unaligned_be16(FC_FDMI_PORT_ATTR_FC4TYPES, 3948c2ecf20Sopenharmony_ci &entry->type); 3958c2ecf20Sopenharmony_ci put_unaligned_be16(len, &entry->len); 3968c2ecf20Sopenharmony_ci memcpy(&entry->value, fc_host_supported_fc4s(lport->host), 3978c2ecf20Sopenharmony_ci FC_FDMI_PORT_ATTR_FC4TYPES_LEN); 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci /* Supported Speed */ 4008c2ecf20Sopenharmony_ci entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 4018c2ecf20Sopenharmony_ci FC_FDMI_PORT_ATTR_FC4TYPES_LEN); 4028c2ecf20Sopenharmony_ci len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 4038c2ecf20Sopenharmony_ci len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN; 4048c2ecf20Sopenharmony_ci put_unaligned_be16(FC_FDMI_PORT_ATTR_SUPPORTEDSPEED, 4058c2ecf20Sopenharmony_ci &entry->type); 4068c2ecf20Sopenharmony_ci put_unaligned_be16(len, &entry->len); 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci put_unaligned_be32(fc_host_supported_speeds(lport->host), 4098c2ecf20Sopenharmony_ci &entry->value); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci /* Current Port Speed */ 4128c2ecf20Sopenharmony_ci entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 4138c2ecf20Sopenharmony_ci FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN); 4148c2ecf20Sopenharmony_ci len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 4158c2ecf20Sopenharmony_ci len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN; 4168c2ecf20Sopenharmony_ci put_unaligned_be16(FC_FDMI_PORT_ATTR_CURRENTPORTSPEED, 4178c2ecf20Sopenharmony_ci &entry->type); 4188c2ecf20Sopenharmony_ci put_unaligned_be16(len, &entry->len); 4198c2ecf20Sopenharmony_ci put_unaligned_be32(lport->link_speed, 4208c2ecf20Sopenharmony_ci &entry->value); 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci /* Max Frame Size */ 4238c2ecf20Sopenharmony_ci entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 4248c2ecf20Sopenharmony_ci FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN); 4258c2ecf20Sopenharmony_ci len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 4268c2ecf20Sopenharmony_ci len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN; 4278c2ecf20Sopenharmony_ci put_unaligned_be16(FC_FDMI_PORT_ATTR_MAXFRAMESIZE, 4288c2ecf20Sopenharmony_ci &entry->type); 4298c2ecf20Sopenharmony_ci put_unaligned_be16(len, &entry->len); 4308c2ecf20Sopenharmony_ci put_unaligned_be32(fc_host_maxframe_size(lport->host), 4318c2ecf20Sopenharmony_ci &entry->value); 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci /* OS Device Name */ 4348c2ecf20Sopenharmony_ci entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 4358c2ecf20Sopenharmony_ci FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN); 4368c2ecf20Sopenharmony_ci len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 4378c2ecf20Sopenharmony_ci len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN; 4388c2ecf20Sopenharmony_ci put_unaligned_be16(FC_FDMI_PORT_ATTR_OSDEVICENAME, 4398c2ecf20Sopenharmony_ci &entry->type); 4408c2ecf20Sopenharmony_ci put_unaligned_be16(len, &entry->len); 4418c2ecf20Sopenharmony_ci /* Use the sysfs device name */ 4428c2ecf20Sopenharmony_ci strncpy((char *)&entry->value, 4438c2ecf20Sopenharmony_ci dev_name(&lport->host->shost_gendev), 4448c2ecf20Sopenharmony_ci strnlen(dev_name(&lport->host->shost_gendev), 4458c2ecf20Sopenharmony_ci FC_FDMI_PORT_ATTR_HOSTNAME_LEN)); 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci /* Host Name */ 4488c2ecf20Sopenharmony_ci entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + 4498c2ecf20Sopenharmony_ci FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN); 4508c2ecf20Sopenharmony_ci len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; 4518c2ecf20Sopenharmony_ci len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN; 4528c2ecf20Sopenharmony_ci put_unaligned_be16(FC_FDMI_PORT_ATTR_HOSTNAME, 4538c2ecf20Sopenharmony_ci &entry->type); 4548c2ecf20Sopenharmony_ci put_unaligned_be16(len, &entry->len); 4558c2ecf20Sopenharmony_ci if (strlen(fc_host_system_hostname(lport->host))) 4568c2ecf20Sopenharmony_ci strncpy((char *)&entry->value, 4578c2ecf20Sopenharmony_ci fc_host_system_hostname(lport->host), 4588c2ecf20Sopenharmony_ci strnlen(fc_host_system_hostname(lport->host), 4598c2ecf20Sopenharmony_ci FC_FDMI_PORT_ATTR_HOSTNAME_LEN)); 4608c2ecf20Sopenharmony_ci else 4618c2ecf20Sopenharmony_ci strncpy((char *)&entry->value, 4628c2ecf20Sopenharmony_ci init_utsname()->nodename, 4638c2ecf20Sopenharmony_ci FC_FDMI_PORT_ATTR_HOSTNAME_LEN); 4648c2ecf20Sopenharmony_ci break; 4658c2ecf20Sopenharmony_ci case FC_FDMI_DPRT: 4668c2ecf20Sopenharmony_ci len = sizeof(struct fc_fdmi_dprt); 4678c2ecf20Sopenharmony_ci ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT, 4688c2ecf20Sopenharmony_ci FC_FDMI_SUBTYPE); 4698c2ecf20Sopenharmony_ci /* Port Name */ 4708c2ecf20Sopenharmony_ci put_unaligned_be64(lport->wwpn, 4718c2ecf20Sopenharmony_ci &ct->payload.dprt.port.portname); 4728c2ecf20Sopenharmony_ci break; 4738c2ecf20Sopenharmony_ci case FC_FDMI_DHBA: 4748c2ecf20Sopenharmony_ci len = sizeof(struct fc_fdmi_dhba); 4758c2ecf20Sopenharmony_ci ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT, 4768c2ecf20Sopenharmony_ci FC_FDMI_SUBTYPE); 4778c2ecf20Sopenharmony_ci /* HBA Identifier */ 4788c2ecf20Sopenharmony_ci put_unaligned_be64(lport->wwpn, &ct->payload.dhba.hbaid.id); 4798c2ecf20Sopenharmony_ci break; 4808c2ecf20Sopenharmony_ci default: 4818c2ecf20Sopenharmony_ci return -EINVAL; 4828c2ecf20Sopenharmony_ci } 4838c2ecf20Sopenharmony_ci *r_ctl = FC_RCTL_DD_UNSOL_CTL; 4848c2ecf20Sopenharmony_ci *fh_type = FC_TYPE_CT; 4858c2ecf20Sopenharmony_ci return 0; 4868c2ecf20Sopenharmony_ci} 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci/** 4898c2ecf20Sopenharmony_ci * fc_ct_fill() - Fill in a common transport service request frame 4908c2ecf20Sopenharmony_ci * @lport: local port. 4918c2ecf20Sopenharmony_ci * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries. 4928c2ecf20Sopenharmony_ci * @fp: frame to contain payload. 4938c2ecf20Sopenharmony_ci * @op: CT opcode. 4948c2ecf20Sopenharmony_ci * @r_ctl: pointer to FC header R_CTL. 4958c2ecf20Sopenharmony_ci * @fh_type: pointer to FC-4 type. 4968c2ecf20Sopenharmony_ci */ 4978c2ecf20Sopenharmony_cistatic inline int fc_ct_fill(struct fc_lport *lport, 4988c2ecf20Sopenharmony_ci u32 fc_id, struct fc_frame *fp, 4998c2ecf20Sopenharmony_ci unsigned int op, enum fc_rctl *r_ctl, 5008c2ecf20Sopenharmony_ci enum fc_fh_type *fh_type, u32 *did) 5018c2ecf20Sopenharmony_ci{ 5028c2ecf20Sopenharmony_ci int rc = -EINVAL; 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci switch (fc_id) { 5058c2ecf20Sopenharmony_ci case FC_FID_MGMT_SERV: 5068c2ecf20Sopenharmony_ci rc = fc_ct_ms_fill(lport, fc_id, fp, op, r_ctl, fh_type); 5078c2ecf20Sopenharmony_ci *did = FC_FID_MGMT_SERV; 5088c2ecf20Sopenharmony_ci break; 5098c2ecf20Sopenharmony_ci case FC_FID_DIR_SERV: 5108c2ecf20Sopenharmony_ci default: 5118c2ecf20Sopenharmony_ci rc = fc_ct_ns_fill(lport, fc_id, fp, op, r_ctl, fh_type); 5128c2ecf20Sopenharmony_ci *did = FC_FID_DIR_SERV; 5138c2ecf20Sopenharmony_ci break; 5148c2ecf20Sopenharmony_ci } 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci return rc; 5178c2ecf20Sopenharmony_ci} 5188c2ecf20Sopenharmony_ci/** 5198c2ecf20Sopenharmony_ci * fc_plogi_fill - Fill in plogi request frame 5208c2ecf20Sopenharmony_ci */ 5218c2ecf20Sopenharmony_cistatic inline void fc_plogi_fill(struct fc_lport *lport, struct fc_frame *fp, 5228c2ecf20Sopenharmony_ci unsigned int op) 5238c2ecf20Sopenharmony_ci{ 5248c2ecf20Sopenharmony_ci struct fc_els_flogi *plogi; 5258c2ecf20Sopenharmony_ci struct fc_els_csp *csp; 5268c2ecf20Sopenharmony_ci struct fc_els_cssp *cp; 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci plogi = fc_frame_payload_get(fp, sizeof(*plogi)); 5298c2ecf20Sopenharmony_ci memset(plogi, 0, sizeof(*plogi)); 5308c2ecf20Sopenharmony_ci plogi->fl_cmd = (u8) op; 5318c2ecf20Sopenharmony_ci put_unaligned_be64(lport->wwpn, &plogi->fl_wwpn); 5328c2ecf20Sopenharmony_ci put_unaligned_be64(lport->wwnn, &plogi->fl_wwnn); 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci csp = &plogi->fl_csp; 5358c2ecf20Sopenharmony_ci csp->sp_hi_ver = 0x20; 5368c2ecf20Sopenharmony_ci csp->sp_lo_ver = 0x20; 5378c2ecf20Sopenharmony_ci csp->sp_bb_cred = htons(10); /* this gets set by gateway */ 5388c2ecf20Sopenharmony_ci csp->sp_bb_data = htons((u16) lport->mfs); 5398c2ecf20Sopenharmony_ci cp = &plogi->fl_cssp[3 - 1]; /* class 3 parameters */ 5408c2ecf20Sopenharmony_ci cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ); 5418c2ecf20Sopenharmony_ci csp->sp_features = htons(FC_SP_FT_CIRO); 5428c2ecf20Sopenharmony_ci csp->sp_tot_seq = htons(255); /* seq. we accept */ 5438c2ecf20Sopenharmony_ci csp->sp_rel_off = htons(0x1f); 5448c2ecf20Sopenharmony_ci csp->sp_e_d_tov = htonl(lport->e_d_tov); 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci cp->cp_rdfs = htons((u16) lport->mfs); 5478c2ecf20Sopenharmony_ci cp->cp_con_seq = htons(255); 5488c2ecf20Sopenharmony_ci cp->cp_open_seq = 1; 5498c2ecf20Sopenharmony_ci} 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci/** 5528c2ecf20Sopenharmony_ci * fc_flogi_fill - Fill in a flogi request frame. 5538c2ecf20Sopenharmony_ci */ 5548c2ecf20Sopenharmony_cistatic inline void fc_flogi_fill(struct fc_lport *lport, struct fc_frame *fp) 5558c2ecf20Sopenharmony_ci{ 5568c2ecf20Sopenharmony_ci struct fc_els_csp *sp; 5578c2ecf20Sopenharmony_ci struct fc_els_cssp *cp; 5588c2ecf20Sopenharmony_ci struct fc_els_flogi *flogi; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci flogi = fc_frame_payload_get(fp, sizeof(*flogi)); 5618c2ecf20Sopenharmony_ci memset(flogi, 0, sizeof(*flogi)); 5628c2ecf20Sopenharmony_ci flogi->fl_cmd = (u8) ELS_FLOGI; 5638c2ecf20Sopenharmony_ci put_unaligned_be64(lport->wwpn, &flogi->fl_wwpn); 5648c2ecf20Sopenharmony_ci put_unaligned_be64(lport->wwnn, &flogi->fl_wwnn); 5658c2ecf20Sopenharmony_ci sp = &flogi->fl_csp; 5668c2ecf20Sopenharmony_ci sp->sp_hi_ver = 0x20; 5678c2ecf20Sopenharmony_ci sp->sp_lo_ver = 0x20; 5688c2ecf20Sopenharmony_ci sp->sp_bb_cred = htons(10); /* this gets set by gateway */ 5698c2ecf20Sopenharmony_ci sp->sp_bb_data = htons((u16) lport->mfs); 5708c2ecf20Sopenharmony_ci cp = &flogi->fl_cssp[3 - 1]; /* class 3 parameters */ 5718c2ecf20Sopenharmony_ci cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ); 5728c2ecf20Sopenharmony_ci if (lport->does_npiv) 5738c2ecf20Sopenharmony_ci sp->sp_features = htons(FC_SP_FT_NPIV); 5748c2ecf20Sopenharmony_ci} 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci/** 5778c2ecf20Sopenharmony_ci * fc_fdisc_fill - Fill in a fdisc request frame. 5788c2ecf20Sopenharmony_ci */ 5798c2ecf20Sopenharmony_cistatic inline void fc_fdisc_fill(struct fc_lport *lport, struct fc_frame *fp) 5808c2ecf20Sopenharmony_ci{ 5818c2ecf20Sopenharmony_ci struct fc_els_csp *sp; 5828c2ecf20Sopenharmony_ci struct fc_els_cssp *cp; 5838c2ecf20Sopenharmony_ci struct fc_els_flogi *fdisc; 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci fdisc = fc_frame_payload_get(fp, sizeof(*fdisc)); 5868c2ecf20Sopenharmony_ci memset(fdisc, 0, sizeof(*fdisc)); 5878c2ecf20Sopenharmony_ci fdisc->fl_cmd = (u8) ELS_FDISC; 5888c2ecf20Sopenharmony_ci put_unaligned_be64(lport->wwpn, &fdisc->fl_wwpn); 5898c2ecf20Sopenharmony_ci put_unaligned_be64(lport->wwnn, &fdisc->fl_wwnn); 5908c2ecf20Sopenharmony_ci sp = &fdisc->fl_csp; 5918c2ecf20Sopenharmony_ci sp->sp_hi_ver = 0x20; 5928c2ecf20Sopenharmony_ci sp->sp_lo_ver = 0x20; 5938c2ecf20Sopenharmony_ci sp->sp_bb_cred = htons(10); /* this gets set by gateway */ 5948c2ecf20Sopenharmony_ci sp->sp_bb_data = htons((u16) lport->mfs); 5958c2ecf20Sopenharmony_ci cp = &fdisc->fl_cssp[3 - 1]; /* class 3 parameters */ 5968c2ecf20Sopenharmony_ci cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ); 5978c2ecf20Sopenharmony_ci} 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci/** 6008c2ecf20Sopenharmony_ci * fc_logo_fill - Fill in a logo request frame. 6018c2ecf20Sopenharmony_ci */ 6028c2ecf20Sopenharmony_cistatic inline void fc_logo_fill(struct fc_lport *lport, struct fc_frame *fp) 6038c2ecf20Sopenharmony_ci{ 6048c2ecf20Sopenharmony_ci struct fc_els_logo *logo; 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci logo = fc_frame_payload_get(fp, sizeof(*logo)); 6078c2ecf20Sopenharmony_ci memset(logo, 0, sizeof(*logo)); 6088c2ecf20Sopenharmony_ci logo->fl_cmd = ELS_LOGO; 6098c2ecf20Sopenharmony_ci hton24(logo->fl_n_port_id, lport->port_id); 6108c2ecf20Sopenharmony_ci logo->fl_n_port_wwn = htonll(lport->wwpn); 6118c2ecf20Sopenharmony_ci} 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci/** 6148c2ecf20Sopenharmony_ci * fc_rtv_fill - Fill in RTV (read timeout value) request frame. 6158c2ecf20Sopenharmony_ci */ 6168c2ecf20Sopenharmony_cistatic inline void fc_rtv_fill(struct fc_lport *lport, struct fc_frame *fp) 6178c2ecf20Sopenharmony_ci{ 6188c2ecf20Sopenharmony_ci struct fc_els_rtv *rtv; 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci rtv = fc_frame_payload_get(fp, sizeof(*rtv)); 6218c2ecf20Sopenharmony_ci memset(rtv, 0, sizeof(*rtv)); 6228c2ecf20Sopenharmony_ci rtv->rtv_cmd = ELS_RTV; 6238c2ecf20Sopenharmony_ci} 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci/** 6268c2ecf20Sopenharmony_ci * fc_rec_fill - Fill in rec request frame 6278c2ecf20Sopenharmony_ci */ 6288c2ecf20Sopenharmony_cistatic inline void fc_rec_fill(struct fc_lport *lport, struct fc_frame *fp) 6298c2ecf20Sopenharmony_ci{ 6308c2ecf20Sopenharmony_ci struct fc_els_rec *rec; 6318c2ecf20Sopenharmony_ci struct fc_exch *ep = fc_seq_exch(fr_seq(fp)); 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci rec = fc_frame_payload_get(fp, sizeof(*rec)); 6348c2ecf20Sopenharmony_ci memset(rec, 0, sizeof(*rec)); 6358c2ecf20Sopenharmony_ci rec->rec_cmd = ELS_REC; 6368c2ecf20Sopenharmony_ci hton24(rec->rec_s_id, lport->port_id); 6378c2ecf20Sopenharmony_ci rec->rec_ox_id = htons(ep->oxid); 6388c2ecf20Sopenharmony_ci rec->rec_rx_id = htons(ep->rxid); 6398c2ecf20Sopenharmony_ci} 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci/** 6428c2ecf20Sopenharmony_ci * fc_prli_fill - Fill in prli request frame 6438c2ecf20Sopenharmony_ci */ 6448c2ecf20Sopenharmony_cistatic inline void fc_prli_fill(struct fc_lport *lport, struct fc_frame *fp) 6458c2ecf20Sopenharmony_ci{ 6468c2ecf20Sopenharmony_ci struct { 6478c2ecf20Sopenharmony_ci struct fc_els_prli prli; 6488c2ecf20Sopenharmony_ci struct fc_els_spp spp; 6498c2ecf20Sopenharmony_ci } *pp; 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci pp = fc_frame_payload_get(fp, sizeof(*pp)); 6528c2ecf20Sopenharmony_ci memset(pp, 0, sizeof(*pp)); 6538c2ecf20Sopenharmony_ci pp->prli.prli_cmd = ELS_PRLI; 6548c2ecf20Sopenharmony_ci pp->prli.prli_spp_len = sizeof(struct fc_els_spp); 6558c2ecf20Sopenharmony_ci pp->prli.prli_len = htons(sizeof(*pp)); 6568c2ecf20Sopenharmony_ci pp->spp.spp_type = FC_TYPE_FCP; 6578c2ecf20Sopenharmony_ci pp->spp.spp_flags = FC_SPP_EST_IMG_PAIR; 6588c2ecf20Sopenharmony_ci pp->spp.spp_params = htonl(lport->service_params); 6598c2ecf20Sopenharmony_ci} 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci/** 6628c2ecf20Sopenharmony_ci * fc_scr_fill - Fill in a scr request frame. 6638c2ecf20Sopenharmony_ci */ 6648c2ecf20Sopenharmony_cistatic inline void fc_scr_fill(struct fc_lport *lport, struct fc_frame *fp) 6658c2ecf20Sopenharmony_ci{ 6668c2ecf20Sopenharmony_ci struct fc_els_scr *scr; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci scr = fc_frame_payload_get(fp, sizeof(*scr)); 6698c2ecf20Sopenharmony_ci memset(scr, 0, sizeof(*scr)); 6708c2ecf20Sopenharmony_ci scr->scr_cmd = ELS_SCR; 6718c2ecf20Sopenharmony_ci scr->scr_reg_func = ELS_SCRF_FULL; 6728c2ecf20Sopenharmony_ci} 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci/** 6758c2ecf20Sopenharmony_ci * fc_els_fill - Fill in an ELS request frame 6768c2ecf20Sopenharmony_ci */ 6778c2ecf20Sopenharmony_cistatic inline int fc_els_fill(struct fc_lport *lport, 6788c2ecf20Sopenharmony_ci u32 did, 6798c2ecf20Sopenharmony_ci struct fc_frame *fp, unsigned int op, 6808c2ecf20Sopenharmony_ci enum fc_rctl *r_ctl, enum fc_fh_type *fh_type) 6818c2ecf20Sopenharmony_ci{ 6828c2ecf20Sopenharmony_ci switch (op) { 6838c2ecf20Sopenharmony_ci case ELS_ADISC: 6848c2ecf20Sopenharmony_ci fc_adisc_fill(lport, fp); 6858c2ecf20Sopenharmony_ci break; 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci case ELS_PLOGI: 6888c2ecf20Sopenharmony_ci fc_plogi_fill(lport, fp, ELS_PLOGI); 6898c2ecf20Sopenharmony_ci break; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci case ELS_FLOGI: 6928c2ecf20Sopenharmony_ci fc_flogi_fill(lport, fp); 6938c2ecf20Sopenharmony_ci break; 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci case ELS_FDISC: 6968c2ecf20Sopenharmony_ci fc_fdisc_fill(lport, fp); 6978c2ecf20Sopenharmony_ci break; 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci case ELS_LOGO: 7008c2ecf20Sopenharmony_ci fc_logo_fill(lport, fp); 7018c2ecf20Sopenharmony_ci break; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci case ELS_RTV: 7048c2ecf20Sopenharmony_ci fc_rtv_fill(lport, fp); 7058c2ecf20Sopenharmony_ci break; 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci case ELS_REC: 7088c2ecf20Sopenharmony_ci fc_rec_fill(lport, fp); 7098c2ecf20Sopenharmony_ci break; 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci case ELS_PRLI: 7128c2ecf20Sopenharmony_ci fc_prli_fill(lport, fp); 7138c2ecf20Sopenharmony_ci break; 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci case ELS_SCR: 7168c2ecf20Sopenharmony_ci fc_scr_fill(lport, fp); 7178c2ecf20Sopenharmony_ci break; 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci default: 7208c2ecf20Sopenharmony_ci return -EINVAL; 7218c2ecf20Sopenharmony_ci } 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci *r_ctl = FC_RCTL_ELS_REQ; 7248c2ecf20Sopenharmony_ci *fh_type = FC_TYPE_ELS; 7258c2ecf20Sopenharmony_ci return 0; 7268c2ecf20Sopenharmony_ci} 7278c2ecf20Sopenharmony_ci#endif /* _FC_ENCODE_H_ */ 728