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	_FC_PORTIF_H
27 #define	_FC_PORTIF_H
28 
29 
30 #include <sys/note.h>
31 
32 #ifdef	__cplusplus
33 extern "C" {
34 #endif
35 
36 
37 /*
38  * To remove the port WWN from the orphan list; An orphan list
39  * scan typically happens during ONLINE processing (after a LIP
40  * in Public loop or link reset) or during RSCN validation.
41  */
42 #define	FC_ORPHAN_SCAN_LIMIT		15
43 
44 /*
45  * Show a limited tolerance on the number of LOGOs that an
46  * N/NL_Port can send; Beyond that it'll be removed entirely
47  * from the port driver's data base. The tolerance counter
48  * is reset after each link reset.
49  */
50 #define	FC_LOGO_TOLERANCE_LIMIT		16
51 #define	FC_LOGO_TOLERANCE_TIME_LIMIT	5000000	/* 5 seconds */
52 
53 /*
54  * ns_flags field definitions in struct
55  * fctl_ns_req_t
56  */
57 #define	FCTL_NS_FILL_NS_MAP		0x01
58 #define	FCTL_NS_GET_DEV_COUNT		0x02
59 #define	FCTL_NS_NO_DATA_BUF		0x04
60 #define	FCTL_NS_BUF_IS_USERLAND		0x08
61 #define	FCTL_NS_BUF_IS_FC_PORTMAP	0x10
62 #define	FCTL_NS_CREATE_DEVICE		0x20
63 #define	FCTL_NS_VALIDATE_PD		0x40
64 #define	FCTL_NS_ASYNC_REQUEST		0x80
65 #define	FCTL_GAN_START_ID		0xFFFFFF
66 
67 
68 
69 /*
70  * Values for the fp_soft_state field in the fc_local_port_t struct.
71  *
72  * Notice below that in two cases, suspend and pm-suspend,there
73  * is no usage of _IN_, which means the bits will stay even after
74  * suspend/pm-suspend is complete they are cleared at the time of
75  * resume/pm-resume.
76  */
77 
78 /*
79  * FP_SOFT_IN_DETACH is set in fp_detach_handler(), which is called from
80  * fp_detach() for the DDI_DETACH flag. FP_SOFT_IN_DETACH is checked in
81  * numerous places. It is never explicitly cleared -- apparently the code
82  * relies on ddi_softstate_free(9F) to clear it.
83  */
84 #define	FP_SOFT_IN_DETACH		0x0002
85 
86 /*
87  * FP_SOFT_SUSPEND is set in fp_suspend_handler() and cleared in
88  * fp_resume_handler.  It is tested in a number of placed in fp and fctl,
89  * including fp_job_handler().
90  */
91 #define	FP_SOFT_SUSPEND			0x0004
92 
93 /*
94  * FP_SOFT_POWER_DOWN is set in fp_power_down() and cleared in fp_power_up().
95  * It is tested in a number of different places in fp/fctl.
96  */
97 #define	FP_SOFT_POWER_DOWN		0x0008
98 #define	FP_SOFT_IN_STATEC_CB		0x0010
99 #define	FP_SOFT_IN_UNSOL_CB		0x0020
100 #define	FP_SOFT_IN_LINK_RESET		0x0040
101 #define	FP_SOFT_BAD_LINK		0x0080
102 #define	FP_SOFT_IN_FCA_RESET		0x0100
103 #define	FP_DETACH_INPROGRESS		0x0200
104 #define	FP_DETACH_FAILED		0x0400
105 #define	FP_SOFT_NO_PMCOMP		0x0800
106 
107 /*
108  * Instruct the port driver to just accept logins from these addresses
109  */
110 #define	FC_MUST_ACCEPT_D_ID(x)		(FC_WELL_KNOWN_ADDR(x) || (x) == 0)
111 
112 #define	FC_IS_REAL_DEVICE(x)		(!FC_MUST_ACCEPT_D_ID(x))
113 
114 /*
115  * Bit definitions for fp_options field in fc_local_port_t
116  * structure for Feature and Hack additions to make
117  * the driver code a real hairball.
118  */
119 #define	FP_NS_SMART_COUNT			0x01
120 #define	FP_SEND_RJT				0x02
121 #define	FP_CORE_ON_OFFLINE_TIMEOUT		0x04
122 #define	FP_RESET_CORE_ON_OFFLINE_TIMEOUT	0x08
123 #define	FP_TARGET_MODE				0x10
124 
125 
126 /*
127  * Values for fp_pm_level in the fc_local_port_t struct. Tracks current PM
128  * level for the local port.
129  */
130 #define	FP_PM_PORT_DOWN			0
131 #define	FP_PM_PORT_UP			1
132 
133 
134 /*
135  * FC port compoment for PM. Used with pm_raise_power() and friends.
136  */
137 #define	FP_PM_COMPONENT			0
138 
139 
140 #define	FCTL_WWN_SIZE(wwn)		\
141 	(sizeof ((wwn)->raw_wwn) / sizeof ((wwn)->raw_wwn[0]))
142 
143 
144 /*
145  * Structure for issuing a work request to the per-instance "job handler"
146  * thread. Primarily allocated/initialized by fctl_alloc_job() and freed by
147  * fctl_dealloc_job().  fctl keeps a kmem_cache of these structs anchored by the
148  * fctl_job_cache global variable.  The cache is created at fctl's _init(9E) and
149  * destroyed at fctl's _fini(9E).  See also fctl_cache_constructor()
150  * and fctl_cache_destructor().
151  */
152 typedef struct job_request {
153 	/*
154 	 * ID code for the job or task to be performed.  Set by fctl_alloc_job()
155 	 * and read by fp_job_handler().
156 	 */
157 	int		job_code;
158 
159 	/*
160 	 * Completion status of the request.  Typically FC_SUCCESS or
161 	 * FC_FAILURE, but may make use of other error code values (such as
162 	 * FC_OFFLINE, FC_BADCMD, FC_NO_MAP, and friends). The complete set
163 	 * of values is not clearly specified.
164 	 */
165 	int		job_result;
166 
167 	/* Execution control flags (defined below) */
168 	int		job_flags;
169 
170 	/*
171 	 * This allows multiple concurrent operations using the same
172 	 * job_request_t struct, such as a PLOGI to a group of remote ports
173 	 * (see fp_plogi_group()).
174 	 *
175 	 * This is why this scheme needs the job_mutex to protect
176 	 * the job_counter variable, plus the additional job_port_sema for
177 	 * synchronizing thread(s).
178 	 */
179 	int		job_counter;
180 
181 
182 	opaque_t	job_cb_arg;		/* callback func arg */
183 
184 	kmutex_t	job_mutex;
185 	ksema_t		job_fctl_sema;
186 	ksema_t		job_port_sema;
187 
188 
189 	void		(*job_comp) (opaque_t, uchar_t result);
190 	fc_packet_t	**job_ulp_pkts;
191 	uint32_t	job_ulp_listlen;	/* packet list length */
192 	void		*job_private;		/* caller's private */
193 	void		*job_arg;		/* caller's argument */
194 
195 	/*
196 	 * Pointer for singly-liked list of outstanding job_request structs,
197 	 * maintained on a per-instance basis by the fp_port_head and
198 	 * fp_port_tail pointers in the fc_local_port_t struct.
199 	 */
200 	struct job_request 	*job_next;
201 } job_request_t;
202 
203 
204 #if	!defined(__lint)
205 _NOTE(SCHEME_PROTECTS_DATA("unique per request",
206 	job_request::job_code job_request::job_result job_request::job_flags
207 	job_request::job_cb_arg job_request::job_comp
208 	job_request::job_ulp_pkts job_request::job_ulp_listlen
209 	job_request::job_private job_request::job_arg))
210 _NOTE(MUTEX_PROTECTS_DATA(fc_local_port::fp_mutex, job_request::job_next))
211 _NOTE(MUTEX_PROTECTS_DATA(job_request::job_mutex, job_request::job_counter))
212 #endif	/* __lint */
213 
214 
215 /*
216  * Values for the job_code field in the job_request_t struct.
217  */
218 #define	JOB_ATTACH_ULP			1	/* ULP call to fc_ulp_add() */
219 #define	JOB_PORT_STARTUP		2
220 #define	JOB_PORT_GETMAP			3
221 #define	JOB_PORT_GETMAP_PLOGI_ALL	4
222 #define	JOB_PLOGI_ONE			5
223 #define	JOB_PLOGI_GROUP			6
224 #define	JOB_LOGO_ONE			7
225 #define	JOB_PORT_OFFLINE		8
226 #define	JOB_PORT_ONLINE			9
227 
228 /* Prepare the local port and the driver softstate for a DDI_DETACH. */
229 #define	JOB_PORT_SHUTDOWN		10
230 
231 /* Handle an unsolicited request in the job thread */
232 #define	JOB_UNSOL_REQUEST		11
233 
234 #define	JOB_NS_CMD			12
235 #define	JOB_LINK_RESET			13
236 #define	JOB_ULP_NOTIFY			14
237 
238 #define	JOB_FCIO_LOGIN			15
239 #define	JOB_FCIO_LOGOUT			16
240 
241 /*
242  * This is used for requests that will not actually be dispatched to the job
243  * thread.
244  */
245 #define	JOB_DUMMY			127
246 
247 
248 /*
249  * Bitmask values for the job_flags field in the job_request_t struct.
250  *
251  * JOB_TYPE_FCTL_ASYNC is set in various places in fp and fctl. If set then
252  * fctl_jobdone() will call the completion function in the job_comp field and
253  * deallocate the job_request_t struct.  If not set then fctl_jobdone() will
254  * sema_v() the job_fctl_sema to wake up any waiting thread.  This bit is also
255  * checked in fc_ulp_login(): if *clear* then fc_ulp_login() will call
256  * fctl_jobwait() in order to block the calling thread in the job_fctl_sema, and
257  * then call fctl_dealloc_job() after fctl_jobwait() returns.
258  *
259  * JOB_TYPE_FP_ASYNC is set in various places in fp. If set then fp_jobdone()
260  * will call fctl_jobdone(); if clear then fp_jobdone() will sema_v() the
261  * job_port_sema in the job_request_t.  fp_port_shutdown() also looks for
262  * JOB_TYPE_FP_ASYNC.  Just to keep thing interesting, JOB_TYPE_FP_ASYNC is
263  * also set in fp_validate_area_domain() and cleared in fp_fcio_login() and
264  * fp_ns_get_devcount()
265  *
266  * The apparent purpose of all this is to allow nested job requests to
267  * occur in parallel.
268  *
269  * JOB_CANCEL_ULP_NOTIFICATION appears to be intended to  the number of
270  * state change callbacks that are reported to ULPs when mutiple state
271  * changes are being processed in parallel.
272  */
273 #define	JOB_TYPE_FCTL_ASYNC		0x01
274 #define	JOB_TYPE_FP_ASYNC		0x02
275 #define	JOB_CANCEL_ULP_NOTIFICATION	0x10
276 
277 
278 
279 typedef struct fc_port_clist {
280 	opaque_t	clist_port;		/* port handle */
281 	uint32_t	clist_state;		/* port state */
282 	uint32_t	clist_len;		/* map len */
283 	uint32_t	clist_size;		/* alloc len */
284 	fc_portmap_t 	*clist_map;		/* changelist */
285 	uint32_t	clist_flags;		/* port topology */
286 	uint32_t	clist_wait;		/* for synchronous requests */
287 	kmutex_t	clist_mutex;		/* clist lock */
288 	kcondvar_t	clist_cv;		/* clist cv */
289 } fc_port_clist_t;
290 
291 #if	!defined(__lint)
292 _NOTE(SCHEME_PROTECTS_DATA("unique per state change", fc_port_clist))
293 #endif	/* __lint */
294 
295 /*
296  * The cmd_size and resp_size shouldn't include the CT HEADER.
297  *
298  * For commands like GAN, the ns_resp_size should indicate the
299  * total number of bytes allocated in the ns_resp_buf to get all
300  * the NS objects.
301  */
302 typedef struct fctl_ns_req {
303 	int			ns_result;
304 	uint32_t		ns_gan_index;
305 	uint32_t		ns_gan_sid;
306 	uint32_t		ns_flags;
307 	uint16_t		ns_cmd_code;	/* NS command code */
308 	caddr_t			ns_cmd_buf;	/* NS command buffer */
309 	uint16_t		ns_cmd_size;	/* NS command length */
310 	uint16_t		ns_resp_size;	/* NS response length */
311 	caddr_t			ns_data_buf;	/* User buffer */
312 	uint32_t		ns_data_len;	/* User buffer length */
313 	uint32_t		ns_gan_max;
314 	fc_ct_header_t		ns_resp_hdr;
315 	fc_remote_port_t	*ns_pd;
316 } fctl_ns_req_t;
317 
318 #if	!defined(__lint)
319 _NOTE(SCHEME_PROTECTS_DATA("unique per state change", fctl_ns_req))
320 #endif	/* __lint */
321 
322 /*
323  * Orphan list of Port WWNs
324  */
325 typedef struct fc_orphan {
326 	int			orp_nscan;	/* Number of scans */
327 	clock_t			orp_tstamp;	/* When it disappeared */
328 	la_wwn_t		orp_pwwn;	/* Port WWN */
329 	struct fc_orphan	*orp_next;	/* Next orphan */
330 } fc_orphan_t;
331 
332 #if	!defined(__lint)
333 _NOTE(SCHEME_PROTECTS_DATA("scans don't interleave",
334 	fc_orphan::orp_nscan fc_orphan::orp_pwwn fc_orphan::orp_tstamp))
335 _NOTE(MUTEX_PROTECTS_DATA(fc_local_port::fp_mutex, fc_orphan::orp_next))
336 #endif /* __lint */
337 
338 
339 fc_remote_node_t *fctl_create_remote_node(la_wwn_t *nwwn, int sleep);
340 void fctl_destroy_remote_node(fc_remote_node_t *rnp);
341 fc_remote_port_t *fctl_create_remote_port(fc_local_port_t *port,
342     la_wwn_t *node_wwn, la_wwn_t *port_wwn, uint32_t d_id,
343     uchar_t recepient, int sleep);
344 int fctl_destroy_remote_port(fc_local_port_t *port, fc_remote_port_t *pd);
345 fc_remote_port_t *fctl_alloc_remote_port(fc_local_port_t *port,
346     la_wwn_t *port_wwn, uint32_t d_id, uchar_t recepient, int sleep);
347 void fctl_dealloc_remote_port(fc_remote_port_t *pd);
348 void fctl_release_remote_port(fc_remote_port_t *pd);
349 void fctl_destroy_all_remote_ports(fc_local_port_t *port);
350 void fctl_link_remote_port_to_remote_node(fc_remote_node_t *rnp,
351     fc_remote_port_t *pd);
352 int fctl_unlink_remote_port_from_remote_node(fc_remote_node_t *rnp,
353     fc_remote_port_t *pd);
354 
355 job_request_t *fctl_alloc_job(int job_code, int job_flags,
356     void (*comp) (opaque_t, uchar_t), opaque_t arg, int sleep);
357 void fctl_dealloc_job(job_request_t *job);
358 void fctl_enque_job(fc_local_port_t *port, job_request_t *job);
359 void fctl_priority_enque_job(fc_local_port_t *port, job_request_t *job);
360 job_request_t *fctl_deque_job(fc_local_port_t *port);
361 void fctl_jobwait(job_request_t *job);
362 void fctl_jobdone(job_request_t *job);
363 
364 void fctl_attach_ulps(fc_local_port_t *port, fc_attach_cmd_t cmd,
365     struct modlinkage *linkage);
366 int fctl_detach_ulps(fc_local_port_t *port, fc_detach_cmd_t cmd,
367     struct modlinkage *linkage);
368 
369 void fctl_add_port(fc_local_port_t *port);
370 void fctl_remove_port(fc_local_port_t *port);
371 int fctl_busy_port(fc_local_port_t *port);
372 void fctl_idle_port(fc_local_port_t *port);
373 
374 fc_remote_port_t *fctl_get_remote_port_by_did(fc_local_port_t *port,
375     uint32_t d_id);
376 fc_remote_port_t *fctl_hold_remote_port_by_did(fc_local_port_t *port,
377     uint32_t d_id);
378 fc_remote_port_t *fctl_get_remote_port_by_pwwn(fc_local_port_t *port,
379     la_wwn_t *pwwn);
380 fc_remote_port_t *fctl_hold_remote_port_by_pwwn(fc_local_port_t *port,
381     la_wwn_t *pwwn);
382 fc_remote_port_t *
383     fctl_get_remote_port_by_pwwn_mutex_held(fc_local_port_t *port,
384     la_wwn_t *pwwn);
385 fc_remote_node_t *fctl_get_remote_node_by_nwwn(la_wwn_t *node_wwn);
386 fc_remote_node_t *fctl_lock_remote_node_by_nwwn(la_wwn_t *node_wwn);
387 fc_remote_port_t *fctl_lookup_pd_by_did(fc_local_port_t *port, uint32_t d_id);
388 fc_remote_port_t *fctl_lookup_pd_by_index(fc_local_port_t *port,
389     uint32_t index);
390 fc_remote_port_t *fctl_lookup_pd_by_wwn(fc_local_port_t *port, la_wwn_t wwn);
391 
392 void fctl_enlist_did_table(fc_local_port_t *port, fc_remote_port_t *pd);
393 void fctl_delist_did_table(fc_local_port_t *port, fc_remote_port_t *pd);
394 void fctl_enlist_pwwn_table(fc_local_port_t *port, fc_remote_port_t *pd);
395 void fctl_delist_pwwn_table(fc_local_port_t *port, fc_remote_port_t *pd);
396 int fctl_enlist_nwwn_table(fc_remote_node_t *rnp, int sleep);
397 void fctl_delist_nwwn_table(fc_remote_node_t *rnp);
398 
399 void fctl_ulp_statec_cb(void *arg);
400 void fctl_ulp_unsol_cb(fc_local_port_t *port, fc_unsol_buf_t *buf,
401     uchar_t type);
402 int fctl_ulp_port_ioctl(fc_local_port_t *port, dev_t dev, int cmd,
403     intptr_t data, int mode, cred_t *credp, int *rval);
404 
405 void fctl_fillout_map(fc_local_port_t *port, fc_portmap_t **map,
406     uint32_t *len, int whole_map, int justcopy, int orphan);
407 void fctl_copy_portmap_held(fc_portmap_t *map, fc_remote_port_t *pd);
408 void fctl_copy_portmap(fc_portmap_t *map, fc_remote_port_t *pd);
409 
410 fctl_ns_req_t *fctl_alloc_ns_cmd(uint32_t cmd_len, uint32_t resp_len,
411     uint32_t data_len, uint32_t ns_flags, int sleep);
412 void fctl_free_ns_cmd(fctl_ns_req_t *ns_cmd);
413 
414 int fctl_remove_if_orphan(fc_local_port_t *port, la_wwn_t *pwwn);
415 int fctl_add_orphan_held(fc_local_port_t *port, fc_remote_port_t *pd);
416 int fctl_add_orphan(fc_local_port_t *port, fc_remote_port_t *pd, int sleep);
417 void fctl_remove_oldies(fc_local_port_t *port);
418 
419 int fctl_is_wwn_zero(la_wwn_t *wwn);
420 int fctl_wwn_cmp(la_wwn_t *src, la_wwn_t *dst);
421 int fctl_atoi(caddr_t string, int base);
422 int fctl_count_fru_ports(fc_local_port_t *port, int npivflag);
423 fc_local_port_t *fctl_get_adapter_port_by_index(fc_local_port_t *port,
424 	uint32_t port_index);
425 
426 void fctl_tc_constructor(timed_counter_t *tc, uint32_t max_value,
427     clock_t timer);
428 void fctl_tc_destructor(timed_counter_t *tc);
429 boolean_t fctl_tc_increment(timed_counter_t *tc);
430 void fctl_tc_reset(timed_counter_t *tc);
431 
432 #ifdef	__cplusplus
433 }
434 #endif
435 
436 #endif	/* _FC_PORTIF_H */
437