1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* 27 * This file defines interfaces between FCOE and LEADVILLE 28 */ 29 30 /* 31 * Driver kernel header files 32 */ 33 #include <sys/conf.h> 34 #include <sys/ddi.h> 35 #include <sys/stat.h> 36 #include <sys/pci.h> 37 #include <sys/sunddi.h> 38 #include <sys/modctl.h> 39 #include <sys/file.h> 40 #include <sys/cred.h> 41 #include <sys/byteorder.h> 42 #include <sys/atomic.h> 43 #include <sys/scsi/scsi.h> 44 #include <sys/mac_client.h> 45 #include <sys/modhash.h> 46 47 /* 48 * LEADVILLE header files 49 */ 50 #include <sys/fibre-channel/fc.h> 51 #include <sys/fibre-channel/impl/fc_fcaif.h> 52 53 /* 54 * COMSTAR head files (BIT_* macro) 55 */ 56 #include <sys/stmf_defines.h> 57 58 /* 59 * FCOE header files 60 */ 61 #include <sys/fcoe/fcoe_common.h> 62 63 /* 64 * Driver's own header files 65 */ 66 #include <fcoei.h> 67 68 /* 69 * forward declaration of static functions 70 */ 71 static void fcoei_port_enabled(void *arg); 72 73 static void fcoei_populate_hba_fru_details(fcoei_soft_state_t *ss, 74 fc_fca_port_info_t *port_info); 75 76 static void fcoei_initiate_ct_req(fcoei_exchange_t *xch); 77 static void fcoei_initiate_fcp_cmd(fcoei_exchange_t *xch); 78 static void fcoei_initiate_els_req(fcoei_exchange_t *xch); 79 static void fcoei_initiate_els_resp(fcoei_exchange_t *xch); 80 81 static void fcoei_fill_els_logi_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm); 82 static void fcoei_fill_els_prli_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm); 83 static void fcoei_fill_els_logo_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm); 84 static void fcoei_fill_els_scr_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm); 85 static void fcoei_fill_els_adisc_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm); 86 static void fcoei_fill_els_linit_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm); 87 static void fcoei_fill_els_rls_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm); 88 static void fcoei_fill_els_rnid_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm); 89 90 static void fcoei_fill_els_acc_resp(fc_packet_t *fpkt, fcoe_frame_t *frm); 91 static void fcoei_fill_els_rjt_resp(fc_packet_t *fpkt, fcoe_frame_t *frm); 92 static void fcoei_fill_els_logi_resp(fc_packet_t *fpkt, fcoe_frame_t *frm); 93 static void fcoei_fill_els_prli_resp(fc_packet_t *fpkt, fcoe_frame_t *frm); 94 static void fcoei_fill_els_logo_resp(fc_packet_t *fpkt, fcoe_frame_t *frm); 95 static void fcoei_fill_els_adisc_resp(fc_packet_t *fpkt, fcoe_frame_t *frm); 96 97 static void fcoei_logo_peer(void *arg); 98 static void fcoei_fpkt_comp(fc_packet_t *fpkt); 99 100 static uint32_t 101 fcoei_xch_abort(mod_hash_key_t key, mod_hash_val_t *val, void *arg); 102 103 104 /* 105 * fcoei_bind_port 106 * Bind LV port instance with fcoei soft state 107 * 108 * Input: 109 * dip = dev info of fcoei soft state 110 * port_info = fcoei specific parameters about LV port 111 * bind_info = LV specific parameters about fcoei soft state 112 * 113 * Returns: 114 * The pointer to fcoei soft state 115 * 116 * Comments: 117 * Unpon the completion of this call, the port must be offline. 118 * fcoei_port_enabled could trigger it to online 119 */ 120 static void * 121 fcoei_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info, 122 fc_fca_bind_info_t *bind_info) 123 { 124 fcoei_soft_state_t *ss; 125 126 /* 127 * get state info based on the dip 128 */ 129 ss = (fcoei_soft_state_t *) 130 ddi_get_soft_state(fcoei_state, ddi_get_instance(dip)); 131 if (!ss) { 132 FCOEI_LOG(__FUNCTION__, "ss is NULL"); 133 return (NULL); 134 } 135 136 /* 137 * make sure this port isn't bound 138 */ 139 if (ss->ss_flags & SS_FLAG_LV_BOUND) { 140 port_info->pi_error = FC_ALREADY; 141 FCOEI_LOG(__FUNCTION__, "ss has been bound"); 142 return (NULL); 143 } 144 145 if (bind_info->port_num) { 146 /* 147 * make sure request is in bounds 148 */ 149 port_info->pi_error = FC_OUTOFBOUNDS; 150 FCOEI_LOG(__FUNCTION__, "port_num is not 0"); 151 return (NULL); 152 } 153 154 /* 155 * stash the ss_bind_info supplied by the FC Transport 156 */ 157 bcopy(bind_info, &ss->ss_bind_info, sizeof (fc_fca_bind_info_t)); 158 ss->ss_port = bind_info->port_handle; 159 160 /* 161 * RNID parameter 162 */ 163 port_info->pi_rnid_params.status = FC_FAILURE; 164 165 /* 166 * populate T11 FC-HBA details 167 */ 168 fcoei_populate_hba_fru_details(ss, port_info); 169 170 /* 171 * set port's current state, and it is always offline before binding 172 * 173 * We hack pi_port_state to tell LV if it's NODMA_FCA 174 */ 175 port_info->pi_port_state = FC_STATE_FCA_IS_NODMA; 176 177 /* 178 * copy login param 179 */ 180 bcopy(&ss->ss_els_logi, &port_info->pi_login_params, 181 sizeof (la_els_logi_t)); 182 183 /* 184 * Mark it as bound 185 */ 186 atomic_or_32(&ss->ss_flags, SS_FLAG_LV_BOUND); 187 188 /* 189 * Let fcoe to report the link status 190 */ 191 fcoei_port_enabled((void *)ss); 192 193 FCOEI_LOG(__FUNCTION__, "Exit fcoei_bind_port: %p", ss); 194 return (ss); 195 } 196 197 /* 198 * fcoei_unbind_port 199 * Un-bind the fcoei port 200 * 201 * Input: 202 * fca_handle = fcoei soft state set in fcoei_bind_port 203 * 204 * Returns: 205 * N/A 206 * 207 * Comments: 208 * Clear binding flag 209 */ 210 static void 211 fcoei_unbind_port(void *fca_handle) 212 { 213 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)fca_handle; 214 215 atomic_and_32(&ss->ss_flags, ~SS_FLAG_LV_BOUND); 216 ss->ss_eport->eport_ctl(ss->ss_eport, FCOE_CMD_PORT_OFFLINE, NULL); 217 FCOEI_LOG(__FUNCTION__, "Exit fcoei_unbind_port: %p", ss); 218 } 219 220 /* 221 * fcoei_init_pkt 222 * Initialize fcoei related part of fc_packet 223 * 224 * Input: 225 * fca_handle = fcoei soft state set in fcoei_bind_port 226 * fpkt = The pointer to fc_packet 227 * sleep = This call can sleep or not 228 * 229 * Returns: 230 * FC_SUCCESS - Initialization completed successfully 231 * 232 * Comments: 233 * Link the exchange elements with proper objects 234 */ 235 /* ARGSUSED */ 236 static int 237 fcoei_init_pkt(void *fca_handle, fc_packet_t *fpkt, int sleep) 238 { 239 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)fca_handle; 240 fcoei_exchange_t *xch = FPKT2XCH(fpkt); 241 242 ASSERT(sleep + 1); 243 xch->xch_ss = ss; 244 xch->xch_fpkt = fpkt; 245 xch->xch_flags = 0; 246 return (FC_SUCCESS); 247 } 248 249 /* 250 * fcoei_un_init_pkt 251 * Uninitialize fcoei related part of fc_packet 252 * 253 * Input: 254 * fca_handle = fcoei soft state set in fcoei_bind_port 255 * fpkt = The pointer to fc_packet 256 * 257 * Returns: 258 * FC_SUCCESS - Uninitialize successfully 259 * 260 * Comments: 261 * Very simple, just return successfully 262 */ 263 /* ARGSUSED */ 264 static int 265 fcoei_un_init_pkt(void *fca_handle, fc_packet_t *fpkt) 266 { 267 ASSERT(fca_handle && fpkt); 268 return (FC_SUCCESS); 269 } 270 271 /* 272 * fcoei_get_cap 273 * Export FCA hardware and software capability. 274 * 275 * Input: 276 * fca_handle = fcoei soft state set in fcoei_bind_port 277 * cap = pointer to the capability string 278 * ptr = buffer pointer for returning capability 279 * 280 * Returns: 281 * FC_CAP_ERROR - no such capability 282 * FC_CAP_FOUND - the capability was returned and cannot be set 283 * 284 * Comments: 285 * FC_CAP_UNSOL_BUF is one important capability, it will affect the 286 * implementation of fcoei_ub_alloc/free. 287 */ 288 static int 289 fcoei_get_cap(void * fca_handle, char *cap, void *ptr) 290 { 291 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)fca_handle; 292 uint32_t *rptr = (uint32_t *)ptr; 293 int rval = FC_CAP_FOUND; 294 295 ASSERT(fca_handle); 296 FCOEI_LOG(__FUNCTION__, "cap: %s", cap); 297 if (strcmp(cap, FC_NODE_WWN) == 0) { 298 bcopy(&ss->ss_els_logi.node_ww_name.raw_wwn[0], ptr, 8); 299 } else if (strcmp(cap, FC_LOGIN_PARAMS) == 0) { 300 bcopy((void *)&ss->ss_els_logi, ptr, sizeof (la_els_logi_t)); 301 } else if (strcmp(cap, FC_CAP_UNSOL_BUF) == 0) { 302 *rptr = (uint32_t)0; 303 } else if (strcmp(cap, FC_CAP_NOSTREAM_ON_UNALIGN_BUF) == 0) { 304 *rptr = (uint32_t)FC_ALLOW_STREAMING; 305 } else if (strcmp(cap, FC_CAP_PAYLOAD_SIZE) == 0) { 306 *rptr = (uint32_t)2136; 307 } else if (strcmp(cap, FC_CAP_POST_RESET_BEHAVIOR) == 0) { 308 *rptr = FC_RESET_RETURN_ALL; 309 } else if (strcmp(cap, FC_CAP_FCP_DMA) == 0) { 310 *rptr = FC_NO_DVMA_SPACE; 311 } else { 312 rval = FC_CAP_ERROR; 313 FCOEI_LOG(__FUNCTION__, "not supported"); 314 } 315 316 return (rval); 317 } 318 319 /* 320 * fcoei_set_cap 321 * Allow the FC Transport to set FCA capabilities if possible 322 * 323 * Input: 324 * fca_handle = fcoei soft state set in fcoei_bind_port 325 * cap = pointer to the capabilities string. 326 * ptr = buffer pointer for capability. 327 * 328 * Returns: 329 * FC_CAP_ERROR - no such capability 330 * 331 * Comments: 332 * Currently, all capabilities can't be changed. 333 */ 334 static int 335 fcoei_set_cap(void * fca_handle, char *cap, void *ptr) 336 { 337 FCOEI_LOG(__FUNCTION__, "cap: %s, %p, %p", cap, fca_handle, ptr); 338 return (FC_CAP_ERROR); 339 } 340 341 /* 342 * fcoei_getmap 343 * Get lilp map 344 * 345 * Input: 346 * fca_handle = fcoei soft state set in fcoei_bind_port 347 * mapbuf = the buffer to store lilp map 348 * 349 * Returns: 350 * FC_FAILURE - Can't get the lilp map 351 * 352 * Comments: 353 * fcoei can't work in loop topology, so it should never get called 354 */ 355 static int 356 fcoei_getmap(void * fca_handle, fc_lilpmap_t *mapbuf) 357 { 358 FCOEI_LOG(__FUNCTION__, "not: %p-%p", fca_handle, mapbuf); 359 return (FC_FAILURE); 360 } 361 362 /* 363 * fcoei_ub_alloc 364 * Pre-allocate unsolicited buffers at the request of LV 365 * 366 * Input: 367 * fca_handle = fcoei soft state set in fcoei_bind_port 368 * tokens = token array for each buffer. 369 * size = number of tokens 370 * count = the acutual number of allocated unsolicited buffers 371 * type = unsolicited buffer type 372 * 373 * Returns: 374 * FC_SUCCESS - The requested buffers have been freeed 375 * 376 * Comments: 377 * fcoei_get_cap will set UNSOL_BUF to 0, so it should never get called. 378 */ 379 static int 380 fcoei_ub_alloc(void * fca_handle, uint64_t tokens[], uint32_t size, 381 uint32_t *count, uint32_t type) 382 { 383 FCOEI_LOG(__FUNCTION__, "not: %p-%p-%x-%p-%x", fca_handle, tokens, 384 size, count, type); 385 return (FC_SUCCESS); 386 } 387 388 /* 389 * fcoei_ub_free 390 * Free the pre-allocated unsolicited buffers at the request of LV 391 * 392 * Input: 393 * fca_handle = fcoei soft state set in fcoei_bind_port 394 * count = number of buffers. 395 * tokens = token array for each buffer. 396 * 397 * Returns: 398 * FC_SUCCESS - The requested buffers have been freeed 399 * 400 * Comments: 401 * fcoei_get_cap will set UNSOL_BUF to 0, so it should never get called. 402 */ 403 static int 404 fcoei_ub_free(void * fca_handle, uint32_t count, uint64_t tokens[]) 405 { 406 FCOEI_EXT_LOG(__FUNCTION__, "not: %p-%x-%p", fca_handle, count, tokens); 407 return (FC_SUCCESS); 408 } 409 410 /* 411 * fcoei_ub_release 412 * Release unsolicited buffers from FC Transport to FCA for future use 413 * 414 * Input: 415 * fca_handle = fcoei soft state set in fcoei_bind_port 416 * count = number of buffers. 417 * tokens = token array for each buffer. 418 * 419 * Returns: 420 * FC_SUCCESS - The requested buffers have been released. 421 * FC_FAILURE - The requested buffers have not been released. 422 * 423 * Comments: 424 * It will always succeed. It has nothing to do with fcoei_ub_alloc/free. 425 */ 426 static int 427 fcoei_ub_release(void * fca_handle, uint32_t count, uint64_t tokens[]) 428 { 429 fc_unsol_buf_t *ub = *((fc_unsol_buf_t **)tokens); 430 431 if (count != 1) { 432 FCOEI_LOG(__FUNCTION__, "count is not 1: %p", fca_handle); 433 return (FC_FAILURE); 434 } 435 436 kmem_free(ub->ub_buffer, ub->ub_bufsize); 437 kmem_free(ub, sizeof (fc_unsol_buf_t)); 438 FCOEI_EXT_LOG(__FUNCTION__, "ub is freeed"); 439 return (FC_SUCCESS); 440 } 441 442 /* 443 * fcoei_abort 444 * Direct FCA driver to abort an outstanding exchange associated with a 445 * specified fc_packet_t struct 446 * 447 * Input: 448 * fca_handle - fcoei soft state set in fcoei_bind_port 449 * fpkt - A pointer to the fc_packet_t for the exchange to be aborted. 450 * flags - Set to KM_SLEEP if the function may sleep, or KM_NOSLEEP if 451 * the function may not sleep. 452 * 453 * Returns: 454 * FC_ABORTED - The specified exchange was successfully aborted. 455 * FC_ABORTING - The specified exchange is being aborted. 456 * FC_ABORT_FAILED - The specified exchange could not be aborted. 457 * FC_TRANSPORT_ERROR - A transport error occurred while attempting to 458 * abort the specified exchange. 459 * FC_BADEXCHANGE - The specified exchange does not exist. 460 * 461 * Comments: 462 * After the exchange is aborted, the FCA driver must update the relevant 463 * fields in the fc_packet_t struct as per normal exchange completion and 464 * call the pkt_comp function to return the fc_packet_t struct to the FC 465 * Transport. 466 * When an exchange is successfully aborted, the FCA driver must set the 467 * pkt_reason field in the fc_packet_t to FC_REASON_ABORTED and the 468 * pkt_state field in the fc_packet_t to FC_PKT_LOCAL_RJT before returning 469 * the fc_packet_t to the FC Transport. 470 * 471 * Unfortunately, LV doesn't conform to the spec. It will take all these 472 * legal return value as failure to abort. 473 */ 474 static int 475 fcoei_abort(void * fca_handle, fc_packet_t *fpkt, int flags) 476 { 477 FCOEI_LOG(__FUNCTION__, "not: %p-%p-%x", fca_handle, fpkt, flags); 478 return (FC_SUCCESS); 479 } 480 481 /* 482 * fcoei_reset 483 * Reset link or hardware 484 * 485 * Input: 486 * fca_handle = fcoei soft state set in fcoei_bind_port 487 * cmd = reset type command 488 * 489 * Returns: 490 * FC_SUCCESS - Reset has completed successfully 491 * FC_FAILURE - Reset has failed 492 * 493 * Comments: 494 * N/A 495 */ 496 static int 497 fcoei_reset(void * fca_handle, uint32_t cmd) 498 { 499 int rval = FC_SUCCESS; 500 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)fca_handle; 501 fcoei_event_t *ae; 502 503 switch (cmd) { 504 case FC_FCA_LINK_RESET: 505 if (ss->ss_link_state != FC_STATE_ONLINE) { 506 FCOEI_LOG(__FUNCTION__, "not online now: ss-%p", ss); 507 rval = FC_FAILURE; 508 break; 509 } 510 511 /* 512 * This is linkreset phase I 513 */ 514 fcoei_logo_peer(ss); 515 delay(FCOE_SEC2TICK(1) / 10); 516 ss->ss_eport->eport_ctl(ss->ss_eport, FCOE_CMD_PORT_OFFLINE, 0); 517 fcoei_port_event(ss->ss_eport, FCOE_NOTIFY_EPORT_LINK_DOWN); 518 519 /* 520 * Perpare linkreset phase II 521 */ 522 ae = kmem_zalloc(sizeof (*ae), KM_SLEEP); 523 ae->ae_type = AE_EVENT_RESET; 524 ae->ae_obj = ss; 525 526 mutex_enter(&ss->ss_watchdog_mutex); 527 list_insert_tail(&ss->ss_event_list, ae); 528 mutex_exit(&ss->ss_watchdog_mutex); 529 break; 530 531 case FC_FCA_RESET: 532 break; 533 534 case FC_FCA_CORE: 535 break; 536 537 case FC_FCA_RESET_CORE: 538 break; 539 540 default: 541 rval = FC_FAILURE; 542 FCOEI_LOG(__FUNCTION__, "cmd-%x not supported", cmd); 543 break; 544 } 545 546 return (rval); 547 } 548 549 /* 550 * fcoei_port_manage 551 * Perform various port management operations at the request of LV 552 * 553 * Input: 554 * fca_handle = fcoei soft state set in fcoei_bind_port 555 * pm = the pointer to the struct specifying the port management operation 556 * 557 * Returns: 558 * FC_SUCCESS - The request completed successfully 559 * FC_FAILURE - The request did not complete successfully 560 * 561 * Comments: 562 * N/A 563 */ 564 static int 565 fcoei_port_manage(void * fca_handle, fc_fca_pm_t *pm) 566 { 567 int rval = FC_FAILURE; 568 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)fca_handle; 569 570 if (fca_handle == NULL || pm == NULL) { 571 return (rval); 572 } 573 574 FCOEI_LOG(__FUNCTION__, "code0x%x, %p", pm->pm_cmd_code, fca_handle); 575 switch (pm->pm_cmd_code) { 576 577 case FC_PORT_GET_NODE_ID: 578 { 579 if (pm->pm_data_len < sizeof (fc_rnid_t)) { 580 rval = FC_NOMEM; 581 break; 582 } 583 ss->ss_rnid.port_id = ss->ss_p2p_info.fca_d_id; 584 bcopy((void *)&ss->ss_rnid, 585 pm->pm_data_buf, sizeof (fc_rnid_t)); 586 rval = FC_SUCCESS; 587 break; 588 } 589 590 case FC_PORT_SET_NODE_ID: 591 { 592 if (pm->pm_data_len < sizeof (fc_rnid_t)) { 593 rval = FC_NOMEM; 594 break; 595 } 596 bcopy(pm->pm_data_buf, 597 (void *)&ss->ss_rnid, sizeof (fc_rnid_t)); 598 rval = FC_SUCCESS; 599 break; 600 } 601 602 default: 603 FCOEI_LOG(__FUNCTION__, "unsupported cmd-%x", pm->pm_cmd_code); 604 rval = FC_INVALID_REQUEST; 605 break; 606 } 607 608 return (rval); 609 } 610 611 /* 612 * fcoei_get_device 613 * Get fcoei remote port with FCID of d_id 614 * 615 * Input: 616 * fca_handle = fcoei soft state set in fcoei_bind_port 617 * d_id = 24-bit FCID of remote port 618 * 619 * Returns: 620 * The pointer to fcoei remote port 621 * 622 * Comments: 623 * fcoei has no remote port device 624 */ 625 static void * 626 fcoei_get_device(void *fca_handle, fc_portid_t d_id) 627 { 628 FCOEI_EXT_LOG(__FUNCTION__, "not supported: %p-%x", fca_handle, d_id); 629 return (NULL); 630 } 631 632 /* 633 * fcoei_notify 634 * Notify the change of target device 635 * 636 * Input: 637 * fca_handle = fcoei soft state set in fcoei_bind_port 638 * cmd = detailed cmd 639 * 640 * Returns: 641 * FC_SUCCESS - Notification completed successfully 642 * 643 * Comments: 644 * It's only needed to support non-COMSTAR FC target, so it should 645 * never get called. 646 */ 647 static int 648 fcoei_notify(void *fca_handle, uint32_t cmd) 649 { 650 FCOEI_LOG(__FUNCTION__, "not supported: %p-%x", fca_handle, cmd); 651 return (FC_SUCCESS); 652 } 653 654 /* 655 * fcoei_transport 656 * Submit FCP/CT requests 657 * 658 * Input: 659 * fca_handle - fcoei soft state set in fcoei_bind_port 660 * fpkt - LV fc_packet 661 * 662 * Returns: 663 * N/A 664 * 665 * Comments: 666 * N/A 667 */ 668 static int 669 fcoei_transport(void *fca_handle, fc_packet_t *fpkt) 670 { 671 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)fca_handle; 672 fcoei_exchange_t *xch = FPKT2XCH(fpkt); 673 uint16_t pkt_tran_flags = fpkt->pkt_tran_flags; 674 675 xch->xch_start_tick = ddi_get_lbolt(); 676 xch->xch_end_tick = xch->xch_start_tick + 677 FCOE_SEC2TICK(fpkt->pkt_timeout); 678 xch->xch_ae.ae_type = AE_EVENT_EXCHANGE; 679 xch->xch_ae.ae_obj = xch; 680 681 if (pkt_tran_flags & FC_TRAN_NO_INTR) { 682 FCOEI_LOG(__FUNCTION__, "AaA polling: %p-%p", fpkt, xch); 683 sema_init(&xch->xch_sema, 0, NULL, SEMA_DRIVER, NULL); 684 } 685 686 mutex_enter(&ss->ss_watchdog_mutex); 687 list_insert_tail(&ss->ss_event_list, &xch->xch_ae); 688 if (ss->ss_flags & SS_FLAG_WATCHDOG_IDLE) { 689 cv_signal(&ss->ss_watchdog_cv); 690 } 691 mutex_exit(&ss->ss_watchdog_mutex); 692 693 if (pkt_tran_flags & FC_TRAN_NO_INTR) { 694 FCOEI_LOG(__FUNCTION__, "BaB polling: %p-%p", fpkt, xch); 695 sema_p(&xch->xch_sema); 696 sema_destroy(&xch->xch_sema); 697 FCOEI_LOG(__FUNCTION__, "after polling: %p-%p", fpkt, xch); 698 } 699 700 return (FC_SUCCESS); 701 } 702 703 /* 704 * fcoei_els_send 705 * Submit ELS request or response 706 * 707 * Input: 708 * fca_handle - fcoei soft state set in fcoei_bind_port 709 * fpkt = LV fc_packet 710 * 711 * Returns: 712 * N/A 713 * 714 * Comments: 715 * N/A 716 */ 717 static int 718 fcoei_els_send(void *fca_handle, fc_packet_t *fpkt) 719 { 720 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)fca_handle; 721 fcoei_exchange_t *xch = FPKT2XCH(fpkt); 722 723 if (fpkt->pkt_tran_flags & FC_TRAN_NO_INTR) { 724 FCOEI_LOG(__FUNCTION__, "ELS poll mode is not supported"); 725 return (FC_BADPACKET); 726 } 727 728 xch->xch_start_tick = ddi_get_lbolt(); 729 xch->xch_end_tick = xch->xch_start_tick + 730 FCOE_SEC2TICK(fpkt->pkt_timeout); 731 xch->xch_ae.ae_type = AE_EVENT_EXCHANGE; 732 xch->xch_ae.ae_obj = xch; 733 734 /* 735 * LV could release ub after this call, so we must save the ub type 736 * for later use 737 */ 738 if (fpkt->pkt_cmd_fhdr.r_ctl == R_CTL_ELS_RSP) { 739 ((uint8_t *)&fpkt->pkt_fca_rsvd1)[0] = 740 ((fc_unsol_buf_t *)fpkt->pkt_ub_resp_token)->ub_buffer[0]; 741 } 742 743 mutex_enter(&ss->ss_watchdog_mutex); 744 list_insert_tail(&ss->ss_event_list, &xch->xch_ae); 745 if (ss->ss_flags & SS_FLAG_WATCHDOG_IDLE) { 746 cv_signal(&ss->ss_watchdog_cv); 747 } 748 mutex_exit(&ss->ss_watchdog_mutex); 749 750 return (FC_SUCCESS); 751 } 752 753 /* 754 * fcoei_populate_hba_fru_details 755 * Fill detailed information about HBA 756 * 757 * Input: 758 * ss - fcoei soft state 759 * port_info = fc_fca_port_info_t that need be updated 760 * 761 * Returns: 762 * N/A 763 * 764 * Comments: 765 * N/A 766 */ 767 static void 768 fcoei_populate_hba_fru_details(fcoei_soft_state_t *ss, 769 fc_fca_port_info_t *port_info) 770 { 771 fca_port_attrs_t *port_attrs = &(port_info->pi_attrs); 772 int instance; 773 774 ASSERT(ss != NULL); 775 (void) snprintf(port_attrs->manufacturer, FCHBA_MANUFACTURER_LEN, 776 "Sun Microsystems, Inc."); 777 (void) snprintf(port_attrs->driver_name, FCHBA_DRIVER_NAME_LEN, 778 "%s", FCOEI_NAME_VERSION); 779 (void) snprintf(port_attrs->driver_version, FCHBA_DRIVER_VERSION_LEN, 780 "%s", FCOEI_VERSION); 781 (void) strcpy(port_attrs->serial_number, "N/A"); 782 (void) strcpy(port_attrs->hardware_version, "N/A"); 783 (void) strcpy(port_attrs->model, "FCoE Virtual FC HBA"); 784 (void) strcpy(port_attrs->model_description, "N/A"); 785 (void) strcpy(port_attrs->firmware_version, "N/A"); 786 (void) strcpy(port_attrs->option_rom_version, "N/A"); 787 788 port_attrs->vendor_specific_id = 0xFC0E; 789 port_attrs->max_frame_size = FCOE_MAX_FC_FRAME_SIZE; 790 port_attrs->supported_cos = 0x10000000; 791 port_attrs->supported_speed = FC_HBA_PORTSPEED_1GBIT | 792 FC_HBA_PORTSPEED_10GBIT; 793 instance = ddi_get_instance(ss->ss_dip); 794 port_attrs->hba_fru_details.high = 795 (short)((instance & 0xffff0000) >> 16); 796 port_attrs->hba_fru_details.low = 797 (short)(instance & 0x0000ffff); 798 } 799 800 /* 801 * fcoei_port_enabled 802 * Notify fcoe that the port has been enabled 803 * 804 * Input: 805 * arg = the related soft state 806 * 807 * Returns: 808 * N/A 809 * 810 * Comments: 811 * Only after this, fcoe will report the link status to us 812 */ 813 static void 814 fcoei_port_enabled(void *arg) 815 { 816 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)arg; 817 818 ss->ss_eport->eport_ctl(ss->ss_eport, FCOE_CMD_PORT_ONLINE, NULL); 819 } 820 821 822 /* 823 * fcoei_initiate_ct_req 824 * Fill and submit CT request 825 * 826 * Input: 827 * xch - the exchange that will be initiated 828 * 829 * Returns: 830 * N/A 831 * 832 * Comments: 833 * N/A 834 */ 835 static void 836 fcoei_initiate_ct_req(fcoei_exchange_t *xch) 837 { 838 fc_packet_t *fpkt = xch->xch_fpkt; 839 fc_ct_header_t *ct = (fc_ct_header_t *)(void *)fpkt->pkt_cmd; 840 uint8_t *bp = (uint8_t *)fpkt->pkt_cmd; 841 fcoe_frame_t *frm; 842 int offset; 843 int idx; 844 uint32_t cmd_len = fpkt->pkt_cmdlen; 845 846 /* 847 * Ensure it's 4-byte aligned 848 */ 849 cmd_len = P2ROUNDUP(cmd_len, 4); 850 851 /* 852 * Allocate CT request frame 853 */ 854 frm = xch->xch_ss->ss_eport->eport_alloc_frame(xch->xch_ss->ss_eport, 855 cmd_len + FCFH_SIZE, NULL); 856 if (frm == NULL) { 857 FCOEI_LOG(__FUNCTION__, "failed to alloc: %p", xch); 858 return; 859 } 860 861 bzero(frm->frm_payload, cmd_len); 862 xch->xch_cnt = xch->xch_ss->ss_sol_cnt; 863 atomic_inc_32(xch->xch_cnt); 864 865 FFM_R_CTL(fpkt->pkt_cmd_fhdr.r_ctl, frm); 866 FFM_D_ID(fpkt->pkt_cmd_fhdr.d_id, frm); 867 FFM_S_ID(fpkt->pkt_cmd_fhdr.s_id, frm); 868 FFM_TYPE(fpkt->pkt_cmd_fhdr.type, frm); 869 FFM_F_CTL(fpkt->pkt_cmd_fhdr.f_ctl, frm); 870 FFM_OXID(xch->xch_oxid, frm); 871 FFM_RXID(xch->xch_rxid, frm); 872 fcoei_init_ifm(frm, xch); 873 874 /* 875 * CT header (FC payload) 876 */ 877 offset = 0; 878 FCOE_V2B_1(ct->ct_rev, FPLD + offset); 879 880 offset = 1; 881 FCOE_V2B_3(ct->ct_inid, FPLD + offset); 882 883 offset = 4; 884 FCOE_V2B_1(ct->ct_fcstype, FPLD + offset); 885 886 offset = 5; 887 FCOE_V2B_1(ct->ct_fcssubtype, FPLD + offset); 888 889 offset = 6; 890 FCOE_V2B_1(ct->ct_options, FPLD + offset); 891 892 offset = 8; 893 FCOE_V2B_2(ct->ct_cmdrsp, FPLD + offset); 894 895 offset = 10; 896 FCOE_V2B_2(ct->ct_aiusize, FPLD + offset); 897 898 offset = 13; 899 FCOE_V2B_1(ct->ct_reason, FPLD + offset); 900 901 offset = 14; 902 FCOE_V2B_1(ct->ct_expln, FPLD + offset); 903 904 offset = 15; 905 FCOE_V2B_1(ct->ct_vendor, FPLD + offset); 906 907 /* 908 * CT payload (FC payload) 909 */ 910 switch (ct->ct_fcstype) { 911 case FCSTYPE_DIRECTORY: 912 switch (ct->ct_cmdrsp) { 913 case NS_GA_NXT: 914 case NS_GPN_ID: 915 case NS_GNN_ID: 916 case NS_GCS_ID: 917 case NS_GFT_ID: 918 case NS_GSPN_ID: 919 case NS_GPT_ID: 920 case NS_GID_FT: 921 case NS_GID_PT: 922 case NS_DA_ID: 923 offset = 16; 924 FCOE_V2B_4(((uint32_t *)(intptr_t)(bp + offset))[0], 925 FPLD + offset); 926 break; 927 928 case NS_GID_PN: 929 offset = 16; 930 bcopy(bp + offset, FPLD + offset, 8); 931 break; 932 933 case NS_RNN_ID: 934 case NS_RPN_ID: 935 offset = 16; 936 FCOE_V2B_4(((uint32_t *)(intptr_t)(bp + offset))[0], 937 FPLD + offset); 938 939 offset = 20; 940 bcopy(bp + offset, FPLD + offset, 8); 941 break; 942 943 case NS_RSPN_ID: 944 offset = 16; 945 FCOE_V2B_4(((uint32_t *)(intptr_t)(bp + offset))[0], 946 FPLD + offset); 947 948 offset = 20; 949 bcopy(bp + offset, FPLD + offset, bp[20] + 1); 950 break; 951 952 case NS_RSNN_NN: 953 offset = 16; 954 bcopy(bp + offset, FPLD + offset, 8); 955 956 offset = 24; 957 bcopy(bp + offset, FPLD + offset, bp[24] + 1); 958 break; 959 960 case NS_RFT_ID: 961 offset = 16; 962 FCOE_V2B_4(((uint32_t *)(intptr_t)(bp + offset))[0], 963 FPLD + offset); 964 965 /* 966 * fp use bcopy to copy fp_fc4_types, 967 * we need to swap order for each integer 968 */ 969 offset = 20; 970 for (idx = 0; idx < 8; idx++) { 971 FCOE_V2B_4( 972 ((uint32_t *)(intptr_t)(bp + offset))[0], 973 FPLD + offset); 974 offset += 4; 975 } 976 break; 977 978 case NS_RCS_ID: 979 case NS_RPT_ID: 980 offset = 16; 981 FCOE_V2B_4(((uint32_t *)(intptr_t)(bp + offset))[0], 982 FPLD + offset); 983 984 offset = 20; 985 FCOE_V2B_4(((uint32_t *)(intptr_t)(bp + offset))[0], 986 FPLD + offset); 987 break; 988 989 case NS_RIP_NN: 990 offset = 16; 991 bcopy(bp + offset, FPLD + offset, 24); 992 break; 993 994 default: 995 fcoei_complete_xch(xch, frm, FC_PKT_FAILURE, 996 FC_REASON_CMD_UNSUPPORTED); 997 break; 998 } 999 break; /* FCSTYPE_DIRECTORY */ 1000 1001 case FCSTYPE_MGMTSERVICE: 1002 switch (ct->ct_cmdrsp) { 1003 case MS_GIEL: 1004 FCOEI_LOG(__FUNCTION__, 1005 "MS_GIEL ct_fcstype %x, ct_cmdrsp: %x", 1006 ct->ct_fcstype, ct->ct_cmdrsp); 1007 break; 1008 1009 default: 1010 fcoei_complete_xch(xch, frm, FC_PKT_FAILURE, 1011 FC_REASON_CMD_UNSUPPORTED); 1012 break; 1013 } 1014 break; /* FCSTYPE_MGMTSERVICE */ 1015 1016 default: 1017 fcoei_complete_xch(xch, frm, FC_PKT_FAILURE, 1018 FC_REASON_CMD_UNSUPPORTED); 1019 break; 1020 } 1021 xch->xch_ss->ss_eport->eport_tx_frame(frm); 1022 } 1023 1024 /* 1025 * fcoei_initiate_fcp_cmd 1026 * Submit FCP command 1027 * 1028 * Input: 1029 * xch - the exchange to be submitted 1030 * 1031 * Returns: 1032 * N/A 1033 * 1034 * Comments: 1035 * N/A 1036 */ 1037 static void 1038 fcoei_initiate_fcp_cmd(fcoei_exchange_t *xch) 1039 { 1040 fc_packet_t *fpkt = xch->xch_fpkt; 1041 fcoe_frame_t *frm; 1042 fcp_cmd_t *fcp_cmd_iu = (fcp_cmd_t *)(void *)fpkt->pkt_cmd; 1043 int offset = 0; 1044 1045 ASSERT((fpkt->pkt_cmdlen % 4) == 0); 1046 frm = xch->xch_ss->ss_eport->eport_alloc_frame(xch->xch_ss->ss_eport, 1047 fpkt->pkt_cmdlen + FCFH_SIZE, NULL); 1048 if (!frm) { 1049 ASSERT(0); 1050 } else { 1051 fcoei_init_ifm(frm, xch); 1052 bzero(frm->frm_payload, fpkt->pkt_cmdlen); 1053 } 1054 1055 /* 1056 * This will affect timing check 1057 */ 1058 xch->xch_cnt = xch->xch_ss->ss_sol_cnt; 1059 atomic_inc_32(xch->xch_cnt); 1060 1061 /* 1062 * Set exchange residual bytes 1063 */ 1064 xch->xch_resid = (int)fpkt->pkt_datalen; 1065 1066 /* 1067 * Fill FCP command IU 1068 * 1069 * fcp_ent_addr 1070 */ 1071 FCOE_V2B_2(fcp_cmd_iu->fcp_ent_addr.ent_addr_0, 1072 frm->frm_payload + offset); 1073 offset += 2; 1074 FCOE_V2B_2(fcp_cmd_iu->fcp_ent_addr.ent_addr_1, 1075 frm->frm_payload + offset); 1076 offset += 2; 1077 FCOE_V2B_2(fcp_cmd_iu->fcp_ent_addr.ent_addr_2, 1078 frm->frm_payload + offset); 1079 offset += 2; 1080 FCOE_V2B_2(fcp_cmd_iu->fcp_ent_addr.ent_addr_3, 1081 frm->frm_payload + offset); 1082 /* 1083 * fcp_cntl 1084 */ 1085 offset = offsetof(fcp_cmd_t, fcp_cntl); 1086 frm->frm_payload[offset] = 0; 1087 1088 offset += 1; 1089 frm->frm_payload[offset] = fcp_cmd_iu->fcp_cntl.cntl_qtype & 0x07; 1090 offset += 1; 1091 frm->frm_payload[offset] = 1092 (fcp_cmd_iu->fcp_cntl.cntl_kill_tsk << 7) | 1093 (fcp_cmd_iu->fcp_cntl.cntl_clr_aca << 6) | 1094 (fcp_cmd_iu->fcp_cntl.cntl_reset_tgt << 5) | 1095 (fcp_cmd_iu->fcp_cntl.cntl_reset_lun << 4) | 1096 (fcp_cmd_iu->fcp_cntl.cntl_clr_tsk << 2) | 1097 (fcp_cmd_iu->fcp_cntl.cntl_abort_tsk << 1); 1098 offset += 1; 1099 frm->frm_payload[offset] = 1100 (fcp_cmd_iu->fcp_cntl.cntl_read_data << 1) | 1101 (fcp_cmd_iu->fcp_cntl.cntl_write_data); 1102 /* 1103 * fcp_cdb 1104 */ 1105 offset = offsetof(fcp_cmd_t, fcp_cdb); 1106 bcopy(fcp_cmd_iu->fcp_cdb, frm->frm_payload + offset, FCP_CDB_SIZE); 1107 /* 1108 * fcp_data_len 1109 */ 1110 offset += FCP_CDB_SIZE; 1111 FCOE_V2B_4(fcp_cmd_iu->fcp_data_len, frm->frm_payload + offset); 1112 1113 /* 1114 * FC frame header 1115 */ 1116 FRM2IFM(frm)->ifm_rctl = fpkt->pkt_cmd_fhdr.r_ctl; 1117 1118 FFM_R_CTL(fpkt->pkt_cmd_fhdr.r_ctl, frm); 1119 FFM_D_ID(fpkt->pkt_cmd_fhdr.d_id, frm); 1120 FFM_S_ID(fpkt->pkt_cmd_fhdr.s_id, frm); 1121 FFM_TYPE(fpkt->pkt_cmd_fhdr.type, frm); 1122 FFM_F_CTL(0x290000, frm); 1123 FFM_OXID(xch->xch_oxid, frm); 1124 FFM_RXID(xch->xch_rxid, frm); 1125 1126 xch->xch_ss->ss_eport->eport_tx_frame(frm); 1127 } 1128 1129 /* 1130 * fcoei_initiate_els_req 1131 * Initiate ELS request 1132 * 1133 * Input: 1134 * xch = the exchange that will be initiated 1135 * 1136 * Returns: 1137 * N/A 1138 * 1139 * Comments: 1140 * N/A 1141 */ 1142 static void 1143 fcoei_initiate_els_req(fcoei_exchange_t *xch) 1144 { 1145 fc_packet_t *fpkt = xch->xch_fpkt; 1146 fcoe_frame_t *frm; 1147 ls_code_t *els_code; 1148 1149 ASSERT((fpkt->pkt_cmdlen % 4) == 0); 1150 frm = xch->xch_ss->ss_eport->eport_alloc_frame(xch->xch_ss->ss_eport, 1151 fpkt->pkt_cmdlen + FCFH_SIZE, NULL); 1152 if (!frm) { 1153 ASSERT(0); 1154 } else { 1155 fcoei_init_ifm(frm, xch); 1156 bzero(frm->frm_payload, fpkt->pkt_cmdlen); 1157 } 1158 1159 /* 1160 * This will affect timing check 1161 */ 1162 xch->xch_cnt = xch->xch_ss->ss_sol_cnt; 1163 atomic_inc_32(xch->xch_cnt); 1164 1165 els_code = (ls_code_t *)(void *)fpkt->pkt_cmd; 1166 switch (els_code->ls_code) { 1167 case LA_ELS_FLOGI: 1168 /* 1169 * For FLOGI, we expect response within E_D_TOV 1170 */ 1171 xch->xch_start_tick = ddi_get_lbolt(); 1172 xch->xch_end_tick = xch->xch_start_tick + 1173 FCOE_SEC2TICK(2); 1174 xch->xch_ss->ss_flags &= ~SS_FLAG_FLOGI_FAILED; 1175 /* FALLTHROUGH */ 1176 1177 case LA_ELS_PLOGI: 1178 fcoei_fill_els_logi_cmd(fpkt, frm); 1179 break; 1180 1181 case LA_ELS_PRLI: 1182 fcoei_fill_els_prli_cmd(fpkt, frm); 1183 break; 1184 1185 case LA_ELS_SCR: 1186 fcoei_fill_els_scr_cmd(fpkt, frm); 1187 break; 1188 1189 case LA_ELS_LINIT: 1190 fcoei_fill_els_linit_cmd(fpkt, frm); 1191 break; 1192 1193 case LA_ELS_ADISC: 1194 fcoei_fill_els_adisc_cmd(fpkt, frm); 1195 break; 1196 1197 case LA_ELS_LOGO: 1198 /* 1199 * For LOGO, we expect response within E_D_TOV 1200 */ 1201 xch->xch_start_tick = ddi_get_lbolt(); 1202 xch->xch_end_tick = xch->xch_start_tick + 1203 FCOE_SEC2TICK(2); 1204 fcoei_fill_els_logo_cmd(fpkt, frm); 1205 break; 1206 case LA_ELS_RLS: 1207 fcoei_fill_els_rls_cmd(fpkt, frm); 1208 break; 1209 case LA_ELS_RNID: 1210 fcoei_fill_els_rnid_cmd(fpkt, frm); 1211 break; 1212 default: 1213 fcoei_complete_xch(xch, frm, FC_PKT_FAILURE, 1214 FC_REASON_CMD_UNSUPPORTED); 1215 return; 1216 } 1217 1218 /* 1219 * set ifm_rtcl 1220 */ 1221 FRM2IFM(frm)->ifm_rctl = fpkt->pkt_cmd_fhdr.r_ctl; 1222 1223 /* 1224 * FCPH 1225 */ 1226 FFM_R_CTL(fpkt->pkt_cmd_fhdr.r_ctl, frm); 1227 FFM_D_ID(fpkt->pkt_cmd_fhdr.d_id, frm); 1228 FFM_S_ID(fpkt->pkt_cmd_fhdr.s_id, frm); 1229 FFM_TYPE(fpkt->pkt_cmd_fhdr.type, frm); 1230 FFM_F_CTL(0x290000, frm); 1231 FFM_OXID(xch->xch_oxid, frm); 1232 FFM_RXID(xch->xch_rxid, frm); 1233 1234 xch->xch_ss->ss_eport->eport_tx_frame(frm); 1235 } 1236 1237 /* 1238 * fcoei_initiate_els_resp 1239 * Originate ELS response 1240 * 1241 * Input: 1242 * xch = the associated exchange 1243 * 1244 * Returns: 1245 * N/A 1246 * 1247 * Comments: 1248 * N/A 1249 */ 1250 static void 1251 fcoei_initiate_els_resp(fcoei_exchange_t *xch) 1252 { 1253 fc_packet_t *fpkt = xch->xch_fpkt; 1254 fcoe_frame_t *frm; 1255 1256 ASSERT((fpkt->pkt_cmdlen % 4) == 0); 1257 frm = xch->xch_ss->ss_eport->eport_alloc_frame(xch->xch_ss->ss_eport, 1258 fpkt->pkt_cmdlen + FCFH_SIZE, NULL); 1259 if (!frm) { 1260 ASSERT(0); 1261 } else { 1262 fcoei_init_ifm(frm, xch); 1263 bzero(frm->frm_payload, fpkt->pkt_cmdlen); 1264 } 1265 1266 /* 1267 * This will affect timing check 1268 */ 1269 xch->xch_cnt = xch->xch_ss->ss_unsol_cnt; 1270 atomic_inc_32(xch->xch_cnt); 1271 1272 /* 1273 * Set ifm_rctl 1274 */ 1275 FRM2IFM(frm)->ifm_rctl = fpkt->pkt_cmd_fhdr.r_ctl; 1276 1277 /* 1278 * FCPH 1279 */ 1280 FFM_R_CTL(fpkt->pkt_cmd_fhdr.r_ctl, frm); 1281 FFM_D_ID(fpkt->pkt_cmd_fhdr.d_id, frm); 1282 FFM_S_ID(fpkt->pkt_cmd_fhdr.s_id, frm); 1283 FFM_TYPE(fpkt->pkt_cmd_fhdr.type, frm); 1284 FFM_F_CTL(0x980000, frm); 1285 FFM_OXID(xch->xch_oxid, frm); 1286 FFM_RXID(xch->xch_rxid, frm); 1287 1288 switch (((uint8_t *)&fpkt->pkt_fca_rsvd1)[0]) { 1289 case LA_ELS_FLOGI: 1290 fcoei_fill_els_logi_resp(fpkt, frm); 1291 break; 1292 1293 case LA_ELS_PLOGI: 1294 if (FRM2SS(frm)->ss_eport->eport_flags & 1295 EPORT_FLAG_IS_DIRECT_P2P) { 1296 FRM2SS(frm)->ss_p2p_info.fca_d_id = FRM_S_ID(frm); 1297 FRM2SS(frm)->ss_p2p_info.d_id = FRM_D_ID(frm); 1298 } 1299 1300 fcoei_fill_els_logi_resp(fpkt, frm); 1301 break; 1302 1303 case LA_ELS_PRLI: 1304 fcoei_fill_els_prli_resp(fpkt, frm); 1305 break; 1306 1307 case LA_ELS_ADISC: 1308 fcoei_fill_els_adisc_resp(fpkt, frm); 1309 break; 1310 1311 case LA_ELS_LOGO: 1312 fcoei_fill_els_logo_resp(fpkt, frm); 1313 break; 1314 case LA_ELS_RSCN: 1315 fcoei_fill_els_acc_resp(fpkt, frm); 1316 break; 1317 1318 default: 1319 fcoei_complete_xch(xch, frm, FC_PKT_FAILURE, 1320 FC_REASON_CMD_UNSUPPORTED); 1321 return; 1322 } 1323 1324 xch->xch_ss->ss_eport->eport_tx_frame(frm); 1325 } 1326 1327 /* 1328 * fcoei_fill_els_logi_cmd 1329 * Fill SCR (state change register) command frame 1330 * 1331 * Input: 1332 * fpkt = LV fc_packet 1333 * frm = Unsolicited frame containing LOGI response 1334 * 1335 * Returns: 1336 * N/A 1337 * 1338 * Comments: 1339 * N/A 1340 */ 1341 static void 1342 fcoei_fill_els_logi_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm) 1343 { 1344 la_els_logi_t *els_logi = (la_els_logi_t *)(void *)fpkt->pkt_cmd; 1345 int offset; 1346 1347 /* 1348 * fill ls_code 1349 */ 1350 offset = 0; 1351 FCOE_V2B_1(els_logi->ls_code.ls_code, FPLD + offset); 1352 1353 /* 1354 * fill common service parameters 1355 */ 1356 offset = 4; 1357 FCOE_V2B_2(els_logi->common_service.fcph_version, FPLD + offset); 1358 1359 offset = 6; 1360 FCOE_V2B_2(els_logi->common_service.btob_credit, FPLD + offset); 1361 1362 offset = 8; 1363 FCOE_V2B_2(els_logi->common_service.cmn_features, FPLD + offset); 1364 1365 offset = 10; 1366 FCOE_V2B_2(els_logi->common_service.rx_bufsize, FPLD + offset); 1367 1368 offset = 12; 1369 FCOE_V2B_2(els_logi->common_service.conc_sequences, FPLD + offset); 1370 1371 offset = 14; 1372 FCOE_V2B_2(els_logi->common_service.relative_offset, FPLD + offset); 1373 1374 offset = 16; 1375 FCOE_V2B_4(els_logi->common_service.e_d_tov, FPLD + offset); 1376 1377 /* 1378 * port/node wwn 1379 */ 1380 offset = 20; 1381 bcopy(&els_logi->nport_ww_name, FPLD + offset, 8); 1382 1383 offset = 28; 1384 bcopy(&els_logi->node_ww_name, FPLD + offset, 8); 1385 1386 /* 1387 * class_3 1388 */ 1389 offset = 68; 1390 FCOE_V2B_2(els_logi->class_3.class_opt, FPLD + offset); 1391 1392 offset = 70; 1393 FCOE_V2B_2(els_logi->class_3.initiator_ctl, FPLD + offset); 1394 1395 offset = 72; 1396 FCOE_V2B_2(els_logi->class_3.recipient_ctl, FPLD + offset); 1397 1398 offset = 74; 1399 FCOE_V2B_2(els_logi->class_3.rcv_size, FPLD + offset); 1400 1401 offset = 76; 1402 FCOE_V2B_2(els_logi->class_3.conc_sequences, FPLD + offset); 1403 1404 offset = 78; 1405 FCOE_V2B_2(els_logi->class_3.n_port_e_to_e_credit, FPLD + offset); 1406 1407 offset = 80; 1408 FCOE_V2B_2(els_logi->class_3.open_seq_per_xchng, FPLD + offset); 1409 /* 1410 * needn't touch other fields 1411 */ 1412 } 1413 1414 /* 1415 * fcoei_fill_prli_cmd 1416 * Fill PRLI command frame 1417 * 1418 * Input: 1419 * fpkt = LV fc_packet 1420 * frm = Unsolicited frame containing PRLI response 1421 * 1422 * Returns: 1423 * N/A 1424 * 1425 * Comments: 1426 * N/A 1427 */ 1428 static void 1429 fcoei_fill_els_prli_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm) 1430 { 1431 int offset = 0; 1432 la_els_prli_t *els_prli = (la_els_prli_t *)(void *)fpkt->pkt_cmd; 1433 struct fcp_prli *fcp_spp = 1434 (struct fcp_prli *)(void *)els_prli->service_params; 1435 1436 /* 1437 * fill basic PRLI fields 1438 */ 1439 offset = 0; 1440 FCOE_V2B_1(els_prli->ls_code, FPLD + offset); 1441 1442 offset = 1; 1443 FCOE_V2B_1(els_prli->page_length, FPLD + offset); 1444 1445 offset = 2; 1446 FCOE_V2B_2(els_prli->payload_length, FPLD + offset); 1447 1448 /* 1449 * fill FCP service parameters page 1450 */ 1451 offset = 4; 1452 FCOE_V2B_1(fcp_spp->type, FPLD + offset); 1453 1454 /* 1455 * PRLI flags, only 3 bits are valid 1456 */ 1457 offset = 6; 1458 1459 FCOE_V2B_2(((fcp_spp->orig_process_assoc_valid << 15) | 1460 (fcp_spp->resp_process_assoc_valid << 14) | 1461 (fcp_spp->establish_image_pair << 13)), FPLD + offset); 1462 1463 /* 1464 * process associator 1465 */ 1466 offset = 8; 1467 FCOE_V2B_4(fcp_spp->orig_process_associator, FPLD + offset); 1468 1469 offset = 12; 1470 FCOE_V2B_4(fcp_spp->resp_process_associator, FPLD + offset); 1471 1472 /* 1473 * FC-4 type 1474 */ 1475 offset = 16; 1476 FCOE_V2B_4((fcp_spp->retry << 8) | 1477 (fcp_spp->confirmed_compl_allowed << 7) | 1478 (fcp_spp->data_overlay_allowed << 6) | 1479 (fcp_spp->initiator_fn << 5) | (fcp_spp->target_fn << 4) | 1480 (fcp_spp->read_xfer_rdy_disabled << 1) | 1481 (fcp_spp->write_xfer_rdy_disabled), FPLD + offset); 1482 } 1483 1484 /* 1485 * fcoei_fill_els_scr_cmd 1486 * Fill SCR (state change register) command frame 1487 * 1488 * Input: 1489 * fpkt = LV fc_packet 1490 * frm = Unsolicited frame containing SCR command 1491 * 1492 * Returns: 1493 * N/A 1494 * 1495 * Comments: 1496 * N/A 1497 */ 1498 static void 1499 fcoei_fill_els_scr_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm) 1500 { 1501 fc_scr_req_t *els_scr = (fc_scr_req_t *)(void *)fpkt->pkt_cmd; 1502 int offset; 1503 1504 offset = 0; 1505 FCOE_V2B_1(els_scr->ls_code.ls_code, FPLD + offset); 1506 1507 offset = 7; 1508 FCOE_V2B_1(els_scr->scr_func, FPLD + offset); 1509 } 1510 1511 /* 1512 * fcoei_fill_els_adisc_cmd 1513 * Fill ADISC command frame 1514 * 1515 * Input: 1516 * fpkt = LV fc_packet 1517 * frm = Unsolicited frame containing ADISC command 1518 * 1519 * Returns: 1520 * N/A 1521 * 1522 * Comments: 1523 * N/A 1524 */ 1525 static void 1526 fcoei_fill_els_adisc_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm) 1527 { 1528 la_els_adisc_t *els_adisc = (la_els_adisc_t *)(void *)fpkt->pkt_cmd; 1529 int offset; 1530 1531 offset = 0; 1532 FCOE_V2B_1(els_adisc->ls_code.ls_code, FPLD + offset); 1533 1534 offset = 5; 1535 FCOE_V2B_3(els_adisc->hard_addr.hard_addr, FPLD + offset); 1536 1537 offset = 8; 1538 bcopy(&els_adisc->port_wwn, FPLD + offset, 8); 1539 1540 offset = 16; 1541 bcopy(&els_adisc->node_wwn, FPLD + offset, 8); 1542 1543 offset = 25; 1544 FCOE_V2B_3(els_adisc->nport_id.port_id, FPLD + offset); 1545 } 1546 1547 /* 1548 * fcoei_fill_els_linit_cmd 1549 * Fill LINIT command frame 1550 * 1551 * Input: 1552 * fpkt = LV fc_packet 1553 * frm = Unsolicited frame containing LINIT command 1554 * 1555 * Returns: 1556 * N/A 1557 * 1558 * Comments: 1559 * N/A 1560 */ 1561 /* ARGSUSED */ 1562 static void 1563 fcoei_fill_els_linit_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm) 1564 { 1565 ASSERT(fpkt && frm); 1566 } 1567 1568 /* 1569 * fcoei_fill_els_logo_cmd 1570 * Fill LOGO command frame 1571 * 1572 * Input: 1573 * fpkt = LV fc_packet 1574 * frm = Unsolicited frame containing LOGO command 1575 * 1576 * Returns: 1577 * N/A 1578 * 1579 * Comments: 1580 * N/A 1581 */ 1582 static void 1583 fcoei_fill_els_logo_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm) 1584 { 1585 la_els_logo_t *els_logo = (la_els_logo_t *)(void *)fpkt->pkt_cmd; 1586 int offset; 1587 1588 offset = 0; 1589 FCOE_V2B_1(els_logo->ls_code.ls_code, FPLD + offset); 1590 1591 offset = 5; 1592 FCOE_V2B_3(els_logo->nport_id.port_id, FPLD + offset); 1593 1594 offset = 8; 1595 bcopy(&els_logo->nport_ww_name, FPLD + offset, 8); 1596 } 1597 1598 static void 1599 fcoei_fill_els_rls_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm) 1600 { 1601 la_els_rls_t *els_rls = (la_els_rls_t *)(void *)fpkt->pkt_cmd; 1602 int offset; 1603 1604 offset = 0; 1605 FCOE_V2B_1(els_rls->ls_code.ls_code, FPLD + offset); 1606 1607 offset = 5; 1608 FCOE_V2B_3(els_rls->rls_portid.port_id, FPLD + offset); 1609 } 1610 1611 static void 1612 fcoei_fill_els_rnid_cmd(fc_packet_t *fpkt, fcoe_frame_t *frm) 1613 { 1614 la_els_rnid_t *els_rnid = (la_els_rnid_t *)(void *)fpkt->pkt_cmd; 1615 int offset; 1616 1617 offset = 0; 1618 FCOE_V2B_1(els_rnid->ls_code.ls_code, FPLD + offset); 1619 1620 offset = 4; 1621 bcopy(&els_rnid->data_format, FPLD + offset, 1); 1622 } 1623 /* 1624 * fcoei_fill_els_acc_resp 1625 * Fill ELS ACC response frame 1626 * 1627 * Input: 1628 * fpkt = LV fc_packet 1629 * frm = Unsolicited frame containing ELS ACC response 1630 * 1631 * Returns: 1632 * N/A 1633 * 1634 * Comments: 1635 * N/A 1636 */ 1637 static void 1638 fcoei_fill_els_acc_resp(fc_packet_t *fpkt, fcoe_frame_t *frm) 1639 { 1640 ls_code_t *els_code = (ls_code_t *)(void *)fpkt->pkt_cmd; 1641 int offset; 1642 1643 offset = 0; 1644 FCOE_V2B_1(els_code->ls_code, FPLD + offset); 1645 1646 offset = 1; 1647 FCOE_V2B_3(els_code->mbz, FPLD + offset); 1648 } 1649 1650 /* 1651 * fcoei_fill_els_rjt_resp 1652 * Fill ELS RJT response frame 1653 * 1654 * Input: 1655 * fpkt = LV fc_packet 1656 * frm = Unsolicited frame containg ELS RJT response 1657 * 1658 * Returns: 1659 * N/A 1660 * 1661 * Comments: 1662 * N/A 1663 */ 1664 static void 1665 fcoei_fill_els_rjt_resp(fc_packet_t *fpkt, fcoe_frame_t *frm) 1666 { 1667 la_els_rjt_t *els_rjt = (la_els_rjt_t *)(void *)fpkt->pkt_cmd; 1668 int offset; 1669 1670 offset = 0; /* reset ls code */ 1671 FCOE_V2B_1(els_rjt->ls_code.ls_code, FPLD + offset); 1672 1673 offset = 5; /* reason code */ 1674 FCOE_V2B_1(els_rjt->action, FPLD + offset); 1675 1676 offset = 6; /* reason explanation */ 1677 FCOE_V2B_1(els_rjt->reason, FPLD + offset); 1678 1679 offset = 7; /* vendor unique */ 1680 FCOE_V2B_1(els_rjt->vu, FPLD + offset); 1681 } 1682 1683 /* 1684 * fcoei_fill_els_adisc_resp 1685 * Fill ADISC response frame 1686 * 1687 * Input: 1688 * fpkt = LV fc_packet 1689 * frm = Unsolicited frame containing ADISC response 1690 * 1691 * Returns: 1692 * N/A 1693 * 1694 * Comments: 1695 * N/A 1696 */ 1697 static void 1698 fcoei_fill_els_adisc_resp(fc_packet_t *fpkt, fcoe_frame_t *frm) 1699 { 1700 la_els_adisc_t *els_adisc = (la_els_adisc_t *)(void *)fpkt->pkt_cmd; 1701 int offset; 1702 1703 if (els_adisc->ls_code.ls_code == LA_ELS_RJT) { 1704 fcoei_fill_els_rjt_resp(fpkt, frm); 1705 } else { 1706 offset = 0; 1707 FCOE_V2B_1(els_adisc->ls_code.ls_code, FPLD + offset); 1708 1709 offset = 5; 1710 FCOE_V2B_3(els_adisc->hard_addr.hard_addr, FPLD + offset); 1711 1712 offset = 8; 1713 bcopy(&els_adisc->port_wwn, FPLD + offset, FC_WWN_SIZE); 1714 1715 offset = 16; 1716 bcopy(&els_adisc->node_wwn, FPLD + offset, FC_WWN_SIZE); 1717 1718 offset = 25; 1719 FCOE_V2B_3(els_adisc->nport_id.port_id, FPLD + offset); 1720 } 1721 } 1722 1723 /* 1724 * fcoei_fill_els_logi_resp 1725 * Fill FLOGI/PLOGI response frame 1726 * 1727 * Input: 1728 * fpkt = LV fc_packet 1729 * frm = Unsolicited frame containing LOGI response 1730 * 1731 * Returns: 1732 * N/A 1733 * 1734 * Comments: 1735 * N/A 1736 */ 1737 static void 1738 fcoei_fill_els_logi_resp(fc_packet_t *fpkt, fcoe_frame_t *frm) 1739 { 1740 ls_code_t *els_code = (ls_code_t *)(void *)fpkt->pkt_cmd; 1741 1742 if (els_code->ls_code == LA_ELS_RJT) { 1743 fcoei_fill_els_rjt_resp(fpkt, frm); 1744 } else { 1745 fcoei_fill_els_logi_cmd(fpkt, frm); 1746 } 1747 } 1748 1749 /* 1750 * fcoei_fill_els_prli_resp 1751 * Fill PRLI response frame 1752 * 1753 * Input: 1754 * fpkt = LV fc_packet 1755 * frm = Unsolicited frame containing PRLI response 1756 * 1757 * Returns: 1758 * N/A 1759 * 1760 * Comments: 1761 * N/A 1762 */ 1763 static void 1764 fcoei_fill_els_prli_resp(fc_packet_t *fpkt, fcoe_frame_t *frm) 1765 { 1766 ls_code_t *els_code = (ls_code_t *)(void *)fpkt->pkt_cmd; 1767 1768 if (els_code->ls_code == LA_ELS_RJT) { 1769 fcoei_fill_els_rjt_resp(fpkt, frm); 1770 } else { 1771 fcoei_fill_els_prli_cmd(fpkt, frm); 1772 } 1773 } 1774 1775 /* 1776 * fcoei_fill_els_logo_resp 1777 * Fill LOGO response frame 1778 * 1779 * Input: 1780 * fpkt = LV fc_packet 1781 * frm = Unsolicited frame containing LOGO response 1782 * 1783 * Returns: 1784 * N/A 1785 * 1786 * Comments: 1787 * N/A 1788 */ 1789 static void 1790 fcoei_fill_els_logo_resp(fc_packet_t *fpkt, fcoe_frame_t *frm) 1791 { 1792 ls_code_t *els_code = (ls_code_t *)(void *)fpkt->pkt_cmd; 1793 1794 if (els_code->ls_code == LA_ELS_RJT) { 1795 fcoei_fill_els_rjt_resp(fpkt, frm); 1796 } else { 1797 fcoei_fill_els_acc_resp(fpkt, frm); 1798 } 1799 } 1800 1801 /* 1802 * fcoei_logo_peer 1803 * Send LOGO to the peer to emulate link offline event 1804 * 1805 * Input: 1806 * arg - fcoei soft state set in fcoei_bind_port 1807 * 1808 * Returns: 1809 * N/A 1810 * 1811 * Comments: 1812 * N/A 1813 */ 1814 static void 1815 fcoei_logo_peer(void *arg) 1816 { 1817 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)arg; 1818 fc_packet_t *fpkt; 1819 fcoei_exchange_t *xch; 1820 la_els_logo_t *els_logo; 1821 1822 /* 1823 * Allocate space for exchange 1824 */ 1825 xch = kmem_zalloc(sizeof (*xch), KM_SLEEP); 1826 1827 /* 1828 * Allocate space for fc_packet 1829 */ 1830 fpkt = kmem_zalloc(sizeof (fc_packet_t), KM_SLEEP); 1831 fpkt->pkt_cmdlen = 20; 1832 fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, KM_SLEEP); 1833 fpkt->pkt_rsplen = 20; 1834 fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, KM_SLEEP); 1835 1836 /* 1837 * Link them together 1838 */ 1839 fpkt->pkt_fca_private = xch; 1840 (void) fcoei_init_pkt(ss, fpkt, 0); 1841 1842 /* 1843 * Initialize FC frame header 1844 */ 1845 if (ss->ss_eport->eport_flags & EPORT_FLAG_IS_DIRECT_P2P) { 1846 fpkt->pkt_cmd_fhdr.d_id = ss->ss_p2p_info.d_id; 1847 } else { 1848 fpkt->pkt_cmd_fhdr.d_id = 0xFFFFFE; 1849 } 1850 1851 fpkt->pkt_cmd_fhdr.s_id = ss->ss_p2p_info.fca_d_id; 1852 fpkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ; 1853 fpkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; 1854 fpkt->pkt_cmd_fhdr.f_ctl = 0x290000; 1855 fpkt->pkt_timeout = 1; 1856 1857 /* 1858 * Initialize LOGO payload 1859 */ 1860 els_logo = (la_els_logo_t *)(void *)fpkt->pkt_cmd; 1861 els_logo->ls_code.ls_code = LA_ELS_LOGO; 1862 els_logo->nport_id.port_id = ss->ss_p2p_info.fca_d_id; 1863 bcopy(ss->ss_eport->eport_portwwn, &els_logo->nport_ww_name, 8); 1864 1865 /* 1866 * Set the completion function 1867 */ 1868 fpkt->pkt_comp = fcoei_fpkt_comp; 1869 if (fcoei_transport(ss, fpkt) != FC_SUCCESS) { 1870 FCOEI_LOG(__FUNCTION__, "fcoei_transport LOGO failed"); 1871 fcoei_fpkt_comp(fpkt); 1872 } 1873 } 1874 1875 /* 1876 * fcoei_fpkt_comp 1877 * internal exchange completion 1878 * 1879 * Input: 1880 * fpkt - fc_packet_t to be completed 1881 * 1882 * Returns: 1883 * N/A 1884 * 1885 * Comments: 1886 * 1887 */ 1888 static void 1889 fcoei_fpkt_comp(fc_packet_t *fpkt) 1890 { 1891 fcoei_exchange_t *xch = FPKT2XCH(fpkt); 1892 1893 FCOEI_LOG(__FUNCTION__, "internal exchange is completed: %p", xch); 1894 1895 (void) fcoei_un_init_pkt(xch->xch_ss, xch->xch_fpkt); 1896 kmem_free(xch->xch_fpkt->pkt_cmd, xch->xch_fpkt->pkt_cmdlen); 1897 kmem_free(xch->xch_fpkt->pkt_resp, xch->xch_fpkt->pkt_rsplen); 1898 kmem_free(xch->xch_fpkt, sizeof (fc_packet_t)); 1899 kmem_free(xch, sizeof (fcoei_exchange_t)); 1900 } 1901 1902 /* 1903 * fcoei_xch_abort 1904 * Prepare to abort the exchange 1905 * 1906 * Input: 1907 * key = oxid/rxid of the exchange 1908 * val = the exchange 1909 * arg = the soft state 1910 * 1911 * Returns: 1912 * MH_WALK_CONTINUE = continue to walk 1913 * 1914 * Comments: 1915 * N/A 1916 */ 1917 /* ARGSUSED */ 1918 static uint32_t 1919 fcoei_xch_abort(mod_hash_key_t key, mod_hash_val_t *val, void *arg) 1920 { 1921 fcoei_exchange_t *xch = (fcoei_exchange_t *)val; 1922 1923 ASSERT(arg == xch->xch_ss); 1924 ASSERT(CMHK(key) != 0xFFFF); 1925 xch->xch_flags |= XCH_FLAG_ABORT; 1926 xch->xch_fpkt->pkt_state = FC_PKT_LOCAL_RJT; 1927 xch->xch_fpkt->pkt_reason = FC_REASON_OFFLINE; 1928 list_insert_tail(&xch->xch_ss->ss_comp_xch_list, xch); 1929 return (MH_WALK_CONTINUE); 1930 } 1931 1932 /* 1933 * fcoei_init_fcatran_vectors 1934 * Initialize fc_fca_tran vectors that are defined in this file 1935 * 1936 * Input: 1937 * fcatran - fc_fca_tran of the soft state 1938 * 1939 * Returns: 1940 * N/A 1941 * 1942 * Comments: 1943 * N/A 1944 */ 1945 void 1946 fcoei_init_fcatran_vectors(fc_fca_tran_t *fcatran) 1947 { 1948 fcatran->fca_bind_port = fcoei_bind_port; 1949 fcatran->fca_unbind_port = fcoei_unbind_port; 1950 fcatran->fca_init_pkt = fcoei_init_pkt; 1951 fcatran->fca_un_init_pkt = fcoei_un_init_pkt; 1952 fcatran->fca_els_send = fcoei_els_send; 1953 fcatran->fca_get_cap = fcoei_get_cap; 1954 fcatran->fca_set_cap = fcoei_set_cap; 1955 fcatran->fca_getmap = fcoei_getmap; 1956 fcatran->fca_transport = fcoei_transport; 1957 fcatran->fca_ub_alloc = fcoei_ub_alloc; 1958 fcatran->fca_ub_free = fcoei_ub_free; 1959 fcatran->fca_ub_release = fcoei_ub_release; 1960 fcatran->fca_abort = fcoei_abort; 1961 fcatran->fca_reset = fcoei_reset; 1962 fcatran->fca_port_manage = fcoei_port_manage; 1963 fcatran->fca_get_device = fcoei_get_device; 1964 fcatran->fca_notify = fcoei_notify; 1965 } 1966 1967 /* 1968 * fcoei_process_event_reset 1969 * link reset phase II 1970 * 1971 * Input: 1972 * arg - fcoei soft state set in fcoei_bind_port 1973 * 1974 * Returns: 1975 * N/A 1976 * 1977 * Comments: 1978 * 1979 */ 1980 void 1981 fcoei_process_event_reset(fcoei_event_t *ae) 1982 { 1983 fcoei_soft_state_t *ss = (fcoei_soft_state_t *)ae->ae_obj; 1984 1985 ASSERT(!MUTEX_HELD(&ss->ss_watchdog_mutex)); 1986 kmem_free(ae, sizeof (*ae)); 1987 1988 mod_hash_walk(ss->ss_sol_oxid_hash, fcoei_xch_abort, ss); 1989 mod_hash_walk(ss->ss_unsol_rxid_hash, fcoei_xch_abort, ss); 1990 fcoei_handle_comp_xch_list(ss); 1991 1992 /* 1993 * Notify LV that the link is up now 1994 */ 1995 ss->ss_eport->eport_ctl(ss->ss_eport, FCOE_CMD_PORT_ONLINE, 0); 1996 } 1997 1998 /* 1999 * fcoei_process_event_exchange 2000 * Process exchange in the single thread context 2001 * 2002 * Input: 2003 * ae = the exchange event 2004 * 2005 * Returns: 2006 * N/A 2007 * 2008 * Comments: 2009 * N/A 2010 */ 2011 void 2012 fcoei_process_event_exchange(fcoei_event_t *ae) 2013 { 2014 fcoei_exchange_t *xch = (fcoei_exchange_t *)ae->ae_obj; 2015 fcoei_exchange_t *xch_tmp; 2016 fc_packet_t *fpkt = xch->xch_fpkt; 2017 2018 /* 2019 * These 4 elements need reset, pkt_state & pkt_reason will be set 2020 */ 2021 fpkt->pkt_action = 0; 2022 fpkt->pkt_expln = 0; 2023 fpkt->pkt_data_resid = 0; 2024 fpkt->pkt_resp_resid = 0; 2025 2026 /* 2027 * port state sanity checking 2028 */ 2029 if ((xch->xch_ss->ss_link_state != FC_STATE_ONLINE) || 2030 xch->xch_ss->ss_port_event_counter) { 2031 /* 2032 * LV will retry it after one second 2033 */ 2034 fcoei_complete_xch(xch, NULL, FC_PKT_PORT_OFFLINE, 2035 FC_REASON_OFFLINE); 2036 return; 2037 } 2038 2039 switch (fpkt->pkt_cmd_fhdr.r_ctl) { 2040 case R_CTL_COMMAND: 2041 FCOEI_INIT_SOL_ID_HASH(xch, xch_tmp); 2042 fcoei_initiate_fcp_cmd(xch); 2043 break; 2044 2045 case R_CTL_ELS_REQ: 2046 FCOEI_INIT_SOL_ID_HASH(xch, xch_tmp); 2047 fcoei_initiate_els_req(xch); 2048 break; 2049 2050 case R_CTL_UNSOL_CONTROL: 2051 FCOEI_INIT_SOL_ID_HASH(xch, xch_tmp); 2052 fcoei_initiate_ct_req(xch); 2053 break; 2054 2055 case R_CTL_ELS_RSP: 2056 /* 2057 * Caution: in leadville, it still uses pkt_cmd_fhdr 2058 * oxid & rxid have been decided when we get unsolicited frames. 2059 * pkt_cmd_fhdr has contained the right oxid and rxid now. 2060 */ 2061 FCOEI_INIT_UNSOL_ID_HASH(xch); 2062 fcoei_initiate_els_resp(xch); 2063 break; 2064 2065 default: 2066 fcoei_complete_xch(xch, NULL, FC_PKT_FAILURE, 2067 FC_REASON_CMD_UNSUPPORTED); 2068 } 2069 } 2070