0001
0002
0003
0004
0005
0006
0007
0008 #ifndef _FC_ENCODE_H_
0009 #define _FC_ENCODE_H_
0010 #include <asm/unaligned.h>
0011 #include <linux/utsname.h>
0012 #include <scsi/fc/fc_ms.h>
0013
0014
0015
0016
0017 #define FC_FCTL_REQ (FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT)
0018 #define FC_FCTL_RESP (FC_FC_EX_CTX | FC_FC_LAST_SEQ | \
0019 FC_FC_END_SEQ | FC_FC_SEQ_INIT)
0020
0021 struct fc_ns_rft {
0022 struct fc_ns_fid fid;
0023 struct fc_ns_fts fts;
0024 };
0025
0026 struct fc_ct_req {
0027 struct fc_ct_hdr hdr;
0028 union {
0029 struct fc_ns_gid_ft gid;
0030 struct fc_ns_rn_id rn;
0031 struct fc_ns_rft rft;
0032 struct fc_ns_rff_id rff;
0033 struct fc_ns_fid fid;
0034 struct fc_ns_rsnn snn;
0035 struct fc_ns_rspn spn;
0036 struct fc_fdmi_rhba rhba;
0037 struct fc_fdmi_rpa rpa;
0038 struct fc_fdmi_dprt dprt;
0039 struct fc_fdmi_dhba dhba;
0040 } payload;
0041 };
0042
0043
0044
0045
0046
0047
0048 static inline void fc_adisc_fill(struct fc_lport *lport, struct fc_frame *fp)
0049 {
0050 struct fc_els_adisc *adisc;
0051
0052 adisc = fc_frame_payload_get(fp, sizeof(*adisc));
0053 memset(adisc, 0, sizeof(*adisc));
0054 adisc->adisc_cmd = ELS_ADISC;
0055 put_unaligned_be64(lport->wwpn, &adisc->adisc_wwpn);
0056 put_unaligned_be64(lport->wwnn, &adisc->adisc_wwnn);
0057 hton24(adisc->adisc_port_id, lport->port_id);
0058 }
0059
0060
0061
0062
0063
0064 static inline struct fc_ct_req *fc_ct_hdr_fill(const struct fc_frame *fp,
0065 unsigned int op, size_t req_size,
0066 enum fc_ct_fs_type fs_type,
0067 u8 subtype)
0068 {
0069 struct fc_ct_req *ct;
0070 size_t ct_plen;
0071
0072 ct_plen = sizeof(struct fc_ct_hdr) + req_size;
0073 ct = fc_frame_payload_get(fp, ct_plen);
0074 memset(ct, 0, ct_plen);
0075 ct->hdr.ct_rev = FC_CT_REV;
0076 ct->hdr.ct_fs_type = fs_type;
0077 ct->hdr.ct_fs_subtype = subtype;
0078 ct->hdr.ct_cmd = htons((u16) op);
0079 return ct;
0080 }
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091 static inline int fc_ct_ns_fill(struct fc_lport *lport,
0092 u32 fc_id, struct fc_frame *fp,
0093 unsigned int op, enum fc_rctl *r_ctl,
0094 enum fc_fh_type *fh_type)
0095 {
0096 struct fc_ct_req *ct;
0097 size_t len;
0098
0099 switch (op) {
0100 case FC_NS_GPN_FT:
0101 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_gid_ft),
0102 FC_FST_DIR, FC_NS_SUBTYPE);
0103 ct->payload.gid.fn_fc4_type = FC_TYPE_FCP;
0104 break;
0105
0106 case FC_NS_GPN_ID:
0107 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_fid),
0108 FC_FST_DIR, FC_NS_SUBTYPE);
0109 ct->payload.gid.fn_fc4_type = FC_TYPE_FCP;
0110 hton24(ct->payload.fid.fp_fid, fc_id);
0111 break;
0112
0113 case FC_NS_RFT_ID:
0114 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rft),
0115 FC_FST_DIR, FC_NS_SUBTYPE);
0116 hton24(ct->payload.rft.fid.fp_fid, lport->port_id);
0117 ct->payload.rft.fts = lport->fcts;
0118 break;
0119
0120 case FC_NS_RFF_ID:
0121 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rff_id),
0122 FC_FST_DIR, FC_NS_SUBTYPE);
0123 hton24(ct->payload.rff.fr_fid.fp_fid, lport->port_id);
0124 ct->payload.rff.fr_type = FC_TYPE_FCP;
0125 if (lport->service_params & FCP_SPPF_INIT_FCN)
0126 ct->payload.rff.fr_feat = FCP_FEAT_INIT;
0127 if (lport->service_params & FCP_SPPF_TARG_FCN)
0128 ct->payload.rff.fr_feat |= FCP_FEAT_TARG;
0129 break;
0130
0131 case FC_NS_RNN_ID:
0132 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rn_id),
0133 FC_FST_DIR, FC_NS_SUBTYPE);
0134 hton24(ct->payload.rn.fr_fid.fp_fid, lport->port_id);
0135 put_unaligned_be64(lport->wwnn, &ct->payload.rn.fr_wwn);
0136 break;
0137
0138 case FC_NS_RSPN_ID:
0139 len = strnlen(fc_host_symbolic_name(lport->host), 255);
0140 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rspn) + len,
0141 FC_FST_DIR, FC_NS_SUBTYPE);
0142 hton24(ct->payload.spn.fr_fid.fp_fid, lport->port_id);
0143 strncpy(ct->payload.spn.fr_name,
0144 fc_host_symbolic_name(lport->host), len);
0145 ct->payload.spn.fr_name_len = len;
0146 break;
0147
0148 case FC_NS_RSNN_NN:
0149 len = strnlen(fc_host_symbolic_name(lport->host), 255);
0150 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rsnn) + len,
0151 FC_FST_DIR, FC_NS_SUBTYPE);
0152 put_unaligned_be64(lport->wwnn, &ct->payload.snn.fr_wwn);
0153 strncpy(ct->payload.snn.fr_name,
0154 fc_host_symbolic_name(lport->host), len);
0155 ct->payload.snn.fr_name_len = len;
0156 break;
0157
0158 default:
0159 return -EINVAL;
0160 }
0161 *r_ctl = FC_RCTL_DD_UNSOL_CTL;
0162 *fh_type = FC_TYPE_CT;
0163 return 0;
0164 }
0165
0166 static inline void fc_ct_ms_fill_attr(struct fc_fdmi_attr_entry *entry,
0167 const char *in, size_t len)
0168 {
0169 int copied;
0170
0171 copied = strscpy(entry->value, in, len);
0172 if (copied > 0 && copied + 1 < len)
0173 memset(entry->value + copied + 1, 0, len - copied - 1);
0174 }
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185 static inline int fc_ct_ms_fill(struct fc_lport *lport,
0186 u32 fc_id, struct fc_frame *fp,
0187 unsigned int op, enum fc_rctl *r_ctl,
0188 enum fc_fh_type *fh_type)
0189 {
0190 struct fc_ct_req *ct;
0191 size_t len;
0192 struct fc_fdmi_attr_entry *entry;
0193 struct fs_fdmi_attrs *hba_attrs;
0194 int numattrs = 0;
0195 struct fc_host_attrs *fc_host = shost_to_fc_host(lport->host);
0196
0197 switch (op) {
0198 case FC_FDMI_RHBA:
0199 numattrs = 11;
0200 len = sizeof(struct fc_fdmi_rhba);
0201 len -= sizeof(struct fc_fdmi_attr_entry);
0202 len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN);
0203 len += FC_FDMI_HBA_ATTR_NODENAME_LEN;
0204 len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN;
0205 len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN;
0206 len += FC_FDMI_HBA_ATTR_MODEL_LEN;
0207 len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN;
0208 len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN;
0209 len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN;
0210 len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN;
0211 len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN;
0212 len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN;
0213 len += FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN;
0214
0215 if (fc_host->fdmi_version == FDMI_V2) {
0216 numattrs += 7;
0217 len += FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN;
0218 len += FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN;
0219 len += FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN;
0220 len += FC_FDMI_HBA_ATTR_FABRICNAME_LEN;
0221 len += FC_FDMI_HBA_ATTR_BIOSVERSION_LEN;
0222 len += FC_FDMI_HBA_ATTR_BIOSSTATE_LEN;
0223 len += FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN;
0224 }
0225
0226 ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
0227 FC_FDMI_SUBTYPE);
0228
0229
0230 put_unaligned_be64(lport->wwpn, &ct->payload.rhba.hbaid.id);
0231
0232 put_unaligned_be32(1, &ct->payload.rhba.port.numport);
0233
0234 put_unaligned_be64(lport->wwpn,
0235 &ct->payload.rhba.port.port[0].portname);
0236
0237
0238 put_unaligned_be32(numattrs,
0239 &ct->payload.rhba.hba_attrs.numattrs);
0240 hba_attrs = &ct->payload.rhba.hba_attrs;
0241 entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr;
0242
0243 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0244 len += FC_FDMI_HBA_ATTR_NODENAME_LEN;
0245 put_unaligned_be16(FC_FDMI_HBA_ATTR_NODENAME,
0246 &entry->type);
0247 put_unaligned_be16(len, &entry->len);
0248 put_unaligned_be64(lport->wwnn,
0249 (__be64 *)&entry->value);
0250
0251
0252 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0253 FC_FDMI_HBA_ATTR_NODENAME_LEN);
0254 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0255 len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN;
0256 put_unaligned_be16(FC_FDMI_HBA_ATTR_MANUFACTURER,
0257 &entry->type);
0258 put_unaligned_be16(len, &entry->len);
0259 fc_ct_ms_fill_attr(entry,
0260 fc_host_manufacturer(lport->host),
0261 FC_FDMI_HBA_ATTR_MANUFACTURER_LEN);
0262
0263
0264 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0265 FC_FDMI_HBA_ATTR_MANUFACTURER_LEN);
0266 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0267 len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN;
0268 put_unaligned_be16(FC_FDMI_HBA_ATTR_SERIALNUMBER,
0269 &entry->type);
0270 put_unaligned_be16(len, &entry->len);
0271 fc_ct_ms_fill_attr(entry,
0272 fc_host_serial_number(lport->host),
0273 FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN);
0274
0275
0276 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0277 FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN);
0278 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0279 len += FC_FDMI_HBA_ATTR_MODEL_LEN;
0280 put_unaligned_be16(FC_FDMI_HBA_ATTR_MODEL,
0281 &entry->type);
0282 put_unaligned_be16(len, &entry->len);
0283 fc_ct_ms_fill_attr(entry,
0284 fc_host_model(lport->host),
0285 FC_FDMI_HBA_ATTR_MODEL_LEN);
0286
0287
0288 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0289 FC_FDMI_HBA_ATTR_MODEL_LEN);
0290 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0291 len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN;
0292 put_unaligned_be16(FC_FDMI_HBA_ATTR_MODELDESCRIPTION,
0293 &entry->type);
0294 put_unaligned_be16(len, &entry->len);
0295 fc_ct_ms_fill_attr(entry,
0296 fc_host_model_description(lport->host),
0297 FC_FDMI_HBA_ATTR_MODELDESCR_LEN);
0298
0299
0300 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0301 FC_FDMI_HBA_ATTR_MODELDESCR_LEN);
0302 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0303 len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN;
0304 put_unaligned_be16(FC_FDMI_HBA_ATTR_HARDWAREVERSION,
0305 &entry->type);
0306 put_unaligned_be16(len, &entry->len);
0307 fc_ct_ms_fill_attr(entry,
0308 fc_host_hardware_version(lport->host),
0309 FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN);
0310
0311
0312 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0313 FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN);
0314 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0315 len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN;
0316 put_unaligned_be16(FC_FDMI_HBA_ATTR_DRIVERVERSION,
0317 &entry->type);
0318 put_unaligned_be16(len, &entry->len);
0319 fc_ct_ms_fill_attr(entry,
0320 fc_host_driver_version(lport->host),
0321 FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN);
0322
0323
0324 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0325 FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN);
0326 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0327 len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN;
0328 put_unaligned_be16(FC_FDMI_HBA_ATTR_OPTIONROMVERSION,
0329 &entry->type);
0330 put_unaligned_be16(len, &entry->len);
0331 fc_ct_ms_fill_attr(entry,
0332 "unknown",
0333 FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN);
0334
0335
0336 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0337 FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN);
0338 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0339 len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN;
0340 put_unaligned_be16(FC_FDMI_HBA_ATTR_FIRMWAREVERSION,
0341 &entry->type);
0342 put_unaligned_be16(len, &entry->len);
0343 fc_ct_ms_fill_attr(entry,
0344 fc_host_firmware_version(lport->host),
0345 FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN);
0346
0347
0348 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0349 FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN);
0350 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0351 len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN;
0352 put_unaligned_be16(FC_FDMI_HBA_ATTR_OSNAMEVERSION,
0353 &entry->type);
0354 put_unaligned_be16(len, &entry->len);
0355 snprintf((char *)&entry->value,
0356 FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN,
0357 "%s v%s",
0358 init_utsname()->sysname,
0359 init_utsname()->release);
0360
0361
0362 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0363 FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN);
0364 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0365 len += FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN;
0366 put_unaligned_be16(FC_FDMI_HBA_ATTR_MAXCTPAYLOAD,
0367 &entry->type);
0368 put_unaligned_be16(len, &entry->len);
0369 put_unaligned_be32(fc_host_max_ct_payload(lport->host),
0370 &entry->value);
0371
0372 if (fc_host->fdmi_version == FDMI_V2) {
0373
0374 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0375 FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN);
0376 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0377 len += FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN;
0378 put_unaligned_be16(FC_FDMI_HBA_ATTR_NODESYMBLNAME,
0379 &entry->type);
0380 put_unaligned_be16(len, &entry->len);
0381 fc_ct_ms_fill_attr(entry,
0382 fc_host_symbolic_name(lport->host),
0383 FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN);
0384
0385
0386 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0387 FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN);
0388 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0389 len += FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN;
0390 put_unaligned_be16(FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO,
0391 &entry->type);
0392 put_unaligned_be16(len, &entry->len);
0393 put_unaligned_be32(0,
0394 &entry->value);
0395
0396
0397 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0398 FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN);
0399 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0400 len += FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN;
0401 put_unaligned_be16(FC_FDMI_HBA_ATTR_NUMBEROFPORTS,
0402 &entry->type);
0403 put_unaligned_be16(len, &entry->len);
0404 put_unaligned_be32(fc_host_num_ports(lport->host),
0405 &entry->value);
0406
0407
0408 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0409 FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN);
0410 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0411 len += FC_FDMI_HBA_ATTR_FABRICNAME_LEN;
0412 put_unaligned_be16(FC_FDMI_HBA_ATTR_FABRICNAME,
0413 &entry->type);
0414 put_unaligned_be16(len, &entry->len);
0415 put_unaligned_be64(fc_host_fabric_name(lport->host),
0416 &entry->value);
0417
0418
0419 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0420 FC_FDMI_HBA_ATTR_FABRICNAME_LEN);
0421 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0422 len += FC_FDMI_HBA_ATTR_BIOSVERSION_LEN;
0423 put_unaligned_be16(FC_FDMI_HBA_ATTR_BIOSVERSION,
0424 &entry->type);
0425 put_unaligned_be16(len, &entry->len);
0426 fc_ct_ms_fill_attr(entry,
0427 fc_host_bootbios_version(lport->host),
0428 FC_FDMI_HBA_ATTR_BIOSVERSION_LEN);
0429
0430
0431 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0432 FC_FDMI_HBA_ATTR_BIOSVERSION_LEN);
0433 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0434 len += FC_FDMI_HBA_ATTR_BIOSSTATE_LEN;
0435 put_unaligned_be16(FC_FDMI_HBA_ATTR_BIOSSTATE,
0436 &entry->type);
0437 put_unaligned_be16(len, &entry->len);
0438 put_unaligned_be32(fc_host_bootbios_state(lport->host),
0439 &entry->value);
0440
0441
0442 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0443 FC_FDMI_HBA_ATTR_BIOSSTATE_LEN);
0444 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0445 len += FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN;
0446 put_unaligned_be16(FC_FDMI_HBA_ATTR_VENDORIDENTIFIER,
0447 &entry->type);
0448 put_unaligned_be16(len, &entry->len);
0449 fc_ct_ms_fill_attr(entry,
0450 fc_host_vendor_identifier(lport->host),
0451 FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN);
0452 }
0453
0454 break;
0455 case FC_FDMI_RPA:
0456 numattrs = 6;
0457 len = sizeof(struct fc_fdmi_rpa);
0458 len -= sizeof(struct fc_fdmi_attr_entry);
0459 len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN);
0460 len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN;
0461 len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN;
0462 len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN;
0463 len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN;
0464 len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN;
0465 len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN;
0466
0467
0468 if (fc_host->fdmi_version == FDMI_V2) {
0469 numattrs += 10;
0470
0471 len += FC_FDMI_PORT_ATTR_NODENAME_LEN;
0472 len += FC_FDMI_PORT_ATTR_PORTNAME_LEN;
0473 len += FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN;
0474 len += FC_FDMI_PORT_ATTR_PORTTYPE_LEN;
0475 len += FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN;
0476 len += FC_FDMI_PORT_ATTR_FABRICNAME_LEN;
0477 len += FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN;
0478 len += FC_FDMI_PORT_ATTR_PORTSTATE_LEN;
0479 len += FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN;
0480 len += FC_FDMI_PORT_ATTR_PORTID_LEN;
0481
0482 }
0483
0484 ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
0485 FC_FDMI_SUBTYPE);
0486
0487
0488 put_unaligned_be64(lport->wwpn,
0489 &ct->payload.rpa.port.portname);
0490
0491
0492 put_unaligned_be32(numattrs,
0493 &ct->payload.rpa.hba_attrs.numattrs);
0494
0495 hba_attrs = &ct->payload.rpa.hba_attrs;
0496 entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr;
0497
0498
0499 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0500 len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN;
0501 put_unaligned_be16(FC_FDMI_PORT_ATTR_FC4TYPES,
0502 &entry->type);
0503 put_unaligned_be16(len, &entry->len);
0504 memcpy(&entry->value, fc_host_supported_fc4s(lport->host),
0505 FC_FDMI_PORT_ATTR_FC4TYPES_LEN);
0506
0507
0508 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0509 FC_FDMI_PORT_ATTR_FC4TYPES_LEN);
0510 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0511 len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN;
0512 put_unaligned_be16(FC_FDMI_PORT_ATTR_SUPPORTEDSPEED,
0513 &entry->type);
0514 put_unaligned_be16(len, &entry->len);
0515
0516 put_unaligned_be32(fc_host_supported_speeds(lport->host),
0517 &entry->value);
0518
0519
0520 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0521 FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN);
0522 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0523 len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN;
0524 put_unaligned_be16(FC_FDMI_PORT_ATTR_CURRENTPORTSPEED,
0525 &entry->type);
0526 put_unaligned_be16(len, &entry->len);
0527 put_unaligned_be32(lport->link_speed,
0528 &entry->value);
0529
0530
0531 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0532 FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN);
0533 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0534 len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN;
0535 put_unaligned_be16(FC_FDMI_PORT_ATTR_MAXFRAMESIZE,
0536 &entry->type);
0537 put_unaligned_be16(len, &entry->len);
0538 put_unaligned_be32(fc_host_maxframe_size(lport->host),
0539 &entry->value);
0540
0541
0542 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0543 FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN);
0544 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0545 len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN;
0546 put_unaligned_be16(FC_FDMI_PORT_ATTR_OSDEVICENAME,
0547 &entry->type);
0548 put_unaligned_be16(len, &entry->len);
0549
0550 fc_ct_ms_fill_attr(entry,
0551 dev_name(&lport->host->shost_gendev),
0552 strnlen(dev_name(&lport->host->shost_gendev),
0553 FC_FDMI_PORT_ATTR_HOSTNAME_LEN));
0554
0555
0556 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0557 FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN);
0558 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0559 len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN;
0560 put_unaligned_be16(FC_FDMI_PORT_ATTR_HOSTNAME,
0561 &entry->type);
0562 put_unaligned_be16(len, &entry->len);
0563 if (strlen(fc_host_system_hostname(lport->host)))
0564 fc_ct_ms_fill_attr(entry,
0565 fc_host_system_hostname(lport->host),
0566 strnlen(fc_host_system_hostname(lport->host),
0567 FC_FDMI_PORT_ATTR_HOSTNAME_LEN));
0568 else
0569 fc_ct_ms_fill_attr(entry,
0570 init_utsname()->nodename,
0571 FC_FDMI_PORT_ATTR_HOSTNAME_LEN);
0572
0573
0574 if (fc_host->fdmi_version == FDMI_V2) {
0575
0576
0577 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0578 FC_FDMI_PORT_ATTR_HOSTNAME_LEN);
0579 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0580 len += FC_FDMI_PORT_ATTR_NODENAME_LEN;
0581 put_unaligned_be16(FC_FDMI_PORT_ATTR_NODENAME,
0582 &entry->type);
0583 put_unaligned_be16(len, &entry->len);
0584 put_unaligned_be64(fc_host_node_name(lport->host),
0585 &entry->value);
0586
0587
0588 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0589 FC_FDMI_PORT_ATTR_NODENAME_LEN);
0590 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0591 len += FC_FDMI_PORT_ATTR_PORTNAME_LEN;
0592 put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTNAME,
0593 &entry->type);
0594 put_unaligned_be16(len, &entry->len);
0595 put_unaligned_be64(lport->wwpn,
0596 &entry->value);
0597
0598
0599 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0600 FC_FDMI_PORT_ATTR_PORTNAME_LEN);
0601 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0602 len += FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN;
0603 put_unaligned_be16(FC_FDMI_PORT_ATTR_SYMBOLICNAME,
0604 &entry->type);
0605 put_unaligned_be16(len, &entry->len);
0606 fc_ct_ms_fill_attr(entry,
0607 fc_host_symbolic_name(lport->host),
0608 FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN);
0609
0610
0611 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0612 FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN);
0613 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0614 len += FC_FDMI_PORT_ATTR_PORTTYPE_LEN;
0615 put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTTYPE,
0616 &entry->type);
0617 put_unaligned_be16(len, &entry->len);
0618 put_unaligned_be32(fc_host_port_type(lport->host),
0619 &entry->value);
0620
0621
0622 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0623 FC_FDMI_PORT_ATTR_PORTTYPE_LEN);
0624 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0625 len += FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN;
0626 put_unaligned_be16(FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC,
0627 &entry->type);
0628 put_unaligned_be16(len, &entry->len);
0629 put_unaligned_be32(fc_host_supported_classes(lport->host),
0630 &entry->value);
0631
0632
0633 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0634 FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN);
0635 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0636 len += FC_FDMI_PORT_ATTR_FABRICNAME_LEN;
0637 put_unaligned_be16(FC_FDMI_PORT_ATTR_FABRICNAME,
0638 &entry->type);
0639 put_unaligned_be16(len, &entry->len);
0640 put_unaligned_be64(fc_host_fabric_name(lport->host),
0641 &entry->value);
0642
0643
0644 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0645 FC_FDMI_PORT_ATTR_FABRICNAME_LEN);
0646 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0647 len += FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN;
0648 put_unaligned_be16(FC_FDMI_PORT_ATTR_CURRENTFC4TYPE,
0649 &entry->type);
0650 put_unaligned_be16(len, &entry->len);
0651 memcpy(&entry->value, fc_host_active_fc4s(lport->host),
0652 FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN);
0653
0654
0655 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0656 FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN);
0657 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0658 len += FC_FDMI_PORT_ATTR_PORTSTATE_LEN;
0659 put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTSTATE,
0660 &entry->type);
0661 put_unaligned_be16(len, &entry->len);
0662 put_unaligned_be32(fc_host_port_state(lport->host),
0663 &entry->value);
0664
0665
0666 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0667 FC_FDMI_PORT_ATTR_PORTSTATE_LEN);
0668 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0669 len += FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN;
0670 put_unaligned_be16(FC_FDMI_PORT_ATTR_DISCOVEREDPORTS,
0671 &entry->type);
0672 put_unaligned_be16(len, &entry->len);
0673 put_unaligned_be32(fc_host_num_discovered_ports(lport->host),
0674 &entry->value);
0675
0676
0677 entry = (struct fc_fdmi_attr_entry *)((char *)entry->value +
0678 FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN);
0679 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
0680 len += FC_FDMI_PORT_ATTR_PORTID_LEN;
0681 put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTID,
0682 &entry->type);
0683 put_unaligned_be16(len, &entry->len);
0684 put_unaligned_be32(fc_host_port_id(lport->host),
0685 &entry->value);
0686 }
0687
0688 break;
0689 case FC_FDMI_DPRT:
0690 len = sizeof(struct fc_fdmi_dprt);
0691 ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
0692 FC_FDMI_SUBTYPE);
0693
0694 put_unaligned_be64(lport->wwpn,
0695 &ct->payload.dprt.port.portname);
0696 break;
0697 case FC_FDMI_DHBA:
0698 len = sizeof(struct fc_fdmi_dhba);
0699 ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT,
0700 FC_FDMI_SUBTYPE);
0701
0702 put_unaligned_be64(lport->wwpn, &ct->payload.dhba.hbaid.id);
0703 break;
0704 default:
0705 return -EINVAL;
0706 }
0707 *r_ctl = FC_RCTL_DD_UNSOL_CTL;
0708 *fh_type = FC_TYPE_CT;
0709 return 0;
0710 }
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721 static inline int fc_ct_fill(struct fc_lport *lport,
0722 u32 fc_id, struct fc_frame *fp,
0723 unsigned int op, enum fc_rctl *r_ctl,
0724 enum fc_fh_type *fh_type, u32 *did)
0725 {
0726 int rc = -EINVAL;
0727
0728 switch (fc_id) {
0729 case FC_FID_MGMT_SERV:
0730 rc = fc_ct_ms_fill(lport, fc_id, fp, op, r_ctl, fh_type);
0731 *did = FC_FID_MGMT_SERV;
0732 break;
0733 case FC_FID_DIR_SERV:
0734 default:
0735 rc = fc_ct_ns_fill(lport, fc_id, fp, op, r_ctl, fh_type);
0736 *did = FC_FID_DIR_SERV;
0737 break;
0738 }
0739
0740 return rc;
0741 }
0742
0743
0744
0745 static inline void fc_plogi_fill(struct fc_lport *lport, struct fc_frame *fp,
0746 unsigned int op)
0747 {
0748 struct fc_els_flogi *plogi;
0749 struct fc_els_csp *csp;
0750 struct fc_els_cssp *cp;
0751
0752 plogi = fc_frame_payload_get(fp, sizeof(*plogi));
0753 memset(plogi, 0, sizeof(*plogi));
0754 plogi->fl_cmd = (u8) op;
0755 put_unaligned_be64(lport->wwpn, &plogi->fl_wwpn);
0756 put_unaligned_be64(lport->wwnn, &plogi->fl_wwnn);
0757
0758 csp = &plogi->fl_csp;
0759 csp->sp_hi_ver = 0x20;
0760 csp->sp_lo_ver = 0x20;
0761 csp->sp_bb_cred = htons(10);
0762 csp->sp_bb_data = htons((u16) lport->mfs);
0763 cp = &plogi->fl_cssp[3 - 1];
0764 cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
0765 csp->sp_features = htons(FC_SP_FT_CIRO);
0766 csp->sp_tot_seq = htons(255);
0767 csp->sp_rel_off = htons(0x1f);
0768 csp->sp_e_d_tov = htonl(lport->e_d_tov);
0769
0770 cp->cp_rdfs = htons((u16) lport->mfs);
0771 cp->cp_con_seq = htons(255);
0772 cp->cp_open_seq = 1;
0773 }
0774
0775
0776
0777
0778 static inline void fc_flogi_fill(struct fc_lport *lport, struct fc_frame *fp)
0779 {
0780 struct fc_els_csp *sp;
0781 struct fc_els_cssp *cp;
0782 struct fc_els_flogi *flogi;
0783
0784 flogi = fc_frame_payload_get(fp, sizeof(*flogi));
0785 memset(flogi, 0, sizeof(*flogi));
0786 flogi->fl_cmd = (u8) ELS_FLOGI;
0787 put_unaligned_be64(lport->wwpn, &flogi->fl_wwpn);
0788 put_unaligned_be64(lport->wwnn, &flogi->fl_wwnn);
0789 sp = &flogi->fl_csp;
0790 sp->sp_hi_ver = 0x20;
0791 sp->sp_lo_ver = 0x20;
0792 sp->sp_bb_cred = htons(10);
0793 sp->sp_bb_data = htons((u16) lport->mfs);
0794 cp = &flogi->fl_cssp[3 - 1];
0795 cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
0796 if (lport->does_npiv)
0797 sp->sp_features = htons(FC_SP_FT_NPIV);
0798 }
0799
0800
0801
0802
0803 static inline void fc_fdisc_fill(struct fc_lport *lport, struct fc_frame *fp)
0804 {
0805 struct fc_els_csp *sp;
0806 struct fc_els_cssp *cp;
0807 struct fc_els_flogi *fdisc;
0808
0809 fdisc = fc_frame_payload_get(fp, sizeof(*fdisc));
0810 memset(fdisc, 0, sizeof(*fdisc));
0811 fdisc->fl_cmd = (u8) ELS_FDISC;
0812 put_unaligned_be64(lport->wwpn, &fdisc->fl_wwpn);
0813 put_unaligned_be64(lport->wwnn, &fdisc->fl_wwnn);
0814 sp = &fdisc->fl_csp;
0815 sp->sp_hi_ver = 0x20;
0816 sp->sp_lo_ver = 0x20;
0817 sp->sp_bb_cred = htons(10);
0818 sp->sp_bb_data = htons((u16) lport->mfs);
0819 cp = &fdisc->fl_cssp[3 - 1];
0820 cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
0821 }
0822
0823
0824
0825
0826 static inline void fc_logo_fill(struct fc_lport *lport, struct fc_frame *fp)
0827 {
0828 struct fc_els_logo *logo;
0829
0830 logo = fc_frame_payload_get(fp, sizeof(*logo));
0831 memset(logo, 0, sizeof(*logo));
0832 logo->fl_cmd = ELS_LOGO;
0833 hton24(logo->fl_n_port_id, lport->port_id);
0834 logo->fl_n_port_wwn = htonll(lport->wwpn);
0835 }
0836
0837
0838
0839
0840 static inline void fc_rtv_fill(struct fc_lport *lport, struct fc_frame *fp)
0841 {
0842 struct fc_els_rtv *rtv;
0843
0844 rtv = fc_frame_payload_get(fp, sizeof(*rtv));
0845 memset(rtv, 0, sizeof(*rtv));
0846 rtv->rtv_cmd = ELS_RTV;
0847 }
0848
0849
0850
0851
0852 static inline void fc_rec_fill(struct fc_lport *lport, struct fc_frame *fp)
0853 {
0854 struct fc_els_rec *rec;
0855 struct fc_exch *ep = fc_seq_exch(fr_seq(fp));
0856
0857 rec = fc_frame_payload_get(fp, sizeof(*rec));
0858 memset(rec, 0, sizeof(*rec));
0859 rec->rec_cmd = ELS_REC;
0860 hton24(rec->rec_s_id, lport->port_id);
0861 rec->rec_ox_id = htons(ep->oxid);
0862 rec->rec_rx_id = htons(ep->rxid);
0863 }
0864
0865
0866
0867
0868 static inline void fc_prli_fill(struct fc_lport *lport, struct fc_frame *fp)
0869 {
0870 struct {
0871 struct fc_els_prli prli;
0872 struct fc_els_spp spp;
0873 } *pp;
0874
0875 pp = fc_frame_payload_get(fp, sizeof(*pp));
0876 memset(pp, 0, sizeof(*pp));
0877 pp->prli.prli_cmd = ELS_PRLI;
0878 pp->prli.prli_spp_len = sizeof(struct fc_els_spp);
0879 pp->prli.prli_len = htons(sizeof(*pp));
0880 pp->spp.spp_type = FC_TYPE_FCP;
0881 pp->spp.spp_flags = FC_SPP_EST_IMG_PAIR;
0882 pp->spp.spp_params = htonl(lport->service_params);
0883 }
0884
0885
0886
0887
0888 static inline void fc_scr_fill(struct fc_lport *lport, struct fc_frame *fp)
0889 {
0890 struct fc_els_scr *scr;
0891
0892 scr = fc_frame_payload_get(fp, sizeof(*scr));
0893 memset(scr, 0, sizeof(*scr));
0894 scr->scr_cmd = ELS_SCR;
0895 scr->scr_reg_func = ELS_SCRF_FULL;
0896 }
0897
0898
0899
0900
0901 static inline int fc_els_fill(struct fc_lport *lport,
0902 u32 did,
0903 struct fc_frame *fp, unsigned int op,
0904 enum fc_rctl *r_ctl, enum fc_fh_type *fh_type)
0905 {
0906 switch (op) {
0907 case ELS_ADISC:
0908 fc_adisc_fill(lport, fp);
0909 break;
0910
0911 case ELS_PLOGI:
0912 fc_plogi_fill(lport, fp, ELS_PLOGI);
0913 break;
0914
0915 case ELS_FLOGI:
0916 fc_flogi_fill(lport, fp);
0917 break;
0918
0919 case ELS_FDISC:
0920 fc_fdisc_fill(lport, fp);
0921 break;
0922
0923 case ELS_LOGO:
0924 fc_logo_fill(lport, fp);
0925 break;
0926
0927 case ELS_RTV:
0928 fc_rtv_fill(lport, fp);
0929 break;
0930
0931 case ELS_REC:
0932 fc_rec_fill(lport, fp);
0933 break;
0934
0935 case ELS_PRLI:
0936 fc_prli_fill(lport, fp);
0937 break;
0938
0939 case ELS_SCR:
0940 fc_scr_fill(lport, fp);
0941 break;
0942
0943 default:
0944 return -EINVAL;
0945 }
0946
0947 *r_ctl = FC_RCTL_ELS_REQ;
0948 *fh_type = FC_TYPE_ELS;
0949 return 0;
0950 }
0951 #endif