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