1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc. 4 * Copyright (c) 2014- QLogic Corporation. 5 * All rights reserved 6 * www.qlogic.com 7 * 8 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter. 9 */ 10 /* 11 * fcbuild.c - FC link service frame building and parsing routines 12 */ 13 14 #include "bfad_drv.h" 15 #include "bfa_fcbuild.h" 16 17 /* 18 * static build functions 19 */ 20 static void fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, 21 __be16 ox_id); 22 static void fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, 23 __be16 ox_id); 24 static struct fchs_s fc_els_req_tmpl; 25 static struct fchs_s fc_els_rsp_tmpl; 26 static struct fchs_s fc_bls_req_tmpl; 27 static struct fchs_s fc_bls_rsp_tmpl; 28 static struct fc_ba_acc_s ba_acc_tmpl; 29 static struct fc_logi_s plogi_tmpl; 30 static struct fc_prli_s prli_tmpl; 31 static struct fc_rrq_s rrq_tmpl; 32 static struct fchs_s fcp_fchs_tmpl; 33 34 void 35 fcbuild_init(void) 36 { 37 /* 38 * fc_els_req_tmpl 39 */ 40 fc_els_req_tmpl.routing = FC_RTG_EXT_LINK; 41 fc_els_req_tmpl.cat_info = FC_CAT_LD_REQUEST; 42 fc_els_req_tmpl.type = FC_TYPE_ELS; 43 fc_els_req_tmpl.f_ctl = 44 bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ | 45 FCTL_SI_XFER); 46 fc_els_req_tmpl.rx_id = FC_RXID_ANY; 47 48 /* 49 * fc_els_rsp_tmpl 50 */ 51 fc_els_rsp_tmpl.routing = FC_RTG_EXT_LINK; 52 fc_els_rsp_tmpl.cat_info = FC_CAT_LD_REPLY; 53 fc_els_rsp_tmpl.type = FC_TYPE_ELS; 54 fc_els_rsp_tmpl.f_ctl = 55 bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH | 56 FCTL_END_SEQ | FCTL_SI_XFER); 57 fc_els_rsp_tmpl.rx_id = FC_RXID_ANY; 58 59 /* 60 * fc_bls_req_tmpl 61 */ 62 fc_bls_req_tmpl.routing = FC_RTG_BASIC_LINK; 63 fc_bls_req_tmpl.type = FC_TYPE_BLS; 64 fc_bls_req_tmpl.f_ctl = bfa_hton3b(FCTL_END_SEQ | FCTL_SI_XFER); 65 fc_bls_req_tmpl.rx_id = FC_RXID_ANY; 66 67 /* 68 * fc_bls_rsp_tmpl 69 */ 70 fc_bls_rsp_tmpl.routing = FC_RTG_BASIC_LINK; 71 fc_bls_rsp_tmpl.cat_info = FC_CAT_BA_ACC; 72 fc_bls_rsp_tmpl.type = FC_TYPE_BLS; 73 fc_bls_rsp_tmpl.f_ctl = 74 bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH | 75 FCTL_END_SEQ | FCTL_SI_XFER); 76 fc_bls_rsp_tmpl.rx_id = FC_RXID_ANY; 77 78 /* 79 * ba_acc_tmpl 80 */ 81 ba_acc_tmpl.seq_id_valid = 0; 82 ba_acc_tmpl.low_seq_cnt = 0; 83 ba_acc_tmpl.high_seq_cnt = 0xFFFF; 84 85 /* 86 * plogi_tmpl 87 */ 88 plogi_tmpl.csp.verhi = FC_PH_VER_PH_3; 89 plogi_tmpl.csp.verlo = FC_PH_VER_4_3; 90 plogi_tmpl.csp.ciro = 0x1; 91 plogi_tmpl.csp.cisc = 0x0; 92 plogi_tmpl.csp.altbbcred = 0x0; 93 plogi_tmpl.csp.conseq = cpu_to_be16(0x00FF); 94 plogi_tmpl.csp.ro_bitmap = cpu_to_be16(0x0002); 95 plogi_tmpl.csp.e_d_tov = cpu_to_be32(2000); 96 97 plogi_tmpl.class3.class_valid = 1; 98 plogi_tmpl.class3.sequential = 1; 99 plogi_tmpl.class3.conseq = 0xFF; 100 plogi_tmpl.class3.ospx = 1; 101 102 /* 103 * prli_tmpl 104 */ 105 prli_tmpl.command = FC_ELS_PRLI; 106 prli_tmpl.pglen = 0x10; 107 prli_tmpl.pagebytes = cpu_to_be16(0x0014); 108 prli_tmpl.parampage.type = FC_TYPE_FCP; 109 prli_tmpl.parampage.imagepair = 1; 110 prli_tmpl.parampage.servparams.rxrdisab = 1; 111 112 /* 113 * rrq_tmpl 114 */ 115 rrq_tmpl.els_cmd.els_code = FC_ELS_RRQ; 116 117 /* 118 * fcp_struct fchs_s mpl 119 */ 120 fcp_fchs_tmpl.routing = FC_RTG_FC4_DEV_DATA; 121 fcp_fchs_tmpl.cat_info = FC_CAT_UNSOLICIT_CMD; 122 fcp_fchs_tmpl.type = FC_TYPE_FCP; 123 fcp_fchs_tmpl.f_ctl = 124 bfa_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER); 125 fcp_fchs_tmpl.seq_id = 1; 126 fcp_fchs_tmpl.rx_id = FC_RXID_ANY; 127 } 128 129 static void 130 fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id) 131 { 132 memset(fchs, 0, sizeof(struct fchs_s)); 133 134 fchs->routing = FC_RTG_FC4_DEV_DATA; 135 fchs->cat_info = FC_CAT_UNSOLICIT_CTRL; 136 fchs->type = FC_TYPE_SERVICES; 137 fchs->f_ctl = 138 bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ | 139 FCTL_SI_XFER); 140 fchs->rx_id = FC_RXID_ANY; 141 fchs->d_id = (d_id); 142 fchs->s_id = (s_id); 143 fchs->ox_id = cpu_to_be16(ox_id); 144 145 /* 146 * @todo no need to set ox_id for request 147 * no need to set rx_id for response 148 */ 149 } 150 151 static void 152 fc_gsresp_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id) 153 { 154 memset(fchs, 0, sizeof(struct fchs_s)); 155 156 fchs->routing = FC_RTG_FC4_DEV_DATA; 157 fchs->cat_info = FC_CAT_SOLICIT_CTRL; 158 fchs->type = FC_TYPE_SERVICES; 159 fchs->f_ctl = 160 bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH | 161 FCTL_END_SEQ | FCTL_SI_XFER); 162 fchs->d_id = d_id; 163 fchs->s_id = s_id; 164 fchs->ox_id = ox_id; 165 } 166 167 void 168 fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id) 169 { 170 memcpy(fchs, &fc_els_req_tmpl, sizeof(struct fchs_s)); 171 fchs->d_id = (d_id); 172 fchs->s_id = (s_id); 173 fchs->ox_id = cpu_to_be16(ox_id); 174 } 175 176 static void 177 fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id) 178 { 179 memcpy(fchs, &fc_els_rsp_tmpl, sizeof(struct fchs_s)); 180 fchs->d_id = d_id; 181 fchs->s_id = s_id; 182 fchs->ox_id = ox_id; 183 } 184 185 static void 186 fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id) 187 { 188 memcpy(fchs, &fc_bls_rsp_tmpl, sizeof(struct fchs_s)); 189 fchs->d_id = d_id; 190 fchs->s_id = s_id; 191 fchs->ox_id = ox_id; 192 } 193 194 static u16 195 fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, 196 __be16 ox_id, wwn_t port_name, wwn_t node_name, 197 u16 pdu_size, u16 bb_cr, u8 els_code) 198 { 199 struct fc_logi_s *plogi = (struct fc_logi_s *) (pld); 200 201 memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s)); 202 203 /* For FC AL bb_cr is 0 and altbbcred is 1 */ 204 if (!bb_cr) 205 plogi->csp.altbbcred = 1; 206 207 plogi->els_cmd.els_code = els_code; 208 if (els_code == FC_ELS_PLOGI) 209 fc_els_req_build(fchs, d_id, s_id, ox_id); 210 else 211 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 212 213 plogi->csp.rxsz = plogi->class3.rxsz = cpu_to_be16(pdu_size); 214 plogi->csp.bbcred = cpu_to_be16(bb_cr); 215 216 memcpy(&plogi->port_name, &port_name, sizeof(wwn_t)); 217 memcpy(&plogi->node_name, &node_name, sizeof(wwn_t)); 218 219 return sizeof(struct fc_logi_s); 220 } 221 222 u16 223 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id, 224 __be16 ox_id, wwn_t port_name, wwn_t node_name, 225 u16 pdu_size, u16 local_bb_credits, u8 bb_scn) 226 { 227 u32 d_id = 0; 228 u16 bbscn_rxsz = (bb_scn << 12) | pdu_size; 229 230 memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s)); 231 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 232 233 flogi->els_cmd.els_code = FC_ELS_ACC; 234 flogi->class3.rxsz = cpu_to_be16(pdu_size); 235 flogi->csp.rxsz = cpu_to_be16(bbscn_rxsz); /* bb_scn/rxsz */ 236 flogi->port_name = port_name; 237 flogi->node_name = node_name; 238 239 flogi->csp.bbcred = cpu_to_be16(local_bb_credits); 240 241 return sizeof(struct fc_logi_s); 242 } 243 244 u16 245 fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, 246 u16 ox_id, wwn_t port_name, wwn_t node_name, 247 u16 pdu_size, u16 bb_cr) 248 { 249 return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name, 250 node_name, pdu_size, bb_cr, FC_ELS_PLOGI); 251 } 252 253 u16 254 fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, 255 u16 ox_id, wwn_t port_name, wwn_t node_name, 256 u16 pdu_size, u16 bb_cr) 257 { 258 return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name, 259 node_name, pdu_size, bb_cr, FC_ELS_ACC); 260 } 261 262 enum fc_parse_status 263 fc_plogi_parse(struct fchs_s *fchs) 264 { 265 struct fc_logi_s *plogi = (struct fc_logi_s *) (fchs + 1); 266 267 if (plogi->class3.class_valid != 1) 268 return FC_PARSE_FAILURE; 269 270 if ((be16_to_cpu(plogi->class3.rxsz) < FC_MIN_PDUSZ) 271 || (be16_to_cpu(plogi->class3.rxsz) > FC_MAX_PDUSZ) 272 || (plogi->class3.rxsz == 0)) 273 return FC_PARSE_FAILURE; 274 275 return FC_PARSE_OK; 276 } 277 278 u16 279 fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, 280 u16 ox_id) 281 { 282 struct fc_prli_s *prli = (struct fc_prli_s *) (pld); 283 284 fc_els_req_build(fchs, d_id, s_id, ox_id); 285 memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s)); 286 287 prli->command = FC_ELS_PRLI; 288 prli->parampage.servparams.initiator = 1; 289 prli->parampage.servparams.retry = 1; 290 prli->parampage.servparams.rec_support = 1; 291 prli->parampage.servparams.task_retry_id = 0; 292 prli->parampage.servparams.confirm = 1; 293 294 return sizeof(struct fc_prli_s); 295 } 296 297 u16 298 fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, 299 __be16 ox_id, enum bfa_lport_role role) 300 { 301 struct fc_prli_s *prli = (struct fc_prli_s *) (pld); 302 303 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 304 memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s)); 305 306 prli->command = FC_ELS_ACC; 307 308 prli->parampage.servparams.initiator = 1; 309 310 prli->parampage.rspcode = FC_PRLI_ACC_XQTD; 311 312 return sizeof(struct fc_prli_s); 313 } 314 315 enum fc_parse_status 316 fc_prli_rsp_parse(struct fc_prli_s *prli, int len) 317 { 318 if (len < sizeof(struct fc_prli_s)) 319 return FC_PARSE_FAILURE; 320 321 if (prli->command != FC_ELS_ACC) 322 return FC_PARSE_FAILURE; 323 324 if ((prli->parampage.rspcode != FC_PRLI_ACC_XQTD) 325 && (prli->parampage.rspcode != FC_PRLI_ACC_PREDEF_IMG)) 326 return FC_PARSE_FAILURE; 327 328 if (prli->parampage.servparams.target != 1) 329 return FC_PARSE_FAILURE; 330 331 return FC_PARSE_OK; 332 } 333 334 u16 335 fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id, u32 s_id, 336 u16 ox_id, wwn_t port_name) 337 { 338 fc_els_req_build(fchs, d_id, s_id, ox_id); 339 340 memset(logo, '\0', sizeof(struct fc_logo_s)); 341 logo->els_cmd.els_code = FC_ELS_LOGO; 342 logo->nport_id = (s_id); 343 logo->orig_port_name = port_name; 344 345 return sizeof(struct fc_logo_s); 346 } 347 348 static u16 349 fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, 350 u32 s_id, __be16 ox_id, wwn_t port_name, 351 wwn_t node_name, u8 els_code) 352 { 353 memset(adisc, '\0', sizeof(struct fc_adisc_s)); 354 355 adisc->els_cmd.els_code = els_code; 356 357 if (els_code == FC_ELS_ADISC) 358 fc_els_req_build(fchs, d_id, s_id, ox_id); 359 else 360 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 361 362 adisc->orig_HA = 0; 363 adisc->orig_port_name = port_name; 364 adisc->orig_node_name = node_name; 365 adisc->nport_id = (s_id); 366 367 return sizeof(struct fc_adisc_s); 368 } 369 370 u16 371 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, 372 u32 s_id, __be16 ox_id, wwn_t port_name, wwn_t node_name) 373 { 374 return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name, 375 node_name, FC_ELS_ADISC); 376 } 377 378 u16 379 fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, 380 u32 s_id, __be16 ox_id, wwn_t port_name, 381 wwn_t node_name) 382 { 383 return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name, 384 node_name, FC_ELS_ACC); 385 } 386 387 enum fc_parse_status 388 fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len, wwn_t port_name, 389 wwn_t node_name) 390 { 391 392 if (len < sizeof(struct fc_adisc_s)) 393 return FC_PARSE_FAILURE; 394 395 if (adisc->els_cmd.els_code != FC_ELS_ACC) 396 return FC_PARSE_FAILURE; 397 398 if (!wwn_is_equal(adisc->orig_port_name, port_name)) 399 return FC_PARSE_FAILURE; 400 401 return FC_PARSE_OK; 402 } 403 404 u16 405 fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, 406 __be16 ox_id) 407 { 408 struct fc_els_cmd_s *acc = pld; 409 410 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 411 412 memset(acc, 0, sizeof(struct fc_els_cmd_s)); 413 acc->els_code = FC_ELS_ACC; 414 415 return sizeof(struct fc_els_cmd_s); 416 } 417 418 u16 419 fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id, 420 u32 s_id, __be16 ox_id, u8 reason_code, 421 u8 reason_code_expl) 422 { 423 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 424 memset(ls_rjt, 0, sizeof(struct fc_ls_rjt_s)); 425 426 ls_rjt->els_cmd.els_code = FC_ELS_LS_RJT; 427 ls_rjt->reason_code = reason_code; 428 ls_rjt->reason_code_expl = reason_code_expl; 429 ls_rjt->vendor_unique = 0x00; 430 431 return sizeof(struct fc_ls_rjt_s); 432 } 433 434 u16 435 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id, 436 u32 s_id, __be16 ox_id, u16 rx_id) 437 { 438 fc_bls_rsp_build(fchs, d_id, s_id, ox_id); 439 440 memcpy(ba_acc, &ba_acc_tmpl, sizeof(struct fc_ba_acc_s)); 441 442 fchs->rx_id = rx_id; 443 444 ba_acc->ox_id = fchs->ox_id; 445 ba_acc->rx_id = fchs->rx_id; 446 447 return sizeof(struct fc_ba_acc_s); 448 } 449 450 u16 451 fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, u32 d_id, 452 u32 s_id, __be16 ox_id) 453 { 454 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 455 memset(els_cmd, 0, sizeof(struct fc_els_cmd_s)); 456 els_cmd->els_code = FC_ELS_ACC; 457 458 return sizeof(struct fc_els_cmd_s); 459 } 460 461 int 462 fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code) 463 { 464 int num_pages = 0; 465 struct fc_prlo_s *prlo; 466 struct fc_tprlo_s *tprlo; 467 468 if (els_code == FC_ELS_PRLO) { 469 prlo = (struct fc_prlo_s *) (fc_frame + 1); 470 num_pages = (be16_to_cpu(prlo->payload_len) - 4) / 16; 471 } else { 472 tprlo = (struct fc_tprlo_s *) (fc_frame + 1); 473 num_pages = (be16_to_cpu(tprlo->payload_len) - 4) / 16; 474 } 475 return num_pages; 476 } 477 478 u16 479 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, u32 d_id, 480 u32 s_id, __be16 ox_id, int num_pages) 481 { 482 int page; 483 484 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 485 486 memset(prlo_acc, 0, (num_pages * 16) + 4); 487 prlo_acc->command = FC_ELS_ACC; 488 prlo_acc->page_len = 0x10; 489 prlo_acc->payload_len = cpu_to_be16((num_pages * 16) + 4); 490 491 for (page = 0; page < num_pages; page++) { 492 prlo_acc->prlo_acc_params[page].opa_valid = 0; 493 prlo_acc->prlo_acc_params[page].rpa_valid = 0; 494 prlo_acc->prlo_acc_params[page].fc4type_csp = FC_TYPE_FCP; 495 prlo_acc->prlo_acc_params[page].orig_process_assc = 0; 496 prlo_acc->prlo_acc_params[page].resp_process_assc = 0; 497 } 498 499 return be16_to_cpu(prlo_acc->payload_len); 500 } 501 502 u16 503 fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, u32 d_id, 504 u32 s_id, __be16 ox_id, u32 data_format, 505 struct fc_rnid_common_id_data_s *common_id_data, 506 struct fc_rnid_general_topology_data_s *gen_topo_data) 507 { 508 memset(rnid_acc, 0, sizeof(struct fc_rnid_acc_s)); 509 510 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 511 512 rnid_acc->els_cmd.els_code = FC_ELS_ACC; 513 rnid_acc->node_id_data_format = data_format; 514 rnid_acc->common_id_data_length = 515 sizeof(struct fc_rnid_common_id_data_s); 516 rnid_acc->common_id_data = *common_id_data; 517 518 if (data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) { 519 rnid_acc->specific_id_data_length = 520 sizeof(struct fc_rnid_general_topology_data_s); 521 rnid_acc->gen_topology_data = *gen_topo_data; 522 return sizeof(struct fc_rnid_acc_s); 523 } else { 524 return sizeof(struct fc_rnid_acc_s) - 525 sizeof(struct fc_rnid_general_topology_data_s); 526 } 527 528 } 529 530 u16 531 fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, u32 d_id, 532 u32 s_id, u32 *pid_list, u16 npids) 533 { 534 u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_hton3b(d_id)); 535 int i = 0; 536 537 fc_els_req_build(fchs, bfa_hton3b(dctlr_id), s_id, 0); 538 539 memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s)); 540 541 rpsc2->els_cmd.els_code = FC_ELS_RPSC; 542 rpsc2->token = cpu_to_be32(FC_BRCD_TOKEN); 543 rpsc2->num_pids = cpu_to_be16(npids); 544 for (i = 0; i < npids; i++) 545 rpsc2->pid_list[i].pid = pid_list[i]; 546 547 return sizeof(struct fc_rpsc2_cmd_s) + ((npids - 1) * (sizeof(u32))); 548 } 549 550 u16 551 fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc, 552 u32 d_id, u32 s_id, __be16 ox_id, 553 struct fc_rpsc_speed_info_s *oper_speed) 554 { 555 memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s)); 556 557 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 558 559 rpsc_acc->command = FC_ELS_ACC; 560 rpsc_acc->num_entries = cpu_to_be16(1); 561 562 rpsc_acc->speed_info[0].port_speed_cap = 563 cpu_to_be16(oper_speed->port_speed_cap); 564 565 rpsc_acc->speed_info[0].port_op_speed = 566 cpu_to_be16(oper_speed->port_op_speed); 567 568 return sizeof(struct fc_rpsc_acc_s); 569 } 570 571 static void 572 fc_gs_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code) 573 { 574 memset(cthdr, 0, sizeof(struct ct_hdr_s)); 575 cthdr->rev_id = CT_GS3_REVISION; 576 cthdr->gs_type = CT_GSTYPE_DIRSERVICE; 577 cthdr->gs_sub_type = CT_GSSUBTYPE_NAMESERVER; 578 cthdr->cmd_rsp_code = cpu_to_be16(cmd_code); 579 } 580 581 static void 582 fc_gs_fdmi_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code) 583 { 584 memset(cthdr, 0, sizeof(struct ct_hdr_s)); 585 cthdr->rev_id = CT_GS3_REVISION; 586 cthdr->gs_type = CT_GSTYPE_MGMTSERVICE; 587 cthdr->gs_sub_type = CT_GSSUBTYPE_HBA_MGMTSERVER; 588 cthdr->cmd_rsp_code = cpu_to_be16(cmd_code); 589 } 590 591 static void 592 fc_gs_ms_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code, 593 u8 sub_type) 594 { 595 memset(cthdr, 0, sizeof(struct ct_hdr_s)); 596 cthdr->rev_id = CT_GS3_REVISION; 597 cthdr->gs_type = CT_GSTYPE_MGMTSERVICE; 598 cthdr->gs_sub_type = sub_type; 599 cthdr->cmd_rsp_code = cpu_to_be16(cmd_code); 600 } 601 602 u16 603 fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, 604 wwn_t port_name) 605 { 606 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 607 struct fcgs_gidpn_req_s *gidpn = (struct fcgs_gidpn_req_s *)(cthdr + 1); 608 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 609 610 fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); 611 fc_gs_cthdr_build(cthdr, s_id, GS_GID_PN); 612 613 memset(gidpn, 0, sizeof(struct fcgs_gidpn_req_s)); 614 gidpn->port_name = port_name; 615 return sizeof(struct fcgs_gidpn_req_s) + sizeof(struct ct_hdr_s); 616 } 617 618 u16 619 fc_gpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, 620 u32 port_id) 621 { 622 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 623 fcgs_gpnid_req_t *gpnid = (fcgs_gpnid_req_t *) (cthdr + 1); 624 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 625 626 fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); 627 fc_gs_cthdr_build(cthdr, s_id, GS_GPN_ID); 628 629 memset(gpnid, 0, sizeof(fcgs_gpnid_req_t)); 630 gpnid->dap = port_id; 631 return sizeof(fcgs_gpnid_req_t) + sizeof(struct ct_hdr_s); 632 } 633 634 u16 635 fc_gs_rjt_build(struct fchs_s *fchs, struct ct_hdr_s *cthdr, 636 u32 d_id, u32 s_id, u16 ox_id, u8 reason_code, 637 u8 reason_code_expl) 638 { 639 fc_gsresp_fchdr_build(fchs, d_id, s_id, ox_id); 640 641 cthdr->cmd_rsp_code = cpu_to_be16(CT_RSP_REJECT); 642 cthdr->rev_id = CT_GS3_REVISION; 643 644 cthdr->reason_code = reason_code; 645 cthdr->exp_code = reason_code_expl; 646 return sizeof(struct ct_hdr_s); 647 } 648 649 u16 650 fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr, 651 u8 set_br_reg, u32 s_id, u16 ox_id) 652 { 653 u32 d_id = bfa_hton3b(FC_FABRIC_CONTROLLER); 654 655 fc_els_req_build(fchs, d_id, s_id, ox_id); 656 657 memset(scr, 0, sizeof(struct fc_scr_s)); 658 scr->command = FC_ELS_SCR; 659 scr->reg_func = FC_SCR_REG_FUNC_FULL; 660 if (set_br_reg) 661 scr->vu_reg_func = FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE; 662 663 return sizeof(struct fc_scr_s); 664 } 665 666 u16 667 fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, 668 enum bfa_lport_role roles) 669 { 670 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 671 struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1); 672 u32 type_value, d_id = bfa_hton3b(FC_NAME_SERVER); 673 u8 index; 674 675 fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); 676 fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID); 677 678 memset(rftid, 0, sizeof(struct fcgs_rftid_req_s)); 679 680 rftid->dap = s_id; 681 682 /* By default, FCP FC4 Type is registered */ 683 index = FC_TYPE_FCP >> 5; 684 type_value = 1 << (FC_TYPE_FCP % 32); 685 rftid->fc4_type[index] = cpu_to_be32(type_value); 686 687 return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s); 688 } 689 690 u16 691 fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, 692 u8 fc4_type, u8 fc4_ftrs) 693 { 694 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 695 struct fcgs_rffid_req_s *rffid = (struct fcgs_rffid_req_s *)(cthdr + 1); 696 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 697 698 fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); 699 fc_gs_cthdr_build(cthdr, s_id, GS_RFF_ID); 700 701 memset(rffid, 0, sizeof(struct fcgs_rffid_req_s)); 702 703 rffid->dap = s_id; 704 rffid->fc4ftr_bits = fc4_ftrs; 705 rffid->fc4_type = fc4_type; 706 707 return sizeof(struct fcgs_rffid_req_s) + sizeof(struct ct_hdr_s); 708 } 709 710 u16 711 fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, 712 u8 *name) 713 { 714 715 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 716 struct fcgs_rspnid_req_s *rspnid = 717 (struct fcgs_rspnid_req_s *)(cthdr + 1); 718 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 719 720 fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); 721 fc_gs_cthdr_build(cthdr, s_id, GS_RSPN_ID); 722 723 memset(rspnid, 0, sizeof(struct fcgs_rspnid_req_s)); 724 725 rspnid->dap = s_id; 726 strscpy(rspnid->spn, name, sizeof(rspnid->spn)); 727 rspnid->spn_len = (u8) strlen(rspnid->spn); 728 729 return sizeof(struct fcgs_rspnid_req_s) + sizeof(struct ct_hdr_s); 730 } 731 732 u16 733 fc_rsnn_nn_build(struct fchs_s *fchs, void *pyld, u32 s_id, 734 wwn_t node_name, u8 *name) 735 { 736 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 737 struct fcgs_rsnn_nn_req_s *rsnn_nn = 738 (struct fcgs_rsnn_nn_req_s *) (cthdr + 1); 739 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 740 741 fc_gs_fchdr_build(fchs, d_id, s_id, 0); 742 fc_gs_cthdr_build(cthdr, s_id, GS_RSNN_NN); 743 744 memset(rsnn_nn, 0, sizeof(struct fcgs_rsnn_nn_req_s)); 745 746 rsnn_nn->node_name = node_name; 747 strscpy(rsnn_nn->snn, name, sizeof(rsnn_nn->snn)); 748 rsnn_nn->snn_len = (u8) strlen(rsnn_nn->snn); 749 750 return sizeof(struct fcgs_rsnn_nn_req_s) + sizeof(struct ct_hdr_s); 751 } 752 753 u16 754 fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, u8 fc4_type) 755 { 756 757 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 758 struct fcgs_gidft_req_s *gidft = (struct fcgs_gidft_req_s *)(cthdr + 1); 759 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 760 761 fc_gs_fchdr_build(fchs, d_id, s_id, 0); 762 763 fc_gs_cthdr_build(cthdr, s_id, GS_GID_FT); 764 765 memset(gidft, 0, sizeof(struct fcgs_gidft_req_s)); 766 gidft->fc4_type = fc4_type; 767 gidft->domain_id = 0; 768 gidft->area_id = 0; 769 770 return sizeof(struct fcgs_gidft_req_s) + sizeof(struct ct_hdr_s); 771 } 772 773 u16 774 fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id, 775 wwn_t node_name) 776 { 777 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 778 struct fcgs_rnnid_req_s *rnnid = (struct fcgs_rnnid_req_s *)(cthdr + 1); 779 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 780 781 fc_gs_fchdr_build(fchs, d_id, s_id, 0); 782 fc_gs_cthdr_build(cthdr, s_id, GS_RNN_ID); 783 784 memset(rnnid, 0, sizeof(struct fcgs_rnnid_req_s)); 785 rnnid->port_id = port_id; 786 rnnid->node_name = node_name; 787 788 return sizeof(struct fcgs_rnnid_req_s) + sizeof(struct ct_hdr_s); 789 } 790 791 /* 792 * Builds fc hdr and ct hdr for FDMI requests. 793 */ 794 u16 795 fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id, 796 u16 cmd_code) 797 { 798 799 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 800 u32 d_id = bfa_hton3b(FC_MGMT_SERVER); 801 802 fc_gs_fchdr_build(fchs, d_id, s_id, 0); 803 fc_gs_fdmi_cthdr_build(cthdr, s_id, cmd_code); 804 805 return sizeof(struct ct_hdr_s); 806 } 807 808 /* 809 * Given a FC4 Type, this function returns a fc4 type bitmask 810 */ 811 void 812 fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask) 813 { 814 u8 index; 815 __be32 *ptr = (__be32 *) bit_mask; 816 u32 type_value; 817 818 /* 819 * @todo : Check for bitmask size 820 */ 821 822 index = fc4_type >> 5; 823 type_value = 1 << (fc4_type % 32); 824 ptr[index] = cpu_to_be32(type_value); 825 826 } 827 828 /* 829 * GMAL Request 830 */ 831 u16 832 fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn) 833 { 834 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 835 fcgs_gmal_req_t *gmal = (fcgs_gmal_req_t *) (cthdr + 1); 836 u32 d_id = bfa_hton3b(FC_MGMT_SERVER); 837 838 fc_gs_fchdr_build(fchs, d_id, s_id, 0); 839 fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GMAL_CMD, 840 CT_GSSUBTYPE_CFGSERVER); 841 842 memset(gmal, 0, sizeof(fcgs_gmal_req_t)); 843 gmal->wwn = wwn; 844 845 return sizeof(struct ct_hdr_s) + sizeof(fcgs_gmal_req_t); 846 } 847 848 /* 849 * GFN (Get Fabric Name) Request 850 */ 851 u16 852 fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn) 853 { 854 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 855 fcgs_gfn_req_t *gfn = (fcgs_gfn_req_t *) (cthdr + 1); 856 u32 d_id = bfa_hton3b(FC_MGMT_SERVER); 857 858 fc_gs_fchdr_build(fchs, d_id, s_id, 0); 859 fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GFN_CMD, 860 CT_GSSUBTYPE_CFGSERVER); 861 862 memset(gfn, 0, sizeof(fcgs_gfn_req_t)); 863 gfn->wwn = wwn; 864 865 return sizeof(struct ct_hdr_s) + sizeof(fcgs_gfn_req_t); 866 } 867