1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2013 by Delphix. All rights reserved.
24 */
25 #ifndef _STMF_IMPL_H
26 #define _STMF_IMPL_H
27
28 #include <sys/stmf_defines.h>
29 #include <sys/stmf_ioctl.h>
30
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34
35 typedef uint32_t stmf_event_handle_t;
36 #define STMF_MAX_NUM_EVENTS (sizeof (stmf_event_handle_t) * 8)
37 #define STMF_EVENT_ADD(h, e) (atomic_or_32(&(h), \
38 ((uint32_t)1) << (e)))
39 #define STMF_EVENT_REMOVE(h, e) (atomic_and_32(&(h), \
40 ~(((uint32_t)1) << (e))))
41 #define STMF_EVENT_ENABLED(h, e) (((h) & ((uint32_t)1) << (e)) != 0)
42 #define STMF_EVENT_CLEAR_ALL(h) ((h) = 0)
43 #define STMF_EVENT_ALLOC_HANDLE(h) ((h) = 0)
44 #define STMF_EVENT_FREE_HANDLE(h) ((h) = 0)
45
46 #define STMF_TGT_NAME_LEN 256
47 #define STMF_GUID_INPUT 32
48
49 #define STMF_UPDATE_KSTAT_IO(kip, dbuf) \
50 if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) { \
51 kip->reads++; \
52 kip->nread += dbuf->db_data_size; \
53 } else { \
54 kip->writes++; \
55 kip->nwritten += dbuf->db_data_size; \
56 }
57
58 struct stmf_i_scsi_task;
59 struct stmf_itl_data;
60
61 typedef struct stmf_i_lu_provider {
62 stmf_lu_provider_t *ilp_lp;
63 uint32_t ilp_alloc_size;
64 uint32_t ilp_nlus; /* # LUNs being exported */
65 uint32_t ilp_cb_in_progress:1,
66 ilp_rsvd:31;
67 struct stmf_i_lu_provider *ilp_next;
68 struct stmf_pp_data *ilp_ppd;
69 } stmf_i_lu_provider_t;
70
71 typedef struct stmf_i_lu {
72 stmf_lu_t *ilu_lu;
73 uint32_t ilu_alloc_size;
74 uint32_t ilu_flags;
75 uint32_t ilu_ref_cnt;
76 uint8_t ilu_state;
77 uint8_t ilu_prev_state;
78 uint8_t ilu_access;
79 uint8_t ilu_alua;
80 stmf_event_handle_t ilu_event_hdl;
81 struct stmf_i_lu *ilu_next;
82 struct stmf_i_lu *ilu_prev;
83 char *ilu_alias;
84 char ilu_ascii_hex_guid[STMF_GUID_INPUT + 1];
85 kmutex_t ilu_task_lock;
86 uint32_t ilu_task_cntr1;
87 uint32_t ilu_task_cntr2;
88 uint32_t *ilu_cur_task_cntr;
89 uint32_t ilu_ntasks; /* # of tasks in the ilu_task list */
90 uint32_t ilu_ntasks_free; /* # of tasks that are free */
91 uint32_t ilu_ntasks_min_free; /* # minimal free tasks */
92 uint32_t rsvd1;
93 uint32_t ilu_proxy_registered;
94 uint64_t ilu_reg_msgid;
95 struct stmf_i_scsi_task *ilu_tasks;
96 struct stmf_i_scsi_task *ilu_free_tasks;
97 struct stmf_itl_data *ilu_itl_list;
98 kstat_t *ilu_kstat_info;
99 kstat_t *ilu_kstat_io;
100 kmutex_t ilu_kstat_lock;
101 kcondvar_t ilu_offline_pending_cv;
102
103 /* point to the luid entry in stmf_state.stmf_luid_list */
104 void *ilu_luid;
105 } stmf_i_lu_t;
106
107 /*
108 * ilu_flags
109 */
110 #define ILU_STALL_DEREGISTER 0x0001
111 #define ILU_RESET_ACTIVE 0x0002
112
113 typedef struct stmf_i_port_provider {
114 stmf_port_provider_t *ipp_pp;
115 uint32_t ipp_alloc_size;
116 uint32_t ipp_npps;
117 uint32_t ipp_cb_in_progress:1,
118 ipp_rsvd:31;
119 struct stmf_i_port_provider *ipp_next;
120 struct stmf_pp_data *ipp_ppd;
121 } stmf_i_port_provider_t;
122
123 #define MAX_ILPORT 0x10000
124
125 typedef struct stmf_i_local_port {
126 stmf_local_port_t *ilport_lport;
127 uint32_t ilport_alloc_size;
128 uint32_t ilport_nsessions;
129 struct stmf_i_scsi_session *ilport_ss_list;
130 krwlock_t ilport_lock;
131 struct stmf_i_local_port *ilport_next;
132 struct stmf_i_local_port *ilport_prev;
133 uint8_t ilport_state;
134 uint8_t ilport_prev_state;
135 uint8_t ilport_standby;
136 uint8_t ilport_alua;
137 uint16_t ilport_rtpid; /* relative tpid */
138 uint16_t ilport_proxy_registered;
139 uint64_t ilport_reg_msgid;
140 uint8_t ilport_no_standby_lu;
141 uint32_t ilport_unexpected_comp;
142 stmf_event_handle_t ilport_event_hdl;
143 clock_t ilport_last_online_clock;
144 clock_t ilport_avg_interval;
145 uint32_t ilport_online_times;
146 uint32_t ilport_flags;
147 kstat_t *ilport_kstat_info;
148 kstat_t *ilport_kstat_io;
149 kmutex_t ilport_kstat_lock;
150 char ilport_kstat_tgt_name[STMF_TGT_NAME_LEN];
151 /* which target group this port belongs to in stmf_state.stmf_tg_list */
152 void *ilport_tg;
153 id_t ilport_instance;
154 /* XXX Need something to track all the remote ports also */
155 } stmf_i_local_port_t;
156
157 #define STMF_AVG_ONLINE_INTERVAL (30 * drv_usectohz(1000000))
158
159 #define MAX_IRPORT 0x10000
160
161 typedef struct stmf_i_remote_port {
162 struct scsi_devid_desc *irport_id;
163 kmutex_t irport_mutex;
164 int irport_refcnt;
165 id_t irport_instance;
166 avl_node_t irport_ln;
167 } stmf_i_remote_port_t;
168
169 /*
170 * ilport flags
171 */
172 #define ILPORT_FORCED_OFFLINE 0x01
173 #define ILPORT_SS_GOT_INITIAL_LUNS 0x02
174
175 typedef struct stmf_i_scsi_session {
176 stmf_scsi_session_t *iss_ss;
177 uint32_t iss_alloc_size;
178 uint32_t iss_flags;
179 stmf_i_remote_port_t *iss_irport;
180 struct stmf_i_scsi_session *iss_next;
181 /*
182 * Ideally we should maintain 2 maps. One would indicate a new map
183 * which will become available only upon receipt of a REPORT LUN
184 * cmd.
185 */
186 struct stmf_lun_map *iss_sm;
187 /*
188 * which host group the host of this session belongs to in
189 * stmf_state.stmf_hg_list
190 */
191 void *iss_hg;
192 krwlock_t *iss_lockp;
193 time_t iss_creation_time;
194 } stmf_i_scsi_session_t;
195
196 /*
197 * iss flags
198 */
199 #define ISS_LUN_INVENTORY_CHANGED 0x0001
200 #define ISS_RESET_ACTIVE 0x0002
201 #define ISS_BEING_CREATED 0x0004
202 #define ISS_GOT_INITIAL_LUNS 0x0008
203 #define ISS_EVENT_ACTIVE 0x0010
204 #define ISS_NULL_TPTID 0x0020
205
206 #define ITASK_MAX_NCMDS 14
207 #define ITASK_DEFAULT_POLL_TIMEOUT 0
208
209 #define ITASK_TASK_AUDIT_DEPTH 32 /* Must be a power of 2 */
210
211 typedef enum {
212 TE_UNDEFINED,
213 TE_TASK_START,
214 TE_XFER_START,
215 TE_XFER_DONE,
216 TE_SEND_STATUS,
217 TE_SEND_STATUS_DONE,
218 TE_TASK_FREE,
219 TE_TASK_ABORT,
220 TE_TASK_LPORT_ABORTED,
221 TE_TASK_LU_ABORTED,
222 TE_PROCESS_CMD
223 } task_audit_event_t;
224
225 #define CMD_OR_IOF_NA 0xffffffff
226
227 typedef struct stmf_task_audit_rec {
228 task_audit_event_t ta_event;
229 uint32_t ta_cmd_or_iof;
230 uint32_t ta_itask_flags;
231 stmf_data_buf_t *ta_dbuf;
232 timespec_t ta_timestamp;
233 } stmf_task_audit_rec_t;
234
235 struct stmf_worker;
236 typedef struct stmf_i_scsi_task {
237 scsi_task_t *itask_task;
238 uint32_t itask_alloc_size;
239 uint32_t itask_flags;
240 uint64_t itask_proxy_msg_id;
241 stmf_data_buf_t *itask_proxy_dbuf;
242 struct stmf_worker *itask_worker;
243 uint32_t *itask_ilu_task_cntr;
244 struct stmf_i_scsi_task *itask_worker_next;
245 struct stmf_i_scsi_task *itask_lu_next;
246 struct stmf_i_scsi_task *itask_lu_prev;
247 struct stmf_i_scsi_task *itask_lu_free_next;
248 struct stmf_i_scsi_task *itask_abort_next;
249 struct stmf_itl_data *itask_itl_datap;
250 clock_t itask_start_time; /* abort and normal */
251 /* For now we only support 4 parallel buffers. Should be enough. */
252 stmf_data_buf_t *itask_dbufs[4];
253 clock_t itask_poll_timeout;
254 uint8_t itask_cmd_stack[ITASK_MAX_NCMDS];
255 uint8_t itask_ncmds;
256 uint8_t itask_allocated_buf_map;
257 uint16_t itask_cdb_buf_size;
258
259 /* Task profile data */
260 hrtime_t itask_start_timestamp;
261 hrtime_t itask_done_timestamp;
262 hrtime_t itask_waitq_enter_timestamp;
263 hrtime_t itask_waitq_time;
264 hrtime_t itask_lu_read_time;
265 hrtime_t itask_lu_write_time;
266 hrtime_t itask_lport_read_time;
267 hrtime_t itask_lport_write_time;
268 uint64_t itask_read_xfer;
269 uint64_t itask_write_xfer;
270 kmutex_t itask_audit_mutex;
271 uint8_t itask_audit_index;
272 stmf_task_audit_rec_t itask_audit_records[ITASK_TASK_AUDIT_DEPTH];
273 } stmf_i_scsi_task_t;
274
275 #define ITASK_DEFAULT_ABORT_TIMEOUT 5
276
277 /*
278 * itask_flags
279 */
280 #define ITASK_IN_FREE_LIST 0x0001
281 #define ITASK_IN_TRANSITION 0x0002
282 #define ITASK_IN_WORKER_QUEUE 0x0004
283 #define ITASK_BEING_ABORTED 0x0008
284 #define ITASK_BEING_COMPLETED 0x0010
285 #define ITASK_KNOWN_TO_TGT_PORT 0x0020
286 #define ITASK_KNOWN_TO_LU 0x0040
287 #define ITASK_LU_ABORT_CALLED 0x0080
288 #define ITASK_TGT_PORT_ABORT_CALLED 0x0100
289 #define ITASK_DEFAULT_HANDLING 0x0200
290 #define ITASK_CAUSING_LU_RESET 0x0400
291 #define ITASK_CAUSING_TARGET_RESET 0x0800
292 #define ITASK_KSTAT_IN_RUNQ 0x1000
293 #define ITASK_PROXY_TASK 0x2000
294
295 /*
296 * itask cmds.
297 */
298 #define ITASK_CMD_MASK 0x1F
299 #define ITASK_CMD_BUF_NDX(cmd) (((uint8_t)(cmd)) >> 5)
300 #define ITASK_CMD_NEW_TASK 0x1
301 #define ITASK_CMD_DATA_XFER_DONE 0x2
302 #define ITASK_CMD_STATUS_DONE 0x3
303 #define ITASK_CMD_ABORT 0x4
304 #define ITASK_CMD_SEND_STATUS 0x5
305 #define ITASK_CMD_POLL 0x10
306 #define ITASK_CMD_POLL_LU (ITASK_CMD_POLL | 1)
307 #define ITASK_CMD_POLL_LPORT (ITASK_CMD_POLL | 2)
308
309 /*
310 * struct maintained on a per itl basis when the lu registers ITL handle.
311 */
312 typedef struct stmf_itl_data {
313 uint32_t itl_counter;
314 uint8_t itl_flags;
315 uint8_t itl_hdlrm_reason;
316 uint16_t itl_lun;
317 void *itl_handle;
318 struct stmf_i_lu *itl_ilu;
319 struct stmf_i_scsi_session *itl_session;
320 struct stmf_itl_data *itl_next;
321 } stmf_itl_data_t;
322
323 /*
324 * itl flags
325 */
326 #define STMF_ITL_BEING_TERMINATED 0x01
327
328 /*
329 * data structures to maintain provider private data.
330 */
331 typedef struct stmf_pp_data {
332 struct stmf_pp_data *ppd_next;
333 void *ppd_provider;
334 nvlist_t *ppd_nv;
335 uint32_t ppd_lu_provider:1,
336 ppd_port_provider:1,
337 ppd_rsvd:30;
338 uint32_t ppd_alloc_size;
339 uint64_t ppd_token;
340 char ppd_name[8];
341 } stmf_pp_data_t;
342
343 typedef struct stmf_worker {
344 kthread_t *worker_tid;
345 stmf_i_scsi_task_t *worker_task_head;
346 stmf_i_scsi_task_t *worker_task_tail;
347 stmf_i_scsi_task_t *worker_wait_head;
348 stmf_i_scsi_task_t *worker_wait_tail;
349 kmutex_t worker_lock;
350 kcondvar_t worker_cv;
351 uint32_t worker_flags;
352 uint32_t worker_queue_depth; /* ntasks cur queued */
353 uint32_t worker_max_qdepth_pu; /* maxqd / unit time */
354 uint32_t worker_max_sys_qdepth_pu; /* for all workers */
355 uint32_t worker_ref_count; /* # IOs referencing */
356 hrtime_t worker_signal_timestamp;
357 } stmf_worker_t;
358
359 /*
360 * worker flags
361 */
362 #define STMF_WORKER_STARTED 1
363 #define STMF_WORKER_ACTIVE 2
364 #define STMF_WORKER_TERMINATE 4
365
366 /*
367 * data struct for managing transfers.
368 */
369 typedef struct stmf_xfer_data {
370 uint32_t alloc_size; /* Including this struct */
371 uint32_t size_done;
372 uint32_t size_left;
373 uint8_t buf[4];
374 } stmf_xfer_data_t;
375
376 /*
377 * Define frequently used macros
378 */
379 #define TASK_TO_ITASK(x_task) \
380 ((stmf_i_scsi_task_t *)(x_task)->task_stmf_private)
381
382 void stmf_dlun_init();
383 stmf_status_t stmf_dlun_fini();
384 void stmf_worker_init();
385 stmf_status_t stmf_worker_fini();
386 void stmf_task_free(scsi_task_t *task);
387 void stmf_do_task_abort(scsi_task_t *task);
388 void stmf_do_itl_dereg(stmf_lu_t *lu, stmf_itl_data_t *itl,
389 uint8_t hdlrm_reason);
390 void stmf_generate_lu_event(stmf_i_lu_t *ilu, int eventid,
391 void *arg, uint32_t flags);
392 void stmf_generate_lport_event(stmf_i_local_port_t *ilport, int eventid,
393 void *arg, uint32_t flags);
394
395 #ifdef __cplusplus
396 }
397 #endif
398
399 #endif /* _STMF_IMPL_H */