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 
26 #ifndef	_FCSM_H
27 #define	_FCSM_H
28 
29 #ifdef	__cplusplus
30 extern "C" {
31 #endif
32 
33 #ifdef _KERNEL
34 
35 /*
36  * Message printing flags
37  */
38 #define	SM_LOG			1
39 #define	SM_CONSOLE		2
40 #define	SM_LOG_AND_CONSOLE	3
41 
42 /*
43  * Debug levels
44  */
45 #define	SMDL_TRACE	0x0001
46 #define	SMDL_IO		0x0002
47 #define	SMDL_ERR	0x0004
48 #define	SMDL_INFO	0x0008
49 
50 #ifdef	DEBUG
51 #define	FCSM_DEBUG(level, args)	\
52 	if (fcsm_debug & (level))	fcsm_display args
53 
54 extern uint32_t fcsm_debug;
55 #else /* DEBUG */
56 #define	FCSM_DEBUG(level, args)
57 #endif /* DEBUG */
58 
59 #define	FCSM_INIT_INSTANCES	8	/* # of instances for soft_state_init */
60 /*
61  * Open flags
62  */
63 #define	FCSM_IDLE		0x00
64 #define	FCSM_OPEN		0x01
65 #define	FCSM_EXCL		0x02
66 
67 #define	FCSM_ELS_TIMEOUT	(20)	/* secs */
68 #define	FCSM_MS_TIMEOUT		(20)	/* secs */
69 
70 #define	FCSM_OFFLINE_TICKER	(120)	/* secs */
71 
72 /* Definitions for command retries */
73 #define	FCSM_MAX_CMD_RETRIES	5	/* Max retries in case of failure */
74 #define	FCSM_RETRY_INTERVAL	3	/* Retry interval in seconds */
75 #define	FCSM_RETRY_TICKER	1	/* Retry thread execution interval */
76 
77 #define	FCSM_MAX_JOB_RETRIES	3	/* Max retries in case of job failure */
78 
79 /*
80  * fcsm_job - Job structure to issue commands using command thread
81  */
82 typedef struct fcsm_job {
83 	uint32_t	job_code;		/* Command code */
84 	uint32_t	job_flags;		/* Command Flags */
85 	int		job_port_instance;	/* port driver instance */
86 	int		job_result;		/* job completion result */
87 	opaque_t	job_arg;		/* Command Arguments */
88 	opaque_t	job_caller_priv;	/* Caller private */
89 	void		(*job_comp)(opaque_t, struct fcsm_job *, int);
90 						/* completion func */
91 	opaque_t	job_comp_arg;		/* Arg for completion func */
92 	kmutex_t	job_mutex;		/* per command mutex */
93 	ksema_t		job_sema;		/* To wait for completion */
94 	struct fcsm_job	*job_next;		/* for linked list */
95 	int		job_retry_count;	/* Retry count */
96 	void		*job_priv;		/* for fcsm private use	 */
97 	uint32_t	job_priv_flags;		/* fcsm private flags */
98 } fcsm_job_t;
99 
100 /*
101  * fcsm_t - FCSM Structure for per port information
102  */
103 typedef struct fcsm {
104 	kmutex_t		sm_mutex;	/* mutex for protection */
105 	struct fcsm		*sm_next;	/* for global linked list */
106 	int			sm_sid;		/* FCA Port ID */
107 	int			sm_instance;	/* fc port instance number */
108 	uint32_t		sm_port_state;	/* FCA port state */
109 	uint32_t		sm_port_top;	/* Port topology */
110 	uint32_t		sm_state;	/* San Mgmt State information */
111 	uint32_t		sm_flags;	/* San Mgmt Flags (see below) */
112 	int			sm_ncmds;	/* # of pending commands */
113 	int			sm_cb_count;	/* # callbacks in progress */
114 	fc_ulp_port_info_t	sm_port_info;	/* FCA Port Information */
115 	fcsm_job_t		*sm_job_head;	/* port's job queue head */
116 	fcsm_job_t		*sm_job_tail;	/* port's job queue tail */
117 	struct fcsm_cmd		*sm_retry_head;	/* cmd retry queue head */
118 	struct fcsm_cmd		*sm_retry_tail;	/* cmd retry queue tail */
119 	timeout_id_t		sm_retry_tid;	/* retry timer */
120 	timeout_id_t		sm_offline_tid;	/* offline timer */
121 	kcondvar_t		sm_job_cv;	/* cv for job processing */
122 	uint32_t		sm_dev_count;	/* # of devices discovered */
123 	fc_portmap_t		*sm_portmap;	/* device map */
124 	kthread_t		*sm_thread;	/* per port job thread */
125 	kmem_cache_t		*sm_cmd_cache;	/* per port fc packet cache */
126 	la_els_logi_t		sm_ms_service_params;
127 						/* Mgmt Server Login Params */
128 	callb_cpr_t		sm_cpr_info;	/* CPR info */
129 } fcsm_t;
130 
131 
132 typedef struct fcsm_cmd {
133 	fc_packet_t	*cmd_fp_pkt;
134 	fcsm_job_t	*cmd_job;
135 	fcsm_t		*cmd_fcsm;
136 	int		cmd_retry_count;
137 	int		cmd_retry_interval;
138 	int		cmd_max_retries;
139 	struct fcsm_cmd	*cmd_next;
140 	void		(*cmd_comp)(struct fcsm_cmd *);
141 	int		(*cmd_transport)(opaque_t, fc_packet_t *);
142 	uint32_t	cmd_dma_flags;
143 	fc_packet_t	cmd_fc_packet;
144 } fcsm_cmd_t;
145 
146 /*
147  * sm_flags in the per port FCSM Structure
148  */
149 #define	FCSM_ATTACHING			0x0001
150 #define	FCSM_ATTACHED			0x0002
151 #define	FCSM_DETACHING			0x0004
152 #define	FCSM_DETACHED			0x0008
153 #define	FCSM_SUSPENDED			0x0010
154 #define	FCSM_POWER_DOWN			0x0020
155 #define	FCSM_RESTORE_RETRY_TIMEOUT	0x0040
156 #define	FCSM_RESTORE_OFFLINE_TIMEOUT	0x0080
157 #define	FCSM_RETRY_TIMER_ACTIVE		0x0100
158 #define	FCSM_SERIALIZE_JOBTHREAD	0x0200
159 #define	FCSM_CMD_RETRY_Q_SUSPENDED	0x0400
160 #define	FCSM_PORT_OFFLINE		0x0800
161 #define	FCSM_LINK_DOWN			0x1000
162 #define	FCSM_MGMT_SERVER_LOGGED_IN	0x2000
163 #define	FCSM_MGMT_SERVER_LOGIN_IN_PROG	0x4000
164 #define	FCSM_USING_NODMA_FCA		0x8000
165 
166 /* Command flags for Job structure */
167 #define	FCSM_JOBFLAG_SYNC		0x01
168 #define	FCSM_JOBFLAG_ASYNC		0x02
169 #define	FCSM_JOBFLAG_SERIALIZE		0x04
170 #define	FCSM_JOBFLAG_CTHEADER_BE	0X08
171 
172 /* Command codes */
173 #define	FCSM_JOB_NONE			0x00
174 #define	FCSM_JOB_THREAD_SHUTDOWN	0x01
175 #define	FCSM_JOB_LOGIN_NAME_SERVER	0x02
176 #define	FCSM_JOB_LOGIN_MGMT_SERVER	0x03
177 #define	FCSM_JOB_CT_PASSTHRU		0x04
178 
179 /* Private flags for command */
180 #define	FCSM_JOB_PRIV_WAIT_FOR_LOGIN	0x01
181 #define	FCSM_JOB_PRIV_LOGIN_IN_PROG	0x02
182 
183 /* Command DMA Flags */
184 #define	FCSM_CF_CMD_VALID_DMA_MEM	0x01
185 #define	FCSM_CF_CMD_VALID_DMA_BIND	0x02
186 #define	FCSM_CF_RESP_VALID_DMA_MEM	0x04
187 #define	FCSM_CF_RESP_VALID_DMA_BIND	0x08
188 
189 #define	FCSM_INIT_CMD(cmd, job, tran_flags, tran_type, max_retries, func) { \
190 	(cmd)->cmd_job = (job); \
191 	(cmd)->cmd_fc_packet.pkt_tran_flags = (tran_flags); \
192 	(cmd)->cmd_fc_packet.pkt_tran_type = (tran_type); \
193 	(cmd)->cmd_max_retries = max_retries; \
194 	(cmd)->cmd_comp = func; \
195 }
196 
197 /*
198  * Macros to address endian issues
199  * local variable "fcsm" must exist before using these
200  */
201 #define	FCSM_REP_RD(handle, hostaddr, devaddr, cnt)			\
202 	{								\
203 		if (!((fcsm)->sm_flags & FCSM_USING_NODMA_FCA)) {	\
204 			ddi_rep_get8((handle), (uint8_t *)(hostaddr),	\
205 				    (uint8_t *)(devaddr), (cnt),	\
206 				    DDI_DEV_AUTOINCR);			\
207 		} else {						\
208 			bcopy((devaddr), (hostaddr), (cnt));		\
209 		}							\
210 	}
211 
212 #define	FCSM_REP_WR(handle, hostaddr, devaddr, cnt)			\
213 	{								\
214 		if (!((fcsm)->sm_flags & FCSM_USING_NODMA_FCA)) {	\
215 			ddi_rep_put8((handle), (uint8_t *)(hostaddr),	\
216 				    (uint8_t *)(devaddr), (cnt),	\
217 				    DDI_DEV_AUTOINCR);			\
218 		} else {						\
219 			bcopy((hostaddr), (devaddr), (cnt));		\
220 		}							\
221 	}
222 
223 #endif /* _KERNEL */
224 
225 /*
226  * IOCTL Definitions
227  */
228 typedef struct fc_ct_aiu {
229 	fc_ct_header_t	aiu_header;
230 	char		aiu_payload[1];
231 	/* aiu_payload can be up to 'm' bytes (arbitrary length) */
232 } fc_ct_aiu_t;
233 
234 #define	FCSMIO			('S' << 8)
235 #define	FCSMIO_CMD		(FCSMIO | 2000)
236 
237 #define	FCSMIO_SUB_CMD		('Y' << 8)
238 #define	FCSMIO_CT_CMD		(FCSMIO_SUB_CMD + 0x01)
239 #define	FCSMIO_ADAPTER_LIST	(FCSMIO_SUB_CMD + 0x02)
240 #define	FCSMIO_FIND_ADAPTER	(FCSMIO_SUB_CMD + 0x03)
241 
242 #define	FCSM_MAX_CT_SIZE	(65536)		/* 64K */
243 
244 /* Management Server - Fabric Configuration Server Commands */
245 #define	MS_CS_GTIN	0x0100	/* Get Topology Information */
246 #define	MS_CS_GIEL	0x0101	/* Get Interconnect Element List */
247 #define	MS_CS_GIET	0x0111	/* Get Interconnect Element Type */
248 #define	MS_CS_GDID	0x0112	/* Get Domain Identifier */
249 #define	MS_CS_GMID	0x0113	/* Get Management Identifier */
250 #define	MS_CS_GFN	0x0114	/* Get Fabric Name */
251 #define	MS_CS_GIELN	0x0115	/* Get Interconnect Element Logical Name */
252 #define	MS_CS_GMAL	0x0116	/* Get Management Address List */
253 #define	MS_CS_GIEIL	0x0117	/* Get Interconnect Element Information List */
254 #define	MS_CS_GPL	0x0118	/* Get Port List */
255 #define	MS_CS_GPT	0x0121	/* Get Port Type */
256 #define	MS_CS_GPPN	0x0122	/* Get Physical Port Number */
257 #define	MS_CS_GAPNL	0x0124	/* Get Attached Port Name List */
258 #define	MS_CS_GPS	0x0126	/* Get Port State */
259 #define	MS_CS_GATIN	0x0128	/* Get Attached Topology Information */
260 #define	MS_CS_GPLNL	0x0191	/* Get Platform Node Name List */
261 #define	MS_CS_GPLT	0x0192	/* Get Platform Type */
262 #define	MS_CS_GPLML	0x0193	/* Get Platform Management Address List */
263 #define	MS_CS_GNPL	0x01a1	/* Get Platform Name - Node Name */
264 #define	MS_CS_GPNL	0x01a2	/* Get Platform Name List */
265 #define	MS_CS_GNID	0x01b1	/* Get Node Identification Data - Node Name */
266 #define	MS_CS_RIELN	0x0215	/* Register Interconnect Element Logical Name */
267 #define	MS_CS_RPL	0x0280	/* Register Platform */
268 #define	MS_CS_RPLN	0x0291	/* Register Platform Name */
269 #define	MS_CS_RPLT	0x0292	/* Register Platform Type */
270 #define	MS_CS_RPLM	0x0293	/* Register Platform Management Address */
271 #define	MS_CS_DPL	0x0380	/* Deregister Platform */
272 #define	MS_CS_DPLN	0x0391	/* Deregister Platform Node Name */
273 #define	MS_CS_DPLML	0x0393	/* Deregister Platform Management Addr List */
274 
275 #ifdef _KERNEL
276 
277 /*
278  * Driver entry point functions
279  */
280 static int	fcsm_attach(dev_info_t *, ddi_attach_cmd_t);
281 static int	fcsm_detach(dev_info_t *, ddi_detach_cmd_t);
282 static int	fcsm_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
283 static int	fcsm_open(dev_t *, int, int, cred_t *);
284 static int	fcsm_close(dev_t, int, int, cred_t *);
285 static int	fcsm_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
286 
287 /*
288  * FC Transport functions
289  */
290 static int	fcsm_port_attach(opaque_t, fc_ulp_port_info_t *,
291 		    fc_attach_cmd_t, uint32_t);
292 static int	fcsm_port_detach(opaque_t, fc_ulp_port_info_t *,
293 		    fc_detach_cmd_t);
294 static int	fcsm_port_ioctl(opaque_t, opaque_t, dev_t, int, intptr_t,
295 		    int, cred_t *, int *, uint32_t);
296 static void	fcsm_statec_cb(opaque_t, opaque_t, uint32_t, uint32_t,
297 		    fc_portmap_t *, uint32_t, uint32_t);
298 static int	fcsm_els_cb(opaque_t, opaque_t, fc_unsol_buf_t *, uint32_t);
299 static int	fcsm_data_cb(opaque_t, opaque_t, fc_unsol_buf_t *, uint32_t);
300 
301 /*
302  * Internal functions
303  */
304 static int	fcsm_handle_port_attach(fc_ulp_port_info_t *, uint32_t, int);
305 static int	fcsm_handle_port_resume(opaque_t, fc_ulp_port_info_t *,
306 		    fc_attach_cmd_t, uint32_t, fcsm_t *);
307 static int	fcsm_handle_port_detach(fc_ulp_port_info_t *, fcsm_t *,
308 		    fc_detach_cmd_t);
309 static void	fcsm_suspend_port(fcsm_t *);
310 static void	fcsm_resume_port(fcsm_t *);
311 static void	fcsm_cleanup_port(fcsm_t *);
312 static void	fcsm_offline_timeout(void *);
313 static int	fcsm_fciocmd(intptr_t, int, cred_t *, fcio_t *);
314 static int	fcsm_fcio_copyout(fcio_t *, intptr_t, int);
315 static int	fcsm_job_cache_constructor(void *, void *, int);
316 static void	fcsm_job_cache_destructor(void *, void *);
317 static fcsm_job_t *fcsm_alloc_job(int);
318 static void	fcsm_dealloc_job(fcsm_job_t *);
319 static void	fcsm_init_job(fcsm_job_t *, int, uint32_t, uint32_t, opaque_t,
320 		    opaque_t, void (*comp)(opaque_t, fcsm_job_t *, int),
321 		    opaque_t);
322 static int	fcsm_process_job(fcsm_job_t *, int);
323 static void	fcsm_enque_job(fcsm_t *, fcsm_job_t *, int);
324 static fcsm_job_t *fcsm_deque_job(fcsm_t *);
325 static int	fcsm_cmd_cache_constructor(void *, void *, int);
326 static void	fcsm_cmd_cache_destructor(void *, void *);
327 static fcsm_cmd_t	*fcsm_alloc_cmd(fcsm_t *, uint32_t, uint32_t, int);
328 static void	fcsm_free_cmd_dma(fcsm_cmd_t *);
329 static void	fcsm_job_thread(fcsm_t *);
330 static int	fcsm_retry_job(fcsm_t *fcsm, fcsm_job_t *job);
331 static void	fcsm_jobdone(fcsm_job_t *);
332 static void	fcsm_ct_init(fcsm_t *, fcsm_cmd_t *, fc_ct_aiu_t *, size_t,
333 		    void (*comp_func)());
334 static void	fcsm_ct_intr(fcsm_cmd_t *);
335 static void	fcsm_job_ct_passthru(fcsm_job_t *);
336 static int	fcsm_login_and_process_job(fcsm_t *, fcsm_job_t *);
337 static void	fcsm_login_ms_comp(opaque_t, fcsm_job_t *, int);
338 static void	fcsm_els_init(fcsm_cmd_t *, uint32_t);
339 static int	fcsm_xlogi_init(fcsm_t *, fcsm_cmd_t *, uint32_t,
340 		    void (*comp_func)(), uchar_t);
341 static void	fcsm_xlogi_intr(fcsm_cmd_t *);
342 static void	fcsm_job_login_mgmt_server(fcsm_job_t *);
343 int		fcsm_ct_passthru(int, fcio_t *, int, int,
344 		    void (*func)(fcio_t *));
345 static void	fcsm_ct_passthru_comp(opaque_t, fcsm_job_t *, int);
346 static void	fcsm_pkt_common_intr(fc_packet_t *);
347 static int	fcsm_issue_cmd(fcsm_cmd_t *);
348 static int	fcsm_retry_cmd(fcsm_cmd_t *);
349 static void	fcsm_enque_cmd(fcsm_t *, fcsm_cmd_t *);
350 static fcsm_cmd_t *fcsm_deque_cmd(fcsm_t *);
351 static void	fcsm_retry_timeout(void *);
352 static void	fcsm_force_port_detach_all(void);
353 
354 
355 /*
356  * Utility functions
357  */
358 static void	fcsm_disp_devlist(fcsm_t *, fc_portmap_t *, uint32_t);
359 
360 static void	fcsm_display(int, int, fcsm_t *,
361 		    fc_packet_t *, const char *, ...);
362 int		fcsm_pkt_state_to_rval(uchar_t, uint32_t);
363 caddr_t		fcsm_port_state_to_str(uint32_t);
364 caddr_t		fcsm_topology_to_str(uint32_t);
365 static caddr_t	fcsm_dev_type_to_str(uint32_t);
366 
367 
368 #endif /* _KERNEL */
369 
370 
371 #ifdef	__cplusplus
372 }
373 #endif
374 
375 #endif /* _FCSM_H */
376