1 /* 2 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc. 3 * Copyright (c) 2014- QLogic Corporation. 4 * All rights reserved 5 * www.qlogic.com 6 * 7 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter. 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License (GPL) Version 2 as 11 * published by the Free Software Foundation 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 */ 18 /* 19 * fcbuild.c - FC link service frame building and parsing routines 20 */ 21 22 #include "bfad_drv.h" 23 #include "bfa_fcbuild.h" 24 25 /* 26 * static build functions 27 */ 28 static void fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, 29 __be16 ox_id); 30 static void fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, 31 __be16 ox_id); 32 static struct fchs_s fc_els_req_tmpl; 33 static struct fchs_s fc_els_rsp_tmpl; 34 static struct fchs_s fc_bls_req_tmpl; 35 static struct fchs_s fc_bls_rsp_tmpl; 36 static struct fc_ba_acc_s ba_acc_tmpl; 37 static struct fc_logi_s plogi_tmpl; 38 static struct fc_prli_s prli_tmpl; 39 static struct fc_rrq_s rrq_tmpl; 40 static struct fchs_s fcp_fchs_tmpl; 41 42 void 43 fcbuild_init(void) 44 { 45 /* 46 * fc_els_req_tmpl 47 */ 48 fc_els_req_tmpl.routing = FC_RTG_EXT_LINK; 49 fc_els_req_tmpl.cat_info = FC_CAT_LD_REQUEST; 50 fc_els_req_tmpl.type = FC_TYPE_ELS; 51 fc_els_req_tmpl.f_ctl = 52 bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ | 53 FCTL_SI_XFER); 54 fc_els_req_tmpl.rx_id = FC_RXID_ANY; 55 56 /* 57 * fc_els_rsp_tmpl 58 */ 59 fc_els_rsp_tmpl.routing = FC_RTG_EXT_LINK; 60 fc_els_rsp_tmpl.cat_info = FC_CAT_LD_REPLY; 61 fc_els_rsp_tmpl.type = FC_TYPE_ELS; 62 fc_els_rsp_tmpl.f_ctl = 63 bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH | 64 FCTL_END_SEQ | FCTL_SI_XFER); 65 fc_els_rsp_tmpl.rx_id = FC_RXID_ANY; 66 67 /* 68 * fc_bls_req_tmpl 69 */ 70 fc_bls_req_tmpl.routing = FC_RTG_BASIC_LINK; 71 fc_bls_req_tmpl.type = FC_TYPE_BLS; 72 fc_bls_req_tmpl.f_ctl = bfa_hton3b(FCTL_END_SEQ | FCTL_SI_XFER); 73 fc_bls_req_tmpl.rx_id = FC_RXID_ANY; 74 75 /* 76 * fc_bls_rsp_tmpl 77 */ 78 fc_bls_rsp_tmpl.routing = FC_RTG_BASIC_LINK; 79 fc_bls_rsp_tmpl.cat_info = FC_CAT_BA_ACC; 80 fc_bls_rsp_tmpl.type = FC_TYPE_BLS; 81 fc_bls_rsp_tmpl.f_ctl = 82 bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH | 83 FCTL_END_SEQ | FCTL_SI_XFER); 84 fc_bls_rsp_tmpl.rx_id = FC_RXID_ANY; 85 86 /* 87 * ba_acc_tmpl 88 */ 89 ba_acc_tmpl.seq_id_valid = 0; 90 ba_acc_tmpl.low_seq_cnt = 0; 91 ba_acc_tmpl.high_seq_cnt = 0xFFFF; 92 93 /* 94 * plogi_tmpl 95 */ 96 plogi_tmpl.csp.verhi = FC_PH_VER_PH_3; 97 plogi_tmpl.csp.verlo = FC_PH_VER_4_3; 98 plogi_tmpl.csp.ciro = 0x1; 99 plogi_tmpl.csp.cisc = 0x0; 100 plogi_tmpl.csp.altbbcred = 0x0; 101 plogi_tmpl.csp.conseq = cpu_to_be16(0x00FF); 102 plogi_tmpl.csp.ro_bitmap = cpu_to_be16(0x0002); 103 plogi_tmpl.csp.e_d_tov = cpu_to_be32(2000); 104 105 plogi_tmpl.class3.class_valid = 1; 106 plogi_tmpl.class3.sequential = 1; 107 plogi_tmpl.class3.conseq = 0xFF; 108 plogi_tmpl.class3.ospx = 1; 109 110 /* 111 * prli_tmpl 112 */ 113 prli_tmpl.command = FC_ELS_PRLI; 114 prli_tmpl.pglen = 0x10; 115 prli_tmpl.pagebytes = cpu_to_be16(0x0014); 116 prli_tmpl.parampage.type = FC_TYPE_FCP; 117 prli_tmpl.parampage.imagepair = 1; 118 prli_tmpl.parampage.servparams.rxrdisab = 1; 119 120 /* 121 * rrq_tmpl 122 */ 123 rrq_tmpl.els_cmd.els_code = FC_ELS_RRQ; 124 125 /* 126 * fcp_struct fchs_s mpl 127 */ 128 fcp_fchs_tmpl.routing = FC_RTG_FC4_DEV_DATA; 129 fcp_fchs_tmpl.cat_info = FC_CAT_UNSOLICIT_CMD; 130 fcp_fchs_tmpl.type = FC_TYPE_FCP; 131 fcp_fchs_tmpl.f_ctl = 132 bfa_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER); 133 fcp_fchs_tmpl.seq_id = 1; 134 fcp_fchs_tmpl.rx_id = FC_RXID_ANY; 135 } 136 137 static void 138 fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id) 139 { 140 memset(fchs, 0, sizeof(struct fchs_s)); 141 142 fchs->routing = FC_RTG_FC4_DEV_DATA; 143 fchs->cat_info = FC_CAT_UNSOLICIT_CTRL; 144 fchs->type = FC_TYPE_SERVICES; 145 fchs->f_ctl = 146 bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ | 147 FCTL_SI_XFER); 148 fchs->rx_id = FC_RXID_ANY; 149 fchs->d_id = (d_id); 150 fchs->s_id = (s_id); 151 fchs->ox_id = cpu_to_be16(ox_id); 152 153 /* 154 * @todo no need to set ox_id for request 155 * no need to set rx_id for response 156 */ 157 } 158 159 static void 160 fc_gsresp_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id) 161 { 162 memset(fchs, 0, sizeof(struct fchs_s)); 163 164 fchs->routing = FC_RTG_FC4_DEV_DATA; 165 fchs->cat_info = FC_CAT_SOLICIT_CTRL; 166 fchs->type = FC_TYPE_SERVICES; 167 fchs->f_ctl = 168 bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH | 169 FCTL_END_SEQ | FCTL_SI_XFER); 170 fchs->d_id = d_id; 171 fchs->s_id = s_id; 172 fchs->ox_id = ox_id; 173 } 174 175 void 176 fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id) 177 { 178 memcpy(fchs, &fc_els_req_tmpl, sizeof(struct fchs_s)); 179 fchs->d_id = (d_id); 180 fchs->s_id = (s_id); 181 fchs->ox_id = cpu_to_be16(ox_id); 182 } 183 184 static void 185 fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id) 186 { 187 memcpy(fchs, &fc_els_rsp_tmpl, sizeof(struct fchs_s)); 188 fchs->d_id = d_id; 189 fchs->s_id = s_id; 190 fchs->ox_id = ox_id; 191 } 192 193 static void 194 fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id) 195 { 196 memcpy(fchs, &fc_bls_rsp_tmpl, sizeof(struct fchs_s)); 197 fchs->d_id = d_id; 198 fchs->s_id = s_id; 199 fchs->ox_id = ox_id; 200 } 201 202 static u16 203 fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, 204 __be16 ox_id, wwn_t port_name, wwn_t node_name, 205 u16 pdu_size, u16 bb_cr, u8 els_code) 206 { 207 struct fc_logi_s *plogi = (struct fc_logi_s *) (pld); 208 209 memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s)); 210 211 /* For FC AL bb_cr is 0 and altbbcred is 1 */ 212 if (!bb_cr) 213 plogi->csp.altbbcred = 1; 214 215 plogi->els_cmd.els_code = els_code; 216 if (els_code == FC_ELS_PLOGI) 217 fc_els_req_build(fchs, d_id, s_id, ox_id); 218 else 219 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 220 221 plogi->csp.rxsz = plogi->class3.rxsz = cpu_to_be16(pdu_size); 222 plogi->csp.bbcred = cpu_to_be16(bb_cr); 223 224 memcpy(&plogi->port_name, &port_name, sizeof(wwn_t)); 225 memcpy(&plogi->node_name, &node_name, sizeof(wwn_t)); 226 227 return sizeof(struct fc_logi_s); 228 } 229 230 u16 231 fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id, 232 u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size, 233 u8 set_npiv, u8 set_auth, u16 local_bb_credits) 234 { 235 u32 d_id = bfa_hton3b(FC_FABRIC_PORT); 236 __be32 *vvl_info; 237 238 memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s)); 239 240 flogi->els_cmd.els_code = FC_ELS_FLOGI; 241 fc_els_req_build(fchs, d_id, s_id, ox_id); 242 243 flogi->csp.rxsz = flogi->class3.rxsz = cpu_to_be16(pdu_size); 244 flogi->port_name = port_name; 245 flogi->node_name = node_name; 246 247 /* 248 * Set the NPIV Capability Bit ( word 1, bit 31) of Common 249 * Service Parameters. 250 */ 251 flogi->csp.ciro = set_npiv; 252 253 /* set AUTH capability */ 254 flogi->csp.security = set_auth; 255 256 flogi->csp.bbcred = cpu_to_be16(local_bb_credits); 257 258 /* Set brcd token in VVL */ 259 vvl_info = (u32 *)&flogi->vvl[0]; 260 261 /* set the flag to indicate the presence of VVL */ 262 flogi->csp.npiv_supp = 1; /* @todo. field name is not correct */ 263 vvl_info[0] = cpu_to_be32(FLOGI_VVL_BRCD); 264 265 return sizeof(struct fc_logi_s); 266 } 267 268 u16 269 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id, 270 __be16 ox_id, wwn_t port_name, wwn_t node_name, 271 u16 pdu_size, u16 local_bb_credits, u8 bb_scn) 272 { 273 u32 d_id = 0; 274 u16 bbscn_rxsz = (bb_scn << 12) | pdu_size; 275 276 memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s)); 277 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 278 279 flogi->els_cmd.els_code = FC_ELS_ACC; 280 flogi->class3.rxsz = cpu_to_be16(pdu_size); 281 flogi->csp.rxsz = cpu_to_be16(bbscn_rxsz); /* bb_scn/rxsz */ 282 flogi->port_name = port_name; 283 flogi->node_name = node_name; 284 285 flogi->csp.bbcred = cpu_to_be16(local_bb_credits); 286 287 return sizeof(struct fc_logi_s); 288 } 289 290 u16 291 fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id, 292 u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size) 293 { 294 u32 d_id = bfa_hton3b(FC_FABRIC_PORT); 295 296 memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s)); 297 298 flogi->els_cmd.els_code = FC_ELS_FDISC; 299 fc_els_req_build(fchs, d_id, s_id, ox_id); 300 301 flogi->csp.rxsz = flogi->class3.rxsz = cpu_to_be16(pdu_size); 302 flogi->port_name = port_name; 303 flogi->node_name = node_name; 304 305 return sizeof(struct fc_logi_s); 306 } 307 308 u16 309 fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, 310 u16 ox_id, wwn_t port_name, wwn_t node_name, 311 u16 pdu_size, u16 bb_cr) 312 { 313 return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name, 314 node_name, pdu_size, bb_cr, FC_ELS_PLOGI); 315 } 316 317 u16 318 fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, 319 u16 ox_id, wwn_t port_name, wwn_t node_name, 320 u16 pdu_size, u16 bb_cr) 321 { 322 return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name, 323 node_name, pdu_size, bb_cr, FC_ELS_ACC); 324 } 325 326 enum fc_parse_status 327 fc_plogi_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name) 328 { 329 struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); 330 struct fc_logi_s *plogi; 331 struct fc_ls_rjt_s *ls_rjt; 332 333 switch (els_cmd->els_code) { 334 case FC_ELS_LS_RJT: 335 ls_rjt = (struct fc_ls_rjt_s *) (fchs + 1); 336 if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY) 337 return FC_PARSE_BUSY; 338 else 339 return FC_PARSE_FAILURE; 340 case FC_ELS_ACC: 341 plogi = (struct fc_logi_s *) (fchs + 1); 342 if (len < sizeof(struct fc_logi_s)) 343 return FC_PARSE_FAILURE; 344 345 if (!wwn_is_equal(plogi->port_name, port_name)) 346 return FC_PARSE_FAILURE; 347 348 if (!plogi->class3.class_valid) 349 return FC_PARSE_FAILURE; 350 351 if (be16_to_cpu(plogi->class3.rxsz) < (FC_MIN_PDUSZ)) 352 return FC_PARSE_FAILURE; 353 354 return FC_PARSE_OK; 355 default: 356 return FC_PARSE_FAILURE; 357 } 358 } 359 360 enum fc_parse_status 361 fc_plogi_parse(struct fchs_s *fchs) 362 { 363 struct fc_logi_s *plogi = (struct fc_logi_s *) (fchs + 1); 364 365 if (plogi->class3.class_valid != 1) 366 return FC_PARSE_FAILURE; 367 368 if ((be16_to_cpu(plogi->class3.rxsz) < FC_MIN_PDUSZ) 369 || (be16_to_cpu(plogi->class3.rxsz) > FC_MAX_PDUSZ) 370 || (plogi->class3.rxsz == 0)) 371 return FC_PARSE_FAILURE; 372 373 return FC_PARSE_OK; 374 } 375 376 u16 377 fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, 378 u16 ox_id) 379 { 380 struct fc_prli_s *prli = (struct fc_prli_s *) (pld); 381 382 fc_els_req_build(fchs, d_id, s_id, ox_id); 383 memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s)); 384 385 prli->command = FC_ELS_PRLI; 386 prli->parampage.servparams.initiator = 1; 387 prli->parampage.servparams.retry = 1; 388 prli->parampage.servparams.rec_support = 1; 389 prli->parampage.servparams.task_retry_id = 0; 390 prli->parampage.servparams.confirm = 1; 391 392 return sizeof(struct fc_prli_s); 393 } 394 395 u16 396 fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, 397 __be16 ox_id, enum bfa_lport_role role) 398 { 399 struct fc_prli_s *prli = (struct fc_prli_s *) (pld); 400 401 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 402 memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s)); 403 404 prli->command = FC_ELS_ACC; 405 406 prli->parampage.servparams.initiator = 1; 407 408 prli->parampage.rspcode = FC_PRLI_ACC_XQTD; 409 410 return sizeof(struct fc_prli_s); 411 } 412 413 enum fc_parse_status 414 fc_prli_rsp_parse(struct fc_prli_s *prli, int len) 415 { 416 if (len < sizeof(struct fc_prli_s)) 417 return FC_PARSE_FAILURE; 418 419 if (prli->command != FC_ELS_ACC) 420 return FC_PARSE_FAILURE; 421 422 if ((prli->parampage.rspcode != FC_PRLI_ACC_XQTD) 423 && (prli->parampage.rspcode != FC_PRLI_ACC_PREDEF_IMG)) 424 return FC_PARSE_FAILURE; 425 426 if (prli->parampage.servparams.target != 1) 427 return FC_PARSE_FAILURE; 428 429 return FC_PARSE_OK; 430 } 431 432 enum fc_parse_status 433 fc_prli_parse(struct fc_prli_s *prli) 434 { 435 if (prli->parampage.type != FC_TYPE_FCP) 436 return FC_PARSE_FAILURE; 437 438 if (!prli->parampage.imagepair) 439 return FC_PARSE_FAILURE; 440 441 if (!prli->parampage.servparams.initiator) 442 return FC_PARSE_FAILURE; 443 444 return FC_PARSE_OK; 445 } 446 447 u16 448 fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id, u32 s_id, 449 u16 ox_id, wwn_t port_name) 450 { 451 fc_els_req_build(fchs, d_id, s_id, ox_id); 452 453 memset(logo, '\0', sizeof(struct fc_logo_s)); 454 logo->els_cmd.els_code = FC_ELS_LOGO; 455 logo->nport_id = (s_id); 456 logo->orig_port_name = port_name; 457 458 return sizeof(struct fc_logo_s); 459 } 460 461 static u16 462 fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, 463 u32 s_id, __be16 ox_id, wwn_t port_name, 464 wwn_t node_name, u8 els_code) 465 { 466 memset(adisc, '\0', sizeof(struct fc_adisc_s)); 467 468 adisc->els_cmd.els_code = els_code; 469 470 if (els_code == FC_ELS_ADISC) 471 fc_els_req_build(fchs, d_id, s_id, ox_id); 472 else 473 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 474 475 adisc->orig_HA = 0; 476 adisc->orig_port_name = port_name; 477 adisc->orig_node_name = node_name; 478 adisc->nport_id = (s_id); 479 480 return sizeof(struct fc_adisc_s); 481 } 482 483 u16 484 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, 485 u32 s_id, __be16 ox_id, wwn_t port_name, wwn_t node_name) 486 { 487 return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name, 488 node_name, FC_ELS_ADISC); 489 } 490 491 u16 492 fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, 493 u32 s_id, __be16 ox_id, wwn_t port_name, 494 wwn_t node_name) 495 { 496 return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name, 497 node_name, FC_ELS_ACC); 498 } 499 500 enum fc_parse_status 501 fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len, wwn_t port_name, 502 wwn_t node_name) 503 { 504 505 if (len < sizeof(struct fc_adisc_s)) 506 return FC_PARSE_FAILURE; 507 508 if (adisc->els_cmd.els_code != FC_ELS_ACC) 509 return FC_PARSE_FAILURE; 510 511 if (!wwn_is_equal(adisc->orig_port_name, port_name)) 512 return FC_PARSE_FAILURE; 513 514 return FC_PARSE_OK; 515 } 516 517 enum fc_parse_status 518 fc_adisc_parse(struct fchs_s *fchs, void *pld, u32 host_dap, wwn_t node_name, 519 wwn_t port_name) 520 { 521 struct fc_adisc_s *adisc = (struct fc_adisc_s *) pld; 522 523 if (adisc->els_cmd.els_code != FC_ELS_ACC) 524 return FC_PARSE_FAILURE; 525 526 if ((adisc->nport_id == (host_dap)) 527 && wwn_is_equal(adisc->orig_port_name, port_name) 528 && wwn_is_equal(adisc->orig_node_name, node_name)) 529 return FC_PARSE_OK; 530 531 return FC_PARSE_FAILURE; 532 } 533 534 enum fc_parse_status 535 fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name, wwn_t port_name) 536 { 537 struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1); 538 539 if (pdisc->class3.class_valid != 1) 540 return FC_PARSE_FAILURE; 541 542 if ((be16_to_cpu(pdisc->class3.rxsz) < 543 (FC_MIN_PDUSZ - sizeof(struct fchs_s))) 544 || (pdisc->class3.rxsz == 0)) 545 return FC_PARSE_FAILURE; 546 547 if (!wwn_is_equal(pdisc->port_name, port_name)) 548 return FC_PARSE_FAILURE; 549 550 if (!wwn_is_equal(pdisc->node_name, node_name)) 551 return FC_PARSE_FAILURE; 552 553 return FC_PARSE_OK; 554 } 555 556 u16 557 fc_abts_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id) 558 { 559 memcpy(fchs, &fc_bls_req_tmpl, sizeof(struct fchs_s)); 560 fchs->cat_info = FC_CAT_ABTS; 561 fchs->d_id = (d_id); 562 fchs->s_id = (s_id); 563 fchs->ox_id = cpu_to_be16(ox_id); 564 565 return sizeof(struct fchs_s); 566 } 567 568 enum fc_parse_status 569 fc_abts_rsp_parse(struct fchs_s *fchs, int len) 570 { 571 if ((fchs->cat_info == FC_CAT_BA_ACC) 572 || (fchs->cat_info == FC_CAT_BA_RJT)) 573 return FC_PARSE_OK; 574 575 return FC_PARSE_FAILURE; 576 } 577 578 u16 579 fc_rrq_build(struct fchs_s *fchs, struct fc_rrq_s *rrq, u32 d_id, u32 s_id, 580 u16 ox_id, u16 rrq_oxid) 581 { 582 fc_els_req_build(fchs, d_id, s_id, ox_id); 583 584 /* 585 * build rrq payload 586 */ 587 memcpy(rrq, &rrq_tmpl, sizeof(struct fc_rrq_s)); 588 rrq->s_id = (s_id); 589 rrq->ox_id = cpu_to_be16(rrq_oxid); 590 rrq->rx_id = FC_RXID_ANY; 591 592 return sizeof(struct fc_rrq_s); 593 } 594 595 u16 596 fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, 597 __be16 ox_id) 598 { 599 struct fc_els_cmd_s *acc = pld; 600 601 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 602 603 memset(acc, 0, sizeof(struct fc_els_cmd_s)); 604 acc->els_code = FC_ELS_ACC; 605 606 return sizeof(struct fc_els_cmd_s); 607 } 608 609 u16 610 fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id, 611 u32 s_id, __be16 ox_id, u8 reason_code, 612 u8 reason_code_expl) 613 { 614 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 615 memset(ls_rjt, 0, sizeof(struct fc_ls_rjt_s)); 616 617 ls_rjt->els_cmd.els_code = FC_ELS_LS_RJT; 618 ls_rjt->reason_code = reason_code; 619 ls_rjt->reason_code_expl = reason_code_expl; 620 ls_rjt->vendor_unique = 0x00; 621 622 return sizeof(struct fc_ls_rjt_s); 623 } 624 625 u16 626 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id, 627 u32 s_id, __be16 ox_id, u16 rx_id) 628 { 629 fc_bls_rsp_build(fchs, d_id, s_id, ox_id); 630 631 memcpy(ba_acc, &ba_acc_tmpl, sizeof(struct fc_ba_acc_s)); 632 633 fchs->rx_id = rx_id; 634 635 ba_acc->ox_id = fchs->ox_id; 636 ba_acc->rx_id = fchs->rx_id; 637 638 return sizeof(struct fc_ba_acc_s); 639 } 640 641 u16 642 fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, u32 d_id, 643 u32 s_id, __be16 ox_id) 644 { 645 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 646 memset(els_cmd, 0, sizeof(struct fc_els_cmd_s)); 647 els_cmd->els_code = FC_ELS_ACC; 648 649 return sizeof(struct fc_els_cmd_s); 650 } 651 652 int 653 fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code) 654 { 655 int num_pages = 0; 656 struct fc_prlo_s *prlo; 657 struct fc_tprlo_s *tprlo; 658 659 if (els_code == FC_ELS_PRLO) { 660 prlo = (struct fc_prlo_s *) (fc_frame + 1); 661 num_pages = (be16_to_cpu(prlo->payload_len) - 4) / 16; 662 } else { 663 tprlo = (struct fc_tprlo_s *) (fc_frame + 1); 664 num_pages = (be16_to_cpu(tprlo->payload_len) - 4) / 16; 665 } 666 return num_pages; 667 } 668 669 u16 670 fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc, 671 u32 d_id, u32 s_id, __be16 ox_id, int num_pages) 672 { 673 int page; 674 675 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 676 677 memset(tprlo_acc, 0, (num_pages * 16) + 4); 678 tprlo_acc->command = FC_ELS_ACC; 679 680 tprlo_acc->page_len = 0x10; 681 tprlo_acc->payload_len = cpu_to_be16((num_pages * 16) + 4); 682 683 for (page = 0; page < num_pages; page++) { 684 tprlo_acc->tprlo_acc_params[page].opa_valid = 0; 685 tprlo_acc->tprlo_acc_params[page].rpa_valid = 0; 686 tprlo_acc->tprlo_acc_params[page].fc4type_csp = FC_TYPE_FCP; 687 tprlo_acc->tprlo_acc_params[page].orig_process_assc = 0; 688 tprlo_acc->tprlo_acc_params[page].resp_process_assc = 0; 689 } 690 return be16_to_cpu(tprlo_acc->payload_len); 691 } 692 693 u16 694 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, u32 d_id, 695 u32 s_id, __be16 ox_id, int num_pages) 696 { 697 int page; 698 699 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 700 701 memset(prlo_acc, 0, (num_pages * 16) + 4); 702 prlo_acc->command = FC_ELS_ACC; 703 prlo_acc->page_len = 0x10; 704 prlo_acc->payload_len = cpu_to_be16((num_pages * 16) + 4); 705 706 for (page = 0; page < num_pages; page++) { 707 prlo_acc->prlo_acc_params[page].opa_valid = 0; 708 prlo_acc->prlo_acc_params[page].rpa_valid = 0; 709 prlo_acc->prlo_acc_params[page].fc4type_csp = FC_TYPE_FCP; 710 prlo_acc->prlo_acc_params[page].orig_process_assc = 0; 711 prlo_acc->prlo_acc_params[page].resp_process_assc = 0; 712 } 713 714 return be16_to_cpu(prlo_acc->payload_len); 715 } 716 717 u16 718 fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u32 d_id, 719 u32 s_id, u16 ox_id, u32 data_format) 720 { 721 fc_els_req_build(fchs, d_id, s_id, ox_id); 722 723 memset(rnid, 0, sizeof(struct fc_rnid_cmd_s)); 724 725 rnid->els_cmd.els_code = FC_ELS_RNID; 726 rnid->node_id_data_format = data_format; 727 728 return sizeof(struct fc_rnid_cmd_s); 729 } 730 731 u16 732 fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, u32 d_id, 733 u32 s_id, __be16 ox_id, u32 data_format, 734 struct fc_rnid_common_id_data_s *common_id_data, 735 struct fc_rnid_general_topology_data_s *gen_topo_data) 736 { 737 memset(rnid_acc, 0, sizeof(struct fc_rnid_acc_s)); 738 739 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 740 741 rnid_acc->els_cmd.els_code = FC_ELS_ACC; 742 rnid_acc->node_id_data_format = data_format; 743 rnid_acc->common_id_data_length = 744 sizeof(struct fc_rnid_common_id_data_s); 745 rnid_acc->common_id_data = *common_id_data; 746 747 if (data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) { 748 rnid_acc->specific_id_data_length = 749 sizeof(struct fc_rnid_general_topology_data_s); 750 rnid_acc->gen_topology_data = *gen_topo_data; 751 return sizeof(struct fc_rnid_acc_s); 752 } else { 753 return sizeof(struct fc_rnid_acc_s) - 754 sizeof(struct fc_rnid_general_topology_data_s); 755 } 756 757 } 758 759 u16 760 fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc, u32 d_id, 761 u32 s_id, u16 ox_id) 762 { 763 fc_els_req_build(fchs, d_id, s_id, ox_id); 764 765 memset(rpsc, 0, sizeof(struct fc_rpsc_cmd_s)); 766 767 rpsc->els_cmd.els_code = FC_ELS_RPSC; 768 return sizeof(struct fc_rpsc_cmd_s); 769 } 770 771 u16 772 fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, u32 d_id, 773 u32 s_id, u32 *pid_list, u16 npids) 774 { 775 u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_hton3b(d_id)); 776 int i = 0; 777 778 fc_els_req_build(fchs, bfa_hton3b(dctlr_id), s_id, 0); 779 780 memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s)); 781 782 rpsc2->els_cmd.els_code = FC_ELS_RPSC; 783 rpsc2->token = cpu_to_be32(FC_BRCD_TOKEN); 784 rpsc2->num_pids = cpu_to_be16(npids); 785 for (i = 0; i < npids; i++) 786 rpsc2->pid_list[i].pid = pid_list[i]; 787 788 return sizeof(struct fc_rpsc2_cmd_s) + ((npids - 1) * (sizeof(u32))); 789 } 790 791 u16 792 fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc, 793 u32 d_id, u32 s_id, __be16 ox_id, 794 struct fc_rpsc_speed_info_s *oper_speed) 795 { 796 memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s)); 797 798 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 799 800 rpsc_acc->command = FC_ELS_ACC; 801 rpsc_acc->num_entries = cpu_to_be16(1); 802 803 rpsc_acc->speed_info[0].port_speed_cap = 804 cpu_to_be16(oper_speed->port_speed_cap); 805 806 rpsc_acc->speed_info[0].port_op_speed = 807 cpu_to_be16(oper_speed->port_op_speed); 808 809 return sizeof(struct fc_rpsc_acc_s); 810 } 811 812 u16 813 fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id, 814 wwn_t port_name, wwn_t node_name, u16 pdu_size) 815 { 816 struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1); 817 818 memcpy(pdisc, &plogi_tmpl, sizeof(struct fc_logi_s)); 819 820 pdisc->els_cmd.els_code = FC_ELS_PDISC; 821 fc_els_req_build(fchs, d_id, s_id, ox_id); 822 823 pdisc->csp.rxsz = pdisc->class3.rxsz = cpu_to_be16(pdu_size); 824 pdisc->port_name = port_name; 825 pdisc->node_name = node_name; 826 827 return sizeof(struct fc_logi_s); 828 } 829 830 u16 831 fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name) 832 { 833 struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1); 834 835 if (len < sizeof(struct fc_logi_s)) 836 return FC_PARSE_LEN_INVAL; 837 838 if (pdisc->els_cmd.els_code != FC_ELS_ACC) 839 return FC_PARSE_ACC_INVAL; 840 841 if (!wwn_is_equal(pdisc->port_name, port_name)) 842 return FC_PARSE_PWWN_NOT_EQUAL; 843 844 if (!pdisc->class3.class_valid) 845 return FC_PARSE_NWWN_NOT_EQUAL; 846 847 if (be16_to_cpu(pdisc->class3.rxsz) < (FC_MIN_PDUSZ)) 848 return FC_PARSE_RXSZ_INVAL; 849 850 return FC_PARSE_OK; 851 } 852 853 u16 854 fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id, 855 int num_pages) 856 { 857 struct fc_prlo_s *prlo = (struct fc_prlo_s *) (fchs + 1); 858 int page; 859 860 fc_els_req_build(fchs, d_id, s_id, ox_id); 861 memset(prlo, 0, (num_pages * 16) + 4); 862 prlo->command = FC_ELS_PRLO; 863 prlo->page_len = 0x10; 864 prlo->payload_len = cpu_to_be16((num_pages * 16) + 4); 865 866 for (page = 0; page < num_pages; page++) { 867 prlo->prlo_params[page].type = FC_TYPE_FCP; 868 prlo->prlo_params[page].opa_valid = 0; 869 prlo->prlo_params[page].rpa_valid = 0; 870 prlo->prlo_params[page].orig_process_assc = 0; 871 prlo->prlo_params[page].resp_process_assc = 0; 872 } 873 874 return be16_to_cpu(prlo->payload_len); 875 } 876 877 u16 878 fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id, 879 int num_pages, enum fc_tprlo_type tprlo_type, u32 tpr_id) 880 { 881 struct fc_tprlo_s *tprlo = (struct fc_tprlo_s *) (fchs + 1); 882 int page; 883 884 fc_els_req_build(fchs, d_id, s_id, ox_id); 885 memset(tprlo, 0, (num_pages * 16) + 4); 886 tprlo->command = FC_ELS_TPRLO; 887 tprlo->page_len = 0x10; 888 tprlo->payload_len = cpu_to_be16((num_pages * 16) + 4); 889 890 for (page = 0; page < num_pages; page++) { 891 tprlo->tprlo_params[page].type = FC_TYPE_FCP; 892 tprlo->tprlo_params[page].opa_valid = 0; 893 tprlo->tprlo_params[page].rpa_valid = 0; 894 tprlo->tprlo_params[page].orig_process_assc = 0; 895 tprlo->tprlo_params[page].resp_process_assc = 0; 896 if (tprlo_type == FC_GLOBAL_LOGO) { 897 tprlo->tprlo_params[page].global_process_logout = 1; 898 } else if (tprlo_type == FC_TPR_LOGO) { 899 tprlo->tprlo_params[page].tpo_nport_valid = 1; 900 tprlo->tprlo_params[page].tpo_nport_id = (tpr_id); 901 } 902 } 903 904 return be16_to_cpu(tprlo->payload_len); 905 } 906 907 u16 908 fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id, 909 u32 reason_code, u32 reason_expl) 910 { 911 struct fc_ba_rjt_s *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1); 912 913 fc_bls_rsp_build(fchs, d_id, s_id, ox_id); 914 915 fchs->cat_info = FC_CAT_BA_RJT; 916 ba_rjt->reason_code = reason_code; 917 ba_rjt->reason_expl = reason_expl; 918 return sizeof(struct fc_ba_rjt_s); 919 } 920 921 static void 922 fc_gs_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code) 923 { 924 memset(cthdr, 0, sizeof(struct ct_hdr_s)); 925 cthdr->rev_id = CT_GS3_REVISION; 926 cthdr->gs_type = CT_GSTYPE_DIRSERVICE; 927 cthdr->gs_sub_type = CT_GSSUBTYPE_NAMESERVER; 928 cthdr->cmd_rsp_code = cpu_to_be16(cmd_code); 929 } 930 931 static void 932 fc_gs_fdmi_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code) 933 { 934 memset(cthdr, 0, sizeof(struct ct_hdr_s)); 935 cthdr->rev_id = CT_GS3_REVISION; 936 cthdr->gs_type = CT_GSTYPE_MGMTSERVICE; 937 cthdr->gs_sub_type = CT_GSSUBTYPE_HBA_MGMTSERVER; 938 cthdr->cmd_rsp_code = cpu_to_be16(cmd_code); 939 } 940 941 static void 942 fc_gs_ms_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code, 943 u8 sub_type) 944 { 945 memset(cthdr, 0, sizeof(struct ct_hdr_s)); 946 cthdr->rev_id = CT_GS3_REVISION; 947 cthdr->gs_type = CT_GSTYPE_MGMTSERVICE; 948 cthdr->gs_sub_type = sub_type; 949 cthdr->cmd_rsp_code = cpu_to_be16(cmd_code); 950 } 951 952 u16 953 fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, 954 wwn_t port_name) 955 { 956 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 957 struct fcgs_gidpn_req_s *gidpn = (struct fcgs_gidpn_req_s *)(cthdr + 1); 958 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 959 960 fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); 961 fc_gs_cthdr_build(cthdr, s_id, GS_GID_PN); 962 963 memset(gidpn, 0, sizeof(struct fcgs_gidpn_req_s)); 964 gidpn->port_name = port_name; 965 return sizeof(struct fcgs_gidpn_req_s) + sizeof(struct ct_hdr_s); 966 } 967 968 u16 969 fc_gpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, 970 u32 port_id) 971 { 972 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 973 fcgs_gpnid_req_t *gpnid = (fcgs_gpnid_req_t *) (cthdr + 1); 974 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 975 976 fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); 977 fc_gs_cthdr_build(cthdr, s_id, GS_GPN_ID); 978 979 memset(gpnid, 0, sizeof(fcgs_gpnid_req_t)); 980 gpnid->dap = port_id; 981 return sizeof(fcgs_gpnid_req_t) + sizeof(struct ct_hdr_s); 982 } 983 984 u16 985 fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, 986 u32 port_id) 987 { 988 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 989 fcgs_gnnid_req_t *gnnid = (fcgs_gnnid_req_t *) (cthdr + 1); 990 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 991 992 fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); 993 fc_gs_cthdr_build(cthdr, s_id, GS_GNN_ID); 994 995 memset(gnnid, 0, sizeof(fcgs_gnnid_req_t)); 996 gnnid->dap = port_id; 997 return sizeof(fcgs_gnnid_req_t) + sizeof(struct ct_hdr_s); 998 } 999 1000 u16 1001 fc_ct_rsp_parse(struct ct_hdr_s *cthdr) 1002 { 1003 if (be16_to_cpu(cthdr->cmd_rsp_code) != CT_RSP_ACCEPT) { 1004 if (cthdr->reason_code == CT_RSN_LOGICAL_BUSY) 1005 return FC_PARSE_BUSY; 1006 else 1007 return FC_PARSE_FAILURE; 1008 } 1009 1010 return FC_PARSE_OK; 1011 } 1012 1013 u16 1014 fc_gs_rjt_build(struct fchs_s *fchs, struct ct_hdr_s *cthdr, 1015 u32 d_id, u32 s_id, u16 ox_id, u8 reason_code, 1016 u8 reason_code_expl) 1017 { 1018 fc_gsresp_fchdr_build(fchs, d_id, s_id, ox_id); 1019 1020 cthdr->cmd_rsp_code = cpu_to_be16(CT_RSP_REJECT); 1021 cthdr->rev_id = CT_GS3_REVISION; 1022 1023 cthdr->reason_code = reason_code; 1024 cthdr->exp_code = reason_code_expl; 1025 return sizeof(struct ct_hdr_s); 1026 } 1027 1028 u16 1029 fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr, 1030 u8 set_br_reg, u32 s_id, u16 ox_id) 1031 { 1032 u32 d_id = bfa_hton3b(FC_FABRIC_CONTROLLER); 1033 1034 fc_els_req_build(fchs, d_id, s_id, ox_id); 1035 1036 memset(scr, 0, sizeof(struct fc_scr_s)); 1037 scr->command = FC_ELS_SCR; 1038 scr->reg_func = FC_SCR_REG_FUNC_FULL; 1039 if (set_br_reg) 1040 scr->vu_reg_func = FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE; 1041 1042 return sizeof(struct fc_scr_s); 1043 } 1044 1045 u16 1046 fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn, 1047 u32 s_id, u16 ox_id) 1048 { 1049 u32 d_id = bfa_hton3b(FC_FABRIC_CONTROLLER); 1050 u16 payldlen; 1051 1052 fc_els_req_build(fchs, d_id, s_id, ox_id); 1053 rscn->command = FC_ELS_RSCN; 1054 rscn->pagelen = sizeof(rscn->event[0]); 1055 1056 payldlen = sizeof(u32) + rscn->pagelen; 1057 rscn->payldlen = cpu_to_be16(payldlen); 1058 1059 rscn->event[0].format = FC_RSCN_FORMAT_PORTID; 1060 rscn->event[0].portid = s_id; 1061 1062 return sizeof(struct fc_rscn_pl_s); 1063 } 1064 1065 u16 1066 fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, 1067 enum bfa_lport_role roles) 1068 { 1069 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 1070 struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1); 1071 u32 type_value, d_id = bfa_hton3b(FC_NAME_SERVER); 1072 u8 index; 1073 1074 fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); 1075 fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID); 1076 1077 memset(rftid, 0, sizeof(struct fcgs_rftid_req_s)); 1078 1079 rftid->dap = s_id; 1080 1081 /* By default, FCP FC4 Type is registered */ 1082 index = FC_TYPE_FCP >> 5; 1083 type_value = 1 << (FC_TYPE_FCP % 32); 1084 rftid->fc4_type[index] = cpu_to_be32(type_value); 1085 1086 return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s); 1087 } 1088 1089 u16 1090 fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, 1091 u8 *fc4_bitmap, u32 bitmap_size) 1092 { 1093 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 1094 struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1); 1095 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 1096 1097 fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); 1098 fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID); 1099 1100 memset(rftid, 0, sizeof(struct fcgs_rftid_req_s)); 1101 1102 rftid->dap = s_id; 1103 memcpy((void *)rftid->fc4_type, (void *)fc4_bitmap, 1104 (bitmap_size < 32 ? bitmap_size : 32)); 1105 1106 return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s); 1107 } 1108 1109 u16 1110 fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, 1111 u8 fc4_type, u8 fc4_ftrs) 1112 { 1113 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 1114 struct fcgs_rffid_req_s *rffid = (struct fcgs_rffid_req_s *)(cthdr + 1); 1115 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 1116 1117 fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); 1118 fc_gs_cthdr_build(cthdr, s_id, GS_RFF_ID); 1119 1120 memset(rffid, 0, sizeof(struct fcgs_rffid_req_s)); 1121 1122 rffid->dap = s_id; 1123 rffid->fc4ftr_bits = fc4_ftrs; 1124 rffid->fc4_type = fc4_type; 1125 1126 return sizeof(struct fcgs_rffid_req_s) + sizeof(struct ct_hdr_s); 1127 } 1128 1129 u16 1130 fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, 1131 u8 *name) 1132 { 1133 1134 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 1135 struct fcgs_rspnid_req_s *rspnid = 1136 (struct fcgs_rspnid_req_s *)(cthdr + 1); 1137 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 1138 1139 fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); 1140 fc_gs_cthdr_build(cthdr, s_id, GS_RSPN_ID); 1141 1142 memset(rspnid, 0, sizeof(struct fcgs_rspnid_req_s)); 1143 1144 rspnid->dap = s_id; 1145 strlcpy(rspnid->spn, name, sizeof(rspnid->spn)); 1146 rspnid->spn_len = (u8) strlen(rspnid->spn); 1147 1148 return sizeof(struct fcgs_rspnid_req_s) + sizeof(struct ct_hdr_s); 1149 } 1150 1151 u16 1152 fc_rsnn_nn_build(struct fchs_s *fchs, void *pyld, u32 s_id, 1153 wwn_t node_name, u8 *name) 1154 { 1155 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 1156 struct fcgs_rsnn_nn_req_s *rsnn_nn = 1157 (struct fcgs_rsnn_nn_req_s *) (cthdr + 1); 1158 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 1159 1160 fc_gs_fchdr_build(fchs, d_id, s_id, 0); 1161 fc_gs_cthdr_build(cthdr, s_id, GS_RSNN_NN); 1162 1163 memset(rsnn_nn, 0, sizeof(struct fcgs_rsnn_nn_req_s)); 1164 1165 rsnn_nn->node_name = node_name; 1166 strlcpy(rsnn_nn->snn, name, sizeof(rsnn_nn->snn)); 1167 rsnn_nn->snn_len = (u8) strlen(rsnn_nn->snn); 1168 1169 return sizeof(struct fcgs_rsnn_nn_req_s) + sizeof(struct ct_hdr_s); 1170 } 1171 1172 u16 1173 fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, u8 fc4_type) 1174 { 1175 1176 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 1177 struct fcgs_gidft_req_s *gidft = (struct fcgs_gidft_req_s *)(cthdr + 1); 1178 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 1179 1180 fc_gs_fchdr_build(fchs, d_id, s_id, 0); 1181 1182 fc_gs_cthdr_build(cthdr, s_id, GS_GID_FT); 1183 1184 memset(gidft, 0, sizeof(struct fcgs_gidft_req_s)); 1185 gidft->fc4_type = fc4_type; 1186 gidft->domain_id = 0; 1187 gidft->area_id = 0; 1188 1189 return sizeof(struct fcgs_gidft_req_s) + sizeof(struct ct_hdr_s); 1190 } 1191 1192 u16 1193 fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id, 1194 wwn_t port_name) 1195 { 1196 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 1197 struct fcgs_rpnid_req_s *rpnid = (struct fcgs_rpnid_req_s *)(cthdr + 1); 1198 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 1199 1200 fc_gs_fchdr_build(fchs, d_id, s_id, 0); 1201 fc_gs_cthdr_build(cthdr, s_id, GS_RPN_ID); 1202 1203 memset(rpnid, 0, sizeof(struct fcgs_rpnid_req_s)); 1204 rpnid->port_id = port_id; 1205 rpnid->port_name = port_name; 1206 1207 return sizeof(struct fcgs_rpnid_req_s) + sizeof(struct ct_hdr_s); 1208 } 1209 1210 u16 1211 fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id, 1212 wwn_t node_name) 1213 { 1214 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 1215 struct fcgs_rnnid_req_s *rnnid = (struct fcgs_rnnid_req_s *)(cthdr + 1); 1216 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 1217 1218 fc_gs_fchdr_build(fchs, d_id, s_id, 0); 1219 fc_gs_cthdr_build(cthdr, s_id, GS_RNN_ID); 1220 1221 memset(rnnid, 0, sizeof(struct fcgs_rnnid_req_s)); 1222 rnnid->port_id = port_id; 1223 rnnid->node_name = node_name; 1224 1225 return sizeof(struct fcgs_rnnid_req_s) + sizeof(struct ct_hdr_s); 1226 } 1227 1228 u16 1229 fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id, 1230 u32 cos) 1231 { 1232 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 1233 struct fcgs_rcsid_req_s *rcsid = 1234 (struct fcgs_rcsid_req_s *) (cthdr + 1); 1235 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 1236 1237 fc_gs_fchdr_build(fchs, d_id, s_id, 0); 1238 fc_gs_cthdr_build(cthdr, s_id, GS_RCS_ID); 1239 1240 memset(rcsid, 0, sizeof(struct fcgs_rcsid_req_s)); 1241 rcsid->port_id = port_id; 1242 rcsid->cos = cos; 1243 1244 return sizeof(struct fcgs_rcsid_req_s) + sizeof(struct ct_hdr_s); 1245 } 1246 1247 u16 1248 fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id, 1249 u8 port_type) 1250 { 1251 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 1252 struct fcgs_rptid_req_s *rptid = (struct fcgs_rptid_req_s *)(cthdr + 1); 1253 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 1254 1255 fc_gs_fchdr_build(fchs, d_id, s_id, 0); 1256 fc_gs_cthdr_build(cthdr, s_id, GS_RPT_ID); 1257 1258 memset(rptid, 0, sizeof(struct fcgs_rptid_req_s)); 1259 rptid->port_id = port_id; 1260 rptid->port_type = port_type; 1261 1262 return sizeof(struct fcgs_rptid_req_s) + sizeof(struct ct_hdr_s); 1263 } 1264 1265 u16 1266 fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id) 1267 { 1268 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 1269 struct fcgs_ganxt_req_s *ganxt = (struct fcgs_ganxt_req_s *)(cthdr + 1); 1270 u32 d_id = bfa_hton3b(FC_NAME_SERVER); 1271 1272 fc_gs_fchdr_build(fchs, d_id, s_id, 0); 1273 fc_gs_cthdr_build(cthdr, s_id, GS_GA_NXT); 1274 1275 memset(ganxt, 0, sizeof(struct fcgs_ganxt_req_s)); 1276 ganxt->port_id = port_id; 1277 1278 return sizeof(struct ct_hdr_s) + sizeof(struct fcgs_ganxt_req_s); 1279 } 1280 1281 /* 1282 * Builds fc hdr and ct hdr for FDMI requests. 1283 */ 1284 u16 1285 fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id, 1286 u16 cmd_code) 1287 { 1288 1289 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 1290 u32 d_id = bfa_hton3b(FC_MGMT_SERVER); 1291 1292 fc_gs_fchdr_build(fchs, d_id, s_id, 0); 1293 fc_gs_fdmi_cthdr_build(cthdr, s_id, cmd_code); 1294 1295 return sizeof(struct ct_hdr_s); 1296 } 1297 1298 /* 1299 * Given a FC4 Type, this function returns a fc4 type bitmask 1300 */ 1301 void 1302 fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask) 1303 { 1304 u8 index; 1305 __be32 *ptr = (__be32 *) bit_mask; 1306 u32 type_value; 1307 1308 /* 1309 * @todo : Check for bitmask size 1310 */ 1311 1312 index = fc4_type >> 5; 1313 type_value = 1 << (fc4_type % 32); 1314 ptr[index] = cpu_to_be32(type_value); 1315 1316 } 1317 1318 /* 1319 * GMAL Request 1320 */ 1321 u16 1322 fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn) 1323 { 1324 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 1325 fcgs_gmal_req_t *gmal = (fcgs_gmal_req_t *) (cthdr + 1); 1326 u32 d_id = bfa_hton3b(FC_MGMT_SERVER); 1327 1328 fc_gs_fchdr_build(fchs, d_id, s_id, 0); 1329 fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GMAL_CMD, 1330 CT_GSSUBTYPE_CFGSERVER); 1331 1332 memset(gmal, 0, sizeof(fcgs_gmal_req_t)); 1333 gmal->wwn = wwn; 1334 1335 return sizeof(struct ct_hdr_s) + sizeof(fcgs_gmal_req_t); 1336 } 1337 1338 /* 1339 * GFN (Get Fabric Name) Request 1340 */ 1341 u16 1342 fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn) 1343 { 1344 struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; 1345 fcgs_gfn_req_t *gfn = (fcgs_gfn_req_t *) (cthdr + 1); 1346 u32 d_id = bfa_hton3b(FC_MGMT_SERVER); 1347 1348 fc_gs_fchdr_build(fchs, d_id, s_id, 0); 1349 fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GFN_CMD, 1350 CT_GSSUBTYPE_CFGSERVER); 1351 1352 memset(gfn, 0, sizeof(fcgs_gfn_req_t)); 1353 gfn->wwn = wwn; 1354 1355 return sizeof(struct ct_hdr_s) + sizeof(fcgs_gfn_req_t); 1356 } 1357