xref: /illumos-gate/usr/src/uts/common/io/comstar/port/fct/fct_impl.h (revision c946faca5d4627284fb79c6b04e652b471034495)
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	_FCT_IMPL_H
26 #define	_FCT_IMPL_H
27 
28 #ifdef	__cplusplus
29 extern "C" {
30 #endif
31 
32 #define	RSCN_OPTION_VERIFY	0x0001
33 
34 typedef enum fct_li_state {
35 	LI_STATE_DO_FLOGI = 0,	/* FLOGI handled by FCA */
36 	LI_STATE_FINI_TOPOLOGY,	/* Finalize topology */
37 	LI_STATE_N2N_PLOGI,	/* In case of a N2N connection */
38 
39 	LI_STATE_DO_FCLOGIN,	/* Login into 0xFFFFFD */
40 	LI_STATE_DO_SCR,	/* State change registration */
41 
42 	LI_STATE_DO_NSLOGIN,	/* Login into 0xFFFFFC */
43 	LI_STATE_DO_RNN,	/* Register node name */
44 	LI_STATE_DO_RCS,	/* Register classes of service */
45 	LI_STATE_DO_RFT,	/* Register FC-4 types */
46 	LI_STATE_DO_RSPN,	/* Register symbolic port name */
47 	LI_STATE_DO_RSNN,	/* Register symbolic node name */
48 
49 	LI_STATE_MAX		/* Not a real state */
50 } fct_li_state_t;
51 
52 #define	LI_STATE_START			0
53 #define	LI_STATE_MASK			0x3F
54 /* Next state depends on the return value */
55 #define	LI_STATE_FLAG_CMD_RETCHECK	0x40
56 /* Link init cmd is still outstanding */
57 #define	LI_STATE_FLAG_CMD_WAITING	0x80
58 /* Flag to indicate that link info is not available yet */
59 #define	LI_STATE_FLAG_NO_LI_YET		0x100
60 
61 #define	FCT_MAX_CACHED_CMDS	256
62 #define	USEC_ELS_TIMEOUT	(10 * 1000 * 1000)
63 #define	USEC_SOL_TIMEOUT	(10 * 1000 * 1000)
64 #define	USEC_DEREG_RP_TIMEOUT	(25 * 1000 * 1000)
65 #define	USEC_DEREG_RP_INTERVAL	(2 * 1000 * 1000)
66 
67 struct fct_i_cmd;
68 typedef void (* fct_icmd_cb_t)(struct fct_i_cmd *icmd);
69 typedef struct fct_i_cmd {
70 	fct_cmd_t		*icmd_cmd;
71 	uint32_t		 icmd_alloc_size;
72 	fct_struct_id_t		 icmd_struct_id;
73 	uint32_t		 icmd_flags;
74 	clock_t			 icmd_start_time;
75 	struct fct_i_cmd	*icmd_next;	/* iport_abort_queue and irp */
76 	struct fct_i_cmd	*icmd_solcmd_next;	/* iport_solcmd_queue */
77 	fct_icmd_cb_t		 icmd_cb;
78 	void			*icmd_cb_private;
79 } fct_i_cmd_t;
80 
81 /*
82  * icmd_flags
83  */
84 #define	ICMD_SESSION_AFFECTING		0x0002
85 #define	ICMD_IN_IRP_QUEUE		0x0004
86 #define	ICMD_BEING_ABORTED		0x0008
87 #define	ICMD_KNOWN_TO_FCA		0x0020
88 #define	ICMD_FCA_ABORT_CALLED		0x0040
89 #define	ICMD_CMD_COMPLETE		0x0080
90 #define	ICMD_IN_TRANSITION		0x0100
91 #define	ICMD_ABTS_RECEIVED		0x0200
92 #define	ICMD_IMPLICIT			0x0400
93 #define	ICMD_IMPLICIT_CMD_HAS_RESOURCE	0x0800
94 /* High order are debug flags */
95 #define	ICMD_ELS_PROCESSING_STARTED	0x80000000
96 
97 /*
98  * For solicited commands, there's only 3 states:
99  * 1) it's new. We need send it to FCA. ICMD_SOLCMD_NEW is set
100  * 2) it's running. We are waiting for completion.
101  * 3) it's completed. We need free it. ICMD_CMD_COMPLETE is set
102  * ICMD_SOLCMD_NEW and ICMD_CMD_COMPLETE should not be set in the same time
103  */
104 #define	ICMD_IN_SOLCMD_QUEUE		0x010000
105 #define	ICMD_SOLCMD_NEW			0x020000
106 
107 typedef struct fct_i_remote_port {
108 	fct_remote_port_t		*irp_rp;
109 	uint32_t			irp_alloc_size;
110 	fct_struct_id_t			irp_struct_id;
111 	krwlock_t			irp_lock;
112 
113 	/* For queueing to local port */
114 	struct fct_i_remote_port	*irp_next;
115 
116 	/* For queueing to handle elses */
117 	struct fct_i_remote_port	*irp_discovery_next;
118 
119 	fct_i_cmd_t			*irp_els_list;
120 
121 	/*
122 	 * sa stands for session affecting, nsa is non session affecting.
123 	 * The els counts only represent elses under progress not the ones
124 	 * that are terminated. active_xchg_count covers everything including
125 	 * the ones waiting to be terminated.
126 	 */
127 	uint16_t			irp_sa_elses_count;
128 	uint16_t			irp_nsa_elses_count;
129 	uint16_t			irp_fcp_xchg_count;
130 	uint16_t			irp_nonfcp_xchg_count;
131 
132 	uint32_t			irp_flags;
133 	clock_t				irp_deregister_timer;
134 	uint32_t			irp_dereg_count;
135 
136 	uint32_t			irp_portid;
137 	uint8_t				irp_id[24];
138 	uint32_t			irp_rcvd_prli_params;
139 	uint32_t			irp_sent_prli_params;
140 
141 	/*
142 	 * Most HBAs will only register symbolic node name instead of port name,
143 	 * so we use SNN as session alias.
144 	 */
145 	stmf_scsi_session_t		*irp_session;
146 	char				*irp_snn;
147 
148 	/* items will be filled in ns cmd */
149 	uint8_t				irp_fc4types[32]; /* FC-4 types */
150 	char				*irp_spn;	/* port symbolic name */
151 	uint32_t			irp_cos;	/* class of service */
152 
153 	uint32_t			irp_rscn_counter;
154 } fct_i_remote_port_t;
155 
156 /*
157  * structure used for fct_rls_cb() callback private data
158  */
159 typedef struct fct_rls_cb_data {
160 	struct fct_port_link_status	*fct_link_status;
161 	fct_status_t			fct_els_res;
162 } fct_rls_cb_data_t;
163 
164 /*
165  * irp flags
166  */
167 #define	IRP_PLOGI_DONE			0x0001
168 #define	IRP_PRLI_DONE			0x0002
169 #define	IRP_IN_DISCOVERY_QUEUE		0x0004
170 #define	IRP_FCP_CLEANUP			0x0008
171 #define	IRP_SESSION_CLEANUP		(IRP_FCP_CLEANUP | 0x0010)
172 #define	IRP_HANDLE_OPENED		0x0020
173 #define	IRP_SCSI_SESSION_STARTED	0x0040
174 #define	IRP_RSCN_QUEUED			0x0080
175 #define	IRP_SOL_PLOGI_IN_PROGRESS	0x0100
176 
177 typedef struct fct_cmd_slot {
178 	fct_i_cmd_t		*slot_cmd;
179 	uint16_t		slot_no;
180 	uint16_t		slot_next;
181 	uint8_t			slot_uniq_cntr;
182 } fct_cmd_slot_t;
183 #define	FCT_SLOT_EOL		0xffff
184 
185 #define	FCT_HASH_TABLE_SIZE		256
186 #define	FCT_LOOP_HASH(portid)		(portid & 0xff)
187 #define	FCT_FABRIC_HASH(portid)		(((portid & 0x1f00) | \
188 	((portid & 0x70000)>>3)) >> 8)
189 #define	FCT_PORTID_HASH_FUNC(portid) \
190 	((portid & 0xFFFF00)?FCT_FABRIC_HASH(portid):FCT_LOOP_HASH(portid))
191 
192 typedef struct fct_i_local_port {
193 	fct_local_port_t	*iport_port;
194 	uint32_t		iport_alloc_size;
195 	fct_struct_id_t		iport_struct_id;
196 
197 	struct fct_i_local_port	*iport_next;
198 	struct fct_i_local_port	*iport_prev;
199 
200 	char			*iport_alias;
201 	char			iport_alias_mem[16];
202 	uint8_t			iport_id[24];	/* scsi_devid_desc_t */
203 	krwlock_t		iport_lock;
204 	uint32_t		iport_flags;
205 	uint16_t		iport_link_state;
206 	uint8_t			iport_state:7,
207 	    iport_state_not_acked:1;
208 	uint8_t			iport_offline_prstate;
209 	struct fct_link_info	iport_link_info;
210 
211 	fct_i_remote_port_t	**iport_rp_slots;
212 	fct_i_remote_port_t	**iport_rp_tb;
213 	uint32_t		iport_nrps_login; /* currently logged in */
214 	uint32_t		iport_nrps;	/* items in hash table */
215 	uint64_t		iport_last_change;
216 
217 	/*
218 	 * These variables are used to manage fct_cmd_t cache for SCSI traffic
219 	 */
220 	/*
221 	 * Total # of cmds allocated by the driver. Some of which are free
222 	 * and sitting on iport_cached_cmdlist. And some are executing.
223 	 */
224 	uint32_t		iport_total_alloced_ncmds;
225 
226 	/*
227 	 * Max active cmds in last interval (10 or 30 seconds)
228 	 */
229 	uint32_t		iport_max_active_ncmds;
230 
231 	/*
232 	 * # of free cmds sitting on the iport_cached_cmdlist
233 	 */
234 	uint32_t		iport_cached_ncmds;
235 	struct fct_i_cmd	*iport_cached_cmdlist;
236 	kmutex_t		iport_cached_cmd_lock;
237 
238 	/*
239 	 * To release free cmds periodically
240 	 */
241 	clock_t			iport_cmdcheck_clock;
242 
243 	uint16_t		iport_task_green_limit;
244 	uint16_t		iport_task_yellow_limit;
245 	uint16_t		iport_task_red_limit;
246 	/* cmd slots */
247 	uint16_t		iport_nslots_free;
248 
249 	/* upper 16 bits is just a counter to avoid ABA issues */
250 	uint32_t		iport_next_free_slot;
251 
252 	uint8_t			iport_login_retry; /* for flogi and N2N plogi */
253 	uint8_t			iport_link_old_topology;
254 	uint8_t			iport_link_cleanup_retry;
255 	clock_t			iport_li_cmd_timeout; /* for li state m/c */
256 	fct_cmd_slot_t		*iport_cmd_slots;
257 
258 	/* worker thread data */
259 	ddi_taskq_t		*iport_worker_taskq;
260 	kmutex_t		iport_worker_lock;
261 	kcondvar_t		iport_worker_cv;
262 	struct fct_i_event	*iport_event_head;
263 	struct fct_i_event	*iport_event_tail;
264 	struct fct_i_cmd	*iport_abort_queue;
265 	struct fct_i_cmd	**iport_ppicmd_term;
266 
267 	/* link initialization */
268 	fct_status_t		iport_li_comp_status;
269 	enum fct_li_state	iport_li_state;
270 
271 	/* solicited cmd link */
272 	struct fct_i_cmd	*iport_solcmd_queue;
273 
274 	/* rpwe = remote port with pending els(es) */
275 	fct_i_remote_port_t	*iport_rpwe_head;
276 	fct_i_remote_port_t	*iport_rpwe_tail;
277 	kstat_t			*iport_kstat_portstat;
278 	ksema_t			iport_rls_sema;
279 	fct_rls_cb_data_t	iport_rls_cb_data;
280 } fct_i_local_port_t;
281 
282 #define	IPORT_FLOGI_DONE(iport)	PORT_FLOGI_DONE(&(iport)->iport_link_info)
283 
284 /*
285  * iport flags
286  */
287 #define	IPORT_WORKER_RUNNING		0x0001
288 #define	IPORT_TERMINATE_WORKER		0x0002
289 #define	IPORT_WORKER_DOING_TIMEDWAIT	0x0004
290 #define	IPORT_WORKER_DOING_WAIT		0x0008
291 #define	IPORT_FLAG_PORT_OFFLINED	0x0010
292 #define	IPORT_ALLOW_UNSOL_FLOGI		0x0020
293 
294 #define	IS_WORKER_SLEEPING(iport)	((iport)->iport_flags & \
295 	(IPORT_WORKER_DOING_TIMEDWAIT | IPORT_WORKER_DOING_WAIT))
296 
297 /* Limits for scsi task load of local port */
298 #define	FCT_TASK_GREEN_LIMIT		80
299 #define	FCT_TASK_YELLOW_LIMIT		90
300 #define	FCT_TASK_RED_LIMIT		95
301 
302 typedef struct fct_i_event {
303 	struct fct_i_event	*event_next;
304 	int			event_type;
305 } fct_i_event_t;
306 
307 typedef enum { /* Seggested action values for discovery thread */
308     DISC_ACTION_NO_WORK = 0,
309     DISC_ACTION_RESCAN = 1,
310     DISC_ACTION_DELAY_RESCAN = 2,
311     DISC_ACTION_USE_SHORT_DELAY = 4
312 } disc_action_t;
313 
314 /*
315  * Local port state definitions
316  * NOTE that every time there is a state change, the newly set bit suggests
317  * the action. So far there are 3 actions S_PORT_CLEANUP, S_ADAPTER_FATAL
318  * and S_INIT_LINK.
319  */
320 #define	S_RCVD_LINK_DOWN	0x01
321 #define	S_RCVD_LINK_UP		0x02
322 #define	S_LINK_ONLINE		0x04
323 #define	S_INIT_LINK		0x08
324 #define	S_PORT_CLEANUP		0x10
325 
326 #define	PORT_STATE_LINK_DOWN		0x00
327 #define	PORT_STATE_LINK_INIT_START	(S_RCVD_LINK_UP | S_LINK_ONLINE |\
328     S_INIT_LINK)
329 #define	PORT_STATE_LINK_INIT_DONE	(S_LINK_ONLINE)
330 #define	PORT_STATE_LINK_UP_CLEANING	(S_RCVD_LINK_UP | S_PORT_CLEANUP)
331 #define	PORT_STATE_LINK_DOWN_CLEANING	(S_RCVD_LINK_DOWN | S_PORT_CLEANUP)
332 
333 /*
334  * Internal events
335  */
336 #define	FCT_I_EVENT_LINK_INIT_DONE	0x80
337 #define	FCT_I_EVENT_CLEANUP_POLL	0x81
338 
339 /*
340  * Offline processing states, used by worker thread.
341  */
342 #define	FCT_OPR_DONE			0
343 #define	FCT_OPR_START			1
344 #define	FCT_OPR_CMD_CLEANUP_WAIT	2
345 #define	FCT_OPR_INT_CLEANUP_WAIT	3
346 
347 /*
348  * Check time
349  */
350 #define	FCT_CMDLIST_CHECK_SECONDS	10
351 
352 /*
353  * Define frequently used macros
354  */
355 #define	ICMD_TO_CT(x_icmd)	\
356 	((fct_sol_ct_t *)(x_icmd)->icmd_cmd->cmd_specific)
357 
358 #define	ICMD_TO_ELS(x_icmd)	\
359 	((fct_els_t *)(x_icmd)->icmd_cmd->cmd_specific)
360 
361 #define	ICMD_TO_IPORT(x_icmd)	\
362 	((fct_i_local_port_t *)(x_icmd)->icmd_cmd->cmd_port->port_fct_private)
363 
364 #define	ICMD_TO_PORT(x_icmd)	\
365 	((x_icmd)->icmd_cmd->cmd_port)
366 
367 #define	ICMD_TO_IRP(x_icmd)	\
368 	((fct_i_remote_port_t *)(x_icmd)->icmd_cmd->cmd_rp->rp_fct_private)
369 
370 #define	CMD_TO_ICMD(x_cmd)	((fct_i_cmd_t *)(x_cmd)->cmd_fct_private)
371 
372 #define	RP_TO_IRP(x_rp)		((fct_i_remote_port_t *)(x_rp)->rp_fct_private)
373 
374 #define	PORT_TO_IPORT(x_port)	\
375 	((fct_i_local_port_t *)(x_port)->port_fct_private)
376 
377 #define	FCT_IS_ELS_ACC(x_icmd)	\
378 	(((x_icmd)->icmd_cmd->cmd_comp_status == FCT_SUCCESS) &&	\
379 	(ICMD_TO_ELS(x_icmd)->els_resp_payload[0] == ELS_OP_ACC))
380 
381 #define	FCT_IS_CT_ACC(x_icmd)	\
382 	(((x_icmd)->icmd_cmd->cmd_comp_status == FCT_SUCCESS) &&	\
383 	(ICMD_TO_CT(x_icmd)->ct_resp_payload[8] == 0x80) &&\
384 	(ICMD_TO_CT(x_icmd)->ct_resp_payload[9] == 0x02))
385 
386 #define	IPORT_IN_NS_TOPO(x_iport)	\
387 	((x_iport)->iport_link_info.port_topology & PORT_TOPOLOGY_FABRIC_BIT)
388 
389 #define	IS_LOGO_ELS(icmd)	\
390 	(ICMD_TO_ELS(icmd)->els_req_payload[0] == ELS_OP_LOGO)
391 
392 stmf_status_t fct_xfer_scsi_data(scsi_task_t *task,
393     stmf_data_buf_t *dbuf, uint32_t ioflags);
394 stmf_status_t fct_send_scsi_status(scsi_task_t *task, uint32_t ioflags);
395 fct_i_remote_port_t *fct_portid_to_portptr(fct_i_local_port_t *iport,
396     uint32_t portid);
397 fct_i_remote_port_t *fct_lookup_irp_by_nodewwn(fct_i_local_port_t *iport,
398     uint8_t *nodewwn);
399 fct_i_remote_port_t *fct_lookup_irp_by_portwwn(fct_i_local_port_t *iport,
400     uint8_t *portwwn);
401 void fct_queue_rp(fct_i_local_port_t *iport, fct_i_remote_port_t *irp);
402 void fct_deque_rp(fct_i_local_port_t *iport, fct_i_remote_port_t *irp);
403 int fct_implicitly_logo_all(fct_i_local_port_t *iport, int force_implicit);
404 void fct_post_implicit_logo(fct_cmd_t *cmd);
405 void fct_rehash(fct_i_local_port_t *iport);
406 uint8_t fct_local_port_cleanup_done(fct_i_local_port_t *iport);
407 void fct_handle_rcvd_abts(fct_cmd_t *cmd);
408 void fct_fill_abts_acc(fct_cmd_t *cmd);
409 void fct_q_for_termination_lock_held(fct_i_local_port_t *iport,
410     fct_i_cmd_t *icmd, fct_status_t s);
411 disc_action_t fct_handle_port_offline(fct_i_local_port_t *iport);
412 disc_action_t fct_cmd_terminator(fct_i_local_port_t *iport);
413 void fct_cmd_free(fct_cmd_t *cmd);
414 void fct_scsi_task_free(scsi_task_t *task);
415 stmf_status_t fct_scsi_abort(stmf_local_port_t *lport, int abort_cmd,
416     void *arg, uint32_t flags);
417 stmf_status_t fct_info(uint32_t cmd, stmf_local_port_t *lport,
418     void *arg, uint8_t *buf, uint32_t *bufsizep);
419 void fct_event_handler(stmf_local_port_t *lport, int eventid,
420     void *arg, uint32_t flags);
421 uint16_t fct_alloc_cmd_slot(fct_i_local_port_t *iport, fct_cmd_t *cmd);
422 void fct_post_to_discovery_queue(fct_i_local_port_t *iport,
423     fct_i_remote_port_t *irp, fct_i_cmd_t *icmd);
424 fct_cmd_t *fct_create_solct(fct_local_port_t *port, fct_remote_port_t *rp,
425     uint16_t ctop, fct_icmd_cb_t icmdcb);
426 fct_cmd_t *fct_create_solels(fct_local_port_t *port, fct_remote_port_t *rp,
427     int implicit, uchar_t elsop, uint32_t wkdid, fct_icmd_cb_t icmdcb);
428 void fct_handle_solct(fct_cmd_t *cmd);
429 void fct_post_to_solcmd_queue(fct_local_port_t *port, fct_cmd_t *cmd);
430 void fct_logo_cb(fct_i_cmd_t *icmd);
431 void fct_link_init_cb(fct_i_cmd_t *icmd);
432 void fct_gsnn_cb(fct_i_cmd_t *icmd);
433 void fct_gcs_cb(fct_i_cmd_t *icmd);
434 void fct_gft_cb(fct_i_cmd_t *icmd);
435 void fct_gspn_cb(fct_i_cmd_t *icmd);
436 void fct_rls_cb(fct_i_cmd_t *icmd);
437 disc_action_t fct_process_link_init(fct_i_local_port_t *iport);
438 
439 #ifdef	__cplusplus
440 }
441 #endif
442 
443 #endif /* _FCT_IMPL_H */
444