17978SPeter.Dunlap@Sun.COM /* 27978SPeter.Dunlap@Sun.COM * CDDL HEADER START 37978SPeter.Dunlap@Sun.COM * 47978SPeter.Dunlap@Sun.COM * The contents of this file are subject to the terms of the 57978SPeter.Dunlap@Sun.COM * Common Development and Distribution License (the "License"). 67978SPeter.Dunlap@Sun.COM * You may not use this file except in compliance with the License. 77978SPeter.Dunlap@Sun.COM * 87978SPeter.Dunlap@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97978SPeter.Dunlap@Sun.COM * or http://www.opensolaris.org/os/licensing. 107978SPeter.Dunlap@Sun.COM * See the License for the specific language governing permissions 117978SPeter.Dunlap@Sun.COM * and limitations under the License. 127978SPeter.Dunlap@Sun.COM * 137978SPeter.Dunlap@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 147978SPeter.Dunlap@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157978SPeter.Dunlap@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 167978SPeter.Dunlap@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 177978SPeter.Dunlap@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 187978SPeter.Dunlap@Sun.COM * 197978SPeter.Dunlap@Sun.COM * CDDL HEADER END 207978SPeter.Dunlap@Sun.COM */ 217978SPeter.Dunlap@Sun.COM 227978SPeter.Dunlap@Sun.COM /* 2311424SJack.Meng@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 247978SPeter.Dunlap@Sun.COM * Use is subject to license terms. 257978SPeter.Dunlap@Sun.COM */ 267978SPeter.Dunlap@Sun.COM 277978SPeter.Dunlap@Sun.COM #include <sys/conf.h> 287978SPeter.Dunlap@Sun.COM #include <sys/file.h> 297978SPeter.Dunlap@Sun.COM #include <sys/ddi.h> 307978SPeter.Dunlap@Sun.COM #include <sys/sunddi.h> 317978SPeter.Dunlap@Sun.COM #include <sys/cpuvar.h> 329721SPriya.Krishnan@Sun.COM #include <sys/sdt.h> 337978SPeter.Dunlap@Sun.COM 347978SPeter.Dunlap@Sun.COM #include <sys/socket.h> 357978SPeter.Dunlap@Sun.COM #include <sys/strsubr.h> 367978SPeter.Dunlap@Sun.COM #include <sys/socketvar.h> 377978SPeter.Dunlap@Sun.COM #include <sys/sysmacros.h> 387978SPeter.Dunlap@Sun.COM 397978SPeter.Dunlap@Sun.COM #include <sys/idm/idm.h> 407978SPeter.Dunlap@Sun.COM #include <sys/idm/idm_so.h> 4110777SJack.Meng@Sun.COM #include <hd_crc.h> 427978SPeter.Dunlap@Sun.COM 437978SPeter.Dunlap@Sun.COM extern idm_transport_t idm_transport_list[]; 4410777SJack.Meng@Sun.COM /* 4510777SJack.Meng@Sun.COM * -1 - uninitialized 4610777SJack.Meng@Sun.COM * 0 - applicable 4710777SJack.Meng@Sun.COM * others - NA 4810777SJack.Meng@Sun.COM */ 4910777SJack.Meng@Sun.COM static int iscsi_crc32_hd = -1; 507978SPeter.Dunlap@Sun.COM 517978SPeter.Dunlap@Sun.COM void 527978SPeter.Dunlap@Sun.COM idm_pdu_rx(idm_conn_t *ic, idm_pdu_t *pdu) 537978SPeter.Dunlap@Sun.COM { 547978SPeter.Dunlap@Sun.COM iscsi_async_evt_hdr_t *async_evt; 557978SPeter.Dunlap@Sun.COM 567978SPeter.Dunlap@Sun.COM /* 577978SPeter.Dunlap@Sun.COM * If we are in full-featured mode then route SCSI-related 587978SPeter.Dunlap@Sun.COM * commands to the appropriate function vector 597978SPeter.Dunlap@Sun.COM */ 607978SPeter.Dunlap@Sun.COM ic->ic_timestamp = ddi_get_lbolt(); 617978SPeter.Dunlap@Sun.COM mutex_enter(&ic->ic_state_mutex); 627978SPeter.Dunlap@Sun.COM if (ic->ic_ffp && ic->ic_pdu_events == 0) { 637978SPeter.Dunlap@Sun.COM mutex_exit(&ic->ic_state_mutex); 647978SPeter.Dunlap@Sun.COM 657978SPeter.Dunlap@Sun.COM if (idm_pdu_rx_forward_ffp(ic, pdu) == B_TRUE) { 667978SPeter.Dunlap@Sun.COM /* Forwarded SCSI-related commands */ 677978SPeter.Dunlap@Sun.COM return; 687978SPeter.Dunlap@Sun.COM } 697978SPeter.Dunlap@Sun.COM mutex_enter(&ic->ic_state_mutex); 707978SPeter.Dunlap@Sun.COM } 717978SPeter.Dunlap@Sun.COM 727978SPeter.Dunlap@Sun.COM /* 737978SPeter.Dunlap@Sun.COM * If we get here with a SCSI-related PDU then we are not in 747978SPeter.Dunlap@Sun.COM * full-feature mode and the PDU is a protocol error (SCSI command 757978SPeter.Dunlap@Sun.COM * PDU's may sometimes be an exception, see below). All 767978SPeter.Dunlap@Sun.COM * non-SCSI PDU's get treated them the same regardless of whether 777978SPeter.Dunlap@Sun.COM * we are in full-feature mode. 787978SPeter.Dunlap@Sun.COM * 797978SPeter.Dunlap@Sun.COM * Look at the opcode and in some cases the PDU status and 807978SPeter.Dunlap@Sun.COM * determine the appropriate event to send to the connection 817978SPeter.Dunlap@Sun.COM * state machine. Generate the event, passing the PDU as data. 827978SPeter.Dunlap@Sun.COM * If the current connection state allows reception of the event 837978SPeter.Dunlap@Sun.COM * the PDU will be submitted to the IDM client for processing, 847978SPeter.Dunlap@Sun.COM * otherwise the PDU will be dropped. 857978SPeter.Dunlap@Sun.COM */ 867978SPeter.Dunlap@Sun.COM switch (IDM_PDU_OPCODE(pdu)) { 877978SPeter.Dunlap@Sun.COM case ISCSI_OP_LOGIN_CMD: 889721SPriya.Krishnan@Sun.COM DTRACE_ISCSI_2(login__command, idm_conn_t *, ic, 899721SPriya.Krishnan@Sun.COM iscsi_login_hdr_t *, (iscsi_login_hdr_t *)pdu->isp_hdr); 907978SPeter.Dunlap@Sun.COM idm_conn_rx_pdu_event(ic, CE_LOGIN_RCV, (uintptr_t)pdu); 917978SPeter.Dunlap@Sun.COM break; 927978SPeter.Dunlap@Sun.COM case ISCSI_OP_LOGIN_RSP: 937978SPeter.Dunlap@Sun.COM idm_parse_login_rsp(ic, pdu, /* RX */ B_TRUE); 947978SPeter.Dunlap@Sun.COM break; 957978SPeter.Dunlap@Sun.COM case ISCSI_OP_LOGOUT_CMD: 969721SPriya.Krishnan@Sun.COM DTRACE_ISCSI_2(logout__command, idm_conn_t *, ic, 979721SPriya.Krishnan@Sun.COM iscsi_logout_hdr_t *, 989721SPriya.Krishnan@Sun.COM (iscsi_logout_hdr_t *)pdu->isp_hdr); 997978SPeter.Dunlap@Sun.COM idm_parse_logout_req(ic, pdu, /* RX */ B_TRUE); 1007978SPeter.Dunlap@Sun.COM break; 1017978SPeter.Dunlap@Sun.COM case ISCSI_OP_LOGOUT_RSP: 1027978SPeter.Dunlap@Sun.COM idm_parse_logout_rsp(ic, pdu, /* RX */ B_TRUE); 1037978SPeter.Dunlap@Sun.COM break; 1047978SPeter.Dunlap@Sun.COM case ISCSI_OP_ASYNC_EVENT: 1057978SPeter.Dunlap@Sun.COM async_evt = (iscsi_async_evt_hdr_t *)pdu->isp_hdr; 1069162SPeter.Dunlap@Sun.COM switch (async_evt->async_event) { 1077978SPeter.Dunlap@Sun.COM case ISCSI_ASYNC_EVENT_REQUEST_LOGOUT: 1087978SPeter.Dunlap@Sun.COM idm_conn_rx_pdu_event(ic, CE_ASYNC_LOGOUT_RCV, 1097978SPeter.Dunlap@Sun.COM (uintptr_t)pdu); 1107978SPeter.Dunlap@Sun.COM break; 1117978SPeter.Dunlap@Sun.COM case ISCSI_ASYNC_EVENT_DROPPING_CONNECTION: 1127978SPeter.Dunlap@Sun.COM idm_conn_rx_pdu_event(ic, CE_ASYNC_DROP_CONN_RCV, 1137978SPeter.Dunlap@Sun.COM (uintptr_t)pdu); 1147978SPeter.Dunlap@Sun.COM break; 1157978SPeter.Dunlap@Sun.COM case ISCSI_ASYNC_EVENT_DROPPING_ALL_CONNECTIONS: 1167978SPeter.Dunlap@Sun.COM idm_conn_rx_pdu_event(ic, CE_ASYNC_DROP_ALL_CONN_RCV, 1177978SPeter.Dunlap@Sun.COM (uintptr_t)pdu); 1187978SPeter.Dunlap@Sun.COM break; 1197978SPeter.Dunlap@Sun.COM case ISCSI_ASYNC_EVENT_SCSI_EVENT: 1207978SPeter.Dunlap@Sun.COM case ISCSI_ASYNC_EVENT_PARAM_NEGOTIATION: 1217978SPeter.Dunlap@Sun.COM default: 1227978SPeter.Dunlap@Sun.COM idm_conn_rx_pdu_event(ic, CE_MISC_RX, 1237978SPeter.Dunlap@Sun.COM (uintptr_t)pdu); 1247978SPeter.Dunlap@Sun.COM break; 1257978SPeter.Dunlap@Sun.COM } 1267978SPeter.Dunlap@Sun.COM break; 1277978SPeter.Dunlap@Sun.COM case ISCSI_OP_SCSI_CMD: 1287978SPeter.Dunlap@Sun.COM /* 1297978SPeter.Dunlap@Sun.COM * Consider this scenario: We are a target connection 1307978SPeter.Dunlap@Sun.COM * in "in login" state and a "login success sent" event has 1317978SPeter.Dunlap@Sun.COM * been generated but not yet handled. Since we've sent 1327978SPeter.Dunlap@Sun.COM * the login response but we haven't actually transitioned 1337978SPeter.Dunlap@Sun.COM * to FFP mode we might conceivably receive a SCSI command 1347978SPeter.Dunlap@Sun.COM * from the initiator before we are ready. We are actually 1357978SPeter.Dunlap@Sun.COM * in FFP we just don't know it yet -- to address this we 1367978SPeter.Dunlap@Sun.COM * can generate an event corresponding to the SCSI command. 1377978SPeter.Dunlap@Sun.COM * At the point when the event is handled by the state 1387978SPeter.Dunlap@Sun.COM * machine the login request will have been handled and we 1397978SPeter.Dunlap@Sun.COM * should be in FFP. If we are not in FFP by that time 1407978SPeter.Dunlap@Sun.COM * we can reject the SCSI command with a protocol error. 1417978SPeter.Dunlap@Sun.COM * 1427978SPeter.Dunlap@Sun.COM * This scenario only applies to the target. 1439721SPriya.Krishnan@Sun.COM * 1449721SPriya.Krishnan@Sun.COM * Handle dtrace probe in iscsit so we can find all the 1459721SPriya.Krishnan@Sun.COM * pieces of the CDB 1467978SPeter.Dunlap@Sun.COM */ 1479721SPriya.Krishnan@Sun.COM idm_conn_rx_pdu_event(ic, CE_MISC_RX, (uintptr_t)pdu); 1489721SPriya.Krishnan@Sun.COM break; 1497978SPeter.Dunlap@Sun.COM case ISCSI_OP_SCSI_DATA: 1509721SPriya.Krishnan@Sun.COM DTRACE_ISCSI_2(data__receive, idm_conn_t *, ic, 1519721SPriya.Krishnan@Sun.COM iscsi_data_hdr_t *, 1529721SPriya.Krishnan@Sun.COM (iscsi_data_hdr_t *)pdu->isp_hdr); 1539721SPriya.Krishnan@Sun.COM idm_conn_rx_pdu_event(ic, CE_MISC_RX, (uintptr_t)pdu); 1549721SPriya.Krishnan@Sun.COM break; 1559721SPriya.Krishnan@Sun.COM case ISCSI_OP_SCSI_TASK_MGT_MSG: 1569721SPriya.Krishnan@Sun.COM DTRACE_ISCSI_2(task__command, idm_conn_t *, ic, 1579721SPriya.Krishnan@Sun.COM iscsi_scsi_task_mgt_hdr_t *, 1589721SPriya.Krishnan@Sun.COM (iscsi_scsi_task_mgt_hdr_t *)pdu->isp_hdr); 1599721SPriya.Krishnan@Sun.COM idm_conn_rx_pdu_event(ic, CE_MISC_RX, (uintptr_t)pdu); 1609721SPriya.Krishnan@Sun.COM break; 1619721SPriya.Krishnan@Sun.COM case ISCSI_OP_NOOP_OUT: 1629721SPriya.Krishnan@Sun.COM DTRACE_ISCSI_2(nop__receive, idm_conn_t *, ic, 1639721SPriya.Krishnan@Sun.COM iscsi_nop_out_hdr_t *, 1649721SPriya.Krishnan@Sun.COM (iscsi_nop_out_hdr_t *)pdu->isp_hdr); 1659721SPriya.Krishnan@Sun.COM idm_conn_rx_pdu_event(ic, CE_MISC_RX, (uintptr_t)pdu); 1669721SPriya.Krishnan@Sun.COM break; 1679721SPriya.Krishnan@Sun.COM case ISCSI_OP_TEXT_CMD: 1689721SPriya.Krishnan@Sun.COM DTRACE_ISCSI_2(text__command, idm_conn_t *, ic, 1699721SPriya.Krishnan@Sun.COM iscsi_text_hdr_t *, 1709721SPriya.Krishnan@Sun.COM (iscsi_text_hdr_t *)pdu->isp_hdr); 1719721SPriya.Krishnan@Sun.COM idm_conn_rx_pdu_event(ic, CE_MISC_RX, (uintptr_t)pdu); 1729721SPriya.Krishnan@Sun.COM break; 1739721SPriya.Krishnan@Sun.COM /* Initiator PDU's */ 1747978SPeter.Dunlap@Sun.COM case ISCSI_OP_SCSI_DATA_RSP: 1757978SPeter.Dunlap@Sun.COM case ISCSI_OP_RTT_RSP: 1767978SPeter.Dunlap@Sun.COM case ISCSI_OP_SNACK_CMD: 1777978SPeter.Dunlap@Sun.COM case ISCSI_OP_NOOP_IN: 1787978SPeter.Dunlap@Sun.COM case ISCSI_OP_TEXT_RSP: 1797978SPeter.Dunlap@Sun.COM case ISCSI_OP_REJECT_MSG: 1807978SPeter.Dunlap@Sun.COM case ISCSI_OP_SCSI_TASK_MGT_RSP: 1817978SPeter.Dunlap@Sun.COM /* Validate received PDU against current state */ 1827978SPeter.Dunlap@Sun.COM idm_conn_rx_pdu_event(ic, CE_MISC_RX, 1837978SPeter.Dunlap@Sun.COM (uintptr_t)pdu); 1847978SPeter.Dunlap@Sun.COM break; 1857978SPeter.Dunlap@Sun.COM } 1867978SPeter.Dunlap@Sun.COM mutex_exit(&ic->ic_state_mutex); 1877978SPeter.Dunlap@Sun.COM } 1887978SPeter.Dunlap@Sun.COM 1897978SPeter.Dunlap@Sun.COM void 1907978SPeter.Dunlap@Sun.COM idm_pdu_tx_forward(idm_conn_t *ic, idm_pdu_t *pdu) 1917978SPeter.Dunlap@Sun.COM { 1927978SPeter.Dunlap@Sun.COM (*ic->ic_transport_ops->it_tx_pdu)(ic, pdu); 1937978SPeter.Dunlap@Sun.COM } 1947978SPeter.Dunlap@Sun.COM 1957978SPeter.Dunlap@Sun.COM boolean_t 1967978SPeter.Dunlap@Sun.COM idm_pdu_rx_forward_ffp(idm_conn_t *ic, idm_pdu_t *pdu) 1977978SPeter.Dunlap@Sun.COM { 1987978SPeter.Dunlap@Sun.COM /* 1997978SPeter.Dunlap@Sun.COM * If this is an FFP request, call the appropriate handler 2007978SPeter.Dunlap@Sun.COM * and return B_TRUE, otherwise return B_FALSE. 2017978SPeter.Dunlap@Sun.COM */ 2027978SPeter.Dunlap@Sun.COM switch (IDM_PDU_OPCODE(pdu)) { 2037978SPeter.Dunlap@Sun.COM case ISCSI_OP_SCSI_CMD: 2047978SPeter.Dunlap@Sun.COM (*ic->ic_conn_ops.icb_rx_scsi_cmd)(ic, pdu); 2057978SPeter.Dunlap@Sun.COM return (B_TRUE); 2069721SPriya.Krishnan@Sun.COM case ISCSI_OP_SCSI_DATA: 2079721SPriya.Krishnan@Sun.COM DTRACE_ISCSI_2(data__receive, idm_conn_t *, ic, 2089721SPriya.Krishnan@Sun.COM iscsi_data_hdr_t *, 2099721SPriya.Krishnan@Sun.COM (iscsi_data_hdr_t *)pdu->isp_hdr); 2109721SPriya.Krishnan@Sun.COM (*ic->ic_transport_ops->it_rx_dataout)(ic, pdu); 2119721SPriya.Krishnan@Sun.COM return (B_TRUE); 2129721SPriya.Krishnan@Sun.COM case ISCSI_OP_SCSI_TASK_MGT_MSG: 2139721SPriya.Krishnan@Sun.COM DTRACE_ISCSI_2(task__command, idm_conn_t *, ic, 2149721SPriya.Krishnan@Sun.COM iscsi_scsi_task_mgt_hdr_t *, 2159721SPriya.Krishnan@Sun.COM (iscsi_scsi_task_mgt_hdr_t *)pdu->isp_hdr); 2169721SPriya.Krishnan@Sun.COM (*ic->ic_conn_ops.icb_rx_misc)(ic, pdu); 2179721SPriya.Krishnan@Sun.COM return (B_TRUE); 2189721SPriya.Krishnan@Sun.COM case ISCSI_OP_NOOP_OUT: 2199721SPriya.Krishnan@Sun.COM DTRACE_ISCSI_2(nop__receive, idm_conn_t *, ic, 2209721SPriya.Krishnan@Sun.COM iscsi_nop_out_hdr_t *, 2219721SPriya.Krishnan@Sun.COM (iscsi_nop_out_hdr_t *)pdu->isp_hdr); 2229721SPriya.Krishnan@Sun.COM (*ic->ic_conn_ops.icb_rx_misc)(ic, pdu); 2239721SPriya.Krishnan@Sun.COM return (B_TRUE); 2249721SPriya.Krishnan@Sun.COM case ISCSI_OP_TEXT_CMD: 2259721SPriya.Krishnan@Sun.COM DTRACE_ISCSI_2(text__command, idm_conn_t *, ic, 2269721SPriya.Krishnan@Sun.COM iscsi_text_hdr_t *, 2279721SPriya.Krishnan@Sun.COM (iscsi_text_hdr_t *)pdu->isp_hdr); 2289721SPriya.Krishnan@Sun.COM (*ic->ic_conn_ops.icb_rx_misc)(ic, pdu); 2299721SPriya.Krishnan@Sun.COM return (B_TRUE); 2309721SPriya.Krishnan@Sun.COM /* Initiator only */ 2317978SPeter.Dunlap@Sun.COM case ISCSI_OP_SCSI_RSP: 2327978SPeter.Dunlap@Sun.COM (*ic->ic_conn_ops.icb_rx_scsi_rsp)(ic, pdu); 2337978SPeter.Dunlap@Sun.COM return (B_TRUE); 2347978SPeter.Dunlap@Sun.COM case ISCSI_OP_SCSI_DATA_RSP: 2357978SPeter.Dunlap@Sun.COM (*ic->ic_transport_ops->it_rx_datain)(ic, pdu); 2367978SPeter.Dunlap@Sun.COM return (B_TRUE); 2377978SPeter.Dunlap@Sun.COM case ISCSI_OP_RTT_RSP: 2387978SPeter.Dunlap@Sun.COM (*ic->ic_transport_ops->it_rx_rtt)(ic, pdu); 2397978SPeter.Dunlap@Sun.COM return (B_TRUE); 2407978SPeter.Dunlap@Sun.COM case ISCSI_OP_SCSI_TASK_MGT_RSP: 2417978SPeter.Dunlap@Sun.COM case ISCSI_OP_TEXT_RSP: 2427978SPeter.Dunlap@Sun.COM case ISCSI_OP_NOOP_IN: 2437978SPeter.Dunlap@Sun.COM (*ic->ic_conn_ops.icb_rx_misc)(ic, pdu); 2447978SPeter.Dunlap@Sun.COM return (B_TRUE); 2457978SPeter.Dunlap@Sun.COM default: 2467978SPeter.Dunlap@Sun.COM return (B_FALSE); 2477978SPeter.Dunlap@Sun.COM } 2487978SPeter.Dunlap@Sun.COM /*NOTREACHED*/ 2497978SPeter.Dunlap@Sun.COM } 2507978SPeter.Dunlap@Sun.COM 2517978SPeter.Dunlap@Sun.COM void 2527978SPeter.Dunlap@Sun.COM idm_pdu_rx_forward(idm_conn_t *ic, idm_pdu_t *pdu) 2537978SPeter.Dunlap@Sun.COM { 2547978SPeter.Dunlap@Sun.COM /* 2557978SPeter.Dunlap@Sun.COM * Some PDU's specific to FFP get special handling. This function 2567978SPeter.Dunlap@Sun.COM * will normally never be called in FFP with an FFP PDU since this 2577978SPeter.Dunlap@Sun.COM * is a slow path but in can happen on the target side during 2587978SPeter.Dunlap@Sun.COM * the transition to FFP. We primarily call 2597978SPeter.Dunlap@Sun.COM * idm_pdu_rx_forward_ffp here to avoid code duplication. 2607978SPeter.Dunlap@Sun.COM */ 2617978SPeter.Dunlap@Sun.COM if (idm_pdu_rx_forward_ffp(ic, pdu) == B_FALSE) { 2627978SPeter.Dunlap@Sun.COM /* 2637978SPeter.Dunlap@Sun.COM * Non-FFP PDU, use generic RC handler 2647978SPeter.Dunlap@Sun.COM */ 2657978SPeter.Dunlap@Sun.COM (*ic->ic_conn_ops.icb_rx_misc)(ic, pdu); 2667978SPeter.Dunlap@Sun.COM } 2677978SPeter.Dunlap@Sun.COM } 2687978SPeter.Dunlap@Sun.COM 2697978SPeter.Dunlap@Sun.COM void 2707978SPeter.Dunlap@Sun.COM idm_parse_login_rsp(idm_conn_t *ic, idm_pdu_t *login_rsp_pdu, boolean_t rx) 2717978SPeter.Dunlap@Sun.COM { 2727978SPeter.Dunlap@Sun.COM iscsi_login_rsp_hdr_t *login_rsp = 2737978SPeter.Dunlap@Sun.COM (iscsi_login_rsp_hdr_t *)login_rsp_pdu->isp_hdr; 2747978SPeter.Dunlap@Sun.COM idm_conn_event_t new_event; 2757978SPeter.Dunlap@Sun.COM 2767978SPeter.Dunlap@Sun.COM if (login_rsp->status_class == ISCSI_STATUS_CLASS_SUCCESS) { 2777978SPeter.Dunlap@Sun.COM if (!(login_rsp->flags & ISCSI_FLAG_LOGIN_CONTINUE) && 2787978SPeter.Dunlap@Sun.COM (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) && 2797978SPeter.Dunlap@Sun.COM (ISCSI_LOGIN_NEXT_STAGE(login_rsp->flags) == 2807978SPeter.Dunlap@Sun.COM ISCSI_FULL_FEATURE_PHASE)) { 2817978SPeter.Dunlap@Sun.COM new_event = (rx ? CE_LOGIN_SUCCESS_RCV : 2827978SPeter.Dunlap@Sun.COM CE_LOGIN_SUCCESS_SND); 2837978SPeter.Dunlap@Sun.COM } else { 2847978SPeter.Dunlap@Sun.COM new_event = (rx ? CE_MISC_RX : CE_MISC_TX); 2857978SPeter.Dunlap@Sun.COM } 2867978SPeter.Dunlap@Sun.COM } else { 2877978SPeter.Dunlap@Sun.COM new_event = (rx ? CE_LOGIN_FAIL_RCV : CE_LOGIN_FAIL_SND); 2887978SPeter.Dunlap@Sun.COM } 2897978SPeter.Dunlap@Sun.COM 2907978SPeter.Dunlap@Sun.COM if (rx) { 2917978SPeter.Dunlap@Sun.COM idm_conn_rx_pdu_event(ic, new_event, (uintptr_t)login_rsp_pdu); 2927978SPeter.Dunlap@Sun.COM } else { 2937978SPeter.Dunlap@Sun.COM idm_conn_tx_pdu_event(ic, new_event, (uintptr_t)login_rsp_pdu); 2947978SPeter.Dunlap@Sun.COM } 2957978SPeter.Dunlap@Sun.COM } 2967978SPeter.Dunlap@Sun.COM 2977978SPeter.Dunlap@Sun.COM 2987978SPeter.Dunlap@Sun.COM void 2997978SPeter.Dunlap@Sun.COM idm_parse_logout_req(idm_conn_t *ic, idm_pdu_t *logout_req_pdu, boolean_t rx) 3007978SPeter.Dunlap@Sun.COM { 3017978SPeter.Dunlap@Sun.COM iscsi_logout_hdr_t *logout_req = 3027978SPeter.Dunlap@Sun.COM (iscsi_logout_hdr_t *)logout_req_pdu->isp_hdr; 3037978SPeter.Dunlap@Sun.COM idm_conn_event_t new_event; 3047978SPeter.Dunlap@Sun.COM uint8_t reason = 3057978SPeter.Dunlap@Sun.COM (logout_req->flags & ISCSI_FLAG_LOGOUT_REASON_MASK); 3067978SPeter.Dunlap@Sun.COM 3077978SPeter.Dunlap@Sun.COM /* 3087978SPeter.Dunlap@Sun.COM * For a normal logout (close connection or close session) IDM 3097978SPeter.Dunlap@Sun.COM * will terminate processing of all tasks completing the tasks 3107978SPeter.Dunlap@Sun.COM * back to the client with a status indicating the connection 3117978SPeter.Dunlap@Sun.COM * was logged out. These tasks do not get completed. 3127978SPeter.Dunlap@Sun.COM * 3137978SPeter.Dunlap@Sun.COM * For a "close connection for recovery logout) IDM suspends 3147978SPeter.Dunlap@Sun.COM * processing of all tasks and completes them back to the client 3157978SPeter.Dunlap@Sun.COM * with a status indicating connection was logged out for 3167978SPeter.Dunlap@Sun.COM * recovery. Both initiator and target hang onto these tasks. 3177978SPeter.Dunlap@Sun.COM * When we add ERL2 support IDM will need to provide mechanisms 3187978SPeter.Dunlap@Sun.COM * to change the task and buffer associations to a new connection. 3197978SPeter.Dunlap@Sun.COM * 3207978SPeter.Dunlap@Sun.COM * This code doesn't address the possibility of MC/S. We'll 3217978SPeter.Dunlap@Sun.COM * need to decide how the separate connections get handled 3227978SPeter.Dunlap@Sun.COM * in that case. One simple option is to make the client 3237978SPeter.Dunlap@Sun.COM * generate the events for the other connections. 3247978SPeter.Dunlap@Sun.COM */ 3257978SPeter.Dunlap@Sun.COM if (reason == ISCSI_LOGOUT_REASON_CLOSE_SESSION) { 3267978SPeter.Dunlap@Sun.COM new_event = 3277978SPeter.Dunlap@Sun.COM (rx ? CE_LOGOUT_SESSION_RCV : CE_LOGOUT_SESSION_SND); 3287978SPeter.Dunlap@Sun.COM } else if ((reason == ISCSI_LOGOUT_REASON_CLOSE_CONNECTION) || 3297978SPeter.Dunlap@Sun.COM (reason == ISCSI_LOGOUT_REASON_RECOVERY)) { 3307978SPeter.Dunlap@Sun.COM /* Check logout CID against this connection's CID */ 3317978SPeter.Dunlap@Sun.COM if (ntohs(logout_req->cid) == ic->ic_login_cid) { 3327978SPeter.Dunlap@Sun.COM /* Logout is for this connection */ 3337978SPeter.Dunlap@Sun.COM new_event = (rx ? CE_LOGOUT_THIS_CONN_RCV : 3347978SPeter.Dunlap@Sun.COM CE_LOGOUT_THIS_CONN_SND); 3357978SPeter.Dunlap@Sun.COM } else { 3367978SPeter.Dunlap@Sun.COM /* 3377978SPeter.Dunlap@Sun.COM * Logout affects another connection. This is not 3387978SPeter.Dunlap@Sun.COM * a relevant event for this connection so we'll 3397978SPeter.Dunlap@Sun.COM * just treat it as a normal PDU event. Client 3407978SPeter.Dunlap@Sun.COM * will need to lookup the other connection and 3417978SPeter.Dunlap@Sun.COM * generate the event. 3427978SPeter.Dunlap@Sun.COM */ 3437978SPeter.Dunlap@Sun.COM new_event = (rx ? CE_MISC_RX : CE_MISC_TX); 3447978SPeter.Dunlap@Sun.COM } 3457978SPeter.Dunlap@Sun.COM } else { 3467978SPeter.Dunlap@Sun.COM /* Invalid reason code */ 3477978SPeter.Dunlap@Sun.COM new_event = (rx ? CE_RX_PROTOCOL_ERROR : CE_TX_PROTOCOL_ERROR); 3487978SPeter.Dunlap@Sun.COM } 3497978SPeter.Dunlap@Sun.COM 3507978SPeter.Dunlap@Sun.COM if (rx) { 3517978SPeter.Dunlap@Sun.COM idm_conn_rx_pdu_event(ic, new_event, (uintptr_t)logout_req_pdu); 3527978SPeter.Dunlap@Sun.COM } else { 3537978SPeter.Dunlap@Sun.COM idm_conn_tx_pdu_event(ic, new_event, (uintptr_t)logout_req_pdu); 3547978SPeter.Dunlap@Sun.COM } 3557978SPeter.Dunlap@Sun.COM } 3567978SPeter.Dunlap@Sun.COM 3577978SPeter.Dunlap@Sun.COM 3587978SPeter.Dunlap@Sun.COM 3597978SPeter.Dunlap@Sun.COM void 3607978SPeter.Dunlap@Sun.COM idm_parse_logout_rsp(idm_conn_t *ic, idm_pdu_t *logout_rsp_pdu, boolean_t rx) 3617978SPeter.Dunlap@Sun.COM { 3627978SPeter.Dunlap@Sun.COM idm_conn_event_t new_event; 3637978SPeter.Dunlap@Sun.COM iscsi_logout_rsp_hdr_t *logout_rsp = 3647978SPeter.Dunlap@Sun.COM (iscsi_logout_rsp_hdr_t *)logout_rsp_pdu->isp_hdr; 3657978SPeter.Dunlap@Sun.COM 3667978SPeter.Dunlap@Sun.COM if (logout_rsp->response == ISCSI_STATUS_CLASS_SUCCESS) { 3677978SPeter.Dunlap@Sun.COM new_event = rx ? CE_LOGOUT_SUCCESS_RCV : CE_LOGOUT_SUCCESS_SND; 3687978SPeter.Dunlap@Sun.COM } else { 3697978SPeter.Dunlap@Sun.COM new_event = rx ? CE_LOGOUT_FAIL_RCV : CE_LOGOUT_FAIL_SND; 3707978SPeter.Dunlap@Sun.COM } 3717978SPeter.Dunlap@Sun.COM 3727978SPeter.Dunlap@Sun.COM if (rx) { 3737978SPeter.Dunlap@Sun.COM idm_conn_rx_pdu_event(ic, new_event, (uintptr_t)logout_rsp_pdu); 3747978SPeter.Dunlap@Sun.COM } else { 3757978SPeter.Dunlap@Sun.COM idm_conn_tx_pdu_event(ic, new_event, (uintptr_t)logout_rsp_pdu); 3767978SPeter.Dunlap@Sun.COM } 3777978SPeter.Dunlap@Sun.COM } 3787978SPeter.Dunlap@Sun.COM 3797978SPeter.Dunlap@Sun.COM /* 3807978SPeter.Dunlap@Sun.COM * idm_svc_conn_create() 3817978SPeter.Dunlap@Sun.COM * Transport-agnostic service connection creation, invoked from the transport 3827978SPeter.Dunlap@Sun.COM * layer. 3837978SPeter.Dunlap@Sun.COM */ 3847978SPeter.Dunlap@Sun.COM idm_status_t 3857978SPeter.Dunlap@Sun.COM idm_svc_conn_create(idm_svc_t *is, idm_transport_type_t tt, 3867978SPeter.Dunlap@Sun.COM idm_conn_t **ic_result) 3877978SPeter.Dunlap@Sun.COM { 3887978SPeter.Dunlap@Sun.COM idm_conn_t *ic; 3897978SPeter.Dunlap@Sun.COM idm_status_t rc; 3907978SPeter.Dunlap@Sun.COM 39111078SPeter.Cudhea@Sun.COM /* 39211078SPeter.Cudhea@Sun.COM * Skip some work if we can already tell we are going offline. 39311078SPeter.Cudhea@Sun.COM * Otherwise we will destroy this connection later as part of 39411078SPeter.Cudhea@Sun.COM * shutting down the svc. 39511078SPeter.Cudhea@Sun.COM */ 3969162SPeter.Dunlap@Sun.COM mutex_enter(&is->is_mutex); 3979162SPeter.Dunlap@Sun.COM if (!is->is_online) { 3989162SPeter.Dunlap@Sun.COM mutex_exit(&is->is_mutex); 3999162SPeter.Dunlap@Sun.COM return (IDM_STATUS_FAIL); 4009162SPeter.Dunlap@Sun.COM } 4019162SPeter.Dunlap@Sun.COM mutex_exit(&is->is_mutex); 4029162SPeter.Dunlap@Sun.COM 4037978SPeter.Dunlap@Sun.COM ic = idm_conn_create_common(CONN_TYPE_TGT, tt, 4047978SPeter.Dunlap@Sun.COM &is->is_svc_req.sr_conn_ops); 405*11552SPeter.Cudhea@Sun.COM if (ic == NULL) { 406*11552SPeter.Cudhea@Sun.COM return (IDM_STATUS_FAIL); 407*11552SPeter.Cudhea@Sun.COM } 4087978SPeter.Dunlap@Sun.COM ic->ic_svc_binding = is; 4097978SPeter.Dunlap@Sun.COM 4107978SPeter.Dunlap@Sun.COM /* 4117978SPeter.Dunlap@Sun.COM * Prepare connection state machine 4127978SPeter.Dunlap@Sun.COM */ 4137978SPeter.Dunlap@Sun.COM if ((rc = idm_conn_sm_init(ic)) != 0) { 4147978SPeter.Dunlap@Sun.COM idm_conn_destroy_common(ic); 4157978SPeter.Dunlap@Sun.COM return (rc); 4167978SPeter.Dunlap@Sun.COM } 4177978SPeter.Dunlap@Sun.COM 4187978SPeter.Dunlap@Sun.COM 4197978SPeter.Dunlap@Sun.COM *ic_result = ic; 4207978SPeter.Dunlap@Sun.COM 4217978SPeter.Dunlap@Sun.COM mutex_enter(&idm.idm_global_mutex); 4227978SPeter.Dunlap@Sun.COM list_insert_tail(&idm.idm_tgt_conn_list, ic); 4237978SPeter.Dunlap@Sun.COM idm.idm_tgt_conn_count++; 4247978SPeter.Dunlap@Sun.COM mutex_exit(&idm.idm_global_mutex); 4257978SPeter.Dunlap@Sun.COM 4269162SPeter.Dunlap@Sun.COM return (IDM_STATUS_SUCCESS); 4277978SPeter.Dunlap@Sun.COM } 4287978SPeter.Dunlap@Sun.COM 4297978SPeter.Dunlap@Sun.COM void 4307978SPeter.Dunlap@Sun.COM idm_svc_conn_destroy(idm_conn_t *ic) 4317978SPeter.Dunlap@Sun.COM { 4327978SPeter.Dunlap@Sun.COM mutex_enter(&idm.idm_global_mutex); 4337978SPeter.Dunlap@Sun.COM list_remove(&idm.idm_tgt_conn_list, ic); 4347978SPeter.Dunlap@Sun.COM idm.idm_tgt_conn_count--; 4357978SPeter.Dunlap@Sun.COM mutex_exit(&idm.idm_global_mutex); 4367978SPeter.Dunlap@Sun.COM 4377978SPeter.Dunlap@Sun.COM if (ic->ic_transport_private != NULL) { 4387978SPeter.Dunlap@Sun.COM ic->ic_transport_ops->it_tgt_conn_destroy(ic); 4397978SPeter.Dunlap@Sun.COM } 4407978SPeter.Dunlap@Sun.COM idm_conn_destroy_common(ic); 4417978SPeter.Dunlap@Sun.COM } 4427978SPeter.Dunlap@Sun.COM 4437978SPeter.Dunlap@Sun.COM /* 4447978SPeter.Dunlap@Sun.COM * idm_conn_create_common() 4457978SPeter.Dunlap@Sun.COM * 4467978SPeter.Dunlap@Sun.COM * Allocate and initialize IDM connection context 4477978SPeter.Dunlap@Sun.COM */ 4487978SPeter.Dunlap@Sun.COM idm_conn_t * 4497978SPeter.Dunlap@Sun.COM idm_conn_create_common(idm_conn_type_t conn_type, idm_transport_type_t tt, 4507978SPeter.Dunlap@Sun.COM idm_conn_ops_t *conn_ops) 4517978SPeter.Dunlap@Sun.COM { 4527978SPeter.Dunlap@Sun.COM idm_conn_t *ic; 4537978SPeter.Dunlap@Sun.COM idm_transport_t *it; 4547978SPeter.Dunlap@Sun.COM idm_transport_type_t type; 4557978SPeter.Dunlap@Sun.COM 4567978SPeter.Dunlap@Sun.COM for (type = 0; type < IDM_TRANSPORT_NUM_TYPES; type++) { 4577978SPeter.Dunlap@Sun.COM it = &idm_transport_list[type]; 4587978SPeter.Dunlap@Sun.COM 4597978SPeter.Dunlap@Sun.COM if ((it->it_ops != NULL) && (it->it_type == tt)) 4607978SPeter.Dunlap@Sun.COM break; 4617978SPeter.Dunlap@Sun.COM } 4627978SPeter.Dunlap@Sun.COM ASSERT(it->it_type == tt); 4637978SPeter.Dunlap@Sun.COM if (it->it_type != tt) 4647978SPeter.Dunlap@Sun.COM return (NULL); 4657978SPeter.Dunlap@Sun.COM 4667978SPeter.Dunlap@Sun.COM ic = kmem_zalloc(sizeof (idm_conn_t), KM_SLEEP); 4677978SPeter.Dunlap@Sun.COM 4687978SPeter.Dunlap@Sun.COM /* Initialize data */ 4699721SPriya.Krishnan@Sun.COM ic->ic_target_name[0] = '\0'; 4709721SPriya.Krishnan@Sun.COM ic->ic_initiator_name[0] = '\0'; 4719721SPriya.Krishnan@Sun.COM ic->ic_isid[0] = '\0'; 4729721SPriya.Krishnan@Sun.COM ic->ic_tsih[0] = '\0'; 4737978SPeter.Dunlap@Sun.COM ic->ic_conn_type = conn_type; 4747978SPeter.Dunlap@Sun.COM ic->ic_conn_ops = *conn_ops; 4757978SPeter.Dunlap@Sun.COM ic->ic_transport_ops = it->it_ops; 4767978SPeter.Dunlap@Sun.COM ic->ic_transport_type = tt; 4777978SPeter.Dunlap@Sun.COM ic->ic_transport_private = NULL; /* Set by transport service */ 4787978SPeter.Dunlap@Sun.COM ic->ic_internal_cid = idm_cid_alloc(); 4797978SPeter.Dunlap@Sun.COM if (ic->ic_internal_cid == 0) { 4807978SPeter.Dunlap@Sun.COM kmem_free(ic, sizeof (idm_conn_t)); 4817978SPeter.Dunlap@Sun.COM return (NULL); 4827978SPeter.Dunlap@Sun.COM } 4837978SPeter.Dunlap@Sun.COM mutex_init(&ic->ic_mutex, NULL, MUTEX_DEFAULT, NULL); 4847978SPeter.Dunlap@Sun.COM cv_init(&ic->ic_cv, NULL, CV_DEFAULT, NULL); 4857978SPeter.Dunlap@Sun.COM idm_refcnt_init(&ic->ic_refcnt, ic); 4867978SPeter.Dunlap@Sun.COM 4877978SPeter.Dunlap@Sun.COM return (ic); 4887978SPeter.Dunlap@Sun.COM } 4897978SPeter.Dunlap@Sun.COM 4907978SPeter.Dunlap@Sun.COM void 4917978SPeter.Dunlap@Sun.COM idm_conn_destroy_common(idm_conn_t *ic) 4927978SPeter.Dunlap@Sun.COM { 4939162SPeter.Dunlap@Sun.COM idm_conn_sm_fini(ic); 4947978SPeter.Dunlap@Sun.COM idm_refcnt_destroy(&ic->ic_refcnt); 4957978SPeter.Dunlap@Sun.COM cv_destroy(&ic->ic_cv); 4967978SPeter.Dunlap@Sun.COM mutex_destroy(&ic->ic_mutex); 4977978SPeter.Dunlap@Sun.COM idm_cid_free(ic->ic_internal_cid); 4987978SPeter.Dunlap@Sun.COM 4997978SPeter.Dunlap@Sun.COM kmem_free(ic, sizeof (idm_conn_t)); 5007978SPeter.Dunlap@Sun.COM } 5017978SPeter.Dunlap@Sun.COM 5027978SPeter.Dunlap@Sun.COM /* 5037978SPeter.Dunlap@Sun.COM * Invoked from the SM as a result of client's invocation of 5047978SPeter.Dunlap@Sun.COM * idm_ini_conn_connect() 5057978SPeter.Dunlap@Sun.COM */ 5067978SPeter.Dunlap@Sun.COM idm_status_t 5077978SPeter.Dunlap@Sun.COM idm_ini_conn_finish(idm_conn_t *ic) 5087978SPeter.Dunlap@Sun.COM { 5097978SPeter.Dunlap@Sun.COM /* invoke transport-specific connection */ 5107978SPeter.Dunlap@Sun.COM return (ic->ic_transport_ops->it_ini_conn_connect(ic)); 5117978SPeter.Dunlap@Sun.COM } 5127978SPeter.Dunlap@Sun.COM 5137978SPeter.Dunlap@Sun.COM idm_status_t 5147978SPeter.Dunlap@Sun.COM idm_tgt_conn_finish(idm_conn_t *ic) 5157978SPeter.Dunlap@Sun.COM { 5167978SPeter.Dunlap@Sun.COM idm_status_t rc; 5177978SPeter.Dunlap@Sun.COM 5187978SPeter.Dunlap@Sun.COM rc = idm_notify_client(ic, CN_CONNECT_ACCEPT, NULL); 5197978SPeter.Dunlap@Sun.COM if (rc != IDM_STATUS_SUCCESS) { 5207978SPeter.Dunlap@Sun.COM return (IDM_STATUS_REJECT); 5217978SPeter.Dunlap@Sun.COM } 5227978SPeter.Dunlap@Sun.COM 5237978SPeter.Dunlap@Sun.COM /* Target client is ready to receive a login, start connection */ 5247978SPeter.Dunlap@Sun.COM return (ic->ic_transport_ops->it_tgt_conn_connect(ic)); 5257978SPeter.Dunlap@Sun.COM } 5267978SPeter.Dunlap@Sun.COM 5277978SPeter.Dunlap@Sun.COM idm_transport_t * 5287978SPeter.Dunlap@Sun.COM idm_transport_lookup(idm_conn_req_t *cr) 5297978SPeter.Dunlap@Sun.COM { 5307978SPeter.Dunlap@Sun.COM idm_transport_type_t type; 5317978SPeter.Dunlap@Sun.COM idm_transport_t *it; 5327978SPeter.Dunlap@Sun.COM idm_transport_caps_t caps; 5337978SPeter.Dunlap@Sun.COM 5347978SPeter.Dunlap@Sun.COM /* 5357978SPeter.Dunlap@Sun.COM * Make sure all available transports are setup. We call this now 5367978SPeter.Dunlap@Sun.COM * instead of at initialization time in case IB has become available 5377978SPeter.Dunlap@Sun.COM * since we started (hotplug, etc). 5387978SPeter.Dunlap@Sun.COM */ 53911424SJack.Meng@Sun.COM idm_transport_setup(cr->cr_li, cr->cr_boot_conn); 5407978SPeter.Dunlap@Sun.COM 5417978SPeter.Dunlap@Sun.COM /* Determine the transport for this connection */ 5427978SPeter.Dunlap@Sun.COM for (type = 0; type < IDM_TRANSPORT_NUM_TYPES; type++) { 5437978SPeter.Dunlap@Sun.COM it = &idm_transport_list[type]; 5447978SPeter.Dunlap@Sun.COM 5457978SPeter.Dunlap@Sun.COM if (it->it_ops == NULL) { 5467978SPeter.Dunlap@Sun.COM /* transport is not registered */ 5477978SPeter.Dunlap@Sun.COM continue; 5487978SPeter.Dunlap@Sun.COM } 5497978SPeter.Dunlap@Sun.COM 5507978SPeter.Dunlap@Sun.COM if (it->it_ops->it_conn_is_capable(cr, &caps)) { 5517978SPeter.Dunlap@Sun.COM return (it); 5527978SPeter.Dunlap@Sun.COM } 5537978SPeter.Dunlap@Sun.COM } 5547978SPeter.Dunlap@Sun.COM 5557978SPeter.Dunlap@Sun.COM ASSERT(0); 5567978SPeter.Dunlap@Sun.COM return (NULL); /* Make gcc happy */ 5577978SPeter.Dunlap@Sun.COM } 5587978SPeter.Dunlap@Sun.COM 5597978SPeter.Dunlap@Sun.COM void 56011424SJack.Meng@Sun.COM idm_transport_setup(ldi_ident_t li, boolean_t boot_conn) 5617978SPeter.Dunlap@Sun.COM { 5627978SPeter.Dunlap@Sun.COM idm_transport_type_t type; 5637978SPeter.Dunlap@Sun.COM idm_transport_t *it; 5647978SPeter.Dunlap@Sun.COM int rc; 5657978SPeter.Dunlap@Sun.COM 5667978SPeter.Dunlap@Sun.COM for (type = 0; type < IDM_TRANSPORT_NUM_TYPES; type++) { 5677978SPeter.Dunlap@Sun.COM it = &idm_transport_list[type]; 5687978SPeter.Dunlap@Sun.COM /* 5697978SPeter.Dunlap@Sun.COM * We may want to store the LDI handle in the idm_svc_t 5707978SPeter.Dunlap@Sun.COM * and then allow multiple calls to ldi_open_by_name. This 5717978SPeter.Dunlap@Sun.COM * would enable the LDI code to track who has the device open 5727978SPeter.Dunlap@Sun.COM * which could be useful in the case where we have multiple 5737978SPeter.Dunlap@Sun.COM * services and perhaps also have initiator and target opening 5747978SPeter.Dunlap@Sun.COM * the transport simultaneously. For now we stick with the 5757978SPeter.Dunlap@Sun.COM * plan. 5767978SPeter.Dunlap@Sun.COM */ 5777978SPeter.Dunlap@Sun.COM if (it->it_ops == NULL) { 5787978SPeter.Dunlap@Sun.COM /* transport is not ready, try to initialize it */ 5797978SPeter.Dunlap@Sun.COM if (it->it_type == IDM_TRANSPORT_TYPE_SOCKETS) { 5807978SPeter.Dunlap@Sun.COM idm_so_init(it); 5817978SPeter.Dunlap@Sun.COM } else { 58211424SJack.Meng@Sun.COM if (boot_conn == B_TRUE) { 58311424SJack.Meng@Sun.COM /* 58411424SJack.Meng@Sun.COM * iSCSI boot doesn't need iSER. 58511424SJack.Meng@Sun.COM * Open iSER here may drive IO to 58611424SJack.Meng@Sun.COM * a failed session and cause 58711424SJack.Meng@Sun.COM * deadlock 58811424SJack.Meng@Sun.COM */ 58911424SJack.Meng@Sun.COM continue; 59011424SJack.Meng@Sun.COM } 5917978SPeter.Dunlap@Sun.COM rc = ldi_open_by_name(it->it_device_path, 5927978SPeter.Dunlap@Sun.COM FREAD | FWRITE, kcred, &it->it_ldi_hdl, li); 5937978SPeter.Dunlap@Sun.COM /* 5947978SPeter.Dunlap@Sun.COM * If the open is successful we will have 5957978SPeter.Dunlap@Sun.COM * filled in the LDI handle in the transport 5967978SPeter.Dunlap@Sun.COM * table and we expect that the transport 5977978SPeter.Dunlap@Sun.COM * registered itself. 5987978SPeter.Dunlap@Sun.COM */ 5997978SPeter.Dunlap@Sun.COM if (rc != 0) { 6007978SPeter.Dunlap@Sun.COM it->it_ldi_hdl = NULL; 6017978SPeter.Dunlap@Sun.COM } 6027978SPeter.Dunlap@Sun.COM } 6037978SPeter.Dunlap@Sun.COM } 6047978SPeter.Dunlap@Sun.COM } 6057978SPeter.Dunlap@Sun.COM } 6067978SPeter.Dunlap@Sun.COM 6079162SPeter.Dunlap@Sun.COM void 6089162SPeter.Dunlap@Sun.COM idm_transport_teardown() 6099162SPeter.Dunlap@Sun.COM { 6109162SPeter.Dunlap@Sun.COM idm_transport_type_t type; 6119162SPeter.Dunlap@Sun.COM idm_transport_t *it; 6129162SPeter.Dunlap@Sun.COM 6139162SPeter.Dunlap@Sun.COM ASSERT(mutex_owned(&idm.idm_global_mutex)); 6149162SPeter.Dunlap@Sun.COM 6159162SPeter.Dunlap@Sun.COM /* Caller holds the IDM global mutex */ 6169162SPeter.Dunlap@Sun.COM for (type = 0; type < IDM_TRANSPORT_NUM_TYPES; type++) { 6179162SPeter.Dunlap@Sun.COM it = &idm_transport_list[type]; 6189162SPeter.Dunlap@Sun.COM /* If we have an open LDI handle on this driver, close it */ 6199162SPeter.Dunlap@Sun.COM if (it->it_ldi_hdl != NULL) { 6209162SPeter.Dunlap@Sun.COM (void) ldi_close(it->it_ldi_hdl, FNDELAY, kcred); 6219162SPeter.Dunlap@Sun.COM it->it_ldi_hdl = NULL; 6229162SPeter.Dunlap@Sun.COM } 6239162SPeter.Dunlap@Sun.COM } 6249162SPeter.Dunlap@Sun.COM } 6259162SPeter.Dunlap@Sun.COM 6267978SPeter.Dunlap@Sun.COM /* 6277978SPeter.Dunlap@Sun.COM * ID pool code. We use this to generate unique structure identifiers without 6287978SPeter.Dunlap@Sun.COM * searching the existing structures. This avoids the need to lock entire 6297978SPeter.Dunlap@Sun.COM * sets of structures at inopportune times. Adapted from the CIFS server code. 6307978SPeter.Dunlap@Sun.COM * 6317978SPeter.Dunlap@Sun.COM * A pool of IDs is a pool of 16 bit numbers. It is implemented as a bitmap. 6327978SPeter.Dunlap@Sun.COM * A bit set to '1' indicates that that particular value has been allocated. 6337978SPeter.Dunlap@Sun.COM * The allocation process is done shifting a bit through the whole bitmap. 6347978SPeter.Dunlap@Sun.COM * The current position of that index bit is kept in the idm_idpool_t 6357978SPeter.Dunlap@Sun.COM * structure and represented by a byte index (0 to buffer size minus 1) and 6367978SPeter.Dunlap@Sun.COM * a bit index (0 to 7). 6377978SPeter.Dunlap@Sun.COM * 6387978SPeter.Dunlap@Sun.COM * The pools start with a size of 8 bytes or 64 IDs. Each time the pool runs 6397978SPeter.Dunlap@Sun.COM * out of IDs its current size is doubled until it reaches its maximum size 6407978SPeter.Dunlap@Sun.COM * (8192 bytes or 65536 IDs). The IDs 0 and 65535 are never given out which 6417978SPeter.Dunlap@Sun.COM * means that a pool can have a maximum number of 65534 IDs available. 6427978SPeter.Dunlap@Sun.COM */ 6437978SPeter.Dunlap@Sun.COM 6447978SPeter.Dunlap@Sun.COM static int 6457978SPeter.Dunlap@Sun.COM idm_idpool_increment( 6467978SPeter.Dunlap@Sun.COM idm_idpool_t *pool) 6477978SPeter.Dunlap@Sun.COM { 6487978SPeter.Dunlap@Sun.COM uint8_t *new_pool; 6497978SPeter.Dunlap@Sun.COM uint32_t new_size; 6507978SPeter.Dunlap@Sun.COM 6517978SPeter.Dunlap@Sun.COM ASSERT(pool->id_magic == IDM_IDPOOL_MAGIC); 6527978SPeter.Dunlap@Sun.COM 6537978SPeter.Dunlap@Sun.COM new_size = pool->id_size * 2; 6547978SPeter.Dunlap@Sun.COM if (new_size <= IDM_IDPOOL_MAX_SIZE) { 6557978SPeter.Dunlap@Sun.COM new_pool = kmem_alloc(new_size / 8, KM_NOSLEEP); 6567978SPeter.Dunlap@Sun.COM if (new_pool) { 6577978SPeter.Dunlap@Sun.COM bzero(new_pool, new_size / 8); 6587978SPeter.Dunlap@Sun.COM bcopy(pool->id_pool, new_pool, pool->id_size / 8); 6597978SPeter.Dunlap@Sun.COM kmem_free(pool->id_pool, pool->id_size / 8); 6607978SPeter.Dunlap@Sun.COM pool->id_pool = new_pool; 6617978SPeter.Dunlap@Sun.COM pool->id_free_counter += new_size - pool->id_size; 6627978SPeter.Dunlap@Sun.COM pool->id_max_free_counter += new_size - pool->id_size; 6637978SPeter.Dunlap@Sun.COM pool->id_size = new_size; 6647978SPeter.Dunlap@Sun.COM pool->id_idx_msk = (new_size / 8) - 1; 6657978SPeter.Dunlap@Sun.COM if (new_size >= IDM_IDPOOL_MAX_SIZE) { 6667978SPeter.Dunlap@Sun.COM /* id -1 made unavailable */ 6677978SPeter.Dunlap@Sun.COM pool->id_pool[pool->id_idx_msk] = 0x80; 6687978SPeter.Dunlap@Sun.COM pool->id_free_counter--; 6697978SPeter.Dunlap@Sun.COM pool->id_max_free_counter--; 6707978SPeter.Dunlap@Sun.COM } 6717978SPeter.Dunlap@Sun.COM return (0); 6727978SPeter.Dunlap@Sun.COM } 6737978SPeter.Dunlap@Sun.COM } 6747978SPeter.Dunlap@Sun.COM return (-1); 6757978SPeter.Dunlap@Sun.COM } 6767978SPeter.Dunlap@Sun.COM 6777978SPeter.Dunlap@Sun.COM /* 6787978SPeter.Dunlap@Sun.COM * idm_idpool_constructor 6797978SPeter.Dunlap@Sun.COM * 6807978SPeter.Dunlap@Sun.COM * This function initializes the pool structure provided. 6817978SPeter.Dunlap@Sun.COM */ 6827978SPeter.Dunlap@Sun.COM 6837978SPeter.Dunlap@Sun.COM int 6847978SPeter.Dunlap@Sun.COM idm_idpool_create(idm_idpool_t *pool) 6857978SPeter.Dunlap@Sun.COM { 6867978SPeter.Dunlap@Sun.COM 6877978SPeter.Dunlap@Sun.COM ASSERT(pool->id_magic != IDM_IDPOOL_MAGIC); 6887978SPeter.Dunlap@Sun.COM 6897978SPeter.Dunlap@Sun.COM pool->id_size = IDM_IDPOOL_MIN_SIZE; 6907978SPeter.Dunlap@Sun.COM pool->id_idx_msk = (IDM_IDPOOL_MIN_SIZE / 8) - 1; 6917978SPeter.Dunlap@Sun.COM pool->id_free_counter = IDM_IDPOOL_MIN_SIZE - 1; 6927978SPeter.Dunlap@Sun.COM pool->id_max_free_counter = IDM_IDPOOL_MIN_SIZE - 1; 6937978SPeter.Dunlap@Sun.COM pool->id_bit = 0x02; 6947978SPeter.Dunlap@Sun.COM pool->id_bit_idx = 1; 6957978SPeter.Dunlap@Sun.COM pool->id_idx = 0; 6967978SPeter.Dunlap@Sun.COM pool->id_pool = (uint8_t *)kmem_alloc((IDM_IDPOOL_MIN_SIZE / 8), 6977978SPeter.Dunlap@Sun.COM KM_SLEEP); 6987978SPeter.Dunlap@Sun.COM bzero(pool->id_pool, (IDM_IDPOOL_MIN_SIZE / 8)); 6997978SPeter.Dunlap@Sun.COM /* -1 id made unavailable */ 7007978SPeter.Dunlap@Sun.COM pool->id_pool[0] = 0x01; /* id 0 made unavailable */ 7017978SPeter.Dunlap@Sun.COM mutex_init(&pool->id_mutex, NULL, MUTEX_DEFAULT, NULL); 7027978SPeter.Dunlap@Sun.COM pool->id_magic = IDM_IDPOOL_MAGIC; 7037978SPeter.Dunlap@Sun.COM return (0); 7047978SPeter.Dunlap@Sun.COM } 7057978SPeter.Dunlap@Sun.COM 7067978SPeter.Dunlap@Sun.COM /* 7077978SPeter.Dunlap@Sun.COM * idm_idpool_destructor 7087978SPeter.Dunlap@Sun.COM * 7097978SPeter.Dunlap@Sun.COM * This function tears down and frees the resources associated with the 7107978SPeter.Dunlap@Sun.COM * pool provided. 7117978SPeter.Dunlap@Sun.COM */ 7127978SPeter.Dunlap@Sun.COM 7137978SPeter.Dunlap@Sun.COM void 7147978SPeter.Dunlap@Sun.COM idm_idpool_destroy(idm_idpool_t *pool) 7157978SPeter.Dunlap@Sun.COM { 7167978SPeter.Dunlap@Sun.COM ASSERT(pool->id_magic == IDM_IDPOOL_MAGIC); 7177978SPeter.Dunlap@Sun.COM ASSERT(pool->id_free_counter == pool->id_max_free_counter); 7187978SPeter.Dunlap@Sun.COM pool->id_magic = (uint32_t)~IDM_IDPOOL_MAGIC; 7197978SPeter.Dunlap@Sun.COM mutex_destroy(&pool->id_mutex); 7207978SPeter.Dunlap@Sun.COM kmem_free(pool->id_pool, (size_t)(pool->id_size / 8)); 7217978SPeter.Dunlap@Sun.COM } 7227978SPeter.Dunlap@Sun.COM 7237978SPeter.Dunlap@Sun.COM /* 7247978SPeter.Dunlap@Sun.COM * idm_idpool_alloc 7257978SPeter.Dunlap@Sun.COM * 7267978SPeter.Dunlap@Sun.COM * This function allocates an ID from the pool provided. 7277978SPeter.Dunlap@Sun.COM */ 7287978SPeter.Dunlap@Sun.COM int 7297978SPeter.Dunlap@Sun.COM idm_idpool_alloc(idm_idpool_t *pool, uint16_t *id) 7307978SPeter.Dunlap@Sun.COM { 7317978SPeter.Dunlap@Sun.COM uint32_t i; 7327978SPeter.Dunlap@Sun.COM uint8_t bit; 7337978SPeter.Dunlap@Sun.COM uint8_t bit_idx; 7347978SPeter.Dunlap@Sun.COM uint8_t byte; 7357978SPeter.Dunlap@Sun.COM 7367978SPeter.Dunlap@Sun.COM ASSERT(pool->id_magic == IDM_IDPOOL_MAGIC); 7377978SPeter.Dunlap@Sun.COM 7387978SPeter.Dunlap@Sun.COM mutex_enter(&pool->id_mutex); 7397978SPeter.Dunlap@Sun.COM if ((pool->id_free_counter == 0) && idm_idpool_increment(pool)) { 7407978SPeter.Dunlap@Sun.COM mutex_exit(&pool->id_mutex); 7417978SPeter.Dunlap@Sun.COM return (-1); 7427978SPeter.Dunlap@Sun.COM } 7437978SPeter.Dunlap@Sun.COM 7447978SPeter.Dunlap@Sun.COM i = pool->id_size; 7457978SPeter.Dunlap@Sun.COM while (i) { 7467978SPeter.Dunlap@Sun.COM bit = pool->id_bit; 7477978SPeter.Dunlap@Sun.COM bit_idx = pool->id_bit_idx; 7487978SPeter.Dunlap@Sun.COM byte = pool->id_pool[pool->id_idx]; 7497978SPeter.Dunlap@Sun.COM while (bit) { 7507978SPeter.Dunlap@Sun.COM if (byte & bit) { 7517978SPeter.Dunlap@Sun.COM bit = bit << 1; 7527978SPeter.Dunlap@Sun.COM bit_idx++; 7537978SPeter.Dunlap@Sun.COM continue; 7547978SPeter.Dunlap@Sun.COM } 7557978SPeter.Dunlap@Sun.COM pool->id_pool[pool->id_idx] |= bit; 7567978SPeter.Dunlap@Sun.COM *id = (uint16_t)(pool->id_idx * 8 + (uint32_t)bit_idx); 7577978SPeter.Dunlap@Sun.COM pool->id_free_counter--; 7587978SPeter.Dunlap@Sun.COM pool->id_bit = bit; 7597978SPeter.Dunlap@Sun.COM pool->id_bit_idx = bit_idx; 7607978SPeter.Dunlap@Sun.COM mutex_exit(&pool->id_mutex); 7617978SPeter.Dunlap@Sun.COM return (0); 7627978SPeter.Dunlap@Sun.COM } 7637978SPeter.Dunlap@Sun.COM pool->id_bit = 1; 7647978SPeter.Dunlap@Sun.COM pool->id_bit_idx = 0; 7657978SPeter.Dunlap@Sun.COM pool->id_idx++; 7667978SPeter.Dunlap@Sun.COM pool->id_idx &= pool->id_idx_msk; 7677978SPeter.Dunlap@Sun.COM --i; 7687978SPeter.Dunlap@Sun.COM } 7697978SPeter.Dunlap@Sun.COM /* 7707978SPeter.Dunlap@Sun.COM * This section of code shouldn't be reached. If there are IDs 7717978SPeter.Dunlap@Sun.COM * available and none could be found there's a problem. 7727978SPeter.Dunlap@Sun.COM */ 7737978SPeter.Dunlap@Sun.COM ASSERT(0); 7747978SPeter.Dunlap@Sun.COM mutex_exit(&pool->id_mutex); 7757978SPeter.Dunlap@Sun.COM return (-1); 7767978SPeter.Dunlap@Sun.COM } 7777978SPeter.Dunlap@Sun.COM 7787978SPeter.Dunlap@Sun.COM /* 7797978SPeter.Dunlap@Sun.COM * idm_idpool_free 7807978SPeter.Dunlap@Sun.COM * 7817978SPeter.Dunlap@Sun.COM * This function frees the ID provided. 7827978SPeter.Dunlap@Sun.COM */ 7837978SPeter.Dunlap@Sun.COM void 7847978SPeter.Dunlap@Sun.COM idm_idpool_free(idm_idpool_t *pool, uint16_t id) 7857978SPeter.Dunlap@Sun.COM { 7867978SPeter.Dunlap@Sun.COM ASSERT(pool->id_magic == IDM_IDPOOL_MAGIC); 7877978SPeter.Dunlap@Sun.COM ASSERT(id != 0); 7887978SPeter.Dunlap@Sun.COM ASSERT(id != 0xFFFF); 7897978SPeter.Dunlap@Sun.COM 7907978SPeter.Dunlap@Sun.COM mutex_enter(&pool->id_mutex); 7917978SPeter.Dunlap@Sun.COM if (pool->id_pool[id >> 3] & (1 << (id & 7))) { 7927978SPeter.Dunlap@Sun.COM pool->id_pool[id >> 3] &= ~(1 << (id & 7)); 7937978SPeter.Dunlap@Sun.COM pool->id_free_counter++; 7947978SPeter.Dunlap@Sun.COM ASSERT(pool->id_free_counter <= pool->id_max_free_counter); 7957978SPeter.Dunlap@Sun.COM mutex_exit(&pool->id_mutex); 7967978SPeter.Dunlap@Sun.COM return; 7977978SPeter.Dunlap@Sun.COM } 7987978SPeter.Dunlap@Sun.COM /* Freeing a free ID. */ 7997978SPeter.Dunlap@Sun.COM ASSERT(0); 8007978SPeter.Dunlap@Sun.COM mutex_exit(&pool->id_mutex); 8017978SPeter.Dunlap@Sun.COM } 8027978SPeter.Dunlap@Sun.COM 8037978SPeter.Dunlap@Sun.COM uint32_t 8047978SPeter.Dunlap@Sun.COM idm_cid_alloc(void) 8057978SPeter.Dunlap@Sun.COM { 8067978SPeter.Dunlap@Sun.COM /* 8077978SPeter.Dunlap@Sun.COM * ID pool works with 16-bit identifiers right now. That should 8087978SPeter.Dunlap@Sun.COM * be plenty since we will probably never have more than 2^16 8097978SPeter.Dunlap@Sun.COM * connections simultaneously. 8107978SPeter.Dunlap@Sun.COM */ 8117978SPeter.Dunlap@Sun.COM uint16_t cid16; 8127978SPeter.Dunlap@Sun.COM 8137978SPeter.Dunlap@Sun.COM if (idm_idpool_alloc(&idm.idm_conn_id_pool, &cid16) == -1) { 8147978SPeter.Dunlap@Sun.COM return (0); /* Fail */ 8157978SPeter.Dunlap@Sun.COM } 8167978SPeter.Dunlap@Sun.COM 8177978SPeter.Dunlap@Sun.COM return ((uint32_t)cid16); 8187978SPeter.Dunlap@Sun.COM } 8197978SPeter.Dunlap@Sun.COM 8207978SPeter.Dunlap@Sun.COM void 8217978SPeter.Dunlap@Sun.COM idm_cid_free(uint32_t cid) 8227978SPeter.Dunlap@Sun.COM { 8237978SPeter.Dunlap@Sun.COM idm_idpool_free(&idm.idm_conn_id_pool, (uint16_t)cid); 8247978SPeter.Dunlap@Sun.COM } 8257978SPeter.Dunlap@Sun.COM 8267978SPeter.Dunlap@Sun.COM 8277978SPeter.Dunlap@Sun.COM /* 8287978SPeter.Dunlap@Sun.COM * Code for generating the header and data digests 8297978SPeter.Dunlap@Sun.COM * 8307978SPeter.Dunlap@Sun.COM * This is the CRC-32C table 8317978SPeter.Dunlap@Sun.COM * Generated with: 8327978SPeter.Dunlap@Sun.COM * width = 32 bits 8337978SPeter.Dunlap@Sun.COM * poly = 0x1EDC6F41 8347978SPeter.Dunlap@Sun.COM * reflect input bytes = true 8357978SPeter.Dunlap@Sun.COM * reflect output bytes = true 8367978SPeter.Dunlap@Sun.COM */ 8377978SPeter.Dunlap@Sun.COM 8387978SPeter.Dunlap@Sun.COM uint32_t idm_crc32c_table[256] = 8397978SPeter.Dunlap@Sun.COM { 8407978SPeter.Dunlap@Sun.COM 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 8417978SPeter.Dunlap@Sun.COM 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 8427978SPeter.Dunlap@Sun.COM 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 8437978SPeter.Dunlap@Sun.COM 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 8447978SPeter.Dunlap@Sun.COM 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 8457978SPeter.Dunlap@Sun.COM 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 8467978SPeter.Dunlap@Sun.COM 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 8477978SPeter.Dunlap@Sun.COM 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 8487978SPeter.Dunlap@Sun.COM 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 8497978SPeter.Dunlap@Sun.COM 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 8507978SPeter.Dunlap@Sun.COM 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 8517978SPeter.Dunlap@Sun.COM 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 8527978SPeter.Dunlap@Sun.COM 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 8537978SPeter.Dunlap@Sun.COM 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, 8547978SPeter.Dunlap@Sun.COM 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 8557978SPeter.Dunlap@Sun.COM 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 8567978SPeter.Dunlap@Sun.COM 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 8577978SPeter.Dunlap@Sun.COM 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 8587978SPeter.Dunlap@Sun.COM 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 8597978SPeter.Dunlap@Sun.COM 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 8607978SPeter.Dunlap@Sun.COM 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 8617978SPeter.Dunlap@Sun.COM 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 8627978SPeter.Dunlap@Sun.COM 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 8637978SPeter.Dunlap@Sun.COM 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 8647978SPeter.Dunlap@Sun.COM 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 8657978SPeter.Dunlap@Sun.COM 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 8667978SPeter.Dunlap@Sun.COM 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 8677978SPeter.Dunlap@Sun.COM 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 8687978SPeter.Dunlap@Sun.COM 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 8697978SPeter.Dunlap@Sun.COM 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, 8707978SPeter.Dunlap@Sun.COM 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 8717978SPeter.Dunlap@Sun.COM 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, 8727978SPeter.Dunlap@Sun.COM 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 8737978SPeter.Dunlap@Sun.COM 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 8747978SPeter.Dunlap@Sun.COM 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 8757978SPeter.Dunlap@Sun.COM 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, 8767978SPeter.Dunlap@Sun.COM 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 8777978SPeter.Dunlap@Sun.COM 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 8787978SPeter.Dunlap@Sun.COM 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 8797978SPeter.Dunlap@Sun.COM 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 8807978SPeter.Dunlap@Sun.COM 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 8817978SPeter.Dunlap@Sun.COM 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 8827978SPeter.Dunlap@Sun.COM 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 8837978SPeter.Dunlap@Sun.COM 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 8847978SPeter.Dunlap@Sun.COM 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 8857978SPeter.Dunlap@Sun.COM 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 8867978SPeter.Dunlap@Sun.COM 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 8877978SPeter.Dunlap@Sun.COM 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 8887978SPeter.Dunlap@Sun.COM 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 8897978SPeter.Dunlap@Sun.COM 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, 8907978SPeter.Dunlap@Sun.COM 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 8917978SPeter.Dunlap@Sun.COM 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 8927978SPeter.Dunlap@Sun.COM 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 8937978SPeter.Dunlap@Sun.COM 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, 8947978SPeter.Dunlap@Sun.COM 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 8957978SPeter.Dunlap@Sun.COM 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 8967978SPeter.Dunlap@Sun.COM 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 8977978SPeter.Dunlap@Sun.COM 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 8987978SPeter.Dunlap@Sun.COM 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 8997978SPeter.Dunlap@Sun.COM 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 9007978SPeter.Dunlap@Sun.COM 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 9017978SPeter.Dunlap@Sun.COM 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 9027978SPeter.Dunlap@Sun.COM 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 9037978SPeter.Dunlap@Sun.COM 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351 9047978SPeter.Dunlap@Sun.COM }; 9057978SPeter.Dunlap@Sun.COM 9067978SPeter.Dunlap@Sun.COM /* 9077978SPeter.Dunlap@Sun.COM * iscsi_crc32c - Steps through buffer one byte at at time, calculates 9087978SPeter.Dunlap@Sun.COM * reflected crc using table. 9097978SPeter.Dunlap@Sun.COM */ 9107978SPeter.Dunlap@Sun.COM uint32_t 9117978SPeter.Dunlap@Sun.COM idm_crc32c(void *address, unsigned long length) 9127978SPeter.Dunlap@Sun.COM { 9137978SPeter.Dunlap@Sun.COM uint8_t *buffer = address; 9147978SPeter.Dunlap@Sun.COM uint32_t crc = 0xffffffff, result; 9157978SPeter.Dunlap@Sun.COM #ifdef _BIG_ENDIAN 9167978SPeter.Dunlap@Sun.COM uint8_t byte0, byte1, byte2, byte3; 9177978SPeter.Dunlap@Sun.COM #endif 9187978SPeter.Dunlap@Sun.COM 9197978SPeter.Dunlap@Sun.COM ASSERT(address != NULL); 9207978SPeter.Dunlap@Sun.COM 92110777SJack.Meng@Sun.COM if (iscsi_crc32_hd == -1) { 92210777SJack.Meng@Sun.COM if (hd_crc32_avail((uint32_t *)idm_crc32c_table) == B_TRUE) { 92310777SJack.Meng@Sun.COM iscsi_crc32_hd = 0; 92410777SJack.Meng@Sun.COM } else { 92510777SJack.Meng@Sun.COM iscsi_crc32_hd = 1; 92610777SJack.Meng@Sun.COM } 92710777SJack.Meng@Sun.COM } 92810777SJack.Meng@Sun.COM if (iscsi_crc32_hd == 0) 92910777SJack.Meng@Sun.COM return (HW_CRC32(buffer, length, crc)); 93010777SJack.Meng@Sun.COM 9317978SPeter.Dunlap@Sun.COM while (length--) { 9327978SPeter.Dunlap@Sun.COM crc = idm_crc32c_table[(crc ^ *buffer++) & 0xFFL] ^ 9337978SPeter.Dunlap@Sun.COM (crc >> 8); 9347978SPeter.Dunlap@Sun.COM } 9357978SPeter.Dunlap@Sun.COM result = crc ^ 0xffffffff; 9367978SPeter.Dunlap@Sun.COM 9377978SPeter.Dunlap@Sun.COM #ifdef _BIG_ENDIAN 9387978SPeter.Dunlap@Sun.COM byte0 = (uint8_t)(result & 0xFF); 9397978SPeter.Dunlap@Sun.COM byte1 = (uint8_t)((result >> 8) & 0xFF); 9407978SPeter.Dunlap@Sun.COM byte2 = (uint8_t)((result >> 16) & 0xFF); 9417978SPeter.Dunlap@Sun.COM byte3 = (uint8_t)((result >> 24) & 0xFF); 9427978SPeter.Dunlap@Sun.COM result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3); 9437978SPeter.Dunlap@Sun.COM #endif /* _BIG_ENDIAN */ 9447978SPeter.Dunlap@Sun.COM 9457978SPeter.Dunlap@Sun.COM return (result); 9467978SPeter.Dunlap@Sun.COM } 9477978SPeter.Dunlap@Sun.COM 9487978SPeter.Dunlap@Sun.COM 9497978SPeter.Dunlap@Sun.COM /* 9507978SPeter.Dunlap@Sun.COM * idm_crc32c_continued - Continues stepping through buffer one 9517978SPeter.Dunlap@Sun.COM * byte at at time, calculates reflected crc using table. 9527978SPeter.Dunlap@Sun.COM */ 9537978SPeter.Dunlap@Sun.COM uint32_t 9547978SPeter.Dunlap@Sun.COM idm_crc32c_continued(void *address, unsigned long length, uint32_t crc) 9557978SPeter.Dunlap@Sun.COM { 9567978SPeter.Dunlap@Sun.COM uint8_t *buffer = address; 9577978SPeter.Dunlap@Sun.COM uint32_t result; 9587978SPeter.Dunlap@Sun.COM #ifdef _BIG_ENDIAN 9597978SPeter.Dunlap@Sun.COM uint8_t byte0, byte1, byte2, byte3; 9607978SPeter.Dunlap@Sun.COM #endif 9617978SPeter.Dunlap@Sun.COM 9627978SPeter.Dunlap@Sun.COM ASSERT(address != NULL); 9637978SPeter.Dunlap@Sun.COM 96410777SJack.Meng@Sun.COM if (iscsi_crc32_hd == -1) { 96510777SJack.Meng@Sun.COM if (hd_crc32_avail((uint32_t *)idm_crc32c_table) == B_TRUE) { 96610777SJack.Meng@Sun.COM iscsi_crc32_hd = 0; 96710777SJack.Meng@Sun.COM } else { 96810777SJack.Meng@Sun.COM iscsi_crc32_hd = 1; 96910777SJack.Meng@Sun.COM } 97010777SJack.Meng@Sun.COM } 97110777SJack.Meng@Sun.COM if (iscsi_crc32_hd == 0) 97210777SJack.Meng@Sun.COM return (HW_CRC32_CONT(buffer, length, crc)); 97310777SJack.Meng@Sun.COM 97410777SJack.Meng@Sun.COM 9757978SPeter.Dunlap@Sun.COM #ifdef _BIG_ENDIAN 9767978SPeter.Dunlap@Sun.COM byte0 = (uint8_t)((crc >> 24) & 0xFF); 9777978SPeter.Dunlap@Sun.COM byte1 = (uint8_t)((crc >> 16) & 0xFF); 9787978SPeter.Dunlap@Sun.COM byte2 = (uint8_t)((crc >> 8) & 0xFF); 9797978SPeter.Dunlap@Sun.COM byte3 = (uint8_t)(crc & 0xFF); 9807978SPeter.Dunlap@Sun.COM crc = ((byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0); 9817978SPeter.Dunlap@Sun.COM #endif 9827978SPeter.Dunlap@Sun.COM 9837978SPeter.Dunlap@Sun.COM crc = crc ^ 0xffffffff; 9847978SPeter.Dunlap@Sun.COM while (length--) { 9857978SPeter.Dunlap@Sun.COM crc = idm_crc32c_table[(crc ^ *buffer++) & 0xFFL] ^ 9867978SPeter.Dunlap@Sun.COM (crc >> 8); 9877978SPeter.Dunlap@Sun.COM } 9887978SPeter.Dunlap@Sun.COM result = crc ^ 0xffffffff; 9897978SPeter.Dunlap@Sun.COM 9907978SPeter.Dunlap@Sun.COM #ifdef _BIG_ENDIAN 9917978SPeter.Dunlap@Sun.COM byte0 = (uint8_t)(result & 0xFF); 9927978SPeter.Dunlap@Sun.COM byte1 = (uint8_t)((result >> 8) & 0xFF); 9937978SPeter.Dunlap@Sun.COM byte2 = (uint8_t)((result >> 16) & 0xFF); 9947978SPeter.Dunlap@Sun.COM byte3 = (uint8_t)((result >> 24) & 0xFF); 9957978SPeter.Dunlap@Sun.COM result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3); 9967978SPeter.Dunlap@Sun.COM #endif 9977978SPeter.Dunlap@Sun.COM return (result); 9987978SPeter.Dunlap@Sun.COM } 9997978SPeter.Dunlap@Sun.COM 10007978SPeter.Dunlap@Sun.COM /* ARGSUSED */ 10017978SPeter.Dunlap@Sun.COM int 10027978SPeter.Dunlap@Sun.COM idm_task_constructor(void *hdl, void *arg, int flags) 10037978SPeter.Dunlap@Sun.COM { 10047978SPeter.Dunlap@Sun.COM idm_task_t *idt = (idm_task_t *)hdl; 10057978SPeter.Dunlap@Sun.COM uint32_t next_task; 10067978SPeter.Dunlap@Sun.COM 10077978SPeter.Dunlap@Sun.COM mutex_init(&idt->idt_mutex, NULL, MUTEX_DEFAULT, NULL); 10087978SPeter.Dunlap@Sun.COM 10097978SPeter.Dunlap@Sun.COM /* Find the next free task ID */ 10107978SPeter.Dunlap@Sun.COM rw_enter(&idm.idm_taskid_table_lock, RW_WRITER); 10117978SPeter.Dunlap@Sun.COM next_task = idm.idm_taskid_next; 10127978SPeter.Dunlap@Sun.COM while (idm.idm_taskid_table[next_task]) { 10137978SPeter.Dunlap@Sun.COM next_task++; 10147978SPeter.Dunlap@Sun.COM if (next_task == idm.idm_taskid_max) 10157978SPeter.Dunlap@Sun.COM next_task = 0; 10167978SPeter.Dunlap@Sun.COM if (next_task == idm.idm_taskid_next) { 10177978SPeter.Dunlap@Sun.COM rw_exit(&idm.idm_taskid_table_lock); 10187978SPeter.Dunlap@Sun.COM return (-1); 10197978SPeter.Dunlap@Sun.COM } 10207978SPeter.Dunlap@Sun.COM } 10217978SPeter.Dunlap@Sun.COM 10227978SPeter.Dunlap@Sun.COM idm.idm_taskid_table[next_task] = idt; 10237978SPeter.Dunlap@Sun.COM idm.idm_taskid_next = (next_task + 1) % idm.idm_taskid_max; 10247978SPeter.Dunlap@Sun.COM rw_exit(&idm.idm_taskid_table_lock); 10257978SPeter.Dunlap@Sun.COM 10267978SPeter.Dunlap@Sun.COM idt->idt_tt = next_task; 10277978SPeter.Dunlap@Sun.COM 10287978SPeter.Dunlap@Sun.COM list_create(&idt->idt_inbufv, sizeof (idm_buf_t), 10297978SPeter.Dunlap@Sun.COM offsetof(idm_buf_t, idb_buflink)); 10307978SPeter.Dunlap@Sun.COM list_create(&idt->idt_outbufv, sizeof (idm_buf_t), 10317978SPeter.Dunlap@Sun.COM offsetof(idm_buf_t, idb_buflink)); 10327978SPeter.Dunlap@Sun.COM idm_refcnt_init(&idt->idt_refcnt, idt); 10337978SPeter.Dunlap@Sun.COM 10347978SPeter.Dunlap@Sun.COM /* 10357978SPeter.Dunlap@Sun.COM * Set the transport header pointer explicitly. This removes the 10367978SPeter.Dunlap@Sun.COM * need for per-transport header allocation, which simplifies cache 10377978SPeter.Dunlap@Sun.COM * init considerably. If at a later date we have an additional IDM 10387978SPeter.Dunlap@Sun.COM * transport that requires a different size, we'll revisit this. 10397978SPeter.Dunlap@Sun.COM */ 10407978SPeter.Dunlap@Sun.COM idt->idt_transport_hdr = (void *)(idt + 1); /* pointer arithmetic */ 104111081SPriya.Krishnan@Sun.COM idt->idt_flags = 0; 10427978SPeter.Dunlap@Sun.COM return (0); 10437978SPeter.Dunlap@Sun.COM } 10447978SPeter.Dunlap@Sun.COM 10457978SPeter.Dunlap@Sun.COM /* ARGSUSED */ 10467978SPeter.Dunlap@Sun.COM void 10477978SPeter.Dunlap@Sun.COM idm_task_destructor(void *hdl, void *arg) 10487978SPeter.Dunlap@Sun.COM { 10497978SPeter.Dunlap@Sun.COM idm_task_t *idt = (idm_task_t *)hdl; 10507978SPeter.Dunlap@Sun.COM 10517978SPeter.Dunlap@Sun.COM /* Remove the task from the ID table */ 10527978SPeter.Dunlap@Sun.COM rw_enter(&idm.idm_taskid_table_lock, RW_WRITER); 10537978SPeter.Dunlap@Sun.COM idm.idm_taskid_table[idt->idt_tt] = NULL; 10547978SPeter.Dunlap@Sun.COM rw_exit(&idm.idm_taskid_table_lock); 10557978SPeter.Dunlap@Sun.COM 10567978SPeter.Dunlap@Sun.COM /* free the inbuf and outbuf */ 10577978SPeter.Dunlap@Sun.COM idm_refcnt_destroy(&idt->idt_refcnt); 10587978SPeter.Dunlap@Sun.COM list_destroy(&idt->idt_inbufv); 10597978SPeter.Dunlap@Sun.COM list_destroy(&idt->idt_outbufv); 10607978SPeter.Dunlap@Sun.COM 10619162SPeter.Dunlap@Sun.COM /* 10629162SPeter.Dunlap@Sun.COM * The final call to idm_task_rele may happen with the task 10639162SPeter.Dunlap@Sun.COM * mutex held which may invoke this destructor immediately. 10649162SPeter.Dunlap@Sun.COM * Stall here until the task mutex owner lets go. 10659162SPeter.Dunlap@Sun.COM */ 10669162SPeter.Dunlap@Sun.COM mutex_enter(&idt->idt_mutex); 10677978SPeter.Dunlap@Sun.COM mutex_destroy(&idt->idt_mutex); 10687978SPeter.Dunlap@Sun.COM } 10697978SPeter.Dunlap@Sun.COM 10707978SPeter.Dunlap@Sun.COM /* 10717978SPeter.Dunlap@Sun.COM * idm_listbuf_insert searches from the back of the list looking for the 10727978SPeter.Dunlap@Sun.COM * insertion point. 10737978SPeter.Dunlap@Sun.COM */ 10747978SPeter.Dunlap@Sun.COM void 10757978SPeter.Dunlap@Sun.COM idm_listbuf_insert(list_t *lst, idm_buf_t *buf) 10767978SPeter.Dunlap@Sun.COM { 10777978SPeter.Dunlap@Sun.COM idm_buf_t *idb; 10787978SPeter.Dunlap@Sun.COM 10797978SPeter.Dunlap@Sun.COM /* iterate through the list to find the insertion point */ 10807978SPeter.Dunlap@Sun.COM for (idb = list_tail(lst); idb != NULL; idb = list_prev(lst, idb)) { 10817978SPeter.Dunlap@Sun.COM 10827978SPeter.Dunlap@Sun.COM if (idb->idb_bufoffset < buf->idb_bufoffset) { 10837978SPeter.Dunlap@Sun.COM 10847978SPeter.Dunlap@Sun.COM list_insert_after(lst, idb, buf); 10857978SPeter.Dunlap@Sun.COM return; 10867978SPeter.Dunlap@Sun.COM } 10877978SPeter.Dunlap@Sun.COM } 10887978SPeter.Dunlap@Sun.COM 10897978SPeter.Dunlap@Sun.COM /* add the buf to the head of the list */ 10907978SPeter.Dunlap@Sun.COM list_insert_head(lst, buf); 10917978SPeter.Dunlap@Sun.COM 10927978SPeter.Dunlap@Sun.COM } 10937978SPeter.Dunlap@Sun.COM 10947978SPeter.Dunlap@Sun.COM /*ARGSUSED*/ 10957978SPeter.Dunlap@Sun.COM void 10967978SPeter.Dunlap@Sun.COM idm_wd_thread(void *arg) 10977978SPeter.Dunlap@Sun.COM { 10987978SPeter.Dunlap@Sun.COM idm_conn_t *ic; 109911066Srafael.vanoni@sun.com clock_t wake_time = SEC_TO_TICK(IDM_WD_INTERVAL); 11007978SPeter.Dunlap@Sun.COM clock_t idle_time; 11017978SPeter.Dunlap@Sun.COM 11028209SJames.Moore@Sun.COM /* Record the thread id for thread_join() */ 11038209SJames.Moore@Sun.COM idm.idm_wd_thread_did = curthread->t_did; 11047978SPeter.Dunlap@Sun.COM mutex_enter(&idm.idm_global_mutex); 11057978SPeter.Dunlap@Sun.COM idm.idm_wd_thread_running = B_TRUE; 11067978SPeter.Dunlap@Sun.COM cv_signal(&idm.idm_wd_cv); 11077978SPeter.Dunlap@Sun.COM 11087978SPeter.Dunlap@Sun.COM while (idm.idm_wd_thread_running) { 11097978SPeter.Dunlap@Sun.COM for (ic = list_head(&idm.idm_tgt_conn_list); 11107978SPeter.Dunlap@Sun.COM ic != NULL; 11117978SPeter.Dunlap@Sun.COM ic = list_next(&idm.idm_tgt_conn_list, ic)) { 11127978SPeter.Dunlap@Sun.COM idle_time = ddi_get_lbolt() - ic->ic_timestamp; 11137978SPeter.Dunlap@Sun.COM 11147978SPeter.Dunlap@Sun.COM /* 11159586SPeter.Dunlap@Sun.COM * If this connection is in FFP then grab a hold 11169586SPeter.Dunlap@Sun.COM * and check the various timeout thresholds. Otherwise 11179586SPeter.Dunlap@Sun.COM * the connection is closing and we should just 11189586SPeter.Dunlap@Sun.COM * move on to the next one. 11199586SPeter.Dunlap@Sun.COM */ 11209586SPeter.Dunlap@Sun.COM mutex_enter(&ic->ic_state_mutex); 11219586SPeter.Dunlap@Sun.COM if (ic->ic_ffp) { 11229586SPeter.Dunlap@Sun.COM idm_conn_hold(ic); 11239586SPeter.Dunlap@Sun.COM } else { 11249586SPeter.Dunlap@Sun.COM mutex_exit(&ic->ic_state_mutex); 11259586SPeter.Dunlap@Sun.COM continue; 11269586SPeter.Dunlap@Sun.COM } 11279586SPeter.Dunlap@Sun.COM 11289586SPeter.Dunlap@Sun.COM /* 11297978SPeter.Dunlap@Sun.COM * If there hasn't been any activity on this 11309586SPeter.Dunlap@Sun.COM * connection for the keepalive timeout period 11319586SPeter.Dunlap@Sun.COM * and if the client has provided a keepalive 11329586SPeter.Dunlap@Sun.COM * callback then call the keepalive callback. 11339586SPeter.Dunlap@Sun.COM * This allows the client to take action to keep 11349586SPeter.Dunlap@Sun.COM * the link alive (like send a nop PDU). 11359586SPeter.Dunlap@Sun.COM */ 11369586SPeter.Dunlap@Sun.COM if ((TICK_TO_SEC(idle_time) >= 11379586SPeter.Dunlap@Sun.COM IDM_TRANSPORT_KEEPALIVE_IDLE_TIMEOUT) && 11389586SPeter.Dunlap@Sun.COM !ic->ic_keepalive) { 11399586SPeter.Dunlap@Sun.COM ic->ic_keepalive = B_TRUE; 11409586SPeter.Dunlap@Sun.COM if (ic->ic_conn_ops.icb_keepalive) { 11419586SPeter.Dunlap@Sun.COM mutex_exit(&ic->ic_state_mutex); 11429586SPeter.Dunlap@Sun.COM mutex_exit(&idm.idm_global_mutex); 11439586SPeter.Dunlap@Sun.COM (*ic->ic_conn_ops.icb_keepalive)(ic); 11449586SPeter.Dunlap@Sun.COM mutex_enter(&idm.idm_global_mutex); 11459586SPeter.Dunlap@Sun.COM mutex_enter(&ic->ic_state_mutex); 11469586SPeter.Dunlap@Sun.COM } 11479586SPeter.Dunlap@Sun.COM } else if ((TICK_TO_SEC(idle_time) < 11489586SPeter.Dunlap@Sun.COM IDM_TRANSPORT_KEEPALIVE_IDLE_TIMEOUT)) { 11499586SPeter.Dunlap@Sun.COM /* Reset keepalive */ 11509586SPeter.Dunlap@Sun.COM ic->ic_keepalive = B_FALSE; 11519586SPeter.Dunlap@Sun.COM } 11529586SPeter.Dunlap@Sun.COM 11539586SPeter.Dunlap@Sun.COM /* 11549586SPeter.Dunlap@Sun.COM * If there hasn't been any activity on this 11559586SPeter.Dunlap@Sun.COM * connection for the failure timeout period then 11567978SPeter.Dunlap@Sun.COM * drop the connection. We expect the initiator 11577978SPeter.Dunlap@Sun.COM * to keep the connection alive if it wants the 11587978SPeter.Dunlap@Sun.COM * connection to stay open. 11597978SPeter.Dunlap@Sun.COM * 11607978SPeter.Dunlap@Sun.COM * If it turns out to be desireable to take a 11617978SPeter.Dunlap@Sun.COM * more active role in maintaining the connect 11627978SPeter.Dunlap@Sun.COM * we could add a client callback to send 11637978SPeter.Dunlap@Sun.COM * a "keepalive" kind of message (no doubt a nop) 11647978SPeter.Dunlap@Sun.COM * and fire that on a shorter timer. 11657978SPeter.Dunlap@Sun.COM */ 11667978SPeter.Dunlap@Sun.COM if (TICK_TO_SEC(idle_time) > 11677978SPeter.Dunlap@Sun.COM IDM_TRANSPORT_FAIL_IDLE_TIMEOUT) { 11689586SPeter.Dunlap@Sun.COM mutex_exit(&ic->ic_state_mutex); 11699586SPeter.Dunlap@Sun.COM mutex_exit(&idm.idm_global_mutex); 11709586SPeter.Dunlap@Sun.COM IDM_SM_LOG(CE_WARN, "idm_wd_thread: " 11719586SPeter.Dunlap@Sun.COM "conn %p idle for %d seconds, " 11729586SPeter.Dunlap@Sun.COM "sending CE_TRANSPORT_FAIL", 11739586SPeter.Dunlap@Sun.COM (void *)ic, (int)idle_time); 11749586SPeter.Dunlap@Sun.COM idm_conn_event(ic, CE_TRANSPORT_FAIL, NULL); 11759586SPeter.Dunlap@Sun.COM mutex_enter(&idm.idm_global_mutex); 11769586SPeter.Dunlap@Sun.COM mutex_enter(&ic->ic_state_mutex); 11777978SPeter.Dunlap@Sun.COM } 11789586SPeter.Dunlap@Sun.COM 11799586SPeter.Dunlap@Sun.COM idm_conn_rele(ic); 11809586SPeter.Dunlap@Sun.COM 11819586SPeter.Dunlap@Sun.COM mutex_exit(&ic->ic_state_mutex); 11827978SPeter.Dunlap@Sun.COM } 11837978SPeter.Dunlap@Sun.COM 118411066Srafael.vanoni@sun.com (void) cv_reltimedwait(&idm.idm_wd_cv, &idm.idm_global_mutex, 118511066Srafael.vanoni@sun.com wake_time, TR_CLOCK_TICK); 11867978SPeter.Dunlap@Sun.COM } 11877978SPeter.Dunlap@Sun.COM mutex_exit(&idm.idm_global_mutex); 11887978SPeter.Dunlap@Sun.COM 11897978SPeter.Dunlap@Sun.COM thread_exit(); 11907978SPeter.Dunlap@Sun.COM } 1191