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.
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.
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]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
33 #include <sys/types.h>
34 #include <sys/processor.h>
35 #include <sys/obpdefs.h>
36 #include <sys/memlist.h>
37 #include <sys/sbd_ioctl.h>
38 #include <sys/mem_config.h>
39 #include <sys/dr_util.h>
40 #include <sys/drmach.h>
41 #include <sys/param.h> /* for MAXPATHLEN */
42 #include <sys/varargs.h>
45 #define DR_MAXNUM_NT 3
47 /* used to map sbd_comp_type_t to array index */
49 (((t) == SBD_COMP_CPU) ? 0 : \
50 ((t) == SBD_COMP_MEM) ? 1 : \
51 ((t) == SBD_COMP_IO) ? 2 : \
52 ((t) == SBD_COMP_CMP) ? 0 : DR_MAXNUM_NT)
55 (((t) == SBD_COMP_CPU) ? 0 : \
56 ((t) == SBD_COMP_MEM) ? 32 : \
57 ((t) == SBD_COMP_IO) ? 40 : \
58 ((t) == SBD_COMP_CMP) ? 0 : 0)
61 (((t) == SBD_COMP_CPU) ? ((dr_devset_t)0xffffffff) : \
62 ((t) == SBD_COMP_MEM) ? ((dr_devset_t)0x1) : \
63 ((t) == SBD_COMP_IO) ? ((dr_devset_t)0x1ff) : \
64 ((t) == SBD_COMP_CMP) ? ((dr_devset_t)0xffffffff) : 0)
67 * helper macros for constructing and reporting internal error messages.
68 * NOTE: each module which uses one or more this these macros is expected
69 * to supply a char *dr_ie_fmt string containing the SCCS filename
70 * expansion macro (percent M percent) and a sprintf %d to render the
71 * line number argument.
73 #define DR_INTERNAL_ERROR(hp) \
74 drerr_new(1, ESBD_INTERNAL, dr_ie_fmt, __LINE__)
76 #define DR_OP_INTERNAL_ERROR(hp) \
77 drerr_set_c(CE_WARN, &(hp)->h_err, \
78 ESBD_INTERNAL, dr_ie_fmt, __LINE__)
80 #define DR_DEV_INTERNAL_ERROR(cp) \
81 drerr_set_c(CE_WARN, &(cp)->sbdev_error, \
82 ESBD_INTERNAL, dr_ie_fmt, __LINE__)
85 * TODO: Simplify or get rid of this.
86 * Macros for keeping an error code and an associated list of integers.
88 #define DR_MAX_ERR_INT (32)
89 #define DR_GET_E_CODE(sep) ((sep)->e_code)
90 #define DR_SET_E_CODE(sep, en) ((sep)->e_code = (en))
91 #define DR_GET_E_RSC(sep) ((sep)->e_rsc)
94 * Format of dr_devset_t bit masks:
96 * 64 48 40 32 24 16 8 0
97 * |....|...I|IIII|IIII|....|...M|CCCC|CCCC|CCCC|CCCC|CCCC|CCCC|CCCC|CCCC|
99 * 1 = indicates respective component present/attached.
100 * I = I/O, M = Memory, C = CPU.
102 #define _NT2DEVPOS(t, u) (BIX(t) + (u))
103 #define _DEVSET_MASK ((dr_devset_t)0x1ff01ffffffff)
104 #define _CMP_DEVSET_MASK ((dr_devset_t)0x11111111)
105 #define DEVSET_ONEUNIT ((dr_devset_t)1)
106 #define DEVSET_ANYUNIT (dr_devset_t)(-1)
107 #define DEVSET(t, u) \
108 (((u) == DEVSET_ANYUNIT) ? \
109 ((NMASK(t) << _NT2DEVPOS((t), 0)) & _DEVSET_MASK) : \
110 ((t) == SBD_COMP_CMP) ? \
111 (_CMP_DEVSET_MASK << _NT2DEVPOS((t), (u))) : \
112 (DEVSET_ONEUNIT << _NT2DEVPOS((t), (u))))
114 #define DEVSET_IN_SET(ds, t, u) (((ds) & DEVSET((t), (u))) != 0)
115 #define DEVSET_ADD(ds, t, u) ((ds) |= DEVSET((t), (u)))
116 #define DEVSET_DEL(ds, t, u) ((ds) &= ~DEVSET((t), (u)))
117 #define DEVSET_GET_UNITSET(ds, t) \
118 (((ds) & DEVSET((t), DEVSET_ANYUNIT)) >> _NT2DEVPOS((t), 0))
121 * Ops for dr_board_t.b_dev_*
123 #define DR_DEV_IS(ds, cp) DEVSET_IN_SET( \
124 (cp)->sbdev_bp->b_dev_##ds, \
128 #define DR_DEV_ADD(ds, cp) DEVSET_ADD( \
129 (cp)->sbdev_bp->b_dev_##ds, \
133 #define DR_DEV_DEL(ds, cp) DEVSET_DEL( \
134 (cp)->sbdev_bp->b_dev_##ds, \
139 * Ops for dr_board_t.b_dev_present
141 #define DR_DEV_IS_PRESENT(cp) DR_DEV_IS(present, cp)
142 #define DR_DEV_SET_PRESENT(cp) DR_DEV_ADD(present, cp)
143 #define DR_DEV_CLR_PRESENT(cp) DR_DEV_DEL(present, cp)
146 * Ops for dr_board_t.b_dev_attached
148 #define DR_DEV_IS_ATTACHED(cp) DR_DEV_IS(attached, cp)
149 #define DR_DEV_SET_ATTACHED(cp) DR_DEV_ADD(attached, cp)
150 #define DR_DEV_CLR_ATTACHED(cp) DR_DEV_DEL(attached, cp)
153 * Ops for dr_board_t.b_dev_released
155 #define DR_DEV_IS_RELEASED(cp) DR_DEV_IS(released, cp)
156 #define DR_DEV_SET_RELEASED(cp) DR_DEV_ADD(released, cp)
157 #define DR_DEV_CLR_RELEASED(cp) DR_DEV_DEL(released, cp)
160 * Ops for dr_board_t.b_dev_unreferenced
162 #define DR_DEV_IS_UNREFERENCED(cp) DR_DEV_IS(unreferenced, cp)
163 #define DR_DEV_SET_UNREFERENCED(cp) DR_DEV_ADD(unreferenced, cp)
164 #define DR_DEV_CLR_UNREFERENCED(cp) DR_DEV_DEL(unreferenced, cp)
166 #define DR_DEVS_PRESENT(bp) \
167 ((bp)->b_dev_present)
168 #define DR_DEVS_ATTACHED(bp) \
169 ((bp)->b_dev_attached)
170 #define DR_DEVS_RELEASED(bp) \
171 ((bp)->b_dev_released)
172 #define DR_DEVS_UNREFERENCED(bp) \
173 ((bp)->b_dev_unreferenced)
174 #define DR_DEVS_UNATTACHED(bp) \
175 ((bp)->b_dev_present & ~(bp)->b_dev_attached)
176 #define DR_DEVS_CONFIGURE(bp, devs) \
177 ((bp)->b_dev_attached = (devs))
178 #define DR_DEVS_DISCONNECT(bp, devs) \
179 ((bp)->b_dev_present &= ~(devs))
180 #define DR_DEVS_CANCEL(bp, devs) \
181 ((bp)->b_dev_released &= ~(devs), \
182 (bp)->b_dev_unreferenced &= ~(devs))
185 * CMP Specific Helpers
187 #define DR_CMP_CORE_UNUM(cmp, core) (cmp + (core * 4))
189 * DR_UNUM2SBD_UNUM should be set to (unum & (max #of CMP on board - 1))
190 * for all the platforms. So far, all sun4u platforms supported have
191 * the same limit so 0x3 works. One day we might have to make this
192 * a platform specific macro.
195 #define DR_UNUM2SBD_UNUM(n, d) ((d == SBD_COMP_IO) ? (n & 0xf) : \
196 (d == SBD_COMP_CPU) ? (n & 0x3) : \
197 (d == SBD_COMP_CMP) ? (n & 0x3) : \
201 * Some stuff to assist in debug.
204 #define DRDBG_STATE 0x00000001
205 #define DRDBG_QR 0x00000002
206 #define DRDBG_CPU 0x00000004
207 #define DRDBG_MEM 0x00000008
208 #define DRDBG_IO 0x00000010
210 #define PR_ALL if (dr_debug) printf
211 #define PR_STATE if (dr_debug & DRDBG_STATE) printf
212 #define PR_QR if (dr_debug & DRDBG_QR) prom_printf
213 #define PR_CPU if (dr_debug & DRDBG_CPU) printf
214 #define PR_MEM if (dr_debug & DRDBG_MEM) printf
215 #define PR_IO if (dr_debug & DRDBG_IO) printf
216 #define PR_MEMLIST_DUMP if (dr_debug & DRDBG_MEM) MEMLIST_DUMP
218 extern uint_t dr_debug
;
220 #define PR_ALL _NOTE(CONSTANTCONDITION) if (0) printf
221 #define PR_STATE PR_ALL
223 #define PR_CPU PR_ALL
224 #define PR_MEM PR_ALL
226 #define PR_MEMLIST_DUMP _NOTE(CONSTANTCONDITION) if (0) MEMLIST_DUMP
231 * dr_board_t b_sflags.
233 #define DR_BSLOCK 0x01 /* for blocking status (protected by b_slock) */
235 typedef const char *fn_t
;
236 typedef uint64_t dr_devset_t
; /* TODO: fix limitation */
239 * Unsafe devices based on dr.conf prop "unsupported-io-drivers"
248 * PARTIAL state is really only relevant for board state.
254 DR_STATE_UNCONFIGURED
,
255 DR_STATE_PARTIAL
, /* part connected, part configured */
258 DR_STATE_UNREFERENCED
,
263 typedef struct dr_handle
{
264 struct dr_board
*h_bd
;
266 int h_op_intr
; /* nz if op interrupted */
267 dev_t h_dev
; /* dev_t of opened device */
268 int h_cmd
; /* PIM ioctl argument */
269 int h_mode
; /* device open mode */
270 sbd_cmd_t h_sbdcmd
; /* copied-in ioctl cmd struct */
271 sbd_ioctl_arg_t
*h_iap
; /* ptr to caller-space cmd struct */
272 dr_devset_t h_devset
; /* based on h_dev */
274 drmach_opts_t h_opts
; /* command-line platform options */
277 typedef struct dr_common_unit
{
278 dr_state_t sbdev_state
;
279 sbd_state_t sbdev_ostate
;
280 sbd_cond_t sbdev_cond
;
283 struct dr_board
*sbdev_bp
;
285 sbd_comp_type_t sbdev_type
;
287 char sbdev_path
[MAXNAMELEN
];
288 sbd_error_t
*sbdev_error
;
291 typedef struct dr_mem_unit
{
292 dr_common_unit_t sbm_cm
; /* mem-unit state */
296 pgcnt_t sbm_pageslost
;
297 struct memlist
*sbm_dyn_segs
; /* kphysm_add_dynamic segs */
299 * The following fields are used during
300 * the memory detach process only. sbm_mlist
301 * will be used to store the board memlist
302 * following a detach. The memlist will be
303 * used to re-attach the board when configuring
304 * the unit directly after an unconfigure.
306 struct dr_mem_unit
*sbm_peer
;
307 struct memlist
*sbm_mlist
;
308 struct memlist
*sbm_del_mlist
;
309 memhandle_t sbm_memhandle
;
310 pfn_t sbm_alignment_mask
;
311 pfn_t sbm_slice_offset
;
312 uint64_t sbm_slice_size
;
316 * Currently only maintain state information for individual
319 typedef struct dr_cpu_unit
{
320 dr_common_unit_t sbc_cm
; /* cpu-unit state */
321 processorid_t sbc_cpu_id
;
322 cpu_flag_t sbc_cpu_flags
; /* snapshot of CPU flags */
323 ushort_t sbc_pad1
; /* padded for compatibility */
329 typedef struct dr_io_unit
{
330 dr_common_unit_t sbi_cm
; /* io-unit state */
334 dr_common_unit_t du_common
;
335 dr_mem_unit_t du_mem
;
336 dr_cpu_unit_t du_cpu
;
340 typedef struct dr_board
{
341 kmutex_t b_lock
; /* lock for this board struct */
342 kmutex_t b_slock
; /* lock for status on the board */
343 kcondvar_t b_scv
; /* condvar for status on the board */
344 int b_sflags
; /* for serializing status */
345 sbd_state_t b_rstate
; /* board's cfgadm receptacle state */
346 sbd_state_t b_ostate
; /* board's cfgadm occupant state */
347 sbd_cond_t b_cond
; /* cfgadm condition */
350 time_t b_time
; /* time of last board operation */
351 char b_type
[MAXNAMELEN
];
353 int b_num
; /* board number */
354 int b_ndev
; /* # of devices on board */
355 dev_info_t
*b_dip
; /* dip for make-nodes */
356 dr_state_t b_state
; /* board DR state */
357 dr_devset_t b_dev_present
; /* present mask */
358 dr_devset_t b_dev_attached
; /* attached mask */
359 dr_devset_t b_dev_released
; /* released mask */
360 dr_devset_t b_dev_unreferenced
; /* unreferenced mask */
361 char b_path
[MAXNAMELEN
];
362 dr_dev_unit_t
*b_dev
[DR_MAXNUM_NT
];
366 * dr_quiesce.c interfaces
369 typedef struct dr_sr_handle dr_sr_handle_t
;
371 extern dr_sr_handle_t
*dr_get_sr_handle(dr_handle_t
*handle
);
372 extern void dr_release_sr_handle(dr_sr_handle_t
*srh
);
373 extern int dr_suspend(dr_sr_handle_t
*srh
);
374 extern void dr_resume(dr_sr_handle_t
*srh
);
375 extern void dr_check_devices(dev_info_t
*dip
, int *refcount
,
376 dr_handle_t
*handle
, uint64_t *arr
, int *idx
,
377 int len
, int *refcount_non_gldv3
);
378 extern int dr_pt_test_suspend(dr_handle_t
*hp
);
383 extern void dr_init_cpu_unit(dr_cpu_unit_t
*cp
);
384 extern int dr_pre_attach_cpu(dr_handle_t
*hp
,
385 dr_common_unit_t
**devlist
, int devnum
);
386 extern void dr_attach_cpu(dr_handle_t
*hp
, dr_common_unit_t
*cp
);
387 extern int dr_post_attach_cpu(dr_handle_t
*hp
,
388 dr_common_unit_t
**devlist
, int devnum
);
389 extern int dr_pre_release_cpu(dr_handle_t
*hp
,
390 dr_common_unit_t
**devlist
, int devnum
);
391 extern int dr_pre_detach_cpu(dr_handle_t
*hp
,
392 dr_common_unit_t
**devlist
, int devnum
);
393 extern void dr_detach_cpu(dr_handle_t
*hp
, dr_common_unit_t
*cp
);
394 extern int dr_post_detach_cpu(dr_handle_t
*hp
,
395 dr_common_unit_t
**devlist
, int devnum
);
396 extern int dr_cpu_status(dr_handle_t
*hp
, dr_devset_t devset
,
397 sbd_dev_stat_t
*dsp
);
398 extern int dr_cancel_cpu(dr_cpu_unit_t
*cp
);
399 extern int dr_disconnect_cpu(dr_cpu_unit_t
*cp
);
405 extern void dr_init_mem_unit(dr_mem_unit_t
*mp
);
406 extern int dr_pre_attach_mem(dr_handle_t
*hp
,
407 dr_common_unit_t
**devlist
, int devnum
);
408 extern void dr_attach_mem(dr_handle_t
*hp
, dr_common_unit_t
*cp
);
409 extern int dr_post_attach_mem(dr_handle_t
*hp
,
410 dr_common_unit_t
**devlist
, int devnum
);
411 extern int dr_pre_release_mem(dr_handle_t
*hp
,
412 dr_common_unit_t
**devlist
, int devnum
);
413 extern void dr_release_mem(dr_common_unit_t
*cp
);
414 extern void dr_release_mem_done(dr_common_unit_t
*cp
);
415 extern int dr_pre_detach_mem(dr_handle_t
*hp
,
416 dr_common_unit_t
**devlist
, int devnum
);
417 extern void dr_detach_mem(dr_handle_t
*, dr_common_unit_t
*);
418 extern int dr_post_detach_mem(dr_handle_t
*hp
,
419 dr_common_unit_t
**devlist
, int devnum
);
420 extern int dr_mem_status(dr_handle_t
*hp
, dr_devset_t devset
,
421 sbd_dev_stat_t
*dsp
);
422 extern int dr_cancel_mem(dr_mem_unit_t
*mp
);
423 extern int dr_disconnect_mem(dr_mem_unit_t
*mp
);
428 extern void dr_init_io_unit(dr_io_unit_t
*io
);
429 extern int dr_disconnect_io(dr_io_unit_t
*ip
);
430 extern int dr_pre_attach_io(dr_handle_t
*hp
,
431 dr_common_unit_t
**devlist
, int devnum
);
432 extern void dr_attach_io(dr_handle_t
*hp
, dr_common_unit_t
*cp
);
433 extern int dr_post_attach_io(dr_handle_t
*hp
,
434 dr_common_unit_t
**devlist
, int devnum
);
435 extern int dr_pre_release_io(dr_handle_t
*hp
,
436 dr_common_unit_t
**devlist
, int devnum
);
437 extern int dr_pre_detach_io(dr_handle_t
*hp
,
438 dr_common_unit_t
**devlist
, int devnum
);
439 extern void dr_detach_io(dr_handle_t
*hp
, dr_common_unit_t
*cp
);
440 extern int dr_post_detach_io(dr_handle_t
*hp
,
441 dr_common_unit_t
**devlist
, int devnum
);
442 extern int dr_io_status(dr_handle_t
*hp
, dr_devset_t devset
,
443 sbd_dev_stat_t
*dsp
);
449 extern void dr_op_err(int ce
, dr_handle_t
*hp
, int code
, char *fmt
, ...);
450 extern void dr_dev_err(int ce
, dr_common_unit_t
*cp
, int code
);
452 extern dr_cpu_unit_t
*dr_get_cpu_unit(dr_board_t
*bp
, int unit_num
);
453 extern dr_mem_unit_t
*dr_get_mem_unit(dr_board_t
*bp
, int unit_num
);
454 extern dr_io_unit_t
*dr_get_io_unit(dr_board_t
*bp
, int unit_num
);
456 extern dr_board_t
*dr_lookup_board(int board_num
);
457 extern int dr_release_dev_done(dr_common_unit_t
*cp
);
458 extern char *dr_nt_to_dev_type(int type
);
459 extern void dr_device_transition(dr_common_unit_t
*cp
,
460 dr_state_t new_state
);
461 extern void dr_lock_status(dr_board_t
*bp
);
462 extern void dr_unlock_status(dr_board_t
*bp
);
463 extern int dr_cmd_flags(dr_handle_t
*hp
);
469 #endif /* _SYS_DR_H */