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) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 #ifndef	_FCOET_H
25 #define	_FCOET_H
26 
27 #include <sys/stmf_defines.h>
28 
29 #ifdef	__cplusplus
30 extern "C" {
31 #endif
32 
33 #ifdef	_KERNEL
34 
35 #define	FCOET_VERSION	"v20091123-1.02"
36 #define	FCOET_NAME	"COMSTAR FCoET "
37 #define	FCOET_MOD_NAME	FCOET_NAME FCOET_VERSION
38 
39 #define	FCOET_TASKQ_NAME_LEN	32
40 
41 /*
42  * FCOET logging
43  */
44 extern int fcoet_use_ext_log;
45 
46 /*
47  * Caution: 1) LOG will be available in debug/non-debug mode
48  *	    2) Anything which can potentially flood the log should be under
49  *	       extended logging, and use FCOET_EXT_LOG.
50  *	    3) Don't use FCOET_EXT_LOG in performance-critical code path, such
51  *	       as normal SCSI I/O code path. It could hurt system performance.
52  *	    4) Use kmdb to change focet_use_ext_log in the fly to adjust
53  *	       tracing
54  */
55 #define	FCOET_EXT_LOG(log_ident, ...)	\
56 	{	\
57 		if (fcoet_use_ext_log) {	\
58 			fcoe_trace(log_ident, __VA_ARGS__);	\
59 		}	\
60 	}
61 
62 #define	FCOET_LOG(log_ident, ...)	\
63 	fcoe_trace(log_ident, __VA_ARGS__)
64 
65 /*
66  * define common-used constants
67  */
68 #define	FCOET_MAX_LOGINS	2048
69 #define	FCOET_MAX_XCHGES	2048
70 #define	FCOET_SOL_HASH_SIZE	128
71 #define	FCOET_UNSOL_HASH_SIZE	2048
72 
73 typedef enum fcoet_sol_flogi_state {
74 	SFS_WAIT_LINKUP = 0,
75 	SFS_FLOGI_INIT,
76 	SFS_FLOGI_CHECK_TIMEOUT,
77 	SFS_ABTS_INIT,
78 	SFS_CLEAR_FLOGI,
79 	SFS_FLOGI_ACC,
80 	SFS_FLOGI_DONE
81 } fcoet_sol_flogi_state_t;
82 
83 /*
84  * define data structures
85  */
86 struct fcoet_exchange;
87 typedef struct fcoet_soft_state {
88 	/*
89 	 * basic information
90 	 */
91 	dev_info_t		*ss_dip;
92 	int			 ss_instance;
93 	uint32_t		 ss_flags;
94 	fct_local_port_t	*ss_port;
95 	fcoe_port_t		*ss_eport;
96 	char			 ss_alias[32];
97 	uint32_t		 ss_fcp_data_payload_size;
98 
99 	/*
100 	 * support degregister remote port
101 	 */
102 	uint32_t		 ss_rportid_in_dereg;
103 	uint32_t		 ss_rport_dereg_state;
104 
105 	/*
106 	 * oxid/rxid
107 	 */
108 	mod_hash_t		*ss_sol_oxid_hash;
109 	mod_hash_t		*ss_unsol_rxid_hash;
110 	uint16_t		 ss_next_sol_oxid;
111 	uint16_t		 ss_next_unsol_rxid;
112 	int			 ss_sol_oxid_hash_empty;
113 	int			 ss_unsol_rxid_hash_empty;
114 
115 	/*
116 	 * watch thread related stuff
117 	 */
118 	ddi_taskq_t		*ss_watchdog_taskq;
119 	kcondvar_t		 ss_watch_cv;
120 	kmutex_t		 ss_watch_mutex;
121 	uint64_t		 ss_watch_count;
122 	list_t			 ss_abort_xchg_list;
123 
124 	/*
125 	 * topology discovery
126 	 */
127 	struct fcoet_exchange	*ss_sol_flogi;
128 	fcoet_sol_flogi_state_t	 ss_sol_flogi_state;
129 	fct_link_info_t		 ss_link_info;
130 
131 	/*
132 	 * ioctl related stuff
133 	 */
134 	uint32_t		 ss_ioctl_flags;
135 	kmutex_t		 ss_ioctl_mutex;
136 
137 	/*
138 	 * special stuff
139 	 */
140 	uint32_t		 ss_change_state_flags;
141 	uint8_t			 ss_state:7,
142 	    ss_state_not_acked:1;
143 } fcoet_soft_state_t;
144 
145 #define	SS_FLAG_UNSOL_FLOGI_DONE	0x0001
146 #define	SS_FLAG_REPORT_TO_FCT		0x0002
147 #define	SS_FLAG_PORT_DISABLED		0x0004
148 #define	SS_FLAG_STOP_WATCH		0x0008
149 #define	SS_FLAG_TERMINATE_WATCHDOG	0x0010
150 #define	SS_FLAG_WATCHDOG_RUNNING	0x0020
151 #define	SS_FLAG_DOG_WAITING		0x0040
152 #define	SS_FLAG_DELAY_PLOGI		0x0080
153 
154 /*
155  * Sequence and frame are transient objects, so their definition is simple.
156  */
157 
158 /*
159  * Sequence.
160  * we will not use sequence in current implementation
161  */
162 typedef struct fcoet_sequence {
163 	list_t			 seq_frame_list;
164 	struct fcoet_exchange	*seq_exchange;
165 } fcoet_sequence_t;
166 
167 /*
168  * Frame
169  */
170 typedef struct fcoet_frame {
171 	list_node_t		 tfm_seq_node;
172 	fcoe_frame_t		*tfm_fcoe_frame;
173 
174 	struct fcoet_exchange	*tfm_xch;
175 	struct fcoet_sequence	*tfm_seq;
176 	uint8_t			 tfm_rctl;
177 	uint8_t			 tfm_buf_idx;
178 } fcoet_frame_t;
179 
180 /*
181  * FCOET_MAX_DBUF_LEN should better be consistent with sbd_scsi.c. Since
182  * sbd_scsi.c use 128k as the max dbuf size, we'd better define this between
183  * 32k - 128k.
184  */
185 #define	FCOET_MAX_DBUF_LEN	0x20000 /* 128 * 1024 */
186 /*
187  * exchange - cmd alias
188  */
189 typedef struct fcoet_exchange {
190 	/*
191 	 * it is only used for ss_abort_xchg_list
192 	 */
193 	list_node_t		 xch_abort_node;
194 
195 	/*
196 	 * We don't believe oxid/rxid in fct_cmd_t
197 	 */
198 	uint16_t		 xch_oxid;
199 	uint16_t		 xch_rxid;
200 
201 	uint32_t		 xch_flags;
202 	fcoet_soft_state_t	*xch_ss;
203 	fct_cmd_t		*xch_cmd;
204 
205 	fcoet_sequence_t	*xch_current_seq;
206 	clock_t			 xch_start_time;
207 
208 	stmf_data_buf_t		**xch_dbufs;
209 	uint8_t			xch_dbuf_num;
210 	uint8_t			xch_sequence_no;
211 	uint8_t			xch_ref;
212 
213 	int			 xch_left_data_size;
214 } fcoet_exchange_t;
215 /*
216  * Add the reference to avoid such situation:
217  * 1, Frame received, then abort happen (maybe because local port offline, or
218  * remote port abort the cmd), cmd is aborted and then freed right after we
219  * get the exchange from hash table in fcoet_rx_frame.
220  * 2, Frame sent out, then queued in fcoe for release. then abort happen, cmd
221  * is aborted and then freed before fcoe_watchdog() call up to release the
222  * frame.
223  * These two situation should seldom happen. But just invoke this seems won't
224  * downgrade the performance too much, so we keep it.
225  */
226 #define	FCOET_BUSY_XCHG(xch)	atomic_inc_8(&(xch)->xch_ref)
227 #define	FCOET_RELE_XCHG(xch)	atomic_dec_8(&(xch)->xch_ref)
228 
229 #define	XCH_FLAG_NONFCP_REQ_SENT	0x0001
230 #define	XCH_FLAG_NONFCP_RESP_SENT	0x0002
231 #define	XCH_FLAG_FCP_CMD_RCVD		0x0004
232 #define	XCH_FLAG_INI_ASKED_ABORT	0x0008
233 #define	XCH_FLAG_FCT_CALLED_ABORT	0x0010
234 #define	XCH_FLAG_IN_HASH_TABLE		0x0020
235 
236 /*
237  * IOCTL supporting stuff
238  */
239 #define	FCOET_IOCTL_FLAG_MASK		0xFF
240 #define	FCOET_IOCTL_FLAG_IDLE		0x00
241 #define	FCOET_IOCTL_FLAG_OPEN		0x01
242 #define	FCOET_IOCTL_FLAG_EXCL		0x02
243 
244 /*
245  * define common-used conversion and calculation macros
246  */
247 #define	FRM2SS(x_frm)							\
248 	((fcoet_soft_state_t *)(x_frm)->frm_eport->eport_client_private)
249 #define	FRM2TFM(x_frm)	((fcoet_frame_t *)(x_frm)->frm_client_private)
250 
251 #define	PORT2SS(x_port)	((fcoet_soft_state_t *)(x_port)->port_fca_private)
252 #define	EPORT2SS(x_port) ((fcoet_soft_state_t *)(x_port)->eport_client_private)
253 
254 #define	XCH2ELS(x_xch)	((fct_els_t *)x_xch->xch_cmd->cmd_specific)
255 #define	XCH2CT(x_xch)	((fct_ct_t *)x_xch->xch_cmd->cmd_specific)
256 #define	XCH2TASK(x_xch)	((scsi_task_t *)x_xch->xch_cmd->cmd_specific)
257 
258 #define	CMD2ELS(x_cmd)	((fct_els_t *)x_cmd->cmd_specific)
259 #define	CMD2CT(x_cmd)	((fct_sol_ct_t *)x_cmd->cmd_specific)
260 #define	CMD2TASK(x_cmd)	((scsi_task_t *)x_cmd->cmd_specific)
261 #define	CMD2XCH(x_cmd)	((fcoet_exchange_t *)x_cmd->cmd_fca_private)
262 #define	CMD2SS(x_cmd)							\
263 	((fcoet_soft_state_t *)(x_cmd)->cmd_port->port_fca_private)
264 
265 void fcoet_init_tfm(fcoe_frame_t *frm, fcoet_exchange_t *xch);
266 fct_status_t fcoet_send_status(fct_cmd_t *cmd);
267 void fcoet_modhash_find_cb(mod_hash_key_t, mod_hash_val_t);
268 
269 /*
270  * DBUF stuff
271  */
272 #define	FCOET_DB_SEG_NUM(x_db) (x_db->db_port_private)
273 #define	FCOET_DB_NETB(x_db)						\
274 	(((uintptr_t)FCOET_DB_SEG_NUM(x_db)) *			\
275 	sizeof (struct stmf_sglist_ent) + (uintptr_t)(x_db)->db_sglist)
276 
277 #define	FCOET_SET_SEG_NUM(x_db, x_num)			\
278 	{						\
279 		FCOET_DB_SEG_NUM(x_db) = (void *)(unsigned long)x_num;	\
280 	}
281 
282 #define	FCOET_GET_SEG_NUM(x_db)	((int)(unsigned long)FCOET_DB_SEG_NUM(x_db))
283 
284 
285 #define	FCOET_SET_NETB(x_db, x_idx, x_netb)				\
286 	{								\
287 		((void **)FCOET_DB_NETB(x_db))[x_idx] = x_netb;	\
288 	}
289 
290 #define	FCOET_GET_NETB(x_db, x_idx)		\
291 	(((void **)FCOET_DB_NETB(x_db))[x_idx])
292 
293 #define	PRT_FRM_HDR(x_p, x_f)						\
294 	{								\
295 		FCOET_LOG(x_p, "rctl/%x, type/%x, fctl/%x, oxid/%x",	\
296 		    FRM_R_CTL(x_f),		\
297 		    FRM_TYPE(x_f),		\
298 		    FRM_F_CTL(x_f),		\
299 		    FRM_OXID(x_f));		\
300 	}
301 
302 #endif	/* _KERNEL */
303 
304 #ifdef	__cplusplus
305 }
306 #endif
307 
308 #endif /* _FCOET_H */
309