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