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 /* 22*12372SPriya.Krishnan@Sun.COM * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 237978SPeter.Dunlap@Sun.COM */ 247978SPeter.Dunlap@Sun.COM #ifndef _IDM_IMPL_H_ 257978SPeter.Dunlap@Sun.COM #define _IDM_IMPL_H_ 267978SPeter.Dunlap@Sun.COM 277978SPeter.Dunlap@Sun.COM #ifdef __cplusplus 287978SPeter.Dunlap@Sun.COM extern "C" { 297978SPeter.Dunlap@Sun.COM #endif 307978SPeter.Dunlap@Sun.COM 317978SPeter.Dunlap@Sun.COM #include <sys/avl.h> 327978SPeter.Dunlap@Sun.COM #include <sys/socket_impl.h> 337978SPeter.Dunlap@Sun.COM 347978SPeter.Dunlap@Sun.COM /* 357978SPeter.Dunlap@Sun.COM * IDM lock order: 367978SPeter.Dunlap@Sun.COM * 377978SPeter.Dunlap@Sun.COM * idm_taskid_table_lock, idm_task_t.idt_mutex 387978SPeter.Dunlap@Sun.COM */ 397978SPeter.Dunlap@Sun.COM 407978SPeter.Dunlap@Sun.COM #define CF_LOGIN_READY 0x00000001 417978SPeter.Dunlap@Sun.COM #define CF_INITIAL_LOGIN 0x00000002 427978SPeter.Dunlap@Sun.COM #define CF_ERROR 0x80000000 437978SPeter.Dunlap@Sun.COM 447978SPeter.Dunlap@Sun.COM typedef enum { 457978SPeter.Dunlap@Sun.COM CONN_TYPE_INI = 1, 467978SPeter.Dunlap@Sun.COM CONN_TYPE_TGT 477978SPeter.Dunlap@Sun.COM } idm_conn_type_t; 487978SPeter.Dunlap@Sun.COM 497978SPeter.Dunlap@Sun.COM /* 507978SPeter.Dunlap@Sun.COM * Watchdog interval in seconds 517978SPeter.Dunlap@Sun.COM */ 527978SPeter.Dunlap@Sun.COM #define IDM_WD_INTERVAL 5 537978SPeter.Dunlap@Sun.COM 547978SPeter.Dunlap@Sun.COM /* 559586SPeter.Dunlap@Sun.COM * Timeout period before the client "keepalive" callback is invoked in 569586SPeter.Dunlap@Sun.COM * seconds if the connection is idle. 579586SPeter.Dunlap@Sun.COM */ 589586SPeter.Dunlap@Sun.COM #define IDM_TRANSPORT_KEEPALIVE_IDLE_TIMEOUT 20 599586SPeter.Dunlap@Sun.COM 609586SPeter.Dunlap@Sun.COM /* 617978SPeter.Dunlap@Sun.COM * Timeout period before a TRANSPORT_FAIL event is generated in seconds 627978SPeter.Dunlap@Sun.COM * if the connection is idle. 637978SPeter.Dunlap@Sun.COM */ 647978SPeter.Dunlap@Sun.COM #define IDM_TRANSPORT_FAIL_IDLE_TIMEOUT 30 657978SPeter.Dunlap@Sun.COM 667978SPeter.Dunlap@Sun.COM /* 677978SPeter.Dunlap@Sun.COM * IDM reference count structure. Audit code is shamelessly adapted 687978SPeter.Dunlap@Sun.COM * from CIFS server. 697978SPeter.Dunlap@Sun.COM */ 707978SPeter.Dunlap@Sun.COM 717978SPeter.Dunlap@Sun.COM #define REFCNT_AUDIT_STACK_DEPTH 16 727978SPeter.Dunlap@Sun.COM #define REFCNT_AUDIT_BUF_MAX_REC 16 737978SPeter.Dunlap@Sun.COM 747978SPeter.Dunlap@Sun.COM typedef struct { 757978SPeter.Dunlap@Sun.COM uint32_t anr_refcnt; 767978SPeter.Dunlap@Sun.COM int anr_depth; 777978SPeter.Dunlap@Sun.COM pc_t anr_stack[REFCNT_AUDIT_STACK_DEPTH]; 787978SPeter.Dunlap@Sun.COM } refcnt_audit_record_t; 797978SPeter.Dunlap@Sun.COM 807978SPeter.Dunlap@Sun.COM typedef struct { 817978SPeter.Dunlap@Sun.COM int anb_index; 827978SPeter.Dunlap@Sun.COM int anb_max_index; 837978SPeter.Dunlap@Sun.COM refcnt_audit_record_t anb_records[REFCNT_AUDIT_BUF_MAX_REC]; 847978SPeter.Dunlap@Sun.COM } refcnt_audit_buf_t; 857978SPeter.Dunlap@Sun.COM 867978SPeter.Dunlap@Sun.COM #define REFCNT_AUDIT(_rf_) { \ 877978SPeter.Dunlap@Sun.COM refcnt_audit_record_t *anr; \ 887978SPeter.Dunlap@Sun.COM \ 897978SPeter.Dunlap@Sun.COM anr = (_rf_)->ir_audit_buf.anb_records; \ 907978SPeter.Dunlap@Sun.COM anr += (_rf_)->ir_audit_buf.anb_index; \ 917978SPeter.Dunlap@Sun.COM (_rf_)->ir_audit_buf.anb_index++; \ 927978SPeter.Dunlap@Sun.COM (_rf_)->ir_audit_buf.anb_index &= \ 937978SPeter.Dunlap@Sun.COM (_rf_)->ir_audit_buf.anb_max_index; \ 947978SPeter.Dunlap@Sun.COM anr->anr_refcnt = (_rf_)->ir_refcnt; \ 957978SPeter.Dunlap@Sun.COM anr->anr_depth = getpcstack(anr->anr_stack, \ 967978SPeter.Dunlap@Sun.COM REFCNT_AUDIT_STACK_DEPTH); \ 977978SPeter.Dunlap@Sun.COM } 987978SPeter.Dunlap@Sun.COM 997978SPeter.Dunlap@Sun.COM struct idm_refcnt_s; 1007978SPeter.Dunlap@Sun.COM 1017978SPeter.Dunlap@Sun.COM typedef void (idm_refcnt_cb_t)(void *ref_obj); 1027978SPeter.Dunlap@Sun.COM 1037978SPeter.Dunlap@Sun.COM typedef enum { 1047978SPeter.Dunlap@Sun.COM REF_NOWAIT, 1057978SPeter.Dunlap@Sun.COM REF_WAIT_SYNC, 1067978SPeter.Dunlap@Sun.COM REF_WAIT_ASYNC 1077978SPeter.Dunlap@Sun.COM } idm_refcnt_wait_t; 1087978SPeter.Dunlap@Sun.COM 1097978SPeter.Dunlap@Sun.COM typedef struct idm_refcnt_s { 1107978SPeter.Dunlap@Sun.COM int ir_refcnt; 1117978SPeter.Dunlap@Sun.COM void *ir_referenced_obj; 1127978SPeter.Dunlap@Sun.COM idm_refcnt_wait_t ir_waiting; 1137978SPeter.Dunlap@Sun.COM kmutex_t ir_mutex; 1147978SPeter.Dunlap@Sun.COM kcondvar_t ir_cv; 1157978SPeter.Dunlap@Sun.COM idm_refcnt_cb_t *ir_cb; 1167978SPeter.Dunlap@Sun.COM refcnt_audit_buf_t ir_audit_buf; 1177978SPeter.Dunlap@Sun.COM } idm_refcnt_t; 1187978SPeter.Dunlap@Sun.COM 1197978SPeter.Dunlap@Sun.COM /* 1207978SPeter.Dunlap@Sun.COM * connection parameters - These parameters would be populated at 1217978SPeter.Dunlap@Sun.COM * connection create, or during key-value negotiation at login 1227978SPeter.Dunlap@Sun.COM */ 1237978SPeter.Dunlap@Sun.COM typedef struct idm_conn_params_s { 12410261SCharles.Ting@Sun.COM uint32_t max_recv_dataseglen; 12510261SCharles.Ting@Sun.COM uint32_t max_xmit_dataseglen; 12610156SZhang.Yi@Sun.COM uint32_t conn_login_max; 12710156SZhang.Yi@Sun.COM uint32_t conn_login_interval; 12810156SZhang.Yi@Sun.COM boolean_t nonblock_socket; 1297978SPeter.Dunlap@Sun.COM } idm_conn_param_t; 1307978SPeter.Dunlap@Sun.COM 1317978SPeter.Dunlap@Sun.COM typedef struct idm_svc_s { 1327978SPeter.Dunlap@Sun.COM list_node_t is_list_node; 1337978SPeter.Dunlap@Sun.COM kmutex_t is_mutex; 1347978SPeter.Dunlap@Sun.COM kcondvar_t is_cv; 1357978SPeter.Dunlap@Sun.COM kmutex_t is_count_mutex; 1367978SPeter.Dunlap@Sun.COM kcondvar_t is_count_cv; 1377978SPeter.Dunlap@Sun.COM idm_refcnt_t is_refcnt; 1387978SPeter.Dunlap@Sun.COM int is_online; 1397978SPeter.Dunlap@Sun.COM /* transport-specific service components */ 1407978SPeter.Dunlap@Sun.COM void *is_so_svc; 1417978SPeter.Dunlap@Sun.COM void *is_iser_svc; 1427978SPeter.Dunlap@Sun.COM idm_svc_req_t is_svc_req; 1437978SPeter.Dunlap@Sun.COM } idm_svc_t; 1447978SPeter.Dunlap@Sun.COM 1459721SPriya.Krishnan@Sun.COM #define ISCSI_MAX_TSIH_LEN 6 /* 0x%04x */ 1469721SPriya.Krishnan@Sun.COM #define ISCSI_MAX_ISID_LEN ISCSI_ISID_LEN * 2 1479721SPriya.Krishnan@Sun.COM 1487978SPeter.Dunlap@Sun.COM typedef struct idm_conn_s { 1497978SPeter.Dunlap@Sun.COM list_node_t ic_list_node; 1507978SPeter.Dunlap@Sun.COM void *ic_handle; 1517978SPeter.Dunlap@Sun.COM idm_refcnt_t ic_refcnt; 1527978SPeter.Dunlap@Sun.COM idm_svc_t *ic_svc_binding; /* Target conn. only */ 1537978SPeter.Dunlap@Sun.COM idm_sockaddr_t ic_ini_dst_addr; 1547978SPeter.Dunlap@Sun.COM struct sockaddr_storage ic_laddr; /* conn local address */ 1557978SPeter.Dunlap@Sun.COM struct sockaddr_storage ic_raddr; /* conn remote address */ 1569721SPriya.Krishnan@Sun.COM 1579721SPriya.Krishnan@Sun.COM /* 1589721SPriya.Krishnan@Sun.COM * the target_name, initiator_name, initiator session 1599721SPriya.Krishnan@Sun.COM * identifier and target session identifying handle 1609721SPriya.Krishnan@Sun.COM * are only used for target connections. 1619721SPriya.Krishnan@Sun.COM */ 1629721SPriya.Krishnan@Sun.COM char ic_target_name[ISCSI_MAX_NAME_LEN + 1]; 1639721SPriya.Krishnan@Sun.COM char ic_initiator_name[ISCSI_MAX_NAME_LEN + 1]; 1649721SPriya.Krishnan@Sun.COM char ic_tsih[ISCSI_MAX_TSIH_LEN + 1]; 1659721SPriya.Krishnan@Sun.COM char ic_isid[ISCSI_MAX_ISID_LEN + 1]; 1667978SPeter.Dunlap@Sun.COM idm_conn_state_t ic_state; 1677978SPeter.Dunlap@Sun.COM idm_conn_state_t ic_last_state; 1687978SPeter.Dunlap@Sun.COM sm_audit_buf_t ic_state_audit; 1697978SPeter.Dunlap@Sun.COM kmutex_t ic_state_mutex; 1707978SPeter.Dunlap@Sun.COM kcondvar_t ic_state_cv; 1717978SPeter.Dunlap@Sun.COM uint32_t ic_state_flags; 1727978SPeter.Dunlap@Sun.COM timeout_id_t ic_state_timeout; 1737978SPeter.Dunlap@Sun.COM struct idm_conn_s *ic_reinstate_conn; /* For conn reinst. */ 1747978SPeter.Dunlap@Sun.COM struct idm_conn_s *ic_logout_conn; /* For other conn logout */ 1757978SPeter.Dunlap@Sun.COM taskq_t *ic_state_taskq; 1767978SPeter.Dunlap@Sun.COM int ic_pdu_events; 1777978SPeter.Dunlap@Sun.COM boolean_t ic_login_info_valid; 1787978SPeter.Dunlap@Sun.COM boolean_t ic_rdma_extensions; 1797978SPeter.Dunlap@Sun.COM uint16_t ic_login_cid; 1807978SPeter.Dunlap@Sun.COM 1817978SPeter.Dunlap@Sun.COM kmutex_t ic_mutex; 1827978SPeter.Dunlap@Sun.COM kcondvar_t ic_cv; 1837978SPeter.Dunlap@Sun.COM idm_status_t ic_conn_sm_status; 1847978SPeter.Dunlap@Sun.COM 1857978SPeter.Dunlap@Sun.COM boolean_t ic_ffp; 1869586SPeter.Dunlap@Sun.COM boolean_t ic_keepalive; 1877978SPeter.Dunlap@Sun.COM uint32_t ic_internal_cid; 1887978SPeter.Dunlap@Sun.COM 1897978SPeter.Dunlap@Sun.COM uint32_t ic_conn_flags; 1907978SPeter.Dunlap@Sun.COM idm_conn_type_t ic_conn_type; 1917978SPeter.Dunlap@Sun.COM idm_conn_ops_t ic_conn_ops; 1927978SPeter.Dunlap@Sun.COM idm_transport_ops_t *ic_transport_ops; 1937978SPeter.Dunlap@Sun.COM idm_transport_type_t ic_transport_type; 1947978SPeter.Dunlap@Sun.COM int ic_transport_hdrlen; 1957978SPeter.Dunlap@Sun.COM void *ic_transport_private; 1967978SPeter.Dunlap@Sun.COM idm_conn_param_t ic_conn_params; 1977978SPeter.Dunlap@Sun.COM /* 1987978SPeter.Dunlap@Sun.COM * Save client callback to interpose idm callback 1997978SPeter.Dunlap@Sun.COM */ 2007978SPeter.Dunlap@Sun.COM idm_pdu_cb_t *ic_client_callback; 2017978SPeter.Dunlap@Sun.COM clock_t ic_timestamp; 2027978SPeter.Dunlap@Sun.COM } idm_conn_t; 2037978SPeter.Dunlap@Sun.COM 2047978SPeter.Dunlap@Sun.COM #define IDM_CONN_HEADER_DIGEST 0x00000001 2057978SPeter.Dunlap@Sun.COM #define IDM_CONN_DATA_DIGEST 0x00000002 2067978SPeter.Dunlap@Sun.COM #define IDM_CONN_USE_SCOREBOARD 0x00000004 2077978SPeter.Dunlap@Sun.COM 2087978SPeter.Dunlap@Sun.COM #define IDM_CONN_ISINI(ICI_IC) ((ICI_IC)->ic_conn_type == CONN_TYPE_INI) 2097978SPeter.Dunlap@Sun.COM #define IDM_CONN_ISTGT(ICI_IC) ((ICI_IC)->ic_conn_type == CONN_TYPE_TGT) 2107978SPeter.Dunlap@Sun.COM 2117978SPeter.Dunlap@Sun.COM /* 2127978SPeter.Dunlap@Sun.COM * An IDM target task can transfer data using multiple buffers. The task 2137978SPeter.Dunlap@Sun.COM * will maintain a list of buffers, and each buffer will contain the relative 2147978SPeter.Dunlap@Sun.COM * offset of the transfer and a pointer to the next buffer in the list. 2157978SPeter.Dunlap@Sun.COM * 2167978SPeter.Dunlap@Sun.COM * Note on client private data: 2177978SPeter.Dunlap@Sun.COM * idt_private is intended to be a pointer to some sort of client- 2187978SPeter.Dunlap@Sun.COM * specific state. 2197978SPeter.Dunlap@Sun.COM * 2207978SPeter.Dunlap@Sun.COM * idt_client_handle is a more generic client-private piece of data that can 2217978SPeter.Dunlap@Sun.COM * be used by the client for the express purpose of task lookup. The driving 2227978SPeter.Dunlap@Sun.COM * use case for this is for the client to store the initiator task tag for 2237978SPeter.Dunlap@Sun.COM * a given task so that it may be more easily retrieved for task management. 2247978SPeter.Dunlap@Sun.COM * 2257978SPeter.Dunlap@Sun.COM * The key take away here is that clients should never call 2267978SPeter.Dunlap@Sun.COM * idm_task_find_by_handle in the performance path. 2277978SPeter.Dunlap@Sun.COM * 2287978SPeter.Dunlap@Sun.COM * An initiator will require only one buffer per task, the offset will be 0. 2297978SPeter.Dunlap@Sun.COM */ 2307978SPeter.Dunlap@Sun.COM 2317978SPeter.Dunlap@Sun.COM typedef struct idm_task_s { 2327978SPeter.Dunlap@Sun.COM idm_conn_t *idt_ic; /* Associated connection */ 2337978SPeter.Dunlap@Sun.COM /* connection type is in idt_ic->ic_conn_type */ 2347978SPeter.Dunlap@Sun.COM kmutex_t idt_mutex; 2357978SPeter.Dunlap@Sun.COM void *idt_private; /* Client private data */ 2367978SPeter.Dunlap@Sun.COM uintptr_t idt_client_handle; /* Client private */ 2377978SPeter.Dunlap@Sun.COM uint32_t idt_tt; /* Task tag */ 2387978SPeter.Dunlap@Sun.COM uint32_t idt_r2t_ttt; /* R2T Target Task tag */ 2397978SPeter.Dunlap@Sun.COM idm_task_state_t idt_state; 2407978SPeter.Dunlap@Sun.COM idm_refcnt_t idt_refcnt; 2417978SPeter.Dunlap@Sun.COM 2427978SPeter.Dunlap@Sun.COM /* 2437978SPeter.Dunlap@Sun.COM * Statistics 2447978SPeter.Dunlap@Sun.COM */ 2457978SPeter.Dunlap@Sun.COM int idt_tx_to_ini_start; 2467978SPeter.Dunlap@Sun.COM int idt_tx_to_ini_done; 2477978SPeter.Dunlap@Sun.COM int idt_rx_from_ini_start; 2487978SPeter.Dunlap@Sun.COM int idt_rx_from_ini_done; 2499162SPeter.Dunlap@Sun.COM int idt_tx_bytes; /* IDM_CONN_USE_SCOREBOARD */ 2509162SPeter.Dunlap@Sun.COM int idt_rx_bytes; /* IDM_CONN_USE_SCOREBOARD */ 2517978SPeter.Dunlap@Sun.COM 2527978SPeter.Dunlap@Sun.COM uint32_t idt_exp_datasn; /* expected datasn */ 2537978SPeter.Dunlap@Sun.COM uint32_t idt_exp_rttsn; /* expected rttsn */ 2547978SPeter.Dunlap@Sun.COM list_t idt_inbufv; /* chunks of IN buffers */ 2557978SPeter.Dunlap@Sun.COM list_t idt_outbufv; /* chunks of OUT buffers */ 2567978SPeter.Dunlap@Sun.COM 2577978SPeter.Dunlap@Sun.COM /* 2587978SPeter.Dunlap@Sun.COM * Transport header, which describes this tasks remote tagged buffer 2597978SPeter.Dunlap@Sun.COM */ 2607978SPeter.Dunlap@Sun.COM int idt_transport_hdrlen; 2617978SPeter.Dunlap@Sun.COM void *idt_transport_hdr; 26211081SPriya.Krishnan@Sun.COM uint32_t idt_flags; /* phase collapse */ 2637978SPeter.Dunlap@Sun.COM } idm_task_t; 2647978SPeter.Dunlap@Sun.COM 2657978SPeter.Dunlap@Sun.COM int idm_task_constructor(void *task_void, void *arg, int flags); 2667978SPeter.Dunlap@Sun.COM void idm_task_destructor(void *task_void, void *arg); 2677978SPeter.Dunlap@Sun.COM 2687978SPeter.Dunlap@Sun.COM #define IDM_TASKIDS_MAX 16384 2697978SPeter.Dunlap@Sun.COM #define IDM_BUF_MAGIC 0x49425546 /* "IBUF" */ 2707978SPeter.Dunlap@Sun.COM 27111081SPriya.Krishnan@Sun.COM #define IDM_TASK_PHASECOLLAPSE_REQ 0x00000001 /* request phase collapse */ 27211081SPriya.Krishnan@Sun.COM #define IDM_TASK_PHASECOLLAPSE_SUCCESS 0x00000002 /* phase collapse success */ 27311081SPriya.Krishnan@Sun.COM 2747978SPeter.Dunlap@Sun.COM /* Protect with task mutex */ 2757978SPeter.Dunlap@Sun.COM typedef struct idm_buf_s { 2767978SPeter.Dunlap@Sun.COM uint32_t idb_magic; /* "IBUF" */ 2777978SPeter.Dunlap@Sun.COM 2787978SPeter.Dunlap@Sun.COM /* 2797978SPeter.Dunlap@Sun.COM * Note: idm_tx_link *must* be the second element in the list for 2807978SPeter.Dunlap@Sun.COM * proper TX PDU ordering. 2817978SPeter.Dunlap@Sun.COM */ 2827978SPeter.Dunlap@Sun.COM list_node_t idm_tx_link; /* link in a list of TX objects */ 2837978SPeter.Dunlap@Sun.COM 2847978SPeter.Dunlap@Sun.COM list_node_t idb_buflink; /* link in a multi-buffer data xfer */ 2857978SPeter.Dunlap@Sun.COM idm_conn_t *idb_ic; /* Associated connection */ 2867978SPeter.Dunlap@Sun.COM void *idb_buf; /* data */ 2877978SPeter.Dunlap@Sun.COM uint64_t idb_buflen; /* length of buffer */ 2887978SPeter.Dunlap@Sun.COM size_t idb_bufoffset; /* offset in a multi-buffer xfer */ 2897978SPeter.Dunlap@Sun.COM boolean_t idb_bufalloc; /* true if alloc'd in idm_buf_alloc */ 2907978SPeter.Dunlap@Sun.COM /* 2917978SPeter.Dunlap@Sun.COM * DataPDUInOrder=Yes, so to track that the PDUs in a sequence are sent 2927978SPeter.Dunlap@Sun.COM * in continuously increasing address order, check that offsets for a 2937978SPeter.Dunlap@Sun.COM * single buffer xfer are in order. 2947978SPeter.Dunlap@Sun.COM */ 2957978SPeter.Dunlap@Sun.COM uint32_t idb_exp_offset; 2967978SPeter.Dunlap@Sun.COM size_t idb_xfer_len; /* Current requested xfer len */ 2977978SPeter.Dunlap@Sun.COM void *idb_buf_private; /* transport-specific buf handle */ 2987978SPeter.Dunlap@Sun.COM void *idb_reg_private; /* transport-specific reg handle */ 2999162SPeter.Dunlap@Sun.COM void *idb_bufptr; /* transport-specific bcopy pointer */ 3009162SPeter.Dunlap@Sun.COM boolean_t idb_bufbcopy; /* true if bcopy required */ 3019162SPeter.Dunlap@Sun.COM 3027978SPeter.Dunlap@Sun.COM idm_buf_cb_t *idb_buf_cb; /* Data Completion Notify, tgt only */ 3037978SPeter.Dunlap@Sun.COM void *idb_cb_arg; /* Client private data */ 3047978SPeter.Dunlap@Sun.COM idm_task_t *idb_task_binding; 3059162SPeter.Dunlap@Sun.COM timespec_t idb_xfer_start; 3069162SPeter.Dunlap@Sun.COM timespec_t idb_xfer_done; 3077978SPeter.Dunlap@Sun.COM boolean_t idb_in_transport; 3087978SPeter.Dunlap@Sun.COM boolean_t idb_tx_thread; /* Sockets only */ 3097978SPeter.Dunlap@Sun.COM iscsi_hdr_t idb_data_hdr_tmpl; /* Sockets only */ 3107978SPeter.Dunlap@Sun.COM idm_status_t idb_status; 3117978SPeter.Dunlap@Sun.COM } idm_buf_t; 3127978SPeter.Dunlap@Sun.COM 3139162SPeter.Dunlap@Sun.COM typedef enum { 3149162SPeter.Dunlap@Sun.COM BP_CHECK_QUICK, 3159162SPeter.Dunlap@Sun.COM BP_CHECK_THOROUGH, 3169162SPeter.Dunlap@Sun.COM BP_CHECK_ASSERT 3179162SPeter.Dunlap@Sun.COM } idm_bufpat_check_type_t; 3189162SPeter.Dunlap@Sun.COM 3199162SPeter.Dunlap@Sun.COM #define BUFPAT_MATCH(bc_bufpat, bc_idb) \ 3209162SPeter.Dunlap@Sun.COM ((bufpat->bufpat_idb == bc_idb) && \ 3219162SPeter.Dunlap@Sun.COM (bufpat->bufpat_bufmagic == IDM_BUF_MAGIC)) 3229162SPeter.Dunlap@Sun.COM 3239162SPeter.Dunlap@Sun.COM typedef struct idm_bufpat_s { 3249162SPeter.Dunlap@Sun.COM void *bufpat_idb; 3259162SPeter.Dunlap@Sun.COM uint32_t bufpat_bufmagic; 3269162SPeter.Dunlap@Sun.COM uint32_t bufpat_offset; 3279162SPeter.Dunlap@Sun.COM } idm_bufpat_t; 3289162SPeter.Dunlap@Sun.COM 3297978SPeter.Dunlap@Sun.COM #define PDU_MAX_IOVLEN 12 3307978SPeter.Dunlap@Sun.COM #define IDM_PDU_MAGIC 0x49504455 /* "IPDU" */ 3317978SPeter.Dunlap@Sun.COM 3327978SPeter.Dunlap@Sun.COM typedef struct idm_pdu_s { 3337978SPeter.Dunlap@Sun.COM uint32_t isp_magic; /* "IPDU" */ 3347978SPeter.Dunlap@Sun.COM 3357978SPeter.Dunlap@Sun.COM /* 3367978SPeter.Dunlap@Sun.COM * Internal - Order is vital. idm_tx_link *must* be the second 3377978SPeter.Dunlap@Sun.COM * element in this structure for proper TX PDU ordering. 3387978SPeter.Dunlap@Sun.COM */ 3397978SPeter.Dunlap@Sun.COM list_node_t idm_tx_link; 3407978SPeter.Dunlap@Sun.COM 3417978SPeter.Dunlap@Sun.COM list_node_t isp_client_lnd; 3427978SPeter.Dunlap@Sun.COM 3437978SPeter.Dunlap@Sun.COM idm_conn_t *isp_ic; /* Must be set */ 3447978SPeter.Dunlap@Sun.COM iscsi_hdr_t *isp_hdr; 3457978SPeter.Dunlap@Sun.COM uint_t isp_hdrlen; 3467978SPeter.Dunlap@Sun.COM uint8_t *isp_data; 3477978SPeter.Dunlap@Sun.COM uint_t isp_datalen; 3487978SPeter.Dunlap@Sun.COM 3497978SPeter.Dunlap@Sun.COM /* Transport header */ 3507978SPeter.Dunlap@Sun.COM void *isp_transport_hdr; 3517978SPeter.Dunlap@Sun.COM uint32_t isp_transport_hdrlen; 3527978SPeter.Dunlap@Sun.COM void *isp_transport_private; 3537978SPeter.Dunlap@Sun.COM 3547978SPeter.Dunlap@Sun.COM /* 3557978SPeter.Dunlap@Sun.COM * isp_data is used for sending SCSI status, NOP, text, scsi and 3567978SPeter.Dunlap@Sun.COM * non-scsi data. Data is received using isp_iov and isp_iovlen 3577978SPeter.Dunlap@Sun.COM * to support data over multiple buffers. 3587978SPeter.Dunlap@Sun.COM */ 3597978SPeter.Dunlap@Sun.COM void *isp_private; 3607978SPeter.Dunlap@Sun.COM idm_pdu_cb_t *isp_callback; 3617978SPeter.Dunlap@Sun.COM idm_status_t isp_status; 3627978SPeter.Dunlap@Sun.COM 3637978SPeter.Dunlap@Sun.COM /* 3647978SPeter.Dunlap@Sun.COM * The following four elements are only used in 3657978SPeter.Dunlap@Sun.COM * idm_sorecv_scsidata() currently. 3667978SPeter.Dunlap@Sun.COM */ 3677978SPeter.Dunlap@Sun.COM struct iovec isp_iov[PDU_MAX_IOVLEN]; 3687978SPeter.Dunlap@Sun.COM int isp_iovlen; 3697978SPeter.Dunlap@Sun.COM idm_buf_t *isp_sorx_buf; 3707978SPeter.Dunlap@Sun.COM 3717978SPeter.Dunlap@Sun.COM /* Implementation data for idm_pdu_alloc and sorx PDU cache */ 3727978SPeter.Dunlap@Sun.COM uint32_t isp_flags; 3737978SPeter.Dunlap@Sun.COM uint_t isp_hdrbuflen; 3747978SPeter.Dunlap@Sun.COM uint_t isp_databuflen; 375*12372SPriya.Krishnan@Sun.COM time_t isp_queue_time; 3767978SPeter.Dunlap@Sun.COM } idm_pdu_t; 3777978SPeter.Dunlap@Sun.COM 3787978SPeter.Dunlap@Sun.COM /* 3797978SPeter.Dunlap@Sun.COM * This "generic" object is used when removing an item from the ic_tx_list 3807978SPeter.Dunlap@Sun.COM * in order to determine whether it's an idm_pdu_t or an idm_buf_t 3817978SPeter.Dunlap@Sun.COM */ 3827978SPeter.Dunlap@Sun.COM 3837978SPeter.Dunlap@Sun.COM typedef struct { 3847978SPeter.Dunlap@Sun.COM uint32_t idm_tx_obj_magic; 3857978SPeter.Dunlap@Sun.COM /* 3867978SPeter.Dunlap@Sun.COM * idm_tx_link *must* be the second element in this structure. 3877978SPeter.Dunlap@Sun.COM */ 3887978SPeter.Dunlap@Sun.COM list_node_t idm_tx_link; 3897978SPeter.Dunlap@Sun.COM } idm_tx_obj_t; 3907978SPeter.Dunlap@Sun.COM 3917978SPeter.Dunlap@Sun.COM 3927978SPeter.Dunlap@Sun.COM #define IDM_PDU_OPCODE(PDU) \ 3937978SPeter.Dunlap@Sun.COM ((PDU)->isp_hdr->opcode & ISCSI_OPCODE_MASK) 3947978SPeter.Dunlap@Sun.COM 3957978SPeter.Dunlap@Sun.COM #define IDM_PDU_ALLOC 0x00000001 3967978SPeter.Dunlap@Sun.COM #define IDM_PDU_ADDL_HDR 0x00000002 3977978SPeter.Dunlap@Sun.COM #define IDM_PDU_ADDL_DATA 0x00000004 3987978SPeter.Dunlap@Sun.COM #define IDM_PDU_LOGIN_TX 0x00000008 39911081SPriya.Krishnan@Sun.COM #define IDM_PDU_SET_STATSN 0x00000010 40011081SPriya.Krishnan@Sun.COM #define IDM_PDU_ADVANCE_STATSN 0x00000020 4017978SPeter.Dunlap@Sun.COM 4027978SPeter.Dunlap@Sun.COM #define OSD_EXT_CDB_AHSLEN (200 - 15) 4037978SPeter.Dunlap@Sun.COM #define BIDI_AHS_LENGTH 5 4047978SPeter.Dunlap@Sun.COM #define IDM_SORX_CACHE_AHSLEN \ 4057978SPeter.Dunlap@Sun.COM (((OSD_EXT_CDB_AHSLEN + 3) + \ 4067978SPeter.Dunlap@Sun.COM (BIDI_AHS_LENGTH + 3)) / sizeof (uint32_t)) 4077978SPeter.Dunlap@Sun.COM #define IDM_SORX_CACHE_HDRLEN (sizeof (iscsi_hdr_t) + IDM_SORX_CACHE_AHSLEN) 4087978SPeter.Dunlap@Sun.COM 4097978SPeter.Dunlap@Sun.COM /* 4107978SPeter.Dunlap@Sun.COM * ID pool 4117978SPeter.Dunlap@Sun.COM */ 4127978SPeter.Dunlap@Sun.COM 4137978SPeter.Dunlap@Sun.COM #define IDM_IDPOOL_MAGIC 0x4944504C /* IDPL */ 4147978SPeter.Dunlap@Sun.COM #define IDM_IDPOOL_MIN_SIZE 64 /* Number of IDs to begin with */ 4157978SPeter.Dunlap@Sun.COM #define IDM_IDPOOL_MAX_SIZE 64 * 1024 4167978SPeter.Dunlap@Sun.COM 4177978SPeter.Dunlap@Sun.COM typedef struct idm_idpool { 4187978SPeter.Dunlap@Sun.COM uint32_t id_magic; 4197978SPeter.Dunlap@Sun.COM kmutex_t id_mutex; 4207978SPeter.Dunlap@Sun.COM uint8_t *id_pool; 4217978SPeter.Dunlap@Sun.COM uint32_t id_size; 4227978SPeter.Dunlap@Sun.COM uint8_t id_bit; 4237978SPeter.Dunlap@Sun.COM uint8_t id_bit_idx; 4247978SPeter.Dunlap@Sun.COM uint32_t id_idx; 4257978SPeter.Dunlap@Sun.COM uint32_t id_idx_msk; 4267978SPeter.Dunlap@Sun.COM uint32_t id_free_counter; 4277978SPeter.Dunlap@Sun.COM uint32_t id_max_free_counter; 4287978SPeter.Dunlap@Sun.COM } idm_idpool_t; 4297978SPeter.Dunlap@Sun.COM 4307978SPeter.Dunlap@Sun.COM /* 4317978SPeter.Dunlap@Sun.COM * Global IDM state structure 4327978SPeter.Dunlap@Sun.COM */ 4337978SPeter.Dunlap@Sun.COM typedef struct { 4347978SPeter.Dunlap@Sun.COM kmutex_t idm_global_mutex; 4357978SPeter.Dunlap@Sun.COM taskq_t *idm_global_taskq; 4367978SPeter.Dunlap@Sun.COM kthread_t *idm_wd_thread; 4377978SPeter.Dunlap@Sun.COM kt_did_t idm_wd_thread_did; 4387978SPeter.Dunlap@Sun.COM boolean_t idm_wd_thread_running; 4397978SPeter.Dunlap@Sun.COM kcondvar_t idm_wd_cv; 4407978SPeter.Dunlap@Sun.COM list_t idm_tgt_svc_list; 4417978SPeter.Dunlap@Sun.COM kcondvar_t idm_tgt_svc_cv; 4427978SPeter.Dunlap@Sun.COM list_t idm_tgt_conn_list; 4437978SPeter.Dunlap@Sun.COM int idm_tgt_conn_count; 4447978SPeter.Dunlap@Sun.COM list_t idm_ini_conn_list; 4457978SPeter.Dunlap@Sun.COM kmem_cache_t *idm_buf_cache; 4467978SPeter.Dunlap@Sun.COM kmem_cache_t *idm_task_cache; 4477978SPeter.Dunlap@Sun.COM krwlock_t idm_taskid_table_lock; 4487978SPeter.Dunlap@Sun.COM idm_task_t **idm_taskid_table; 4497978SPeter.Dunlap@Sun.COM uint32_t idm_taskid_next; 4507978SPeter.Dunlap@Sun.COM uint32_t idm_taskid_max; 4517978SPeter.Dunlap@Sun.COM idm_idpool_t idm_conn_id_pool; 4527978SPeter.Dunlap@Sun.COM kmem_cache_t *idm_sotx_pdu_cache; 4537978SPeter.Dunlap@Sun.COM kmem_cache_t *idm_sorx_pdu_cache; 4549247SPeter.Dunlap@Sun.COM kmem_cache_t *idm_so_128k_buf_cache; 4557978SPeter.Dunlap@Sun.COM } idm_global_t; 4567978SPeter.Dunlap@Sun.COM 4577978SPeter.Dunlap@Sun.COM idm_global_t idm; /* Global state */ 4587978SPeter.Dunlap@Sun.COM 4597978SPeter.Dunlap@Sun.COM int 4607978SPeter.Dunlap@Sun.COM idm_idpool_create(idm_idpool_t *pool); 4617978SPeter.Dunlap@Sun.COM 4627978SPeter.Dunlap@Sun.COM void 4637978SPeter.Dunlap@Sun.COM idm_idpool_destroy(idm_idpool_t *pool); 4647978SPeter.Dunlap@Sun.COM 4657978SPeter.Dunlap@Sun.COM int 4667978SPeter.Dunlap@Sun.COM idm_idpool_alloc(idm_idpool_t *pool, uint16_t *id); 4677978SPeter.Dunlap@Sun.COM 4687978SPeter.Dunlap@Sun.COM void 4697978SPeter.Dunlap@Sun.COM idm_idpool_free(idm_idpool_t *pool, uint16_t id); 4707978SPeter.Dunlap@Sun.COM 4717978SPeter.Dunlap@Sun.COM void 4727978SPeter.Dunlap@Sun.COM idm_pdu_rx(idm_conn_t *ic, idm_pdu_t *pdu); 4737978SPeter.Dunlap@Sun.COM 4747978SPeter.Dunlap@Sun.COM void 4757978SPeter.Dunlap@Sun.COM idm_pdu_tx_forward(idm_conn_t *ic, idm_pdu_t *pdu); 4767978SPeter.Dunlap@Sun.COM 4777978SPeter.Dunlap@Sun.COM boolean_t 4787978SPeter.Dunlap@Sun.COM idm_pdu_rx_forward_ffp(idm_conn_t *ic, idm_pdu_t *pdu); 4797978SPeter.Dunlap@Sun.COM 4807978SPeter.Dunlap@Sun.COM void 4817978SPeter.Dunlap@Sun.COM idm_pdu_rx_forward(idm_conn_t *ic, idm_pdu_t *pdu); 4827978SPeter.Dunlap@Sun.COM 4837978SPeter.Dunlap@Sun.COM void 4847978SPeter.Dunlap@Sun.COM idm_pdu_tx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu); 4857978SPeter.Dunlap@Sun.COM 4867978SPeter.Dunlap@Sun.COM void 4877978SPeter.Dunlap@Sun.COM idm_pdu_rx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu); 4887978SPeter.Dunlap@Sun.COM 4897978SPeter.Dunlap@Sun.COM void idm_parse_login_rsp(idm_conn_t *ic, idm_pdu_t *logout_req_pdu, 4907978SPeter.Dunlap@Sun.COM boolean_t rx); 4917978SPeter.Dunlap@Sun.COM 4927978SPeter.Dunlap@Sun.COM void idm_parse_logout_req(idm_conn_t *ic, idm_pdu_t *logout_req_pdu, 4937978SPeter.Dunlap@Sun.COM boolean_t rx); 4947978SPeter.Dunlap@Sun.COM 4957978SPeter.Dunlap@Sun.COM void idm_parse_logout_rsp(idm_conn_t *ic, idm_pdu_t *login_rsp_pdu, 4967978SPeter.Dunlap@Sun.COM boolean_t rx); 4977978SPeter.Dunlap@Sun.COM 4987978SPeter.Dunlap@Sun.COM idm_status_t idm_svc_conn_create(idm_svc_t *is, idm_transport_type_t type, 4997978SPeter.Dunlap@Sun.COM idm_conn_t **ic_result); 5007978SPeter.Dunlap@Sun.COM 5017978SPeter.Dunlap@Sun.COM void idm_svc_conn_destroy(idm_conn_t *ic); 5027978SPeter.Dunlap@Sun.COM 5037978SPeter.Dunlap@Sun.COM idm_status_t idm_ini_conn_finish(idm_conn_t *ic); 5047978SPeter.Dunlap@Sun.COM 5057978SPeter.Dunlap@Sun.COM idm_status_t idm_tgt_conn_finish(idm_conn_t *ic); 5067978SPeter.Dunlap@Sun.COM 5077978SPeter.Dunlap@Sun.COM idm_conn_t *idm_conn_create_common(idm_conn_type_t conn_type, 5087978SPeter.Dunlap@Sun.COM idm_transport_type_t tt, idm_conn_ops_t *conn_ops); 5097978SPeter.Dunlap@Sun.COM 5107978SPeter.Dunlap@Sun.COM void idm_conn_destroy_common(idm_conn_t *ic); 5117978SPeter.Dunlap@Sun.COM 5127978SPeter.Dunlap@Sun.COM void idm_conn_close(idm_conn_t *ic); 5137978SPeter.Dunlap@Sun.COM 5147978SPeter.Dunlap@Sun.COM uint32_t idm_cid_alloc(void); 5157978SPeter.Dunlap@Sun.COM 5167978SPeter.Dunlap@Sun.COM void idm_cid_free(uint32_t cid); 5177978SPeter.Dunlap@Sun.COM 5187978SPeter.Dunlap@Sun.COM uint32_t idm_crc32c(void *address, unsigned long length); 5197978SPeter.Dunlap@Sun.COM 5207978SPeter.Dunlap@Sun.COM uint32_t idm_crc32c_continued(void *address, unsigned long length, 5217978SPeter.Dunlap@Sun.COM uint32_t crc); 5227978SPeter.Dunlap@Sun.COM 5237978SPeter.Dunlap@Sun.COM void idm_listbuf_insert(list_t *lst, idm_buf_t *buf); 5247978SPeter.Dunlap@Sun.COM 5257978SPeter.Dunlap@Sun.COM idm_conn_t *idm_lookup_conn(uint8_t *isid, uint16_t tsih, uint16_t cid); 5267978SPeter.Dunlap@Sun.COM 5277978SPeter.Dunlap@Sun.COM #ifdef __cplusplus 5287978SPeter.Dunlap@Sun.COM } 5297978SPeter.Dunlap@Sun.COM #endif 5307978SPeter.Dunlap@Sun.COM 5317978SPeter.Dunlap@Sun.COM #endif /* _IDM_IMPL_H_ */ 532