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