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