xref: /titanic_50/usr/src/uts/sun4u/ngdr/sys/dr.h (revision e07d9cb85217949d497b02d7211de8a197d2f2eb)
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 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef _SYS_DR_H
27 #define	_SYS_DR_H
28 
29 #pragma ident	"%Z%%M%	%I%	%E% SMI"
30 
31 #ifdef	__cplusplus
32 extern "C" {
33 #endif
34 
35 #include <sys/types.h>
36 #include <sys/processor.h>
37 #include <sys/obpdefs.h>
38 #include <sys/memlist.h>
39 #include <sys/sbd_ioctl.h>
40 #include <sys/mem_config.h>
41 #include <sys/dr_util.h>
42 #include <sys/drmach.h>
43 #include <sys/param.h>			/* for MAXPATHLEN */
44 #include <sys/varargs.h>
45 #include <sys/note.h>
46 
47 #define	DR_MAXNUM_NT		3
48 
49 /* used to map sbd_comp_type_t to array index */
50 #define	NIX(t)							\
51 	(((t) == SBD_COMP_CPU) ? 0 :				\
52 	((t) == SBD_COMP_MEM) ? 1 :				\
53 	((t) == SBD_COMP_IO) ? 2 :				\
54 	((t) == SBD_COMP_CMP) ? 0 : DR_MAXNUM_NT)
55 
56 #define	BIX(t)							\
57 	(((t) == SBD_COMP_CPU) ? 0 :				\
58 	((t) == SBD_COMP_MEM) ? 32 :				\
59 	((t) == SBD_COMP_IO) ? 40 :				\
60 	((t) == SBD_COMP_CMP) ? 0 : 0)
61 
62 #define	NMASK(t)						\
63 	(((t) == SBD_COMP_CPU) ? ((dr_devset_t)0xffffffff) :	\
64 	((t) == SBD_COMP_MEM) ? ((dr_devset_t)0x1) :		\
65 	((t) == SBD_COMP_IO) ? ((dr_devset_t)0x1ff) :		\
66 	((t) == SBD_COMP_CMP) ? ((dr_devset_t)0xffffffff) : 0)
67 
68 /*
69  * helper macros for constructing and reporting internal error messages.
70  * NOTE: each module which uses one or more this these macros is expected
71  * to supply a char *dr_ie_fmt string containing the SCCS filename
72  * expansion macro (percent M percent) and a sprintf %d to render the
73  * line number argument.
74  */
75 #define	DR_INTERNAL_ERROR(hp)				\
76 	drerr_new(1, ESBD_INTERNAL, dr_ie_fmt, __LINE__)
77 
78 #define	DR_OP_INTERNAL_ERROR(hp)			\
79 	drerr_set_c(CE_WARN, &(hp)->h_err,		\
80 		ESBD_INTERNAL, dr_ie_fmt, __LINE__)
81 
82 #define	DR_DEV_INTERNAL_ERROR(cp)			\
83 	drerr_set_c(CE_WARN, &(cp)->sbdev_error,	\
84 		ESBD_INTERNAL, dr_ie_fmt, __LINE__)
85 
86 /*
87  * TODO: Simplify or get rid of this.
88  * Macros for keeping an error code and an associated list of integers.
89  */
90 #define	DR_MAX_ERR_INT		(32)
91 #define	DR_GET_E_CODE(sep)	((sep)->e_code)
92 #define	DR_SET_E_CODE(sep, en)	((sep)->e_code = (en))
93 #define	DR_GET_E_RSC(sep)	((sep)->e_rsc)
94 
95 /*
96  * Format of dr_devset_t bit masks:
97  *
98  * 64        48        40        32        24        16        8         0
99  *  |....|...I|IIII|IIII|....|...M|CCCC|CCCC|CCCC|CCCC|CCCC|CCCC|CCCC|CCCC|
100  *
101  * 1 = indicates respective component present/attached.
102  * I = I/O, M = Memory, C = CPU.
103  */
104 #define	_NT2DEVPOS(t, u)	(BIX(t) + (u))
105 #define	_DEVSET_MASK		((dr_devset_t)0x1ff01ffffffff)
106 #define	_CMP_DEVSET_MASK	((dr_devset_t)0x11111111)
107 #define	DEVSET_ONEUNIT		((dr_devset_t)1)
108 #define	DEVSET_ANYUNIT		(dr_devset_t)(-1)
109 #define	DEVSET(t, u) \
110 	(((u) == DEVSET_ANYUNIT) ? \
111 		((NMASK(t) << _NT2DEVPOS((t), 0)) & _DEVSET_MASK) : \
112 	((t) == SBD_COMP_CMP) ? \
113 		(_CMP_DEVSET_MASK << _NT2DEVPOS((t), (u))) : \
114 		(DEVSET_ONEUNIT << _NT2DEVPOS((t), (u))))
115 
116 #define	DEVSET_IN_SET(ds, t, u)	(((ds) & DEVSET((t), (u))) != 0)
117 #define	DEVSET_ADD(ds, t, u)	((ds) |= DEVSET((t), (u)))
118 #define	DEVSET_DEL(ds, t, u)	((ds) &= ~DEVSET((t), (u)))
119 #define	DEVSET_GET_UNITSET(ds, t) \
120 	(((ds) & DEVSET((t), DEVSET_ANYUNIT)) >> _NT2DEVPOS((t), 0))
121 
122 /*
123  * Ops for dr_board_t.b_dev_*
124  */
125 #define	DR_DEV_IS(ds, cp)	DEVSET_IN_SET( \
126 					(cp)->sbdev_bp->b_dev_##ds, \
127 					(cp)->sbdev_type, \
128 					(cp)->sbdev_unum)
129 
130 #define	DR_DEV_ADD(ds, cp)	DEVSET_ADD( \
131 					(cp)->sbdev_bp->b_dev_##ds, \
132 					(cp)->sbdev_type, \
133 					(cp)->sbdev_unum)
134 
135 #define	DR_DEV_DEL(ds, cp)	DEVSET_DEL( \
136 					(cp)->sbdev_bp->b_dev_##ds, \
137 					(cp)->sbdev_type, \
138 					(cp)->sbdev_unum)
139 
140 /*
141  * Ops for dr_board_t.b_dev_present
142  */
143 #define	DR_DEV_IS_PRESENT(cp)		DR_DEV_IS(present, cp)
144 #define	DR_DEV_SET_PRESENT(cp)		DR_DEV_ADD(present, cp)
145 #define	DR_DEV_CLR_PRESENT(cp)		DR_DEV_DEL(present, cp)
146 
147 /*
148  * Ops for dr_board_t.b_dev_attached
149  */
150 #define	DR_DEV_IS_ATTACHED(cp)		DR_DEV_IS(attached, cp)
151 #define	DR_DEV_SET_ATTACHED(cp)		DR_DEV_ADD(attached, cp)
152 #define	DR_DEV_CLR_ATTACHED(cp)		DR_DEV_DEL(attached, cp)
153 
154 /*
155  * Ops for dr_board_t.b_dev_released
156  */
157 #define	DR_DEV_IS_RELEASED(cp)		DR_DEV_IS(released, cp)
158 #define	DR_DEV_SET_RELEASED(cp)		DR_DEV_ADD(released, cp)
159 #define	DR_DEV_CLR_RELEASED(cp)		DR_DEV_DEL(released, cp)
160 
161 /*
162  * Ops for dr_board_t.b_dev_unreferenced
163  */
164 #define	DR_DEV_IS_UNREFERENCED(cp)	DR_DEV_IS(unreferenced, cp)
165 #define	DR_DEV_SET_UNREFERENCED(cp)	DR_DEV_ADD(unreferenced, cp)
166 #define	DR_DEV_CLR_UNREFERENCED(cp)	DR_DEV_DEL(unreferenced, cp)
167 
168 #define	DR_DEVS_PRESENT(bp) \
169 			((bp)->b_dev_present)
170 #define	DR_DEVS_ATTACHED(bp) \
171 			((bp)->b_dev_attached)
172 #define	DR_DEVS_RELEASED(bp) \
173 			((bp)->b_dev_released)
174 #define	DR_DEVS_UNREFERENCED(bp) \
175 			((bp)->b_dev_unreferenced)
176 #define	DR_DEVS_UNATTACHED(bp) \
177 			((bp)->b_dev_present & ~(bp)->b_dev_attached)
178 #define	DR_DEVS_CONFIGURE(bp, devs) \
179 			((bp)->b_dev_attached = (devs))
180 #define	DR_DEVS_DISCONNECT(bp, devs) \
181 			((bp)->b_dev_present &= ~(devs))
182 #define	DR_DEVS_CANCEL(bp, devs) \
183 			((bp)->b_dev_released &= ~(devs), \
184 			(bp)->b_dev_unreferenced &= ~(devs))
185 
186 /*
187  * CMP Specific Helpers
188  */
189 #define	DR_CMP_CORE_UNUM(cmp, core)	(cmp + (core * 4))
190 /*
191  * DR_UNUM2SBD_UNUM should be set to (unum & (max #of CMP on board - 1))
192  * for all the platforms.  So far, all sun4u platforms supported have
193  * the same limit so 0x3 works.  One day we might have to make this
194  * a platform specific macro.
195  */
196 
197 #define	DR_UNUM2SBD_UNUM(n, d)		((d == SBD_COMP_IO) ? (n & 0xf) : \
198 					(d == SBD_COMP_CPU) ? (n & 0x3) : \
199 					(d == SBD_COMP_CMP) ? (n & 0x3) : \
200 						(n))
201 
202 /*
203  * Some stuff to assist in debug.
204  */
205 #ifdef DEBUG
206 #define	DRDBG_STATE	0x00000001
207 #define	DRDBG_QR	0x00000002
208 #define	DRDBG_CPU	0x00000004
209 #define	DRDBG_MEM	0x00000008
210 #define	DRDBG_IO	0x00000010
211 
212 #define	PR_ALL		if (dr_debug)			printf
213 #define	PR_STATE	if (dr_debug & DRDBG_STATE)	printf
214 #define	PR_QR		if (dr_debug & DRDBG_QR)	prom_printf
215 #define	PR_CPU		if (dr_debug & DRDBG_CPU)	printf
216 #define	PR_MEM		if (dr_debug & DRDBG_MEM)	printf
217 #define	PR_IO		if (dr_debug & DRDBG_IO)	printf
218 #define	PR_MEMLIST_DUMP	if (dr_debug & DRDBG_MEM)	MEMLIST_DUMP
219 
220 extern uint_t	dr_debug;
221 #else /* DEBUG */
222 #define	PR_ALL		_NOTE(CONSTANTCONDITION) if (0) printf
223 #define	PR_STATE	PR_ALL
224 #define	PR_QR		PR_ALL
225 #define	PR_CPU		PR_ALL
226 #define	PR_MEM		PR_ALL
227 #define	PR_IO		PR_ALL
228 #define	PR_MEMLIST_DUMP	_NOTE(CONSTANTCONDITION) if (0) MEMLIST_DUMP
229 
230 #endif /* DEBUG */
231 
232 /*
233  * dr_board_t b_sflags.
234  */
235 #define	DR_BSLOCK	0x01	/* for blocking status (protected by b_slock) */
236 
237 typedef const char	*fn_t;
238 typedef uint64_t	dr_devset_t;	/* TODO: fix limitation */
239 
240 /*
241  * Unsafe devices based on dr.conf prop "unsupported-io-drivers"
242  */
243 typedef struct {
244 	char	**devnames;
245 	uint_t	ndevs;
246 } dr_unsafe_devs_t;
247 
248 /*
249  * Device states.
250  * PARTIAL state is really only relevant for board state.
251  */
252 typedef enum {
253 	DR_STATE_EMPTY = 0,
254 	DR_STATE_OCCUPIED,
255 	DR_STATE_CONNECTED,
256 	DR_STATE_UNCONFIGURED,
257 	DR_STATE_PARTIAL,		/* part connected, part configured */
258 	DR_STATE_CONFIGURED,
259 	DR_STATE_RELEASE,
260 	DR_STATE_UNREFERENCED,
261 	DR_STATE_FATAL,
262 	DR_STATE_MAX
263 } dr_state_t;
264 
265 typedef struct dr_handle {
266 	struct dr_board	*h_bd;
267 	sbd_error_t	*h_err;
268 	int		h_op_intr;	/* nz if op interrupted */
269 	dev_t		h_dev;		/* dev_t of opened device */
270 	int		h_cmd;		/* PIM ioctl argument */
271 	int		h_mode;		/* device open mode */
272 	sbd_cmd_t 	h_sbdcmd;	/* copied-in ioctl cmd struct */
273 	sbd_ioctl_arg_t	*h_iap;		/* ptr to caller-space cmd struct */
274 	dr_devset_t	h_devset;	/* based on h_dev */
275 	uint_t		h_ndi;
276 	drmach_opts_t	h_opts;		/* command-line platform options */
277 } dr_handle_t;
278 
279 typedef struct dr_common_unit {
280 	dr_state_t		sbdev_state;
281 	sbd_state_t		sbdev_ostate;
282 	sbd_cond_t		sbdev_cond;
283 	time_t			sbdev_time;
284 	int			sbdev_busy;
285 	struct dr_board		*sbdev_bp;
286 	int			sbdev_unum;
287 	sbd_comp_type_t		sbdev_type;
288 	drmachid_t		sbdev_id;
289 	char			sbdev_path[MAXNAMELEN];
290 	sbd_error_t		*sbdev_error;
291 } dr_common_unit_t;
292 
293 typedef struct dr_mem_unit {
294 	dr_common_unit_t	sbm_cm;		/* mem-unit state */
295 	uint_t			sbm_flags;
296 	pfn_t			sbm_basepfn;
297 	pgcnt_t			sbm_npages;
298 	pgcnt_t			sbm_pageslost;
299 	struct memlist		*sbm_dyn_segs;	/* kphysm_add_dynamic segs */
300 	/*
301 	 * The following fields are used during
302 	 * the memory detach process only. sbm_mlist
303 	 * will be used to store the board memlist
304 	 * following a detach.  The memlist will be
305 	 * used to re-attach the board when configuring
306 	 * the unit directly after an unconfigure.
307 	 */
308 	struct dr_mem_unit	*sbm_peer;
309 	struct memlist		*sbm_mlist;
310 	struct memlist		*sbm_del_mlist;
311 	memhandle_t		sbm_memhandle;
312 	pfn_t			sbm_alignment_mask;
313 	pfn_t			sbm_slice_offset;
314 	uint64_t		sbm_slice_size;
315 } dr_mem_unit_t;
316 
317 /*
318  * Currently only maintain state information for individual
319  * components.
320  */
321 typedef struct dr_cpu_unit {
322 	dr_common_unit_t	sbc_cm;		/* cpu-unit state */
323 	processorid_t		sbc_cpu_id;
324 	cpu_flag_t		sbc_cpu_flags;	/* snapshot of CPU flags */
325 	ushort_t		sbc_pad1;	/* padded for compatibility */
326 	int			sbc_speed;
327 	int			sbc_ecache;
328 	int			sbc_cpu_impl;
329 } dr_cpu_unit_t;
330 
331 typedef struct dr_io_unit {
332 	dr_common_unit_t	sbi_cm;		/* io-unit state */
333 } dr_io_unit_t;
334 
335 typedef union {
336 	dr_common_unit_t	du_common;
337 	dr_mem_unit_t		du_mem;
338 	dr_cpu_unit_t		du_cpu;
339 	dr_io_unit_t		du_io;
340 } dr_dev_unit_t;
341 
342 typedef struct dr_board {
343 	kmutex_t	b_lock;		/* lock for this board struct */
344 	kmutex_t	b_slock;	/* lock for status on the board */
345 	kcondvar_t	b_scv;		/* condvar for status on the board */
346 	int		b_sflags;	/* for serializing status */
347 	sbd_state_t	b_rstate;	/* board's cfgadm receptacle state */
348 	sbd_state_t	b_ostate;	/* board's cfgadm occupant state */
349 	sbd_cond_t	b_cond;		/* cfgadm condition */
350 	int		b_busy;
351 	int		b_assigned;
352 	time_t		b_time;		/* time of last board operation */
353 	char		b_type[MAXNAMELEN];
354 	drmachid_t	b_id;
355 	int		b_num;			/* board number */
356 	int		b_ndev;			/* # of devices on board */
357 	dev_info_t	*b_dip;			/* dip for make-nodes */
358 	dr_state_t	b_state;		/* board DR state */
359 	dr_devset_t	b_dev_present;		/* present mask */
360 	dr_devset_t	b_dev_attached;		/* attached mask */
361 	dr_devset_t	b_dev_released;		/* released mask */
362 	dr_devset_t	b_dev_unreferenced;	/* unreferenced mask */
363 	char		b_path[MAXNAMELEN];
364 	dr_dev_unit_t	*b_dev[DR_MAXNUM_NT];
365 } dr_board_t;
366 
367 /*
368  * dr_quiesce.c interfaces
369  */
370 struct dr_sr_handle;
371 typedef struct dr_sr_handle dr_sr_handle_t;
372 
373 extern dr_sr_handle_t	*dr_get_sr_handle(dr_handle_t *handle);
374 extern void		dr_release_sr_handle(dr_sr_handle_t *srh);
375 extern int		dr_suspend(dr_sr_handle_t *srh);
376 extern void		dr_resume(dr_sr_handle_t *srh);
377 extern void		dr_check_devices(dev_info_t *dip, int *refcount,
378 					dr_handle_t *handle, uint64_t *arr,
379 					int *idx, int len);
380 extern int		dr_pt_test_suspend(dr_handle_t *hp);
381 
382 /*
383  * dr_cpu.c interface
384  */
385 extern void		dr_init_cpu_unit(dr_cpu_unit_t *cp);
386 extern int		dr_pre_attach_cpu(dr_handle_t *hp,
387 				dr_common_unit_t **devlist, int devnum);
388 extern void		dr_attach_cpu(dr_handle_t *hp, dr_common_unit_t *cp);
389 extern int		dr_post_attach_cpu(dr_handle_t *hp,
390 				dr_common_unit_t **devlist, int devnum);
391 extern int		dr_pre_release_cpu(dr_handle_t *hp,
392 				dr_common_unit_t **devlist, int devnum);
393 extern int		dr_pre_detach_cpu(dr_handle_t *hp,
394 				dr_common_unit_t **devlist, int devnum);
395 extern void		dr_detach_cpu(dr_handle_t *hp, dr_common_unit_t *cp);
396 extern int		dr_post_detach_cpu(dr_handle_t *hp,
397 				dr_common_unit_t **devlist, int devnum);
398 extern int		dr_cpu_status(dr_handle_t *hp, dr_devset_t devset,
399 					sbd_dev_stat_t *dsp);
400 extern int		dr_cancel_cpu(dr_cpu_unit_t *cp);
401 extern int		dr_disconnect_cpu(dr_cpu_unit_t *cp);
402 
403 
404 /*
405  * dr_mem.c interface
406  */
407 extern void		dr_init_mem_unit(dr_mem_unit_t *mp);
408 extern int		dr_pre_attach_mem(dr_handle_t *hp,
409 				dr_common_unit_t **devlist, int devnum);
410 extern void		dr_attach_mem(dr_handle_t *hp, dr_common_unit_t *cp);
411 extern int		dr_post_attach_mem(dr_handle_t *hp,
412 				dr_common_unit_t **devlist, int devnum);
413 extern int		dr_pre_release_mem(dr_handle_t *hp,
414 				dr_common_unit_t **devlist, int devnum);
415 extern void		dr_release_mem(dr_common_unit_t *cp);
416 extern void		dr_release_mem_done(dr_common_unit_t *cp);
417 extern int		dr_pre_detach_mem(dr_handle_t *hp,
418 				dr_common_unit_t **devlist, int devnum);
419 extern void		dr_detach_mem(dr_handle_t *, dr_common_unit_t *);
420 extern int		dr_post_detach_mem(dr_handle_t *hp,
421 				dr_common_unit_t **devlist, int devnum);
422 extern int		dr_mem_status(dr_handle_t *hp, dr_devset_t devset,
423 					sbd_dev_stat_t *dsp);
424 extern int		dr_cancel_mem(dr_mem_unit_t *mp);
425 extern int		dr_disconnect_mem(dr_mem_unit_t *mp);
426 
427 /*
428  * dr_io.c interface
429  */
430 extern void		dr_init_io_unit(dr_io_unit_t *io);
431 extern int		dr_disconnect_io(dr_io_unit_t *ip);
432 extern int		dr_pre_attach_io(dr_handle_t *hp,
433 				dr_common_unit_t **devlist, int devnum);
434 extern void		dr_attach_io(dr_handle_t *hp, dr_common_unit_t *cp);
435 extern int		dr_post_attach_io(dr_handle_t *hp,
436 				dr_common_unit_t **devlist, int devnum);
437 extern int		dr_pre_release_io(dr_handle_t *hp,
438 				dr_common_unit_t **devlist, int devnum);
439 extern int		dr_pre_detach_io(dr_handle_t *hp,
440 				dr_common_unit_t **devlist, int devnum);
441 extern void		dr_detach_io(dr_handle_t *hp, dr_common_unit_t *cp);
442 extern int		dr_post_detach_io(dr_handle_t *hp,
443 				dr_common_unit_t **devlist, int devnum);
444 extern int		dr_io_status(dr_handle_t *hp, dr_devset_t devset,
445 					sbd_dev_stat_t *dsp);
446 
447 
448 /*
449  * dr.c interface
450  */
451 extern void dr_op_err(int ce, dr_handle_t *hp, int code, char *fmt, ...);
452 extern void dr_dev_err(int ce, dr_common_unit_t *cp, int code);
453 
454 extern dr_cpu_unit_t	*dr_get_cpu_unit(dr_board_t *bp, int unit_num);
455 extern dr_mem_unit_t	*dr_get_mem_unit(dr_board_t *bp, int unit_num);
456 extern dr_io_unit_t	*dr_get_io_unit(dr_board_t *bp, int unit_num);
457 
458 extern dr_board_t	*dr_lookup_board(int board_num);
459 extern int		dr_release_dev_done(dr_common_unit_t *cp);
460 extern char		*dr_nt_to_dev_type(int type);
461 extern void		dr_device_transition(dr_common_unit_t *cp,
462 				dr_state_t new_state);
463 extern void		dr_lock_status(dr_board_t *bp);
464 extern void		dr_unlock_status(dr_board_t *bp);
465 extern int		dr_cmd_flags(dr_handle_t *hp);
466 
467 #ifdef	__cplusplus
468 }
469 #endif
470 
471 #endif /* _SYS_DR_H */
472