summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/fibre-channel/ulp/fcsm.h
blob: 78b7704b5e47e1f4db7a6d1d4e229f3892d7f270 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_FCSM_H
#define	_FCSM_H

#ifdef	__cplusplus
extern "C" {
#endif

#ifdef _KERNEL

/*
 * Message printing flags
 */
#define	SM_LOG			1
#define	SM_CONSOLE		2
#define	SM_LOG_AND_CONSOLE	3

/*
 * Debug levels
 */
#define	SMDL_TRACE	0x0001
#define	SMDL_IO		0x0002
#define	SMDL_ERR	0x0004
#define	SMDL_INFO	0x0008

#ifdef	DEBUG
#define	FCSM_DEBUG(level, args)	\
	if (fcsm_debug & (level))	fcsm_display args

extern uint32_t fcsm_debug;
#else /* DEBUG */
#define	FCSM_DEBUG(level, args)
#endif /* DEBUG */

#define	FCSM_INIT_INSTANCES	8	/* # of instances for soft_state_init */
/*
 * Open flags
 */
#define	FCSM_IDLE		0x00
#define	FCSM_OPEN		0x01
#define	FCSM_EXCL		0x02

#define	FCSM_ELS_TIMEOUT	(20)	/* secs */
#define	FCSM_MS_TIMEOUT		(20)	/* secs */

#define	FCSM_OFFLINE_TICKER	(120)	/* secs */

/* Definitions for command retries */
#define	FCSM_MAX_CMD_RETRIES	5	/* Max retries in case of failure */
#define	FCSM_RETRY_INTERVAL	3	/* Retry interval in seconds */
#define	FCSM_RETRY_TICKER	1	/* Retry thread execution interval */

#define	FCSM_MAX_JOB_RETRIES	3	/* Max retries in case of job failure */

/*
 * fcsm_job - Job structure to issue commands using command thread
 */
typedef struct fcsm_job {
	uint32_t	job_code;		/* Command code */
	uint32_t	job_flags;		/* Command Flags */
	int		job_port_instance;	/* port driver instance */
	int		job_result;		/* job completion result */
	opaque_t	job_arg;		/* Command Arguments */
	opaque_t	job_caller_priv;	/* Caller private */
	void		(*job_comp)(opaque_t, struct fcsm_job *, int);
						/* completion func */
	opaque_t	job_comp_arg;		/* Arg for completion func */
	kmutex_t	job_mutex;		/* per command mutex */
	ksema_t		job_sema;		/* To wait for completion */
	struct fcsm_job	*job_next;		/* for linked list */
	int		job_retry_count;	/* Retry count */
	void		*job_priv;		/* for fcsm private use	 */
	uint32_t	job_priv_flags;		/* fcsm private flags */
} fcsm_job_t;

/*
 * fcsm_t - FCSM Structure for per port information
 */
typedef struct fcsm {
	kmutex_t		sm_mutex;	/* mutex for protection */
	struct fcsm		*sm_next;	/* for global linked list */
	int			sm_sid;		/* FCA Port ID */
	int			sm_instance;	/* fc port instance number */
	uint32_t		sm_port_state;	/* FCA port state */
	uint32_t		sm_port_top;	/* Port topology */
	uint32_t		sm_state;	/* San Mgmt State information */
	uint32_t		sm_flags;	/* San Mgmt Flags (see below) */
	int			sm_ncmds;	/* # of pending commands */
	int			sm_cb_count;	/* # callbacks in progress */
	fc_ulp_port_info_t	sm_port_info;	/* FCA Port Information */
	fcsm_job_t		*sm_job_head;	/* port's job queue head */
	fcsm_job_t		*sm_job_tail;	/* port's job queue tail */
	struct fcsm_cmd		*sm_retry_head;	/* cmd retry queue head */
	struct fcsm_cmd		*sm_retry_tail;	/* cmd retry queue tail */
	timeout_id_t		sm_retry_tid;	/* retry timer */
	timeout_id_t		sm_offline_tid;	/* offline timer */
	kcondvar_t		sm_job_cv;	/* cv for job processing */
	uint32_t		sm_dev_count;	/* # of devices discovered */
	fc_portmap_t		*sm_portmap;	/* device map */
	kthread_t		*sm_thread;	/* per port job thread */
	kmem_cache_t		*sm_cmd_cache;	/* per port fc packet cache */
	la_els_logi_t		sm_ms_service_params;
						/* Mgmt Server Login Params */
	callb_cpr_t		sm_cpr_info;	/* CPR info */
} fcsm_t;


typedef struct fcsm_cmd {
	fc_packet_t	*cmd_fp_pkt;
	fcsm_job_t	*cmd_job;
	fcsm_t		*cmd_fcsm;
	int		cmd_retry_count;
	int		cmd_retry_interval;
	int		cmd_max_retries;
	struct fcsm_cmd	*cmd_next;
	void		(*cmd_comp)(struct fcsm_cmd *);
	int		(*cmd_transport)(opaque_t, fc_packet_t *);
	uint32_t	cmd_dma_flags;
	fc_packet_t	cmd_fc_packet;
} fcsm_cmd_t;

/*
 * sm_flags in the per port FCSM Structure
 */
#define	FCSM_ATTACHING			0x0001
#define	FCSM_ATTACHED			0x0002
#define	FCSM_DETACHING			0x0004
#define	FCSM_DETACHED			0x0008
#define	FCSM_SUSPENDED			0x0010
#define	FCSM_POWER_DOWN			0x0020
#define	FCSM_RESTORE_RETRY_TIMEOUT	0x0040
#define	FCSM_RESTORE_OFFLINE_TIMEOUT	0x0080
#define	FCSM_RETRY_TIMER_ACTIVE		0x0100
#define	FCSM_SERIALIZE_JOBTHREAD	0x0200
#define	FCSM_CMD_RETRY_Q_SUSPENDED	0x0400
#define	FCSM_PORT_OFFLINE		0x0800
#define	FCSM_LINK_DOWN			0x1000
#define	FCSM_MGMT_SERVER_LOGGED_IN	0x2000
#define	FCSM_MGMT_SERVER_LOGIN_IN_PROG	0x4000
#define	FCSM_USING_NODMA_FCA		0x8000

/* Command flags for Job structure */
#define	FCSM_JOBFLAG_SYNC		0x01
#define	FCSM_JOBFLAG_ASYNC		0x02
#define	FCSM_JOBFLAG_SERIALIZE		0x04
#define	FCSM_JOBFLAG_CTHEADER_BE	0X08

/* Command codes */
#define	FCSM_JOB_NONE			0x00
#define	FCSM_JOB_THREAD_SHUTDOWN	0x01
#define	FCSM_JOB_LOGIN_NAME_SERVER	0x02
#define	FCSM_JOB_LOGIN_MGMT_SERVER	0x03
#define	FCSM_JOB_CT_PASSTHRU		0x04

/* Private flags for command */
#define	FCSM_JOB_PRIV_WAIT_FOR_LOGIN	0x01
#define	FCSM_JOB_PRIV_LOGIN_IN_PROG	0x02

/* Command DMA Flags */
#define	FCSM_CF_CMD_VALID_DMA_MEM	0x01
#define	FCSM_CF_CMD_VALID_DMA_BIND	0x02
#define	FCSM_CF_RESP_VALID_DMA_MEM	0x04
#define	FCSM_CF_RESP_VALID_DMA_BIND	0x08

#define	FCSM_INIT_CMD(cmd, job, tran_flags, tran_type, max_retries, func) { \
	(cmd)->cmd_job = (job); \
	(cmd)->cmd_fc_packet.pkt_tran_flags = (tran_flags); \
	(cmd)->cmd_fc_packet.pkt_tran_type = (tran_type); \
	(cmd)->cmd_max_retries = max_retries; \
	(cmd)->cmd_comp = func; \
}

/*
 * Macros to address endian issues
 * local variable "fcsm" must exist before using these
 */
#define	FCSM_REP_RD(handle, hostaddr, devaddr, cnt)			\
	{								\
		if (!((fcsm)->sm_flags & FCSM_USING_NODMA_FCA)) {	\
			ddi_rep_get8((handle), (uint8_t *)(hostaddr),	\
				    (uint8_t *)(devaddr), (cnt),	\
				    DDI_DEV_AUTOINCR);			\
		} else {						\
			bcopy((devaddr), (hostaddr), (cnt));		\
		}							\
	}

#define	FCSM_REP_WR(handle, hostaddr, devaddr, cnt)			\
	{								\
		if (!((fcsm)->sm_flags & FCSM_USING_NODMA_FCA)) {	\
			ddi_rep_put8((handle), (uint8_t *)(hostaddr),	\
				    (uint8_t *)(devaddr), (cnt),	\
				    DDI_DEV_AUTOINCR);			\
		} else {						\
			bcopy((hostaddr), (devaddr), (cnt));		\
		}							\
	}

#endif /* _KERNEL */

/*
 * IOCTL Definitions
 */
typedef struct fc_ct_aiu {
	fc_ct_header_t	aiu_header;
	char		aiu_payload[1];
	/* aiu_payload can be up to 'm' bytes (arbitrary length) */
} fc_ct_aiu_t;

#define	FCSMIO			('S' << 8)
#define	FCSMIO_CMD		(FCSMIO | 2000)

#define	FCSMIO_SUB_CMD		('Y' << 8)
#define	FCSMIO_CT_CMD		(FCSMIO_SUB_CMD + 0x01)
#define	FCSMIO_ADAPTER_LIST	(FCSMIO_SUB_CMD + 0x02)
#define	FCSMIO_FIND_ADAPTER	(FCSMIO_SUB_CMD + 0x03)

#define	FCSM_MAX_CT_SIZE	(65536)		/* 64K */

/* Management Server - Fabric Configuration Server Commands */
#define	MS_CS_GTIN	0x0100	/* Get Topology Information */
#define	MS_CS_GIEL	0x0101	/* Get Interconnect Element List */
#define	MS_CS_GIET	0x0111	/* Get Interconnect Element Type */
#define	MS_CS_GDID	0x0112	/* Get Domain Identifier */
#define	MS_CS_GMID	0x0113	/* Get Management Identifier */
#define	MS_CS_GFN	0x0114	/* Get Fabric Name */
#define	MS_CS_GIELN	0x0115	/* Get Interconnect Element Logical Name */
#define	MS_CS_GMAL	0x0116	/* Get Management Address List */
#define	MS_CS_GIEIL	0x0117	/* Get Interconnect Element Information List */
#define	MS_CS_GPL	0x0118	/* Get Port List */
#define	MS_CS_GPT	0x0121	/* Get Port Type */
#define	MS_CS_GPPN	0x0122	/* Get Physical Port Number */
#define	MS_CS_GAPNL	0x0124	/* Get Attached Port Name List */
#define	MS_CS_GPS	0x0126	/* Get Port State */
#define	MS_CS_GATIN	0x0128	/* Get Attached Topology Information */
#define	MS_CS_GPLNL	0x0191	/* Get Platform Node Name List */
#define	MS_CS_GPLT	0x0192	/* Get Platform Type */
#define	MS_CS_GPLML	0x0193	/* Get Platform Management Address List */
#define	MS_CS_GNPL	0x01a1	/* Get Platform Name - Node Name */
#define	MS_CS_GPNL	0x01a2	/* Get Platform Name List */
#define	MS_CS_GNID	0x01b1	/* Get Node Identification Data - Node Name */
#define	MS_CS_RIELN	0x0215	/* Register Interconnect Element Logical Name */
#define	MS_CS_RPL	0x0280	/* Register Platform */
#define	MS_CS_RPLN	0x0291	/* Register Platform Name */
#define	MS_CS_RPLT	0x0292	/* Register Platform Type */
#define	MS_CS_RPLM	0x0293	/* Register Platform Management Address */
#define	MS_CS_DPL	0x0380	/* Deregister Platform */
#define	MS_CS_DPLN	0x0391	/* Deregister Platform Node Name */
#define	MS_CS_DPLML	0x0393	/* Deregister Platform Management Addr List */

#ifdef _KERNEL

/*
 * Driver entry point functions
 */
static int	fcsm_attach(dev_info_t *, ddi_attach_cmd_t);
static int	fcsm_detach(dev_info_t *, ddi_detach_cmd_t);
static int	fcsm_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
static int	fcsm_open(dev_t *, int, int, cred_t *);
static int	fcsm_close(dev_t, int, int, cred_t *);
static int	fcsm_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);

/*
 * FC Transport functions
 */
static int	fcsm_port_attach(opaque_t, fc_ulp_port_info_t *,
		    fc_attach_cmd_t, uint32_t);
static int	fcsm_port_detach(opaque_t, fc_ulp_port_info_t *,
		    fc_detach_cmd_t);
static int	fcsm_port_ioctl(opaque_t, opaque_t, dev_t, int, intptr_t,
		    int, cred_t *, int *, uint32_t);
static void	fcsm_statec_cb(opaque_t, opaque_t, uint32_t, uint32_t,
		    fc_portmap_t *, uint32_t, uint32_t);
static int	fcsm_els_cb(opaque_t, opaque_t, fc_unsol_buf_t *, uint32_t);
static int	fcsm_data_cb(opaque_t, opaque_t, fc_unsol_buf_t *, uint32_t);

/*
 * Internal functions
 */
static int	fcsm_handle_port_attach(fc_ulp_port_info_t *, uint32_t, int);
static int	fcsm_handle_port_resume(opaque_t, fc_ulp_port_info_t *,
		    fc_attach_cmd_t, uint32_t, fcsm_t *);
static int	fcsm_handle_port_detach(fc_ulp_port_info_t *, fcsm_t *,
		    fc_detach_cmd_t);
static void	fcsm_suspend_port(fcsm_t *);
static void	fcsm_resume_port(fcsm_t *);
static void	fcsm_cleanup_port(fcsm_t *);
static void	fcsm_offline_timeout(void *);
static int	fcsm_fciocmd(intptr_t, int, cred_t *, fcio_t *);
static int	fcsm_fcio_copyout(fcio_t *, intptr_t, int);
static int	fcsm_job_cache_constructor(void *, void *, int);
static void	fcsm_job_cache_destructor(void *, void *);
static fcsm_job_t *fcsm_alloc_job(int);
static void	fcsm_dealloc_job(fcsm_job_t *);
static void	fcsm_init_job(fcsm_job_t *, int, uint32_t, uint32_t, opaque_t,
		    opaque_t, void (*comp)(opaque_t, fcsm_job_t *, int),
		    opaque_t);
static int	fcsm_process_job(fcsm_job_t *, int);
static void	fcsm_enque_job(fcsm_t *, fcsm_job_t *, int);
static fcsm_job_t *fcsm_deque_job(fcsm_t *);
static int	fcsm_cmd_cache_constructor(void *, void *, int);
static void	fcsm_cmd_cache_destructor(void *, void *);
static fcsm_cmd_t	*fcsm_alloc_cmd(fcsm_t *, uint32_t, uint32_t, int);
static void	fcsm_free_cmd_dma(fcsm_cmd_t *);
static void	fcsm_job_thread(fcsm_t *);
static int	fcsm_retry_job(fcsm_t *fcsm, fcsm_job_t *job);
static void	fcsm_jobdone(fcsm_job_t *);
static void	fcsm_ct_init(fcsm_t *, fcsm_cmd_t *, fc_ct_aiu_t *, size_t,
		    void (*comp_func)());
static void	fcsm_ct_intr(fcsm_cmd_t *);
static void	fcsm_job_ct_passthru(fcsm_job_t *);
static int	fcsm_login_and_process_job(fcsm_t *, fcsm_job_t *);
static void	fcsm_login_ms_comp(opaque_t, fcsm_job_t *, int);
static void	fcsm_els_init(fcsm_cmd_t *, uint32_t);
static int	fcsm_xlogi_init(fcsm_t *, fcsm_cmd_t *, uint32_t,
		    void (*comp_func)(), uchar_t);
static void	fcsm_xlogi_intr(fcsm_cmd_t *);
static void	fcsm_job_login_mgmt_server(fcsm_job_t *);
int		fcsm_ct_passthru(int, fcio_t *, int, int,
		    void (*func)(fcio_t *));
static void	fcsm_ct_passthru_comp(opaque_t, fcsm_job_t *, int);
static void	fcsm_pkt_common_intr(fc_packet_t *);
static int	fcsm_issue_cmd(fcsm_cmd_t *);
static int	fcsm_retry_cmd(fcsm_cmd_t *);
static void	fcsm_enque_cmd(fcsm_t *, fcsm_cmd_t *);
static fcsm_cmd_t *fcsm_deque_cmd(fcsm_t *);
static void	fcsm_retry_timeout(void *);
static void	fcsm_force_port_detach_all(void);


/*
 * Utility functions
 */
static void	fcsm_disp_devlist(fcsm_t *, fc_portmap_t *, uint32_t);

static void	fcsm_display(int, int, fcsm_t *,
		    fc_packet_t *, const char *, ...);
int		fcsm_pkt_state_to_rval(uchar_t, uint32_t);
caddr_t		fcsm_port_state_to_str(uint32_t);
caddr_t		fcsm_topology_to_str(uint32_t);
static caddr_t	fcsm_dev_type_to_str(uint32_t);


#endif /* _KERNEL */


#ifdef	__cplusplus
}
#endif

#endif /* _FCSM_H */