12a8164dfSZhong Wang /* 22a8164dfSZhong Wang * CDDL HEADER START 32a8164dfSZhong Wang * 42a8164dfSZhong Wang * The contents of this file are subject to the terms of the 52a8164dfSZhong Wang * Common Development and Distribution License (the "License"). 62a8164dfSZhong Wang * You may not use this file except in compliance with the License. 72a8164dfSZhong Wang * 82a8164dfSZhong Wang * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 92a8164dfSZhong Wang * or http://www.opensolaris.org/os/licensing. 102a8164dfSZhong Wang * See the License for the specific language governing permissions 112a8164dfSZhong Wang * and limitations under the License. 122a8164dfSZhong Wang * 132a8164dfSZhong Wang * When distributing Covered Code, include this CDDL HEADER in each 142a8164dfSZhong Wang * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 152a8164dfSZhong Wang * If applicable, add the following below this CDDL HEADER, with the 162a8164dfSZhong Wang * fields enclosed by brackets "[]" replaced with your own identifying 172a8164dfSZhong Wang * information: Portions Copyright [yyyy] [name of copyright owner] 182a8164dfSZhong Wang * 192a8164dfSZhong Wang * CDDL HEADER END 202a8164dfSZhong Wang */ 212a8164dfSZhong Wang 222a8164dfSZhong Wang /* 232a8164dfSZhong Wang * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 242a8164dfSZhong Wang * Use is subject to license terms. 252a8164dfSZhong Wang */ 262a8164dfSZhong Wang 272a8164dfSZhong Wang /* 282a8164dfSZhong Wang * The following notice accompanied the original version of this file: 292a8164dfSZhong Wang * 302a8164dfSZhong Wang * BSD LICENSE 312a8164dfSZhong Wang * 322a8164dfSZhong Wang * Copyright(c) 2007 Intel Corporation. All rights reserved. 332a8164dfSZhong Wang * All rights reserved. 342a8164dfSZhong Wang * 352a8164dfSZhong Wang * Redistribution and use in source and binary forms, with or without 362a8164dfSZhong Wang * modification, are permitted provided that the following conditions 372a8164dfSZhong Wang * are met: 382a8164dfSZhong Wang * 392a8164dfSZhong Wang * * Redistributions of source code must retain the above copyright 402a8164dfSZhong Wang * notice, this list of conditions and the following disclaimer. 412a8164dfSZhong Wang * * Redistributions in binary form must reproduce the above copyright 422a8164dfSZhong Wang * notice, this list of conditions and the following disclaimer in 432a8164dfSZhong Wang * the documentation and/or other materials provided with the 442a8164dfSZhong Wang * distribution. 452a8164dfSZhong Wang * * Neither the name of Intel Corporation nor the names of its 462a8164dfSZhong Wang * contributors may be used to endorse or promote products derived 472a8164dfSZhong Wang * from this software without specific prior written permission. 482a8164dfSZhong Wang * 492a8164dfSZhong Wang * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 502a8164dfSZhong Wang * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 512a8164dfSZhong Wang * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 522a8164dfSZhong Wang * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 532a8164dfSZhong Wang * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 542a8164dfSZhong Wang * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 552a8164dfSZhong Wang * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 562a8164dfSZhong Wang * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 572a8164dfSZhong Wang * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 582a8164dfSZhong Wang * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 592a8164dfSZhong Wang * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 602a8164dfSZhong Wang */ 612a8164dfSZhong Wang 622a8164dfSZhong Wang /* 632a8164dfSZhong Wang * This file defines interfaces between fcoe and fcoet driver. 642a8164dfSZhong Wang */ 652a8164dfSZhong Wang 662a8164dfSZhong Wang /* 672a8164dfSZhong Wang * Driver kernel header files 682a8164dfSZhong Wang */ 692a8164dfSZhong Wang #include <sys/conf.h> 702a8164dfSZhong Wang #include <sys/ddi.h> 712a8164dfSZhong Wang #include <sys/stat.h> 722a8164dfSZhong Wang #include <sys/pci.h> 732a8164dfSZhong Wang #include <sys/sunddi.h> 742a8164dfSZhong Wang #include <sys/modctl.h> 752a8164dfSZhong Wang #include <sys/file.h> 762a8164dfSZhong Wang #include <sys/cred.h> 772a8164dfSZhong Wang #include <sys/byteorder.h> 782a8164dfSZhong Wang #include <sys/atomic.h> 792a8164dfSZhong Wang #include <sys/modhash.h> 802a8164dfSZhong Wang #include <sys/scsi/scsi.h> 812a8164dfSZhong Wang #include <sys/ethernet.h> 822a8164dfSZhong Wang 832a8164dfSZhong Wang /* 842a8164dfSZhong Wang * COMSTAR header files 852a8164dfSZhong Wang */ 862a8164dfSZhong Wang #include <sys/stmf_defines.h> 872a8164dfSZhong Wang #include <sys/fct_defines.h> 882a8164dfSZhong Wang #include <sys/stmf.h> 892a8164dfSZhong Wang #include <sys/portif.h> 902a8164dfSZhong Wang #include <sys/fct.h> 912a8164dfSZhong Wang 922a8164dfSZhong Wang /* 932a8164dfSZhong Wang * FCoE header files 942a8164dfSZhong Wang */ 952a8164dfSZhong Wang #include <sys/fcoe/fcoe_common.h> 962a8164dfSZhong Wang 972a8164dfSZhong Wang /* 982a8164dfSZhong Wang * Driver's own header files 992a8164dfSZhong Wang */ 1002a8164dfSZhong Wang #include <fcoet.h> 1012a8164dfSZhong Wang #include <fcoet_eth.h> 1022a8164dfSZhong Wang 1032a8164dfSZhong Wang /* 1042a8164dfSZhong Wang * function forward declaration 1052a8164dfSZhong Wang */ 1062a8164dfSZhong Wang static fcoet_exchange_t *fcoet_create_unsol_exchange(fcoe_frame_t *frame); 1072a8164dfSZhong Wang static int fcoet_process_sol_fcp_data(fcoe_frame_t *frm); 1082a8164dfSZhong Wang static int fcoet_process_unsol_fcp_cmd(fcoe_frame_t *frm); 1092a8164dfSZhong Wang static int fcoet_process_unsol_els_req(fcoe_frame_t *frm); 1102a8164dfSZhong Wang static int fcoet_process_sol_els_rsp(fcoe_frame_t *frm); 1112a8164dfSZhong Wang static int fcoet_process_unsol_abts_req(fcoe_frame_t *frame); 1122a8164dfSZhong Wang static int fcoet_process_sol_abts_acc(fcoe_frame_t *frame); 1132a8164dfSZhong Wang static int fcoet_process_sol_abts_rjt(fcoe_frame_t *frame); 1142a8164dfSZhong Wang static int fcoet_process_unsol_ct_req(fcoe_frame_t *frm); 1152a8164dfSZhong Wang static int fcoet_process_sol_ct_rsp(fcoe_frame_t *frame); 1162a8164dfSZhong Wang static int fcoet_process_sol_flogi_rsp(fcoe_frame_t *frame); 1172a8164dfSZhong Wang static int fcoet_send_sol_fcp_data_done(fcoe_frame_t *frm); 1182a8164dfSZhong Wang static int fcoet_send_fcp_status_done(fcoe_frame_t *frm); 1192a8164dfSZhong Wang static int fcoet_send_unsol_els_rsp_done(fcoe_frame_t *frm); 1202a8164dfSZhong Wang static int fcoet_send_sol_els_req_done(fcoe_frame_t *frm); 1212a8164dfSZhong Wang static int fcoet_send_unsol_bls_acc_done(fcoe_frame_t *frm); 1222a8164dfSZhong Wang static int fcoet_send_unsol_bls_rjt_done(fcoe_frame_t *frm); 1232a8164dfSZhong Wang static int fcoet_send_sol_bls_req_done(fcoe_frame_t *frm); 1242a8164dfSZhong Wang static int fcoet_send_sol_ct_req_done(fcoe_frame_t *frm); 1252a8164dfSZhong Wang static int fcoet_process_unsol_flogi_req(fcoet_exchange_t *xch); 1262a8164dfSZhong Wang 1272a8164dfSZhong Wang /* 1282a8164dfSZhong Wang * rx_frame & release_sol_frame 1292a8164dfSZhong Wang * There should be no same OXID/RXID in on-going exchanges. 1302a8164dfSZhong Wang * RXID -> unsol_rxid_hash 1312a8164dfSZhong Wang * OXID -> sol_oxid_hash 1322a8164dfSZhong Wang */ 1332a8164dfSZhong Wang 1342a8164dfSZhong Wang void 1352a8164dfSZhong Wang fcoet_rx_frame(fcoe_frame_t *frm) 1362a8164dfSZhong Wang { 1372a8164dfSZhong Wang uint8_t rctl = FRM_R_CTL(frm); 1382a8164dfSZhong Wang 1392a8164dfSZhong Wang switch (rctl) { 1402a8164dfSZhong Wang case 0x01: 1412a8164dfSZhong Wang /* 1422a8164dfSZhong Wang * Solicited data 1432a8164dfSZhong Wang */ 1442a8164dfSZhong Wang if (fcoet_process_sol_fcp_data(frm)) { 1452a8164dfSZhong Wang FCOET_LOG("fcoet_rx_frame", 1462a8164dfSZhong Wang "fcoet_process_sol_fcp_data failed"); 1472a8164dfSZhong Wang } 1482a8164dfSZhong Wang break; 1492a8164dfSZhong Wang 1502a8164dfSZhong Wang case 0x06: 1512a8164dfSZhong Wang /* 1522a8164dfSZhong Wang * Unsolicited fcp_cmnd 1532a8164dfSZhong Wang */ 1542a8164dfSZhong Wang if (fcoet_process_unsol_fcp_cmd(frm)) { 1552a8164dfSZhong Wang FCOET_LOG("fcoet_rx_frame", 1562a8164dfSZhong Wang "fcoet_process_unsol_fcp_cmd failed"); 1572a8164dfSZhong Wang } 1582a8164dfSZhong Wang break; 1592a8164dfSZhong Wang 1602a8164dfSZhong Wang case 0x22: 1612a8164dfSZhong Wang /* 1622a8164dfSZhong Wang * unsolicited ELS req 1632a8164dfSZhong Wang */ 1642a8164dfSZhong Wang if (fcoet_process_unsol_els_req(frm)) { 1652a8164dfSZhong Wang FCOET_LOG("fcoet_rx_frame", 1662a8164dfSZhong Wang "fcoet_process_unsol_els_req failed"); 1672a8164dfSZhong Wang } 1682a8164dfSZhong Wang break; 1692a8164dfSZhong Wang 1702a8164dfSZhong Wang case 0x23: 1712a8164dfSZhong Wang /* 1722a8164dfSZhong Wang * solicited ELS rsp 1732a8164dfSZhong Wang */ 1742a8164dfSZhong Wang if (fcoet_process_sol_els_rsp(frm)) { 1752a8164dfSZhong Wang FCOET_LOG("fcoet_rx_frame", 1762a8164dfSZhong Wang "fcoet_process_sol_els_rsp failed"); 1772a8164dfSZhong Wang } 1782a8164dfSZhong Wang break; 1792a8164dfSZhong Wang 1802a8164dfSZhong Wang case 0x81: 1812a8164dfSZhong Wang /* 1822a8164dfSZhong Wang * unsolicted ABTS req 1832a8164dfSZhong Wang */ 1842a8164dfSZhong Wang if (fcoet_process_unsol_abts_req(frm)) { 1852a8164dfSZhong Wang FCOET_LOG("fcoet_rx_frame", 1862a8164dfSZhong Wang "fcoet_process_unsol_abts_req failed"); 1872a8164dfSZhong Wang } 1882a8164dfSZhong Wang break; 1892a8164dfSZhong Wang 1902a8164dfSZhong Wang case 0x84: 1912a8164dfSZhong Wang /* 1922a8164dfSZhong Wang * solicited ABTS acc response 1932a8164dfSZhong Wang */ 1942a8164dfSZhong Wang if (fcoet_process_sol_abts_acc(frm)) { 1952a8164dfSZhong Wang FCOET_LOG("fcoet_rx_frame", 1962a8164dfSZhong Wang "fcoet_process_sol_abts_acc failed"); 1972a8164dfSZhong Wang } 1982a8164dfSZhong Wang break; 1992a8164dfSZhong Wang case 0x85: 2002a8164dfSZhong Wang /* 2012a8164dfSZhong Wang * solcited ABTS rjt response 2022a8164dfSZhong Wang */ 2032a8164dfSZhong Wang if (fcoet_process_sol_abts_rjt(frm)) { 2042a8164dfSZhong Wang FCOET_LOG("fcoet_rx_frame", 2052a8164dfSZhong Wang "fcoet_process_sol_abts_rjt failed"); 2062a8164dfSZhong Wang } 2072a8164dfSZhong Wang break; 2082a8164dfSZhong Wang 2092a8164dfSZhong Wang case 0x02: 2102a8164dfSZhong Wang /* 2112a8164dfSZhong Wang * unsolicited CT req 2122a8164dfSZhong Wang */ 2132a8164dfSZhong Wang if (fcoet_process_unsol_ct_req(frm)) { 2142a8164dfSZhong Wang FCOET_LOG("fcoet_rx_frame", 2152a8164dfSZhong Wang "fcoet_process_sol_ct_rsp failed"); 2162a8164dfSZhong Wang } 2172a8164dfSZhong Wang break; 2182a8164dfSZhong Wang 2192a8164dfSZhong Wang case 0x03: 2202a8164dfSZhong Wang /* 2212a8164dfSZhong Wang * sol ct rsp 2222a8164dfSZhong Wang */ 2232a8164dfSZhong Wang if (fcoet_process_sol_ct_rsp(frm)) { 2242a8164dfSZhong Wang FCOET_LOG("fcoet_rx_frame", 2252a8164dfSZhong Wang "fcoet_process_sol_ct_rsp failed"); 2262a8164dfSZhong Wang } 2272a8164dfSZhong Wang break; 2282a8164dfSZhong Wang 2292a8164dfSZhong Wang default: 2302a8164dfSZhong Wang /* 2312a8164dfSZhong Wang * Unsupported frame 2322a8164dfSZhong Wang */ 2332a8164dfSZhong Wang PRT_FRM_HDR("Unsupported unsol frame: ", frm); 2342a8164dfSZhong Wang break; 2352a8164dfSZhong Wang } 2362a8164dfSZhong Wang 2372a8164dfSZhong Wang /* 2382a8164dfSZhong Wang * Release the frame in the end 2392a8164dfSZhong Wang */ 2402a8164dfSZhong Wang frm->frm_eport->eport_free_netb(frm->frm_netb); 2412a8164dfSZhong Wang frm->frm_eport->eport_release_frame(frm); 2422a8164dfSZhong Wang } 2432a8164dfSZhong Wang 2442a8164dfSZhong Wang /* 2452a8164dfSZhong Wang * For solicited frames, after FCoE has sent it out, it will call this 2462a8164dfSZhong Wang * to notify client(FCoEI/FCoET) about its completion. 2472a8164dfSZhong Wang */ 2482a8164dfSZhong Wang void 2492a8164dfSZhong Wang fcoet_release_sol_frame(fcoe_frame_t *frm) 2502a8164dfSZhong Wang { 2512a8164dfSZhong Wang fcoet_exchange_t *xch = FRM2TFM(frm)->tfm_xch; 2522a8164dfSZhong Wang 2532a8164dfSZhong Wang /* 2542a8164dfSZhong Wang * From now, we should not access both frm_hdr and frm_payload. Its 2552a8164dfSZhong Wang * mblk could have been released by MAC driver. 2562a8164dfSZhong Wang */ 2572a8164dfSZhong Wang switch (FRM2TFM(frm)->tfm_rctl) { 2582a8164dfSZhong Wang case 0x01: 2592a8164dfSZhong Wang if (xch && xch->xch_flags & XCH_FLAG_FCT_CALLED_ABORT) { 2602a8164dfSZhong Wang FCOET_RELE_XCHG(xch); 2612a8164dfSZhong Wang break; 2622a8164dfSZhong Wang } 2632a8164dfSZhong Wang if (fcoet_send_sol_fcp_data_done(frm)) { 2642a8164dfSZhong Wang ASSERT(0); 2652a8164dfSZhong Wang } 2662a8164dfSZhong Wang break; 2672a8164dfSZhong Wang 2682a8164dfSZhong Wang case 0x05: 2692a8164dfSZhong Wang break; 2702a8164dfSZhong Wang 2712a8164dfSZhong Wang case 0x07: 2722a8164dfSZhong Wang if (xch && xch->xch_flags & XCH_FLAG_FCT_CALLED_ABORT) { 2732a8164dfSZhong Wang FCOET_RELE_XCHG(xch); 2742a8164dfSZhong Wang break; 2752a8164dfSZhong Wang } 2762a8164dfSZhong Wang 2772a8164dfSZhong Wang if (fcoet_send_fcp_status_done(frm)) { 2782a8164dfSZhong Wang ASSERT(0); 2792a8164dfSZhong Wang } 2802a8164dfSZhong Wang break; 2812a8164dfSZhong Wang 2822a8164dfSZhong Wang case 0x23: 2832a8164dfSZhong Wang if (xch && xch->xch_flags & XCH_FLAG_FCT_CALLED_ABORT) { 2842a8164dfSZhong Wang FCOET_RELE_XCHG(xch); 2852a8164dfSZhong Wang break; 2862a8164dfSZhong Wang } 2872a8164dfSZhong Wang if (fcoet_send_unsol_els_rsp_done(frm)) { 2882a8164dfSZhong Wang ASSERT(0); 2892a8164dfSZhong Wang } 2902a8164dfSZhong Wang break; 2912a8164dfSZhong Wang 2922a8164dfSZhong Wang case 0x22: 2932a8164dfSZhong Wang if (fcoet_send_sol_els_req_done(frm)) { 2942a8164dfSZhong Wang ASSERT(0); 2952a8164dfSZhong Wang } 2962a8164dfSZhong Wang break; 2972a8164dfSZhong Wang 2982a8164dfSZhong Wang case 0x84: 2992a8164dfSZhong Wang if (fcoet_send_unsol_bls_acc_done(frm)) { 3002a8164dfSZhong Wang ASSERT(0); 3012a8164dfSZhong Wang } 3022a8164dfSZhong Wang break; 3032a8164dfSZhong Wang 3042a8164dfSZhong Wang case 0x85: 3052a8164dfSZhong Wang if (fcoet_send_unsol_bls_rjt_done(frm)) { 3062a8164dfSZhong Wang ASSERT(0); 3072a8164dfSZhong Wang } 3082a8164dfSZhong Wang break; 3092a8164dfSZhong Wang 3102a8164dfSZhong Wang case 0x81: 3112a8164dfSZhong Wang if (fcoet_send_sol_bls_req_done(frm)) { 3122a8164dfSZhong Wang ASSERT(0); 3132a8164dfSZhong Wang } 3142a8164dfSZhong Wang break; 3152a8164dfSZhong Wang 3162a8164dfSZhong Wang case 0x02: 3172a8164dfSZhong Wang if (fcoet_send_sol_ct_req_done(frm)) { 3182a8164dfSZhong Wang ASSERT(0); 3192a8164dfSZhong Wang } 3202a8164dfSZhong Wang break; 3212a8164dfSZhong Wang 3222a8164dfSZhong Wang case 0x03: 3232a8164dfSZhong Wang default: 3242a8164dfSZhong Wang /* 3252a8164dfSZhong Wang * Unsupported frame 3262a8164dfSZhong Wang */ 3272a8164dfSZhong Wang PRT_FRM_HDR("Unsupported sol frame: ", frm); 3282a8164dfSZhong Wang break; 3292a8164dfSZhong Wang } 3302a8164dfSZhong Wang 3312a8164dfSZhong Wang /* 3322a8164dfSZhong Wang * We should release the frame 3332a8164dfSZhong Wang */ 3342a8164dfSZhong Wang FRM2SS(frm)->ss_eport->eport_release_frame(frm); 3352a8164dfSZhong Wang } 3362a8164dfSZhong Wang 3372a8164dfSZhong Wang void 3382a8164dfSZhong Wang fcoet_port_event(fcoe_port_t *eport, uint32_t event) 3392a8164dfSZhong Wang { 3402a8164dfSZhong Wang fcoet_soft_state_t *ss = EPORT2SS(eport); 3412a8164dfSZhong Wang switch (event) { 3422a8164dfSZhong Wang case FCOE_NOTIFY_EPORT_LINK_UP: 3432a8164dfSZhong Wang if (eport->eport_mtu >= FCOE_MIN_MTU_SIZE) { 3442a8164dfSZhong Wang ss->ss_fcp_data_payload_size = 3452a8164dfSZhong Wang FCOE_DEFAULT_FCP_DATA_PAYLOAD_SIZE; 3462a8164dfSZhong Wang } else { 3472a8164dfSZhong Wang ss->ss_fcp_data_payload_size = 3482a8164dfSZhong Wang FCOE_MIN_FCP_DATA_PAYLOAD_SIZE; 3492a8164dfSZhong Wang } 3502a8164dfSZhong Wang FCOET_LOG("fcoet_port_event", "LINK UP notified"); 3512a8164dfSZhong Wang mutex_enter(&ss->ss_watch_mutex); 3522a8164dfSZhong Wang ss->ss_sol_flogi_state = SFS_FLOGI_INIT; 3532a8164dfSZhong Wang cv_signal(&ss->ss_watch_cv); 3542a8164dfSZhong Wang mutex_exit(&ss->ss_watch_mutex); 3552a8164dfSZhong Wang break; 3562a8164dfSZhong Wang case FCOE_NOTIFY_EPORT_LINK_DOWN: 3572a8164dfSZhong Wang fct_handle_event(ss->ss_port, 3582a8164dfSZhong Wang FCT_EVENT_LINK_DOWN, 0, 0); 3592a8164dfSZhong Wang /* Need clear up all other things */ 3602a8164dfSZhong Wang FCOET_LOG("fcoet_port_event", "LINK DOWN notified"); 3612a8164dfSZhong Wang ss->ss_sol_flogi_state = SFS_WAIT_LINKUP; 3622a8164dfSZhong Wang break; 3632a8164dfSZhong Wang default: 3642a8164dfSZhong Wang break; 3652a8164dfSZhong Wang } 3662a8164dfSZhong Wang } 3672a8164dfSZhong Wang 3682a8164dfSZhong Wang /* 3692a8164dfSZhong Wang * For unsolicited exchanges, FCoET is only responsible for allocation of 3702a8164dfSZhong Wang * req_payload. FCT will allocate resp_payload after the exchange is 3712a8164dfSZhong Wang * passed on. 3722a8164dfSZhong Wang */ 3732a8164dfSZhong Wang static fcoet_exchange_t * 3742a8164dfSZhong Wang fcoet_create_unsol_exchange(fcoe_frame_t *frm) 3752a8164dfSZhong Wang { 3762a8164dfSZhong Wang uint8_t r_ctl; 3772a8164dfSZhong Wang int cdb_size; 3782a8164dfSZhong Wang fcoet_exchange_t *xch, *xch_tmp; 3792a8164dfSZhong Wang fct_cmd_t *cmd; 3802a8164dfSZhong Wang fcoe_fcp_cmnd_t *ffc; 3812a8164dfSZhong Wang uint32_t task_expected_len = 0; 3822a8164dfSZhong Wang 3832a8164dfSZhong Wang r_ctl = FRM_R_CTL(frm); 3842a8164dfSZhong Wang switch (r_ctl) { 3852a8164dfSZhong Wang case 0x22: 3862a8164dfSZhong Wang /* 3872a8164dfSZhong Wang * FCoET's unsolicited ELS 3882a8164dfSZhong Wang */ 3892a8164dfSZhong Wang cmd = (fct_cmd_t *)fct_alloc(FCT_STRUCT_CMD_RCVD_ELS, 3902a8164dfSZhong Wang GET_STRUCT_SIZE(fcoet_exchange_t) + 3912a8164dfSZhong Wang frm->frm_payload_size, 0); 3922a8164dfSZhong Wang if (cmd == NULL) { 3932a8164dfSZhong Wang FCOET_EXT_LOG(0, "can't get cmd"); 3942a8164dfSZhong Wang return (NULL); 3952a8164dfSZhong Wang } 3962a8164dfSZhong Wang break; 3972a8164dfSZhong Wang 3982a8164dfSZhong Wang case 0x06: 3992a8164dfSZhong Wang /* 4002a8164dfSZhong Wang * FCoET's unsolicited SCSI cmd 4012a8164dfSZhong Wang */ 4022a8164dfSZhong Wang cdb_size = 16; /* need improve later */ 4032a8164dfSZhong Wang cmd = fct_scsi_task_alloc(FRM2SS(frm)->ss_port, FCT_HANDLE_NONE, 4042a8164dfSZhong Wang FRM_S_ID(frm), frm->frm_payload, cdb_size, 4052a8164dfSZhong Wang STMF_TASK_EXT_NONE); 4062a8164dfSZhong Wang if (cmd == NULL) { 4072a8164dfSZhong Wang FCOET_EXT_LOG(0, "can't get fcp cmd"); 4082a8164dfSZhong Wang return (NULL); 4092a8164dfSZhong Wang } 4102a8164dfSZhong Wang ffc = (fcoe_fcp_cmnd_t *)frm->frm_payload; 4112a8164dfSZhong Wang task_expected_len = FCOE_B2V_4(ffc->ffc_fcp_dl); 4122a8164dfSZhong Wang break; 4132a8164dfSZhong Wang 4142a8164dfSZhong Wang default: 4152a8164dfSZhong Wang FCOET_EXT_LOG(0, "unsupported R_CTL: %x", r_ctl); 4162a8164dfSZhong Wang return (NULL); 4172a8164dfSZhong Wang } 4182a8164dfSZhong Wang 4192a8164dfSZhong Wang /* 4202a8164dfSZhong Wang * xch initialization 4212a8164dfSZhong Wang */ 4222a8164dfSZhong Wang xch = CMD2XCH(cmd); 4232a8164dfSZhong Wang xch->xch_oxid = FRM_OXID(frm); 4242a8164dfSZhong Wang xch->xch_flags = 0; 4252a8164dfSZhong Wang xch->xch_ss = FRM2SS(frm); 4262a8164dfSZhong Wang xch->xch_cmd = cmd; 4272a8164dfSZhong Wang xch->xch_current_seq = NULL; 4282a8164dfSZhong Wang xch->xch_left_data_size = 0; 4292a8164dfSZhong Wang if (task_expected_len) { 4302a8164dfSZhong Wang xch->xch_dbuf_num = 4312a8164dfSZhong Wang (task_expected_len + FCOET_MAX_DBUF_LEN - 1) / 4322a8164dfSZhong Wang FCOET_MAX_DBUF_LEN; 4332a8164dfSZhong Wang xch->xch_dbufs = 4342a8164dfSZhong Wang kmem_zalloc(xch->xch_dbuf_num * sizeof (stmf_data_buf_t *), 4352a8164dfSZhong Wang KM_SLEEP); 4362a8164dfSZhong Wang } 4372a8164dfSZhong Wang xch->xch_start_time = ddi_get_lbolt(); 4382a8164dfSZhong Wang do { 4392a8164dfSZhong Wang xch->xch_rxid = atomic_add_16_nv( 4402a8164dfSZhong Wang &xch->xch_ss->ss_next_unsol_rxid, 1); 4412a8164dfSZhong Wang if (xch->xch_rxid == 0xFFFF) { 4422a8164dfSZhong Wang xch->xch_rxid = atomic_add_16_nv( 4432a8164dfSZhong Wang &xch->xch_ss->ss_next_unsol_rxid, 1); 4442a8164dfSZhong Wang } 4452a8164dfSZhong Wang } while (mod_hash_find(FRM2SS(frm)->ss_unsol_rxid_hash, 4462a8164dfSZhong Wang (mod_hash_key_t)(intptr_t)xch->xch_rxid, 4472a8164dfSZhong Wang (mod_hash_val_t)&xch_tmp) == 0); 4482a8164dfSZhong Wang 4492a8164dfSZhong Wang xch->xch_sequence_no = 0; 4502a8164dfSZhong Wang xch->xch_ref = 0; 4512a8164dfSZhong Wang (void) mod_hash_insert(xch->xch_ss->ss_unsol_rxid_hash, 4522a8164dfSZhong Wang (mod_hash_key_t)(intptr_t)xch->xch_rxid, (mod_hash_val_t)xch); 4532a8164dfSZhong Wang xch->xch_flags |= XCH_FLAG_IN_HASH_TABLE; 4542a8164dfSZhong Wang 4552a8164dfSZhong Wang /* 4562a8164dfSZhong Wang * cmd initialization 4572a8164dfSZhong Wang */ 4582a8164dfSZhong Wang cmd->cmd_port = FRM2SS(frm)->ss_port; 4592a8164dfSZhong Wang cmd->cmd_rp_handle = FCT_HANDLE_NONE; 4602a8164dfSZhong Wang cmd->cmd_rportid = FRM_S_ID(frm); 4612a8164dfSZhong Wang cmd->cmd_lportid = FRM_D_ID(frm); 4622a8164dfSZhong Wang cmd->cmd_oxid = xch->xch_oxid; 4632a8164dfSZhong Wang cmd->cmd_rxid = xch->xch_rxid; 4642a8164dfSZhong Wang 4652a8164dfSZhong Wang fcoet_init_tfm(frm, xch); 4662a8164dfSZhong Wang return (xch); 4672a8164dfSZhong Wang } 4682a8164dfSZhong Wang 4692a8164dfSZhong Wang int 4702a8164dfSZhong Wang fcoet_clear_unsol_exchange(fcoet_exchange_t *xch) 4712a8164dfSZhong Wang { 4722a8164dfSZhong Wang mod_hash_val_t val = NULL; 4732a8164dfSZhong Wang 4742a8164dfSZhong Wang if (mod_hash_remove(xch->xch_ss->ss_unsol_rxid_hash, 4752a8164dfSZhong Wang (mod_hash_key_t)(intptr_t)xch->xch_rxid, &val) == 0) { 4762a8164dfSZhong Wang if (xch->xch_dbuf_num) { 4772a8164dfSZhong Wang kmem_free((void*)xch->xch_dbufs, 4782a8164dfSZhong Wang xch->xch_dbuf_num * sizeof (void *)); 4792a8164dfSZhong Wang xch->xch_dbufs = NULL; 4802a8164dfSZhong Wang xch->xch_dbuf_num = 0; 4812a8164dfSZhong Wang } 4822a8164dfSZhong Wang ASSERT(xch->xch_flags & XCH_FLAG_IN_HASH_TABLE); 4832a8164dfSZhong Wang ASSERT((fcoet_exchange_t *)val == xch); 4842a8164dfSZhong Wang xch->xch_flags &= ~XCH_FLAG_IN_HASH_TABLE; 4852a8164dfSZhong Wang return (FCOE_SUCCESS); 4862a8164dfSZhong Wang } 4872a8164dfSZhong Wang 4882a8164dfSZhong Wang FCOET_LOG("fcoet_clear_unsol_exchange", "xch %p already cleared from " 4892a8164dfSZhong Wang "hash table", xch); 4902a8164dfSZhong Wang return (FCOE_FAILURE); 4912a8164dfSZhong Wang } 4922a8164dfSZhong Wang 4932a8164dfSZhong Wang void 4942a8164dfSZhong Wang fcoet_clear_sol_exchange(fcoet_exchange_t *xch) 4952a8164dfSZhong Wang { 4962a8164dfSZhong Wang mod_hash_val_t val = NULL; 4972a8164dfSZhong Wang 4982a8164dfSZhong Wang if (xch->xch_flags & XCH_FLAG_IN_HASH_TABLE) { 4992a8164dfSZhong Wang (void) mod_hash_remove(xch->xch_ss->ss_sol_oxid_hash, 5002a8164dfSZhong Wang (mod_hash_key_t)(intptr_t)xch->xch_oxid, &val); 5012a8164dfSZhong Wang ASSERT((fcoet_exchange_t *)val == xch); 5022a8164dfSZhong Wang xch->xch_flags &= ~XCH_FLAG_IN_HASH_TABLE; 5032a8164dfSZhong Wang } 5042a8164dfSZhong Wang } 5052a8164dfSZhong Wang 5062a8164dfSZhong Wang static int 5072a8164dfSZhong Wang fcoet_process_sol_fcp_data(fcoe_frame_t *frm) 5082a8164dfSZhong Wang { 5092a8164dfSZhong Wang fcoet_exchange_t *xch = NULL; 5102a8164dfSZhong Wang fcoet_soft_state_t *ss = NULL; 5112a8164dfSZhong Wang fct_status_t fc_st; 5122a8164dfSZhong Wang uint32_t iof; 5132a8164dfSZhong Wang uint16_t unsol_rxid; 5142a8164dfSZhong Wang int sge_idx; 5152a8164dfSZhong Wang stmf_data_buf_t *dbuf; 5162a8164dfSZhong Wang int data_offset; 5172a8164dfSZhong Wang 5182a8164dfSZhong Wang unsol_rxid = FRM_RXID(frm); 5192a8164dfSZhong Wang if (mod_hash_find_cb(FRM2SS(frm)->ss_unsol_rxid_hash, 5202a8164dfSZhong Wang (mod_hash_key_t)(intptr_t)unsol_rxid, 5212a8164dfSZhong Wang (mod_hash_val_t)&xch, fcoet_modhash_find_cb) != 0) { 5222a8164dfSZhong Wang return (FCOE_FAILURE); 5232a8164dfSZhong Wang } 5242a8164dfSZhong Wang 5252a8164dfSZhong Wang /* 5262a8164dfSZhong Wang * we will always have a buf waiting there 5272a8164dfSZhong Wang */ 5282a8164dfSZhong Wang data_offset = FRM_PARAM(frm); 5292a8164dfSZhong Wang dbuf = xch->xch_dbufs[data_offset/FCOET_MAX_DBUF_LEN]; 5302a8164dfSZhong Wang ASSERT(dbuf); 5312a8164dfSZhong Wang ss = xch->xch_ss; 5322a8164dfSZhong Wang sge_idx = (data_offset % FCOET_MAX_DBUF_LEN)/ 5332a8164dfSZhong Wang ss->ss_fcp_data_payload_size; 5342a8164dfSZhong Wang 5352a8164dfSZhong Wang ASSERT(((sge_idx < FCOET_GET_SEG_NUM(dbuf) - 1) && 5362a8164dfSZhong Wang (frm->frm_payload_size == ss->ss_fcp_data_payload_size)) || 5372a8164dfSZhong Wang ((sge_idx == FCOET_GET_SEG_NUM(dbuf) - 1) && 5382a8164dfSZhong Wang (frm->frm_payload_size % ss->ss_fcp_data_payload_size == 5392a8164dfSZhong Wang dbuf->db_data_size % ss->ss_fcp_data_payload_size))); 5402a8164dfSZhong Wang 5412a8164dfSZhong Wang bcopy(frm->frm_payload, dbuf->db_sglist[sge_idx].seg_addr, 5422a8164dfSZhong Wang frm->frm_payload_size); 5432a8164dfSZhong Wang 5442a8164dfSZhong Wang xch->xch_left_data_size -= frm->frm_payload_size; 5452a8164dfSZhong Wang if (xch->xch_left_data_size <= 0) { 5462a8164dfSZhong Wang fc_st = FCT_SUCCESS; 5472a8164dfSZhong Wang iof = 0; 5482a8164dfSZhong Wang dbuf->db_xfer_status = fc_st; 5492a8164dfSZhong Wang dbuf->db_flags |= DB_DONT_REUSE; 5502a8164dfSZhong Wang fct_scsi_data_xfer_done(xch->xch_cmd, dbuf, iof); 5512a8164dfSZhong Wang } 5522a8164dfSZhong Wang 5532a8164dfSZhong Wang FCOET_RELE_XCHG(xch); 5542a8164dfSZhong Wang return (FCOE_SUCCESS); 5552a8164dfSZhong Wang } 5562a8164dfSZhong Wang 5572a8164dfSZhong Wang static int 5582a8164dfSZhong Wang fcoet_process_unsol_fcp_cmd(fcoe_frame_t *frm) 5592a8164dfSZhong Wang { 5602a8164dfSZhong Wang fcoet_exchange_t *xch; 5612a8164dfSZhong Wang fcoe_fcp_cmnd_t *ffc; 5622a8164dfSZhong Wang uint8_t tm; 5632a8164dfSZhong Wang scsi_task_t *task; 5642a8164dfSZhong Wang 5652a8164dfSZhong Wang xch = fcoet_create_unsol_exchange(frm); 5662a8164dfSZhong Wang if (xch == NULL) { 5672a8164dfSZhong Wang FCOET_LOG("fcoet_process_unsol_fcp_cmd", "can't get exchange"); 5682a8164dfSZhong Wang return (FCOE_FAILURE); 5692a8164dfSZhong Wang } 5702a8164dfSZhong Wang 5712a8164dfSZhong Wang ffc = (fcoe_fcp_cmnd_t *)frm->frm_payload; 5722a8164dfSZhong Wang task = XCH2TASK(xch); 5732a8164dfSZhong Wang task->task_csn_size = 8; 5742a8164dfSZhong Wang task->task_max_nbufs = 1; 5752a8164dfSZhong Wang task->task_cmd_seq_no = FCOE_B2V_1(ffc->ffc_ref_num); 5762a8164dfSZhong Wang task->task_flags = FCOE_B2V_1(ffc->ffc_attribute) & 0x07; 5772a8164dfSZhong Wang task->task_flags |= 5782a8164dfSZhong Wang (FCOE_B2V_1(ffc->ffc_addlen_rdwr) & 0x03) << 5; 5792a8164dfSZhong Wang task->task_expected_xfer_length = FCOE_B2V_4(ffc->ffc_fcp_dl); 5802a8164dfSZhong Wang 5812a8164dfSZhong Wang tm = FCOE_B2V_1(ffc->ffc_management_flags); 5822a8164dfSZhong Wang if (tm) { 5832a8164dfSZhong Wang if (tm & BIT_1) { 5842a8164dfSZhong Wang task->task_mgmt_function = TM_ABORT_TASK_SET; 5852a8164dfSZhong Wang } else if (tm & BIT_2) { 5862a8164dfSZhong Wang task->task_mgmt_function = TM_CLEAR_TASK_SET; 5872a8164dfSZhong Wang } else if (tm & BIT_4) { 5882a8164dfSZhong Wang task->task_mgmt_function = TM_LUN_RESET; 5892a8164dfSZhong Wang } else if (tm & BIT_5) { 5902a8164dfSZhong Wang task->task_mgmt_function = TM_TARGET_COLD_RESET; 5912a8164dfSZhong Wang } else if (tm & BIT_6) { 5922a8164dfSZhong Wang task->task_mgmt_function = TM_CLEAR_ACA; 5932a8164dfSZhong Wang } else { 5942a8164dfSZhong Wang task->task_mgmt_function = TM_ABORT_TASK; 5952a8164dfSZhong Wang } 5962a8164dfSZhong Wang } 5972a8164dfSZhong Wang 5982a8164dfSZhong Wang bcopy(ffc->ffc_cdb, task->task_cdb, 16); 5992a8164dfSZhong Wang fct_post_rcvd_cmd(xch->xch_cmd, NULL); 6002a8164dfSZhong Wang return (FCOE_SUCCESS); 6012a8164dfSZhong Wang } 6022a8164dfSZhong Wang /* 6032a8164dfSZhong Wang * It must be from link 6042a8164dfSZhong Wang * req_payload has been allocated when create_unsol_exchange 6052a8164dfSZhong Wang */ 6062a8164dfSZhong Wang static int 6072a8164dfSZhong Wang fcoet_process_unsol_els_req(fcoe_frame_t *frm) 6082a8164dfSZhong Wang { 6092a8164dfSZhong Wang int ret = FCOE_SUCCESS; 6102a8164dfSZhong Wang fcoet_exchange_t *xch; 6112a8164dfSZhong Wang 6122a8164dfSZhong Wang xch = fcoet_create_unsol_exchange(frm); 6132a8164dfSZhong Wang ASSERT(xch); 6142a8164dfSZhong Wang ASSERT(FRM_IS_LAST_FRAME(frm)); 6152a8164dfSZhong Wang 6162a8164dfSZhong Wang /* 6172a8164dfSZhong Wang * For the reason of keeping symmetric, we do copy here as in 6182a8164dfSZhong Wang * process_sol_els instead of in create_unsol_exchange. 6192a8164dfSZhong Wang * req_payload depends on how to allocate buf in create_unsol_exchange 6202a8164dfSZhong Wang */ 6212a8164dfSZhong Wang XCH2ELS(xch)->els_req_alloc_size = 0; 6222a8164dfSZhong Wang XCH2ELS(xch)->els_req_size = frm->frm_payload_size; 6232a8164dfSZhong Wang XCH2ELS(xch)->els_req_payload = 6242a8164dfSZhong Wang GET_BYTE_OFFSET(xch, GET_STRUCT_SIZE(fcoet_exchange_t)); 6252a8164dfSZhong Wang bcopy(frm->frm_payload, XCH2ELS(xch)->els_req_payload, 6262a8164dfSZhong Wang XCH2ELS(xch)->els_req_size); 6272a8164dfSZhong Wang if (XCH2ELS(xch)->els_req_payload[0] != ELS_OP_FLOGI) { 6282a8164dfSZhong Wang /* 6292a8164dfSZhong Wang * Ensure LINK_UP event has been handled, or PLOIG has 6302a8164dfSZhong Wang * been processed by FCT, or else it will be discarded. 6312a8164dfSZhong Wang * It need more consideration later ??? 6322a8164dfSZhong Wang */ 6332a8164dfSZhong Wang if ((XCH2ELS(xch)->els_req_payload[0] == ELS_OP_PLOGI) && 6342a8164dfSZhong Wang (xch->xch_ss->ss_flags & SS_FLAG_DELAY_PLOGI)) { 6352a8164dfSZhong Wang delay(STMF_SEC2TICK(1)/2); 6362a8164dfSZhong Wang } 6372a8164dfSZhong Wang 6382a8164dfSZhong Wang if ((XCH2ELS(xch)->els_req_payload[0] == ELS_OP_PRLI) && 6392a8164dfSZhong Wang (xch->xch_ss->ss_flags & SS_FLAG_DELAY_PLOGI)) { 6402a8164dfSZhong Wang atomic_and_32(&xch->xch_ss->ss_flags, 6412a8164dfSZhong Wang ~SS_FLAG_DELAY_PLOGI); 6422a8164dfSZhong Wang delay(STMF_SEC2TICK(1)/3); 6432a8164dfSZhong Wang } 6442a8164dfSZhong Wang fct_post_rcvd_cmd(xch->xch_cmd, NULL); 6452a8164dfSZhong Wang } else { 6462a8164dfSZhong Wang /* 6472a8164dfSZhong Wang * We always handle FLOGI internally 6482a8164dfSZhong Wang * Save dst mac address from FLOGI request to restore later 6492a8164dfSZhong Wang */ 6502a8164dfSZhong Wang bcopy((char *)frm->frm_hdr-22, 6512a8164dfSZhong Wang frm->frm_eport->eport_efh_dst, ETHERADDRL); 6522a8164dfSZhong Wang ret = fcoet_process_unsol_flogi_req(xch); 6532a8164dfSZhong Wang } 6542a8164dfSZhong Wang return (ret); 6552a8164dfSZhong Wang } 6562a8164dfSZhong Wang 6572a8164dfSZhong Wang 6582a8164dfSZhong Wang /* 6592a8164dfSZhong Wang * It must be from link, but could be incomplete because of network problems 6602a8164dfSZhong Wang */ 6612a8164dfSZhong Wang static int 6622a8164dfSZhong Wang fcoet_process_sol_els_rsp(fcoe_frame_t *frm) 6632a8164dfSZhong Wang { 6642a8164dfSZhong Wang uint32_t actual_size; 6652a8164dfSZhong Wang fct_status_t fc_st; 6662a8164dfSZhong Wang uint32_t iof; 6672a8164dfSZhong Wang uint16_t sol_oxid; 6682a8164dfSZhong Wang fcoet_exchange_t *xch = NULL; 6692a8164dfSZhong Wang fct_els_t *els = NULL; 6702a8164dfSZhong Wang int ret = FCOE_SUCCESS; 6712a8164dfSZhong Wang 6722a8164dfSZhong Wang sol_oxid = FRM_OXID(frm); 6732a8164dfSZhong Wang if (mod_hash_find_cb(FRM2SS(frm)->ss_sol_oxid_hash, 6742a8164dfSZhong Wang (mod_hash_key_t)(intptr_t)sol_oxid, 6752a8164dfSZhong Wang (mod_hash_val_t *)&xch, fcoet_modhash_find_cb) != 0) { 6762a8164dfSZhong Wang return (FCOE_FAILURE); 6772a8164dfSZhong Wang } 6782a8164dfSZhong Wang if (xch != FRM2SS(frm)->ss_sol_flogi) { 6792a8164dfSZhong Wang fcoet_clear_sol_exchange(xch); 6802a8164dfSZhong Wang } 6812a8164dfSZhong Wang 6822a8164dfSZhong Wang fcoet_init_tfm(frm, xch); 6832a8164dfSZhong Wang els = CMD2ELS(xch->xch_cmd); 6842a8164dfSZhong Wang ASSERT(FRM_IS_LAST_FRAME(frm)); 6852a8164dfSZhong Wang actual_size = els->els_resp_size; 6862a8164dfSZhong Wang if (actual_size > frm->frm_payload_size) { 6872a8164dfSZhong Wang actual_size = frm->frm_payload_size; 6882a8164dfSZhong Wang } 6892a8164dfSZhong Wang 6902a8164dfSZhong Wang els->els_resp_size = (uint16_t)actual_size; 6912a8164dfSZhong Wang bcopy(frm->frm_payload, els->els_resp_payload, actual_size); 6922a8164dfSZhong Wang 6932a8164dfSZhong Wang if (xch->xch_ss->ss_sol_flogi == xch) { 6942a8164dfSZhong Wang /* 6952a8164dfSZhong Wang * We handle FLOGI internally 6962a8164dfSZhong Wang */ 6972a8164dfSZhong Wang ret = fcoet_process_sol_flogi_rsp(frm); 6982a8164dfSZhong Wang FCOET_RELE_XCHG(xch); 6992a8164dfSZhong Wang } else { 7002a8164dfSZhong Wang fc_st = FCT_SUCCESS; 7012a8164dfSZhong Wang iof = FCT_IOF_FCA_DONE; 7022a8164dfSZhong Wang FCOET_RELE_XCHG(xch); 7032a8164dfSZhong Wang fct_send_cmd_done(xch->xch_cmd, fc_st, iof); 7042a8164dfSZhong Wang } 7052a8164dfSZhong Wang return (ret); 7062a8164dfSZhong Wang } 7072a8164dfSZhong Wang 7082a8164dfSZhong Wang /* 7092a8164dfSZhong Wang * It's still in the context of being aborted exchange, but FCT can't support 7102a8164dfSZhong Wang * this scheme, so there are two fct_cmd_t that are bound with one exchange. 7112a8164dfSZhong Wang */ 7122a8164dfSZhong Wang static int 7132a8164dfSZhong Wang fcoet_process_unsol_abts_req(fcoe_frame_t *frm) 7142a8164dfSZhong Wang { 7152a8164dfSZhong Wang fct_cmd_t *cmd; 7162a8164dfSZhong Wang fcoet_exchange_t *xch = NULL; 7172a8164dfSZhong Wang uint16_t unsol_rxid; 7182a8164dfSZhong Wang 7192a8164dfSZhong Wang FCOET_LOG("fcoet_process_unsol_abts_req", "ABTS: %x/%x", 7202a8164dfSZhong Wang FRM_OXID(frm), FRM_RXID(frm)); 7212a8164dfSZhong Wang unsol_rxid = FRM_RXID(frm); 7222a8164dfSZhong Wang if (mod_hash_find_cb(FRM2SS(frm)->ss_unsol_rxid_hash, 7232a8164dfSZhong Wang (mod_hash_key_t)(intptr_t)unsol_rxid, 7242a8164dfSZhong Wang (mod_hash_val_t *)&xch, fcoet_modhash_find_cb) != 0) { 7252a8164dfSZhong Wang FCOET_LOG("fcoet_process_unsol_abts_req", 7262a8164dfSZhong Wang "can't find aborted exchange"); 7272a8164dfSZhong Wang return (FCOE_SUCCESS); 7282a8164dfSZhong Wang } 7292a8164dfSZhong Wang 7302a8164dfSZhong Wang fcoet_init_tfm(frm, xch); 7312a8164dfSZhong Wang if (!FRM_IS_LAST_FRAME(frm)) { 7322a8164dfSZhong Wang FCOET_LOG("fcoet_process_unsol_abts_req", 7332a8164dfSZhong Wang "not supported this kind frame"); 7342a8164dfSZhong Wang FCOET_RELE_XCHG(xch); 7352a8164dfSZhong Wang return (FCOE_FAILURE); 7362a8164dfSZhong Wang } 7372a8164dfSZhong Wang 7382a8164dfSZhong Wang cmd = (fct_cmd_t *)fct_alloc(FCT_STRUCT_CMD_RCVD_ABTS, 0, 0); 7392a8164dfSZhong Wang if (cmd == NULL) { 7402a8164dfSZhong Wang FCOET_LOG("fcoet_process_unsol_abts_req", 7412a8164dfSZhong Wang "can't alloc fct_cmd_t"); 7422a8164dfSZhong Wang FCOET_RELE_XCHG(xch); 7432a8164dfSZhong Wang return (FCOE_FAILURE); 7442a8164dfSZhong Wang } 7452a8164dfSZhong Wang 7462a8164dfSZhong Wang xch->xch_flags |= XCH_FLAG_INI_ASKED_ABORT; 7472a8164dfSZhong Wang cmd->cmd_fca_private = xch; 7482a8164dfSZhong Wang cmd->cmd_port = xch->xch_cmd->cmd_port; 7492a8164dfSZhong Wang cmd->cmd_rp_handle = xch->xch_cmd->cmd_rp_handle; 7502a8164dfSZhong Wang cmd->cmd_rportid = xch->xch_cmd->cmd_rportid; 7512a8164dfSZhong Wang cmd->cmd_lportid = xch->xch_cmd->cmd_lportid; 7522a8164dfSZhong Wang cmd->cmd_oxid = xch->xch_cmd->cmd_oxid; 7532a8164dfSZhong Wang cmd->cmd_rxid = xch->xch_cmd->cmd_rxid; 7542a8164dfSZhong Wang fct_post_rcvd_cmd(cmd, NULL); 7552a8164dfSZhong Wang FCOET_LOG("fcoet_process_unsol_abts_req", 7562a8164dfSZhong Wang "abts now: xch/%p, frm/%p - time/%p", 7572a8164dfSZhong Wang xch, frm, ddi_get_lbolt()); 7582a8164dfSZhong Wang 7592a8164dfSZhong Wang FCOET_RELE_XCHG(xch); 7602a8164dfSZhong Wang return (FCOE_SUCCESS); 7612a8164dfSZhong Wang } 7622a8164dfSZhong Wang 7632a8164dfSZhong Wang static int 7642a8164dfSZhong Wang fcoet_process_sol_abts_acc(fcoe_frame_t *frm) 7652a8164dfSZhong Wang { 7662a8164dfSZhong Wang fcoet_exchange_t *xch = NULL; 7672a8164dfSZhong Wang uint16_t sol_oxid; 7682a8164dfSZhong Wang 7692a8164dfSZhong Wang sol_oxid = FRM_OXID(frm); 7702a8164dfSZhong Wang if (mod_hash_remove(FRM2SS(frm)->ss_sol_oxid_hash, 7712a8164dfSZhong Wang (mod_hash_key_t)(intptr_t)sol_oxid, 7722a8164dfSZhong Wang (mod_hash_val_t *)&xch) != 0) { 7732a8164dfSZhong Wang /* 7742a8164dfSZhong Wang * So far ABTS for FLOGI might be removed from ss_sol_oxid_hash 7752a8164dfSZhong Wang * in fcoet_watch_handle_sol_flogi, Will improve it later 7762a8164dfSZhong Wang */ 7772a8164dfSZhong Wang return (FCOE_SUCCESS); 7782a8164dfSZhong Wang } 7792a8164dfSZhong Wang 7802a8164dfSZhong Wang xch->xch_flags &= ~XCH_FLAG_IN_HASH_TABLE; 7812a8164dfSZhong Wang if (!FRM_IS_LAST_FRAME(frm)) { 7822a8164dfSZhong Wang FCOET_LOG("fcoet_process_sol_abts_acc", 7832a8164dfSZhong Wang "not supported this kind frame"); 7842a8164dfSZhong Wang FCOET_RELE_XCHG(xch); 7852a8164dfSZhong Wang return (FCOE_FAILURE); 7862a8164dfSZhong Wang } 7872a8164dfSZhong Wang FCOET_LOG("fcoet_process_sol_abts_acc", 7882a8164dfSZhong Wang "ABTS received but there is nothing to do"); 7892a8164dfSZhong Wang return (FCOE_SUCCESS); 7902a8164dfSZhong Wang } 7912a8164dfSZhong Wang 7922a8164dfSZhong Wang static int 7932a8164dfSZhong Wang fcoet_process_sol_abts_rjt(fcoe_frame_t *frm) 7942a8164dfSZhong Wang { 7952a8164dfSZhong Wang fcoet_exchange_t *xch = NULL; 7962a8164dfSZhong Wang uint16_t sol_oxid; 7972a8164dfSZhong Wang 7982a8164dfSZhong Wang sol_oxid = FRM_OXID(frm); 7992a8164dfSZhong Wang if (mod_hash_remove(FRM2SS(frm)->ss_sol_oxid_hash, 8002a8164dfSZhong Wang (mod_hash_key_t)(intptr_t)sol_oxid, 8012a8164dfSZhong Wang (mod_hash_val_t *)&xch) != 0) { 8022a8164dfSZhong Wang /* 8032a8164dfSZhong Wang * So far ABTS for FLOGI might be removed from ss_sol_oxid_hash 8042a8164dfSZhong Wang * in fcoet_watch_handle_sol_flogi, Will improve it later 8052a8164dfSZhong Wang */ 8062a8164dfSZhong Wang return (FCOE_SUCCESS); 8072a8164dfSZhong Wang } 8082a8164dfSZhong Wang 8092a8164dfSZhong Wang xch->xch_flags &= ~XCH_FLAG_IN_HASH_TABLE; 8102a8164dfSZhong Wang 8112a8164dfSZhong Wang if (!FRM_IS_LAST_FRAME(frm)) { 8122a8164dfSZhong Wang FCOET_LOG("fcoet_process_sol_abts_rjt", 8132a8164dfSZhong Wang "not supported this kind frame"); 8142a8164dfSZhong Wang return (FCOE_FAILURE); 8152a8164dfSZhong Wang } 8162a8164dfSZhong Wang 8172a8164dfSZhong Wang FCOET_LOG("fcoet_process_sol_abts_rjt", 8182a8164dfSZhong Wang "ABTS_RJT received rjt reason %x but there is nothing to do", 8192a8164dfSZhong Wang frm->frm_payload[1]); 8202a8164dfSZhong Wang return (FCOE_SUCCESS); 8212a8164dfSZhong Wang } 8222a8164dfSZhong Wang 8232a8164dfSZhong Wang static int 8242a8164dfSZhong Wang fcoet_process_unsol_ct_req(fcoe_frame_t *frm) 8252a8164dfSZhong Wang { 8262a8164dfSZhong Wang /* 8272a8164dfSZhong Wang * If you want to implement virtual name server, or FC/ETH 8282a8164dfSZhong Wang * gateway, you can do it here 8292a8164dfSZhong Wang */ 8302a8164dfSZhong Wang if (!FRM_IS_LAST_FRAME(frm)) { 8312a8164dfSZhong Wang FCOET_LOG("fcoet_process_unsol_ct_req", 8322a8164dfSZhong Wang "not supported this kind frame"); 8332a8164dfSZhong Wang return (FCOE_FAILURE); 8342a8164dfSZhong Wang } 8352a8164dfSZhong Wang 8362a8164dfSZhong Wang FCOET_LOG("fcoet_process_unsol_ct_req", 8372a8164dfSZhong Wang "No support for unsolicited CT request"); 8382a8164dfSZhong Wang return (FCOE_SUCCESS); 8392a8164dfSZhong Wang } 8402a8164dfSZhong Wang 8412a8164dfSZhong Wang static int 8422a8164dfSZhong Wang fcoet_process_sol_ct_rsp(fcoe_frame_t *frm) 8432a8164dfSZhong Wang { 8442a8164dfSZhong Wang uint32_t actual_size; 8452a8164dfSZhong Wang fct_status_t fc_st; 8462a8164dfSZhong Wang uint32_t iof; 8472a8164dfSZhong Wang fct_sol_ct_t *ct = NULL; 8482a8164dfSZhong Wang fcoet_exchange_t *xch = NULL; 8492a8164dfSZhong Wang uint16_t sol_oxid; 8502a8164dfSZhong Wang 8512a8164dfSZhong Wang sol_oxid = FRM_OXID(frm); 8522a8164dfSZhong Wang 8532a8164dfSZhong Wang if (mod_hash_remove(FRM2SS(frm)->ss_sol_oxid_hash, 8542a8164dfSZhong Wang (mod_hash_key_t)(intptr_t)sol_oxid, 8552a8164dfSZhong Wang (mod_hash_val_t *)&xch) != 0) { 8562a8164dfSZhong Wang return (FCOE_SUCCESS); 8572a8164dfSZhong Wang } 8582a8164dfSZhong Wang 8592a8164dfSZhong Wang xch->xch_flags &= ~XCH_FLAG_IN_HASH_TABLE; 8602a8164dfSZhong Wang fcoet_init_tfm(frm, xch); 8612a8164dfSZhong Wang 8622a8164dfSZhong Wang ASSERT(FRM_IS_LAST_FRAME(frm)); 8632a8164dfSZhong Wang actual_size = CMD2ELS(xch->xch_cmd)->els_resp_size; 8642a8164dfSZhong Wang if (actual_size > frm->frm_payload_size) { 8652a8164dfSZhong Wang actual_size = frm->frm_payload_size; 8662a8164dfSZhong Wang } 8672a8164dfSZhong Wang ct = CMD2CT(xch->xch_cmd); 8682a8164dfSZhong Wang ct->ct_resp_size = (uint16_t)actual_size; 8692a8164dfSZhong Wang 8702a8164dfSZhong Wang bcopy(frm->frm_payload, 8712a8164dfSZhong Wang CMD2CT(xch->xch_cmd)->ct_resp_payload, actual_size); 8722a8164dfSZhong Wang 8732a8164dfSZhong Wang fc_st = FCT_SUCCESS; 8742a8164dfSZhong Wang iof = FCT_IOF_FCA_DONE; 8752a8164dfSZhong Wang fct_send_cmd_done(xch->xch_cmd, fc_st, iof); 8762a8164dfSZhong Wang 8772a8164dfSZhong Wang return (FCOE_SUCCESS); 8782a8164dfSZhong Wang } 8792a8164dfSZhong Wang 8802a8164dfSZhong Wang static int 8812a8164dfSZhong Wang fcoet_send_sol_fcp_data_done(fcoe_frame_t *frm) 8822a8164dfSZhong Wang { 8832a8164dfSZhong Wang fcoet_exchange_t *xch = FRM2TFM(frm)->tfm_xch; 8842a8164dfSZhong Wang stmf_data_buf_t *dbuf; 8852a8164dfSZhong Wang int dbuf_index; 8862a8164dfSZhong Wang uint32_t iof; 8872a8164dfSZhong Wang 8882a8164dfSZhong Wang dbuf_index = FRM2TFM(frm)->tfm_buf_idx; 8892a8164dfSZhong Wang xch->xch_left_data_size -= frm->frm_payload_size; 8902a8164dfSZhong Wang dbuf = xch->xch_dbufs[dbuf_index]; 8912a8164dfSZhong Wang ASSERT((dbuf) && (dbuf->db_flags & DB_DIRECTION_TO_RPORT)); 8922a8164dfSZhong Wang 8932a8164dfSZhong Wang /* 8942a8164dfSZhong Wang * We decrease db_sglist_length only for READ-type commands. 8952a8164dfSZhong Wang * For INQUIRY, resid could be non-zero, then db_sglist_length will 8962a8164dfSZhong Wang * be useful. 8972a8164dfSZhong Wang */ 8982a8164dfSZhong Wang dbuf->db_sglist_length--; 8992a8164dfSZhong Wang if ((xch->xch_left_data_size <= 0) || (!dbuf->db_sglist_length)) { 9002a8164dfSZhong Wang iof = 0; 9012a8164dfSZhong Wang dbuf->db_xfer_status = FCT_SUCCESS; 9022a8164dfSZhong Wang dbuf->db_flags |= DB_DONT_REUSE; 9032a8164dfSZhong Wang if (dbuf->db_flags & DB_SEND_STATUS_GOOD) { 9042a8164dfSZhong Wang if (fcoet_send_status(xch->xch_cmd) != FCT_SUCCESS) { 9052a8164dfSZhong Wang return (FCOE_FAILURE); 9062a8164dfSZhong Wang } 9072a8164dfSZhong Wang } else { 9082a8164dfSZhong Wang fct_scsi_data_xfer_done(xch->xch_cmd, dbuf, iof); 9092a8164dfSZhong Wang } 9102a8164dfSZhong Wang } 9112a8164dfSZhong Wang FCOET_RELE_XCHG(xch); 9122a8164dfSZhong Wang return (FCOE_SUCCESS); 9132a8164dfSZhong Wang } 9142a8164dfSZhong Wang 9152a8164dfSZhong Wang static int 9162a8164dfSZhong Wang fcoet_send_fcp_status_done(fcoe_frame_t *frm) 9172a8164dfSZhong Wang { 9182a8164dfSZhong Wang fcoet_exchange_t *xch = FRM2TFM(frm)->tfm_xch; 9192a8164dfSZhong Wang fct_status_t fc_st = FCT_SUCCESS; 9202a8164dfSZhong Wang uint32_t iof = FCT_IOF_FCA_DONE; 9212a8164dfSZhong Wang 9222a8164dfSZhong Wang if (xch->xch_flags & XCH_FLAG_FCT_CALLED_ABORT) { 9232a8164dfSZhong Wang FCOET_RELE_XCHG(xch); 9242a8164dfSZhong Wang return (FCOE_SUCCESS); 9252a8164dfSZhong Wang } 9262a8164dfSZhong Wang 9272a8164dfSZhong Wang if (fcoet_clear_unsol_exchange(xch) == FCOE_SUCCESS) { 9282a8164dfSZhong Wang FCOET_RELE_XCHG(xch); 9292a8164dfSZhong Wang fct_send_response_done(xch->xch_cmd, fc_st, iof); 9302a8164dfSZhong Wang } else { 9312a8164dfSZhong Wang /* Already cleared from hash table by abort */ 9322a8164dfSZhong Wang FCOET_RELE_XCHG(xch); 9332a8164dfSZhong Wang } 9342a8164dfSZhong Wang 9352a8164dfSZhong Wang return (FCOE_SUCCESS); 9362a8164dfSZhong Wang } 9372a8164dfSZhong Wang 9382a8164dfSZhong Wang /* 9392a8164dfSZhong Wang * Solicited frames callback area 9402a8164dfSZhong Wang */ 9412a8164dfSZhong Wang static int 9422a8164dfSZhong Wang fcoet_send_unsol_els_rsp_done(fcoe_frame_t *frm) 9432a8164dfSZhong Wang { 9442a8164dfSZhong Wang fcoet_exchange_t *xch = FRM2TFM(frm)->tfm_xch; 9452a8164dfSZhong Wang fct_status_t fc_st; 9462a8164dfSZhong Wang uint32_t iof; 9472a8164dfSZhong Wang 9482a8164dfSZhong Wang FCOET_EXT_LOG("fcoet_send_unsol_els_rsp_done", 9492a8164dfSZhong Wang "frm/oxid/els: %p/%x/%x", 9502a8164dfSZhong Wang frm, FRM_OXID(frm), XCH2ELS(xch)->els_req_payload[0]); 9512a8164dfSZhong Wang if (xch->xch_flags & XCH_FLAG_FCT_CALLED_ABORT) { 9522a8164dfSZhong Wang FCOET_RELE_XCHG(xch); 9532a8164dfSZhong Wang return (FCOE_SUCCESS); 9542a8164dfSZhong Wang } 9552a8164dfSZhong Wang 9562a8164dfSZhong Wang if (fcoet_clear_unsol_exchange(xch) == FCOE_FAILURE) { 9572a8164dfSZhong Wang FCOET_RELE_XCHG(xch); 9582a8164dfSZhong Wang return (FCOE_SUCCESS); 9592a8164dfSZhong Wang } 9602a8164dfSZhong Wang 9612a8164dfSZhong Wang FCOET_RELE_XCHG(xch); 9622a8164dfSZhong Wang if (XCH2ELS(xch)->els_req_payload[0] != ELS_OP_FLOGI) { 9632a8164dfSZhong Wang fc_st = FCT_SUCCESS; 9642a8164dfSZhong Wang iof = FCT_IOF_FCA_DONE; 9652a8164dfSZhong Wang fct_send_response_done(xch->xch_cmd, fc_st, iof); 9662a8164dfSZhong Wang } else { 9672a8164dfSZhong Wang /* 9682a8164dfSZhong Wang * We need update ss_link_info and flags. 9692a8164dfSZhong Wang */ 9702a8164dfSZhong Wang mutex_enter(&xch->xch_ss->ss_watch_mutex); 9712a8164dfSZhong Wang xch->xch_ss->ss_link_info.portid = 9722a8164dfSZhong Wang xch->xch_cmd->cmd_lportid; 9732a8164dfSZhong Wang xch->xch_ss->ss_link_info.port_topology = 9742a8164dfSZhong Wang PORT_TOPOLOGY_PT_TO_PT; 9752a8164dfSZhong Wang if (frm->frm_eport->eport_link_speed == FCOE_PORT_SPEED_1G) { 9762a8164dfSZhong Wang xch->xch_ss->ss_link_info.port_speed = PORT_SPEED_1G; 9772a8164dfSZhong Wang } else if (frm->frm_eport->eport_link_speed == 9782a8164dfSZhong Wang FCOE_PORT_SPEED_10G) { 9792a8164dfSZhong Wang xch->xch_ss->ss_link_info.port_speed = PORT_SPEED_10G; 9802a8164dfSZhong Wang } 9812a8164dfSZhong Wang xch->xch_ss->ss_link_info.port_no_fct_flogi = 1; 9822a8164dfSZhong Wang xch->xch_ss->ss_link_info.port_fca_flogi_done = 1; 9832a8164dfSZhong Wang xch->xch_ss->ss_link_info.port_fct_flogi_done = 0; 9842a8164dfSZhong Wang bcopy(XCH2ELS(xch)->els_req_payload + 20, 9852a8164dfSZhong Wang xch->xch_ss->ss_link_info.port_rpwwn, 8); 9862a8164dfSZhong Wang bcopy(XCH2ELS(xch)->els_req_payload + 28, 9872a8164dfSZhong Wang xch->xch_ss->ss_link_info.port_rnwwn, 8); 9882a8164dfSZhong Wang atomic_or_32(&xch->xch_ss->ss_flags, 9892a8164dfSZhong Wang SS_FLAG_UNSOL_FLOGI_DONE); 9902a8164dfSZhong Wang atomic_or_32(&xch->xch_ss->ss_flags, 9912a8164dfSZhong Wang SS_FLAG_REPORT_TO_FCT); 9922a8164dfSZhong Wang 9932a8164dfSZhong Wang xch->xch_ss->ss_sol_flogi_state = SFS_FLOGI_ACC; 9942a8164dfSZhong Wang mutex_exit(&xch->xch_ss->ss_watch_mutex); 9952a8164dfSZhong Wang 9962a8164dfSZhong Wang fct_free(xch->xch_cmd); 9972a8164dfSZhong Wang } 9982a8164dfSZhong Wang return (FCOE_SUCCESS); 9992a8164dfSZhong Wang } 10002a8164dfSZhong Wang 10012a8164dfSZhong Wang /* ARGSUSED */ 10022a8164dfSZhong Wang static int 10032a8164dfSZhong Wang fcoet_send_sol_els_req_done(fcoe_frame_t *frm) 10042a8164dfSZhong Wang { 10052a8164dfSZhong Wang return (FCOE_SUCCESS); 10062a8164dfSZhong Wang } 10072a8164dfSZhong Wang 10082a8164dfSZhong Wang /* 10092a8164dfSZhong Wang * FCT have released relevant fct_cmd_t and fcoet_exchange_t now, so it's not 10102a8164dfSZhong Wang * needed to notify FCT anything. Just do nothing. 10112a8164dfSZhong Wang */ 10122a8164dfSZhong Wang /* ARGSUSED */ 10132a8164dfSZhong Wang static int 10142a8164dfSZhong Wang fcoet_send_unsol_bls_acc_done(fcoe_frame_t *frm) 10152a8164dfSZhong Wang { 10162a8164dfSZhong Wang FCOET_LOG("fcoet_send_unsol_bls_acc_done", 10172a8164dfSZhong Wang "Unsolicited BA_ACC sent out and released "); 10182a8164dfSZhong Wang 10192a8164dfSZhong Wang return (FCOE_SUCCESS); 10202a8164dfSZhong Wang } 10212a8164dfSZhong Wang 10222a8164dfSZhong Wang /* ARGSUSED */ 10232a8164dfSZhong Wang static int 10242a8164dfSZhong Wang fcoet_send_unsol_bls_rjt_done(fcoe_frame_t *frm) 10252a8164dfSZhong Wang { 10262a8164dfSZhong Wang FCOET_LOG("fcoet_send_unsol_bls_rjt_done", 10272a8164dfSZhong Wang "Unsolicited BA_RJT sent out and released"); 10282a8164dfSZhong Wang return (FCOE_SUCCESS); 10292a8164dfSZhong Wang } 10302a8164dfSZhong Wang 10312a8164dfSZhong Wang /* ARGSUSED */ 10322a8164dfSZhong Wang static int 10332a8164dfSZhong Wang fcoet_send_sol_bls_req_done(fcoe_frame_t *frm) 10342a8164dfSZhong Wang { 10352a8164dfSZhong Wang FCOET_LOG("fcoet_send_sol_bls_req_done", 10362a8164dfSZhong Wang "Soclited ABTS was sent out and released"); 10372a8164dfSZhong Wang return (FCOE_SUCCESS); 10382a8164dfSZhong Wang } 10392a8164dfSZhong Wang 10402a8164dfSZhong Wang /* ARGSUSED */ 10412a8164dfSZhong Wang static int 10422a8164dfSZhong Wang fcoet_send_sol_ct_req_done(fcoe_frame_t *frm) 10432a8164dfSZhong Wang { 10442a8164dfSZhong Wang FCOET_LOG("fcoet_send_sol_ct_req_done", 10452a8164dfSZhong Wang "CT request was sent out and released"); 10462a8164dfSZhong Wang return (FCOE_SUCCESS); 10472a8164dfSZhong Wang } 10482a8164dfSZhong Wang 10492a8164dfSZhong Wang /* 10502a8164dfSZhong Wang * FCoET can only interpret solicited and unsolicited FLOGI, all the other 10512a8164dfSZhong Wang * ELS/CT/FCP should be passed up to FCT. 10522a8164dfSZhong Wang */ 10532a8164dfSZhong Wang static int 10542a8164dfSZhong Wang fcoet_process_unsol_flogi_req(fcoet_exchange_t *xch) 10552a8164dfSZhong Wang { 10562a8164dfSZhong Wang fcoe_frame_t *frm; 10572a8164dfSZhong Wang 10582a8164dfSZhong Wang atomic_or_32(&xch->xch_ss->ss_flags, SS_FLAG_DELAY_PLOGI); 10592a8164dfSZhong Wang 10602a8164dfSZhong Wang /* 10612a8164dfSZhong Wang * In spec, common service parameter should indicate if it's from 10622a8164dfSZhong Wang * N-port or F-port, but the initial intel implementation is not 10632a8164dfSZhong Wang * spec-compliant, so we use eport_flags to workaround the problem 10642a8164dfSZhong Wang */ 10652a8164dfSZhong Wang if (!(xch->xch_ss->ss_eport->eport_flags & EPORT_FLAG_IS_DIRECT_P2P)) { 10662a8164dfSZhong Wang /* 10672a8164dfSZhong Wang * The topology is switch P2P, so there's no need to respond 10682a8164dfSZhong Wang * to this FLOGI 10692a8164dfSZhong Wang */ 10702a8164dfSZhong Wang FCOET_LOG("fcoet_process_unsol_flogi_req", 10712a8164dfSZhong Wang "skip FLOGI, since we are in switch topology"); 10722a8164dfSZhong Wang return (FCOE_SUCCESS); 10732a8164dfSZhong Wang } 10742a8164dfSZhong Wang 10752a8164dfSZhong Wang /* 10762a8164dfSZhong Wang * Send ACC according to the spec. 10772a8164dfSZhong Wang */ 10782a8164dfSZhong Wang frm = xch->xch_ss->ss_eport->eport_alloc_frame(xch->xch_ss->ss_eport, 10792a8164dfSZhong Wang FLOGI_ACC_PAYLOAD_SIZE + FCFH_SIZE, 0); 10802a8164dfSZhong Wang if (frm == NULL) { 10812a8164dfSZhong Wang ASSERT(0); 10822a8164dfSZhong Wang return (FCOE_FAILURE); 10832a8164dfSZhong Wang } else { 10842a8164dfSZhong Wang fcoet_init_tfm(frm, xch); 10852a8164dfSZhong Wang bzero(frm->frm_payload, frm->frm_payload_size); 10862a8164dfSZhong Wang } 10872a8164dfSZhong Wang 10882a8164dfSZhong Wang FFM_R_CTL(0x23, frm); 10892a8164dfSZhong Wang FRM2TFM(frm)->tfm_rctl = 0x23; 10902a8164dfSZhong Wang FFM_TYPE(0x01, frm); 10912a8164dfSZhong Wang FFM_F_CTL(0x980000, frm); 10922a8164dfSZhong Wang FFM_OXID(xch->xch_oxid, frm); 10932a8164dfSZhong Wang FFM_RXID(xch->xch_rxid, frm); 10942a8164dfSZhong Wang FFM_S_ID(0xFFFFFE, frm); 10952a8164dfSZhong Wang 10962a8164dfSZhong Wang /* 10972a8164dfSZhong Wang * ACC 10982a8164dfSZhong Wang */ 10992a8164dfSZhong Wang frm->frm_payload[0] = 0x02; 11002a8164dfSZhong Wang 11012a8164dfSZhong Wang /* 11022a8164dfSZhong Wang * Common Svc Parameters 11032a8164dfSZhong Wang */ 11042a8164dfSZhong Wang frm->frm_payload[4] = 0x20; 11052a8164dfSZhong Wang frm->frm_payload[5] = 0x20; 11062a8164dfSZhong Wang frm->frm_payload[7] = 0x0A; 11072a8164dfSZhong Wang frm->frm_payload[10] = 0x05; 11082a8164dfSZhong Wang frm->frm_payload[11] = 0xAC; 11092a8164dfSZhong Wang bcopy(xch->xch_ss->ss_eport->eport_portwwn, frm->frm_payload + 20, 8); 11102a8164dfSZhong Wang bcopy(xch->xch_ss->ss_eport->eport_nodewwn, frm->frm_payload + 28, 8); 11112a8164dfSZhong Wang 11122a8164dfSZhong Wang /* 11132a8164dfSZhong Wang * Class3 Svc Parameters 11142a8164dfSZhong Wang */ 11152a8164dfSZhong Wang frm->frm_payload[68] = 0x88; 11162a8164dfSZhong Wang 11172a8164dfSZhong Wang /* 11182a8164dfSZhong Wang * Send FLOGI ACC out 11192a8164dfSZhong Wang * After this, we should never use the exchange, because it could 11202a8164dfSZhong Wang * have been released. Please pay attention to other similiar cases. 11212a8164dfSZhong Wang */ 11222a8164dfSZhong Wang xch->xch_ss->ss_eport->eport_tx_frame(frm); 11232a8164dfSZhong Wang return (FCOE_SUCCESS); 11242a8164dfSZhong Wang } 11252a8164dfSZhong Wang 11262a8164dfSZhong Wang static int 11272a8164dfSZhong Wang fcoet_process_sol_flogi_rsp(fcoe_frame_t *frm) 11282a8164dfSZhong Wang { 11292a8164dfSZhong Wang int ret = FCOE_SUCCESS; 11302a8164dfSZhong Wang fcoet_exchange_t *xch = FRM2TFM(frm)->tfm_xch; 11312a8164dfSZhong Wang fct_els_t *els = CMD2ELS(xch->xch_cmd); 1132*1826d2a2SKelly Hu fcoet_soft_state_t *ss = FRM2SS(frm); 11332a8164dfSZhong Wang 11342a8164dfSZhong Wang if (els->els_resp_payload[0] == ELS_OP_ACC) { 11352a8164dfSZhong Wang /* 11362a8164dfSZhong Wang * We need always update ss_link_info and flags for solicited 11372a8164dfSZhong Wang * FLOGI, because someone has assigned address for you. The 11382a8164dfSZhong Wang * initial intel implementation will always assign address for 11392a8164dfSZhong Wang * you even you are in back-to-back mode (direct P2P). 11402a8164dfSZhong Wang */ 1141*1826d2a2SKelly Hu mutex_enter(&ss->ss_watch_mutex); 1142*1826d2a2SKelly Hu if (ss->ss_flags & SS_FLAG_PORT_DISABLED || 1143*1826d2a2SKelly Hu (ss->ss_sol_flogi_state != SFS_FLOGI_INIT && 1144*1826d2a2SKelly Hu ss->ss_sol_flogi_state != SFS_FLOGI_CHECK_TIMEOUT && 1145*1826d2a2SKelly Hu ss->ss_sol_flogi_state != SFS_ABTS_INIT)) { 1146*1826d2a2SKelly Hu /* 1147*1826d2a2SKelly Hu * The status is not correct, this response may be 1148*1826d2a2SKelly Hu * obsolete. 1149*1826d2a2SKelly Hu */ 1150*1826d2a2SKelly Hu mutex_exit(&ss->ss_watch_mutex); 1151*1826d2a2SKelly Hu FCOET_LOG("fcoet_process_sol_flogi_rsp", 1152*1826d2a2SKelly Hu "FLOGI response is obsolete"); 1153*1826d2a2SKelly Hu return (FCOE_FAILURE); 1154*1826d2a2SKelly Hu } 11552a8164dfSZhong Wang if (xch->xch_flags & XCH_FLAG_NONFCP_REQ_SENT) { 11562a8164dfSZhong Wang xch->xch_cmd->cmd_lportid = FRM_D_ID(frm); 11572a8164dfSZhong Wang xch->xch_ss->ss_link_info.portid = 11582a8164dfSZhong Wang xch->xch_cmd->cmd_lportid; 11592a8164dfSZhong Wang /* 11602a8164dfSZhong Wang * Check the bit 28 in 3rd word of the payload 11612a8164dfSZhong Wang * in common service parameters to know the 11622a8164dfSZhong Wang * remote port is F_PORT or N_PORT 11632a8164dfSZhong Wang */ 11642a8164dfSZhong Wang if (els->els_resp_payload[8] & 0x10) { 11652a8164dfSZhong Wang uint8_t src_addr[ETHERADDRL]; 11662a8164dfSZhong Wang frm->frm_eport->eport_flags &= 11672a8164dfSZhong Wang ~EPORT_FLAG_IS_DIRECT_P2P; 11682a8164dfSZhong Wang FCOE_SET_DEFAULT_OUI(src_addr); 11692a8164dfSZhong Wang bcopy(frm->frm_hdr->hdr_d_id, src_addr + 3, 3); 11702a8164dfSZhong Wang bcopy((char *)frm->frm_hdr-22, 11712a8164dfSZhong Wang frm->frm_eport->eport_efh_dst, 11722a8164dfSZhong Wang ETHERADDRL); 11732a8164dfSZhong Wang frm->frm_eport->eport_set_mac_address( 11742a8164dfSZhong Wang frm->frm_eport, src_addr, B_TRUE); 11752a8164dfSZhong Wang xch->xch_ss->ss_link_info.port_topology = 11762a8164dfSZhong Wang PORT_TOPOLOGY_FABRIC_PT_TO_PT; 11772a8164dfSZhong Wang } else { 11782a8164dfSZhong Wang xch->xch_ss->ss_link_info.port_topology = 11792a8164dfSZhong Wang PORT_TOPOLOGY_PT_TO_PT; 11802a8164dfSZhong Wang } 11812a8164dfSZhong Wang 11822a8164dfSZhong Wang xch->xch_ss->ss_link_info.port_speed = PORT_SPEED_10G; 11832a8164dfSZhong Wang xch->xch_ss->ss_link_info.port_no_fct_flogi = 1; 11842a8164dfSZhong Wang xch->xch_ss->ss_link_info.port_fca_flogi_done = 1; 11852a8164dfSZhong Wang xch->xch_ss->ss_link_info.port_fct_flogi_done = 0; 11862a8164dfSZhong Wang xch->xch_ss->ss_sol_flogi_state = SFS_FLOGI_ACC; 11872a8164dfSZhong Wang cv_signal(&xch->xch_ss->ss_watch_cv); 11882a8164dfSZhong Wang FCOET_LOG("fcoet_process_sol_flogi_rsp", 11892a8164dfSZhong Wang "FLOGI is accecpted"); 11902a8164dfSZhong Wang } else { 11912a8164dfSZhong Wang FCOET_LOG("fcoet_process_sol_flogi_rsp", 11922a8164dfSZhong Wang "FLOGI xch_flags/%x", xch->xch_flags); 11932a8164dfSZhong Wang ret = FCOE_FAILURE; 11942a8164dfSZhong Wang } 1195*1826d2a2SKelly Hu mutex_exit(&ss->ss_watch_mutex); 11962a8164dfSZhong Wang } else { 11972a8164dfSZhong Wang FCOET_LOG("fcoet_process_sol_flogi_rsp", "FLOGI is rejected"); 11982a8164dfSZhong Wang ret = FCOE_FAILURE; 11992a8164dfSZhong Wang } 12002a8164dfSZhong Wang return (ret); 12012a8164dfSZhong Wang } 1202