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