xref: /onnv-gate/usr/src/uts/common/sys/idm/idm_impl.h (revision 12372:1d6e0c9ff22e)
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