xref: /illumos-gate/usr/src/uts/common/io/comstar/stmf/stmf_impl.h (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
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 	stmf_event_handle_t ilu_event_hdl;
79 	struct stmf_i_lu *ilu_next;
80 	struct stmf_i_lu *ilu_prev;
81 	char		*ilu_alias;
82 	char		ilu_ascii_hex_guid[STMF_GUID_INPUT + 1];
83 	kmutex_t	ilu_task_lock;
84 	uint32_t	ilu_task_cntr1;
85 	uint32_t	ilu_task_cntr2;
86 	uint32_t	*ilu_cur_task_cntr;
87 	uint32_t	ilu_ntasks;	 /* # of tasks in the ilu_task list */
88 	uint32_t	ilu_ntasks_free;	/* # of tasks that are free */
89 	uint32_t	ilu_ntasks_min_free; /* # minimal free tasks */
90 	struct stmf_i_scsi_task	*ilu_tasks;
91 	struct stmf_i_scsi_task *ilu_free_tasks;
92 	struct stmf_itl_data	*ilu_itl_list;
93 	kstat_t		*ilu_kstat_info;
94 	kstat_t		*ilu_kstat_io;
95 	kmutex_t	ilu_kstat_lock;
96 
97 	/* point to the luid entry in stmf_state.stmf_luid_list */
98 	void		*ilu_luid;
99 } stmf_i_lu_t;
100 
101 /*
102  * ilu_flags
103  */
104 #define	ILU_STALL_DEREGISTER		0x0001
105 #define	ILU_RESET_ACTIVE		0x0002
106 
107 typedef struct stmf_i_port_provider {
108 	stmf_port_provider_t	*ipp_pp;
109 	uint32_t		ipp_alloc_size;
110 	uint32_t		ipp_npps;
111 	uint32_t		ipp_cb_in_progress:1,
112 				ipp_rsvd:31;
113 	struct stmf_i_port_provider *ipp_next;
114 	struct stmf_pp_data	*ipp_ppd;
115 } stmf_i_port_provider_t;
116 
117 typedef struct stmf_i_local_port {
118 	stmf_local_port_t	*ilport_lport;
119 	uint32_t		ilport_alloc_size;
120 	uint32_t		ilport_nsessions;
121 	struct stmf_i_scsi_session *ilport_ss_list;
122 	krwlock_t		ilport_lock;
123 	struct stmf_i_local_port *ilport_next;
124 	struct stmf_i_local_port *ilport_prev;
125 	uint8_t			ilport_state;
126 	uint8_t			ilport_prev_state;
127 	uint16_t		ilport_rtpid; /* relative tpid */
128 	stmf_event_handle_t	ilport_event_hdl;
129 	clock_t			ilport_last_online_clock;
130 	clock_t			ilport_avg_interval;
131 	uint32_t		ilport_online_times;
132 	uint32_t		ilport_flags;
133 	kstat_t			*ilport_kstat_info;
134 	kstat_t			*ilport_kstat_io;
135 	kmutex_t		ilport_kstat_lock;
136 	char			ilport_kstat_tgt_name[STMF_TGT_NAME_LEN];
137 	/* which target group this port belongs to in stmf_state.stmf_tg_list */
138 	void			*ilport_tg;
139 	/* XXX Need something to track all the remote ports also */
140 } stmf_i_local_port_t;
141 
142 #define	STMF_AVG_ONLINE_INTERVAL	(30 * drv_usectohz(1000000))
143 
144 /*
145  * ilport flags
146  */
147 #define	ILPORT_FORCED_OFFLINE		0x01
148 #define	ILPORT_SS_GOT_INITIAL_LUNS	0x02
149 
150 typedef struct stmf_i_scsi_session {
151 	stmf_scsi_session_t	*iss_ss;
152 	uint32_t		iss_alloc_size;
153 	uint32_t		iss_flags;
154 	struct stmf_i_scsi_session *iss_next;
155 	/*
156 	 * Ideally we should maintain 2 maps. One would indicate a new map
157 	 * which will become available only upon receipt of a REPORT LUN
158 	 * cmd.
159 	 */
160 	struct stmf_lun_map	*iss_sm;
161 	/*
162 	 * which host group the host of this session belongs to in
163 	 * stmf_state.stmf_hg_list
164 	 */
165 	void			*iss_hg;
166 	krwlock_t		*iss_lockp;
167 	time_t			iss_creation_time;
168 } stmf_i_scsi_session_t;
169 
170 /*
171  * iss flags
172  */
173 #define	ISS_LUN_INVENTORY_CHANGED		0x0001
174 #define	ISS_RESET_ACTIVE			0x0002
175 #define	ISS_BEING_CREATED			0x0004
176 #define	ISS_GOT_INITIAL_LUNS			0x0008
177 #define	ISS_EVENT_ACTIVE			0x0010
178 
179 #define	ITASK_MAX_NCMDS			14
180 #define	ITASK_DEFAULT_POLL_TIMEOUT	0
181 struct stmf_worker;
182 typedef struct stmf_i_scsi_task {
183 	scsi_task_t		*itask_task;
184 	uint32_t		itask_alloc_size;
185 	uint32_t		itask_flags;
186 	struct stmf_worker	*itask_worker;
187 	uint32_t		*itask_ilu_task_cntr;
188 	struct stmf_i_scsi_task	*itask_worker_next;
189 	struct stmf_i_scsi_task	*itask_lu_next;
190 	struct stmf_i_scsi_task	*itask_lu_prev;
191 	struct stmf_i_scsi_task	*itask_lu_free_next;
192 	struct stmf_i_scsi_task	*itask_abort_next;
193 	struct stmf_itl_data	*itask_itl_datap;
194 	clock_t			itask_start_time;	/* abort and normal */
195 	/* For now we only support 4 parallel buffers. Should be enough. */
196 	stmf_data_buf_t		*itask_dbufs[4];
197 	clock_t			itask_poll_timeout;
198 	uint8_t			itask_cmd_stack[ITASK_MAX_NCMDS];
199 	uint8_t			itask_ncmds;
200 	uint8_t			itask_allocated_buf_map;
201 	uint16_t		itask_cdb_buf_size;
202 } stmf_i_scsi_task_t;
203 
204 #define	ITASK_DEFAULT_ABORT_TIMEOUT	5
205 
206 /*
207  * itask_flags
208  */
209 #define	ITASK_IN_FREE_LIST		0x0001
210 #define	ITASK_IN_TRANSITION		0x0002
211 #define	ITASK_IN_WORKER_QUEUE		0x0004
212 #define	ITASK_BEING_ABORTED		0x0008
213 #define	ITASK_BEING_COMPLETED		0x0010
214 #define	ITASK_KNOWN_TO_TGT_PORT		0x0020
215 #define	ITASK_KNOWN_TO_LU		0x0040
216 #define	ITASK_LU_ABORT_CALLED		0x0080
217 #define	ITASK_TGT_PORT_ABORT_CALLED	0x0100
218 #define	ITASK_DEFAULT_HANDLING		0x0200
219 #define	ITASK_CAUSING_LU_RESET		0x0400
220 #define	ITASK_CAUSING_TARGET_RESET	0x0800
221 
222 /*
223  * itask cmds.
224  */
225 #define	ITASK_CMD_MASK			0x1F
226 #define	ITASK_CMD_BUF_NDX(cmd)		(((uint8_t)(cmd)) >> 5)
227 #define	ITASK_CMD_NEW_TASK		0x1
228 #define	ITASK_CMD_DATA_XFER_DONE	0x2
229 #define	ITASK_CMD_STATUS_DONE		0x3
230 #define	ITASK_CMD_ABORT			0x4
231 #define	ITASK_CMD_SEND_STATUS		0x5
232 #define	ITASK_CMD_POLL			0x10
233 #define	ITASK_CMD_POLL_LU		(ITASK_CMD_POLL | 1)
234 #define	ITASK_CMD_POLL_LPORT		(ITASK_CMD_POLL | 2)
235 
236 /*
237  * struct maintained on a per itl basis when the lu registers ITL handle.
238  */
239 typedef struct stmf_itl_data {
240 	uint32_t			itl_counter;
241 	uint8_t				itl_flags;
242 	uint8_t				itl_hdlrm_reason;
243 	uint16_t			itl_lun;
244 	void				*itl_handle;
245 	struct stmf_i_scsi_session	*itl_session;
246 	struct stmf_itl_data		*itl_next;
247 } stmf_itl_data_t;
248 
249 /*
250  * itl flags
251  */
252 #define	STMF_ITL_BEING_TERMINATED	0x01
253 
254 /*
255  * data structures to maintain provider private data.
256  */
257 typedef struct stmf_pp_data {
258 	struct stmf_pp_data	*ppd_next;
259 	void			*ppd_provider;
260 	nvlist_t		*ppd_nv;
261 	uint32_t		ppd_lu_provider:1,
262 				ppd_port_provider:1,
263 				ppd_rsvd:30;
264 	uint32_t		ppd_alloc_size;
265 	uint64_t		ppd_token;
266 	char			ppd_name[8];
267 } stmf_pp_data_t;
268 
269 typedef struct stmf_worker {
270 	kthread_t		*worker_tid;
271 	stmf_i_scsi_task_t	*worker_task_head;
272 	stmf_i_scsi_task_t	*worker_task_tail;
273 	stmf_i_scsi_task_t	*worker_wait_head;
274 	stmf_i_scsi_task_t	*worker_wait_tail;
275 	kmutex_t		worker_lock;
276 	kcondvar_t		worker_cv;
277 	uint32_t		worker_flags;
278 	uint32_t		worker_queue_depth;	/* ntasks cur queued */
279 	uint32_t		worker_max_qdepth_pu;	/* maxqd / unit time */
280 	uint32_t		worker_max_sys_qdepth_pu; /* for all workers */
281 	uint32_t		worker_ref_count;	/* # IOs referencing */
282 } stmf_worker_t;
283 
284 /*
285  * worker flags
286  */
287 #define	STMF_WORKER_STARTED		1
288 #define	STMF_WORKER_ACTIVE		2
289 #define	STMF_WORKER_TERMINATE		4
290 
291 /*
292  * data struct for managing transfers.
293  */
294 typedef struct stmf_xfer_data {
295 	uint32_t	alloc_size;	/* Including this struct */
296 	uint32_t	size_done;
297 	uint32_t	size_left;
298 	uint8_t		buf[4];
299 } stmf_xfer_data_t;
300 
301 /*
302  * Define frequently used macros
303  */
304 #define	TASK_TO_ITASK(x_task)	\
305 	((stmf_i_scsi_task_t *)(x_task)->task_stmf_private)
306 
307 void stmf_dlun_init();
308 stmf_status_t stmf_dlun_fini();
309 void stmf_worker_init();
310 stmf_status_t stmf_worker_fini();
311 void stmf_task_free(scsi_task_t *task);
312 void stmf_task_lu_free(scsi_task_t *task);
313 void stmf_do_task_abort(scsi_task_t *task);
314 void stmf_do_itl_dereg(stmf_lu_t *lu, stmf_itl_data_t *itl,
315 		uint8_t hdlrm_reason);
316 void stmf_generate_lu_event(stmf_i_lu_t *ilu, int eventid,
317 				void *arg, uint32_t flags);
318 void stmf_generate_lport_event(stmf_i_local_port_t *ilport, int eventid,
319 						void *arg, uint32_t flags);
320 
321 #ifdef	__cplusplus
322 }
323 #endif
324 
325 #endif /* _STMF_IMPL_H */
326