6811333 Remove prom_printf() message in emlxs driver
[opensolaris.git] / usr / src / uts / common / sys / idm / idm_impl.h
blobe18472a18d2443ec7839a3178f951e2c939d81ab
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 #ifndef _IDM_IMPL_H_
26 #define _IDM_IMPL_H_
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
32 #include <sys/avl.h>
33 #include <sys/socket_impl.h>
36 * IDM lock order:
38 * idm_taskid_table_lock, idm_task_t.idt_mutex
41 #define CF_LOGIN_READY 0x00000001
42 #define CF_INITIAL_LOGIN 0x00000002
43 #define CF_ERROR 0x80000000
45 typedef enum {
46 CONN_TYPE_INI = 1,
47 CONN_TYPE_TGT
48 } idm_conn_type_t;
51 * Watchdog interval in seconds
53 #define IDM_WD_INTERVAL 5
56 * Timeout period before a TRANSPORT_FAIL event is generated in seconds
57 * if the connection is idle.
59 #define IDM_TRANSPORT_FAIL_IDLE_TIMEOUT 30
62 * IDM reference count structure. Audit code is shamelessly adapted
63 * from CIFS server.
66 #define REFCNT_AUDIT_STACK_DEPTH 16
67 #define REFCNT_AUDIT_BUF_MAX_REC 16
69 typedef struct {
70 uint32_t anr_refcnt;
71 int anr_depth;
72 pc_t anr_stack[REFCNT_AUDIT_STACK_DEPTH];
73 } refcnt_audit_record_t;
75 typedef struct {
76 int anb_index;
77 int anb_max_index;
78 refcnt_audit_record_t anb_records[REFCNT_AUDIT_BUF_MAX_REC];
79 } refcnt_audit_buf_t;
81 #define REFCNT_AUDIT(_rf_) { \
82 refcnt_audit_record_t *anr; \
84 anr = (_rf_)->ir_audit_buf.anb_records; \
85 anr += (_rf_)->ir_audit_buf.anb_index; \
86 (_rf_)->ir_audit_buf.anb_index++; \
87 (_rf_)->ir_audit_buf.anb_index &= \
88 (_rf_)->ir_audit_buf.anb_max_index; \
89 anr->anr_refcnt = (_rf_)->ir_refcnt; \
90 anr->anr_depth = getpcstack(anr->anr_stack, \
91 REFCNT_AUDIT_STACK_DEPTH); \
94 struct idm_refcnt_s;
96 typedef void (idm_refcnt_cb_t)(void *ref_obj);
98 typedef enum {
99 REF_NOWAIT,
100 REF_WAIT_SYNC,
101 REF_WAIT_ASYNC
102 } idm_refcnt_wait_t;
104 typedef struct idm_refcnt_s {
105 int ir_refcnt;
106 void *ir_referenced_obj;
107 idm_refcnt_wait_t ir_waiting;
108 kmutex_t ir_mutex;
109 kcondvar_t ir_cv;
110 idm_refcnt_cb_t *ir_cb;
111 refcnt_audit_buf_t ir_audit_buf;
112 } idm_refcnt_t;
115 * connection parameters - These parameters would be populated at
116 * connection create, or during key-value negotiation at login
118 typedef struct idm_conn_params_s {
119 uint32_t max_dataseglen;
120 } idm_conn_param_t;
122 typedef struct idm_svc_s {
123 list_node_t is_list_node;
124 kmutex_t is_mutex;
125 kcondvar_t is_cv;
126 kmutex_t is_count_mutex;
127 kcondvar_t is_count_cv;
128 idm_refcnt_t is_refcnt;
129 int is_online;
130 /* transport-specific service components */
131 void *is_so_svc;
132 void *is_iser_svc;
133 idm_svc_req_t is_svc_req;
134 } idm_svc_t;
136 typedef struct idm_conn_s {
137 list_node_t ic_list_node;
138 void *ic_handle;
139 idm_refcnt_t ic_refcnt;
140 idm_svc_t *ic_svc_binding; /* Target conn. only */
141 idm_sockaddr_t ic_ini_dst_addr;
142 struct sockaddr_storage ic_laddr; /* conn local address */
143 struct sockaddr_storage ic_raddr; /* conn remote address */
144 idm_conn_state_t ic_state;
145 idm_conn_state_t ic_last_state;
146 sm_audit_buf_t ic_state_audit;
147 kmutex_t ic_state_mutex;
148 kcondvar_t ic_state_cv;
149 uint32_t ic_state_flags;
150 timeout_id_t ic_state_timeout;
151 struct idm_conn_s *ic_reinstate_conn; /* For conn reinst. */
152 struct idm_conn_s *ic_logout_conn; /* For other conn logout */
153 taskq_t *ic_state_taskq;
154 int ic_pdu_events;
155 boolean_t ic_login_info_valid;
156 boolean_t ic_rdma_extensions;
157 uint16_t ic_login_cid;
159 kmutex_t ic_mutex;
160 kcondvar_t ic_cv;
161 idm_status_t ic_conn_sm_status;
163 boolean_t ic_ffp;
164 uint32_t ic_internal_cid;
166 uint32_t ic_conn_flags;
167 idm_conn_type_t ic_conn_type;
168 idm_conn_ops_t ic_conn_ops;
169 idm_transport_ops_t *ic_transport_ops;
170 idm_transport_type_t ic_transport_type;
171 int ic_transport_hdrlen;
172 void *ic_transport_private;
173 idm_conn_param_t ic_conn_params;
175 * Save client callback to interpose idm callback
177 idm_pdu_cb_t *ic_client_callback;
178 clock_t ic_timestamp;
179 } idm_conn_t;
181 #define IDM_CONN_HEADER_DIGEST 0x00000001
182 #define IDM_CONN_DATA_DIGEST 0x00000002
183 #define IDM_CONN_USE_SCOREBOARD 0x00000004
185 #define IDM_CONN_ISINI(ICI_IC) ((ICI_IC)->ic_conn_type == CONN_TYPE_INI)
186 #define IDM_CONN_ISTGT(ICI_IC) ((ICI_IC)->ic_conn_type == CONN_TYPE_TGT)
189 * An IDM target task can transfer data using multiple buffers. The task
190 * will maintain a list of buffers, and each buffer will contain the relative
191 * offset of the transfer and a pointer to the next buffer in the list.
193 * Note on client private data:
194 * idt_private is intended to be a pointer to some sort of client-
195 * specific state.
197 * idt_client_handle is a more generic client-private piece of data that can
198 * be used by the client for the express purpose of task lookup. The driving
199 * use case for this is for the client to store the initiator task tag for
200 * a given task so that it may be more easily retrieved for task management.
202 * The key take away here is that clients should never call
203 * idm_task_find_by_handle in the performance path.
205 * An initiator will require only one buffer per task, the offset will be 0.
208 typedef struct idm_task_s {
209 idm_conn_t *idt_ic; /* Associated connection */
210 /* connection type is in idt_ic->ic_conn_type */
211 kmutex_t idt_mutex;
212 void *idt_private; /* Client private data */
213 uintptr_t idt_client_handle; /* Client private */
214 uint32_t idt_tt; /* Task tag */
215 uint32_t idt_r2t_ttt; /* R2T Target Task tag */
216 idm_task_state_t idt_state;
217 idm_refcnt_t idt_refcnt;
220 * Statistics
222 int idt_tx_to_ini_start;
223 int idt_tx_to_ini_done;
224 int idt_rx_from_ini_start;
225 int idt_rx_from_ini_done;
227 uint32_t idt_exp_datasn; /* expected datasn */
228 uint32_t idt_exp_rttsn; /* expected rttsn */
229 list_t idt_inbufv; /* chunks of IN buffers */
230 list_t idt_outbufv; /* chunks of OUT buffers */
233 * Transport header, which describes this tasks remote tagged buffer
235 int idt_transport_hdrlen;
236 void *idt_transport_hdr;
237 } idm_task_t;
239 int idm_task_constructor(void *task_void, void *arg, int flags);
240 void idm_task_destructor(void *task_void, void *arg);
242 #define IDM_TASKIDS_MAX 16384
243 #define IDM_BUF_MAGIC 0x49425546 /* "IBUF" */
245 /* Protect with task mutex */
246 typedef struct idm_buf_s {
247 uint32_t idb_magic; /* "IBUF" */
250 * Note: idm_tx_link *must* be the second element in the list for
251 * proper TX PDU ordering.
253 list_node_t idm_tx_link; /* link in a list of TX objects */
255 list_node_t idb_buflink; /* link in a multi-buffer data xfer */
256 idm_conn_t *idb_ic; /* Associated connection */
257 void *idb_buf; /* data */
258 uint64_t idb_buflen; /* length of buffer */
259 size_t idb_bufoffset; /* offset in a multi-buffer xfer */
260 boolean_t idb_bufalloc; /* true if alloc'd in idm_buf_alloc */
262 * DataPDUInOrder=Yes, so to track that the PDUs in a sequence are sent
263 * in continuously increasing address order, check that offsets for a
264 * single buffer xfer are in order.
266 uint32_t idb_exp_offset;
267 size_t idb_xfer_len; /* Current requested xfer len */
268 void *idb_buf_private; /* transport-specific buf handle */
269 void *idb_reg_private; /* transport-specific reg handle */
270 idm_buf_cb_t *idb_buf_cb; /* Data Completion Notify, tgt only */
271 void *idb_cb_arg; /* Client private data */
272 idm_task_t *idb_task_binding;
273 boolean_t idb_in_transport;
274 boolean_t idb_tx_thread; /* Sockets only */
275 iscsi_hdr_t idb_data_hdr_tmpl; /* Sockets only */
276 idm_status_t idb_status;
277 } idm_buf_t;
279 #define PDU_MAX_IOVLEN 12
280 #define IDM_PDU_MAGIC 0x49504455 /* "IPDU" */
282 typedef struct idm_pdu_s {
283 uint32_t isp_magic; /* "IPDU" */
286 * Internal - Order is vital. idm_tx_link *must* be the second
287 * element in this structure for proper TX PDU ordering.
289 list_node_t idm_tx_link;
291 list_node_t isp_client_lnd;
293 idm_conn_t *isp_ic; /* Must be set */
294 iscsi_hdr_t *isp_hdr;
295 uint_t isp_hdrlen;
296 uint8_t *isp_data;
297 uint_t isp_datalen;
299 /* Transport header */
300 void *isp_transport_hdr;
301 uint32_t isp_transport_hdrlen;
302 void *isp_transport_private;
305 * isp_data is used for sending SCSI status, NOP, text, scsi and
306 * non-scsi data. Data is received using isp_iov and isp_iovlen
307 * to support data over multiple buffers.
309 void *isp_private;
310 idm_pdu_cb_t *isp_callback;
311 idm_status_t isp_status;
314 * The following four elements are only used in
315 * idm_sorecv_scsidata() currently.
317 struct iovec isp_iov[PDU_MAX_IOVLEN];
318 int isp_iovlen;
319 idm_buf_t *isp_sorx_buf;
321 /* Implementation data for idm_pdu_alloc and sorx PDU cache */
322 uint32_t isp_flags;
323 uint_t isp_hdrbuflen;
324 uint_t isp_databuflen;
325 } idm_pdu_t;
328 * This "generic" object is used when removing an item from the ic_tx_list
329 * in order to determine whether it's an idm_pdu_t or an idm_buf_t
332 typedef struct {
333 uint32_t idm_tx_obj_magic;
335 * idm_tx_link *must* be the second element in this structure.
337 list_node_t idm_tx_link;
338 } idm_tx_obj_t;
341 #define IDM_PDU_OPCODE(PDU) \
342 ((PDU)->isp_hdr->opcode & ISCSI_OPCODE_MASK)
344 #define IDM_PDU_ALLOC 0x00000001
345 #define IDM_PDU_ADDL_HDR 0x00000002
346 #define IDM_PDU_ADDL_DATA 0x00000004
347 #define IDM_PDU_LOGIN_TX 0x00000008
349 #define OSD_EXT_CDB_AHSLEN (200 - 15)
350 #define BIDI_AHS_LENGTH 5
351 #define IDM_SORX_CACHE_AHSLEN \
352 (((OSD_EXT_CDB_AHSLEN + 3) + \
353 (BIDI_AHS_LENGTH + 3)) / sizeof (uint32_t))
354 #define IDM_SORX_CACHE_HDRLEN (sizeof (iscsi_hdr_t) + IDM_SORX_CACHE_AHSLEN)
357 * ID pool
360 #define IDM_IDPOOL_MAGIC 0x4944504C /* IDPL */
361 #define IDM_IDPOOL_MIN_SIZE 64 /* Number of IDs to begin with */
362 #define IDM_IDPOOL_MAX_SIZE 64 * 1024
364 typedef struct idm_idpool {
365 uint32_t id_magic;
366 kmutex_t id_mutex;
367 uint8_t *id_pool;
368 uint32_t id_size;
369 uint8_t id_bit;
370 uint8_t id_bit_idx;
371 uint32_t id_idx;
372 uint32_t id_idx_msk;
373 uint32_t id_free_counter;
374 uint32_t id_max_free_counter;
375 } idm_idpool_t;
378 * Global IDM state structure
380 typedef struct {
381 kmutex_t idm_global_mutex;
382 taskq_t *idm_global_taskq;
383 kthread_t *idm_wd_thread;
384 kt_did_t idm_wd_thread_did;
385 boolean_t idm_wd_thread_running;
386 kcondvar_t idm_wd_cv;
387 list_t idm_tgt_svc_list;
388 kcondvar_t idm_tgt_svc_cv;
389 list_t idm_tgt_conn_list;
390 int idm_tgt_conn_count;
391 list_t idm_ini_conn_list;
392 kmem_cache_t *idm_buf_cache;
393 kmem_cache_t *idm_task_cache;
394 krwlock_t idm_taskid_table_lock;
395 idm_task_t **idm_taskid_table;
396 uint32_t idm_taskid_next;
397 uint32_t idm_taskid_max;
398 idm_idpool_t idm_conn_id_pool;
399 kmem_cache_t *idm_sotx_pdu_cache;
400 kmem_cache_t *idm_sorx_pdu_cache;
401 } idm_global_t;
403 idm_global_t idm; /* Global state */
406 idm_idpool_create(idm_idpool_t *pool);
408 void
409 idm_idpool_destroy(idm_idpool_t *pool);
412 idm_idpool_alloc(idm_idpool_t *pool, uint16_t *id);
414 void
415 idm_idpool_free(idm_idpool_t *pool, uint16_t id);
417 void
418 idm_pdu_rx(idm_conn_t *ic, idm_pdu_t *pdu);
420 void
421 idm_pdu_tx_forward(idm_conn_t *ic, idm_pdu_t *pdu);
423 boolean_t
424 idm_pdu_rx_forward_ffp(idm_conn_t *ic, idm_pdu_t *pdu);
426 void
427 idm_pdu_rx_forward(idm_conn_t *ic, idm_pdu_t *pdu);
429 void
430 idm_pdu_tx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu);
432 void
433 idm_pdu_rx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu);
435 void idm_parse_login_rsp(idm_conn_t *ic, idm_pdu_t *logout_req_pdu,
436 boolean_t rx);
438 void idm_parse_logout_req(idm_conn_t *ic, idm_pdu_t *logout_req_pdu,
439 boolean_t rx);
441 void idm_parse_logout_rsp(idm_conn_t *ic, idm_pdu_t *login_rsp_pdu,
442 boolean_t rx);
444 idm_status_t idm_svc_conn_create(idm_svc_t *is, idm_transport_type_t type,
445 idm_conn_t **ic_result);
447 void idm_svc_conn_destroy(idm_conn_t *ic);
449 idm_status_t idm_ini_conn_finish(idm_conn_t *ic);
451 idm_status_t idm_tgt_conn_finish(idm_conn_t *ic);
453 idm_conn_t *idm_conn_create_common(idm_conn_type_t conn_type,
454 idm_transport_type_t tt, idm_conn_ops_t *conn_ops);
456 void idm_conn_destroy_common(idm_conn_t *ic);
458 void idm_conn_close(idm_conn_t *ic);
460 uint32_t idm_cid_alloc(void);
462 void idm_cid_free(uint32_t cid);
464 uint32_t idm_crc32c(void *address, unsigned long length);
466 uint32_t idm_crc32c_continued(void *address, unsigned long length,
467 uint32_t crc);
469 void idm_listbuf_insert(list_t *lst, idm_buf_t *buf);
471 int idm_task_compare(const void *v1, const void *v2);
473 idm_conn_t *idm_lookup_conn(uint8_t *isid, uint16_t tsih, uint16_t cid);
475 #ifdef __cplusplus
477 #endif
479 #endif /* _IDM_IMPL_H_ */