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
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
|
/*
* 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 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2010, Intel Corporation.
* All rights reserved.
*/
#ifndef _SYS_DR_H
#define _SYS_DR_H
#include <sys/types.h>
#include <sys/note.h>
#include <sys/processor.h>
#include <sys/obpdefs.h>
#include <sys/memlist.h>
#include <sys/mem_config.h>
#include <sys/param.h> /* for MAXPATHLEN */
#include <sys/varargs.h>
#include <sys/sbd_ioctl.h>
#include <sys/dr_util.h>
#include <sys/drmach.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* helper macros for constructing and reporting internal error messages.
* NOTE: each module which uses one or more this these macros is expected
* to supply a char *dr_ie_fmt string containing the SCCS filename
* expansion macro (percent M percent) and a sprintf %d to render the
* line number argument.
*/
#define DR_INTERNAL_ERROR(hp) \
drerr_new(1, ESBD_INTERNAL, dr_ie_fmt, __LINE__)
#define DR_OP_INTERNAL_ERROR(hp) \
drerr_set_c(CE_WARN, &(hp)->h_err, \
ESBD_INTERNAL, dr_ie_fmt, __LINE__)
#define DR_DEV_INTERNAL_ERROR(cp) \
drerr_set_c(CE_WARN, &(cp)->sbdev_error, \
ESBD_INTERNAL, dr_ie_fmt, __LINE__)
/*
* Macros for keeping an error code and an associated list of integers.
*/
#define DR_MAX_ERR_INT (32)
#define DR_GET_E_CODE(sep) ((sep)->e_code)
#define DR_SET_E_CODE(sep, en) ((sep)->e_code = (en))
#define DR_GET_E_RSC(sep) ((sep)->e_rsc)
/* Number of device node types. */
#define DR_MAXNUM_NT 3
/* used to map sbd_comp_type_t to array index */
#define DEVSET_NIX(t) \
(((t) == SBD_COMP_CPU) ? 0 : \
((t) == SBD_COMP_MEM) ? 1 : \
((t) == SBD_COMP_IO) ? 2 : \
((t) == SBD_COMP_CMP) ? 0 : DR_MAXNUM_NT)
/*
* Format of dr_devset_t bit masks:
*
* 64 56 48 40 32 24 16 8 0
* |....|IIII|IIII|IIII|IIII|MMMM|MMMM|CCCC|CCCC|CCCC|CCCC|CCCC|CCCC|CCCC|CCCC|
*
* 1 = indicates respective component present/attached.
* I = I/O, M = Memory, C = CPU.
*/
#define DEVSET_CPU_OFFSET 0
#define DEVSET_CPU_NUMBER 32
#define DEVSET_MEM_OFFSET (DEVSET_CPU_OFFSET + DEVSET_CPU_NUMBER)
#define DEVSET_MEM_NUMBER 8
#define DEVSET_IO_OFFSET (DEVSET_MEM_OFFSET + DEVSET_MEM_NUMBER)
#define DEVSET_IO_NUMBER 16
#define DEVSET_MAX_BITS (DEVSET_IO_OFFSET + DEVSET_IO_NUMBER)
#define DEVSET_BIX(t) \
(((t) == SBD_COMP_CPU) ? DEVSET_CPU_OFFSET : \
((t) == SBD_COMP_MEM) ? DEVSET_MEM_OFFSET : \
((t) == SBD_COMP_IO) ? DEVSET_IO_OFFSET : \
((t) == SBD_COMP_CMP) ? DEVSET_CPU_OFFSET : 0)
#define DEVSET_NT2DEVPOS(t, u) (((t) == SBD_COMP_CMP) ?\
(DEVSET_BIX(t) + (u) * MAX_CORES_PER_CMP) : DEVSET_BIX(t) + (u))
#if (DEVSET_MAX_BITS <= 64)
typedef uint64_t dr_devset_t;
#define DEVSET_ONEUNIT ((dr_devset_t)1)
#define DEVSET_ANYUNIT ((dr_devset_t)(-1))
#define DEVSET_CPU_NMASK ((dr_devset_t)((1ULL << DEVSET_CPU_NUMBER) - 1))
#define DEVSET_MEM_NMASK ((dr_devset_t)((1ULL << DEVSET_MEM_NUMBER) - 1))
#define DEVSET_IO_NMASK ((dr_devset_t)((1ULL << DEVSET_IO_NUMBER) - 1))
#define DEVSET_CMP_NMASK ((dr_devset_t)((1ULL << MAX_CORES_PER_CMP) - 1))
#define DEVSET_NMASK(t) \
(((t) == SBD_COMP_CPU) ? DEVSET_CPU_NMASK : \
((t) == SBD_COMP_MEM) ? DEVSET_MEM_NMASK : \
((t) == SBD_COMP_IO) ? DEVSET_IO_NMASK : \
((t) == SBD_COMP_CMP) ? DEVSET_CPU_NMASK : 0)
#define DEVSET_MASK \
((DEVSET_CPU_NMASK << DEVSET_CPU_OFFSET) | \
(DEVSET_MEM_NMASK << DEVSET_MEM_OFFSET) | \
(DEVSET_IO_NMASK << DEVSET_IO_OFFSET))
#define DEVSET(t, u) \
(((u) == DEVSET_ANYUNIT) ? \
((DEVSET_NMASK(t) << DEVSET_NT2DEVPOS((t), 0)) & \
DEVSET_MASK) : \
((t) == SBD_COMP_CMP) ? \
(DEVSET_CMP_NMASK << DEVSET_NT2DEVPOS((t), (u))) : \
(DEVSET_ONEUNIT << DEVSET_NT2DEVPOS((t), (u))))
#define DEVSET_IS_NULL(ds) ((ds) == 0)
#define DEVSET_IN_SET(ds, t, u) (((ds) & DEVSET((t), (u))) != 0)
#define DEVSET_ADD(ds, t, u) ((ds) |= DEVSET((t), (u)))
#define DEVSET_DEL(ds, t, u) ((ds) &= ~DEVSET((t), (u)))
#define DEVSET_AND(ds1, ds2) ((ds1) & (ds2))
#define DEVSET_OR(ds1, ds2) ((ds1) | (ds2))
#define DEVSET_NAND(ds1, ds2) ((ds1) & ~(ds2))
#define DEVSET_GET_UNITSET(ds, t) \
(((ds) & DEVSET((t), DEVSET_ANYUNIT)) >> DEVSET_NT2DEVPOS((t), 0))
#define DEVSET_FMT_STR "0x%" PRIx64 ""
#define DEVSET_FMT_ARG(ds) (ds)
#else /* DEVSET_MAX_BITS <= 64 */
#error please implement devset with bitmap to support more 64 devices
#endif /* DEVSET_MAX_BITS <= 64 */
/*
* Ops for dr_board_t.b_dev_*
*/
#define DR_DEV_IS(ds, cp) DEVSET_IN_SET( \
(cp)->sbdev_bp->b_dev_##ds, \
(cp)->sbdev_type, \
(cp)->sbdev_unum)
#define DR_DEV_ADD(ds, cp) DEVSET_ADD( \
(cp)->sbdev_bp->b_dev_##ds, \
(cp)->sbdev_type, \
(cp)->sbdev_unum)
#define DR_DEV_DEL(ds, cp) DEVSET_DEL( \
(cp)->sbdev_bp->b_dev_##ds, \
(cp)->sbdev_type, \
(cp)->sbdev_unum)
/*
* Ops for dr_board_t.b_dev_present
*/
#define DR_DEV_IS_PRESENT(cp) DR_DEV_IS(present, cp)
#define DR_DEV_SET_PRESENT(cp) DR_DEV_ADD(present, cp)
#define DR_DEV_CLR_PRESENT(cp) DR_DEV_DEL(present, cp)
/*
* Ops for dr_board_t.b_dev_attached
*/
#define DR_DEV_IS_ATTACHED(cp) DR_DEV_IS(attached, cp)
#define DR_DEV_SET_ATTACHED(cp) DR_DEV_ADD(attached, cp)
#define DR_DEV_CLR_ATTACHED(cp) DR_DEV_DEL(attached, cp)
/*
* Ops for dr_board_t.b_dev_released
*/
#define DR_DEV_IS_RELEASED(cp) DR_DEV_IS(released, cp)
#define DR_DEV_SET_RELEASED(cp) DR_DEV_ADD(released, cp)
#define DR_DEV_CLR_RELEASED(cp) DR_DEV_DEL(released, cp)
/*
* Ops for dr_board_t.b_dev_unreferenced
*/
#define DR_DEV_IS_UNREFERENCED(cp) DR_DEV_IS(unreferenced, cp)
#define DR_DEV_SET_UNREFERENCED(cp) DR_DEV_ADD(unreferenced, cp)
#define DR_DEV_CLR_UNREFERENCED(cp) DR_DEV_DEL(unreferenced, cp)
#define DR_DEVS_PRESENT(bp) \
((bp)->b_dev_present)
#define DR_DEVS_ATTACHED(bp) \
((bp)->b_dev_attached)
#define DR_DEVS_RELEASED(bp) \
((bp)->b_dev_released)
#define DR_DEVS_UNREFERENCED(bp) \
((bp)->b_dev_unreferenced)
#define DR_DEVS_UNATTACHED(bp) \
((bp)->b_dev_present & ~(bp)->b_dev_attached)
#define DR_DEVS_CONFIGURE(bp, devs) \
((bp)->b_dev_attached = (devs))
#define DR_DEVS_DISCONNECT(bp, devs) \
((bp)->b_dev_present &= ~(devs))
#define DR_DEVS_CANCEL(bp, devs) \
((bp)->b_dev_released &= ~(devs), \
(bp)->b_dev_unreferenced &= ~(devs))
/*
* CMP Specific Helpers
*/
#define DR_CMP_CORE_UNUM(cmp, core) ((cmp) * MAX_CORES_PER_CMP + (core))
/*
* For CPU and CMP devices, DR_UNUM2SBD_UNUM is used to extract the physical
* CPU/CMP id from the device id.
*/
#define DR_UNUM2SBD_UNUM(n, d) \
((d) == SBD_COMP_CPU ? ((n) / MAX_CORES_PER_CMP) : \
(d) == SBD_COMP_CMP ? ((n) / MAX_CORES_PER_CMP) : (n))
/*
* Some stuff to assist in debug.
*/
#ifdef DEBUG
#define DRDBG_STATE 0x00000001
#define DRDBG_QR 0x00000002
#define DRDBG_CPU 0x00000004
#define DRDBG_MEM 0x00000008
#define DRDBG_IO 0x00000010
#define PR_ALL if (dr_debug) printf
#define PR_STATE if (dr_debug & DRDBG_STATE) printf
#define PR_QR if (dr_debug & DRDBG_QR) prom_printf
#define PR_CPU if (dr_debug & DRDBG_CPU) printf
#define PR_MEM if (dr_debug & DRDBG_MEM) printf
#define PR_IO if (dr_debug & DRDBG_IO) printf
#define PR_MEMLIST_DUMP if (dr_debug & DRDBG_MEM) MEMLIST_DUMP
extern uint_t dr_debug;
#else /* DEBUG */
#define PR_ALL _NOTE(CONSTANTCONDITION) if (0) printf
#define PR_STATE PR_ALL
#define PR_QR PR_ALL
#define PR_CPU PR_ALL
#define PR_MEM PR_ALL
#define PR_IO PR_ALL
#define PR_MEMLIST_DUMP _NOTE(CONSTANTCONDITION) if (0) MEMLIST_DUMP
#endif /* DEBUG */
/*
* dr_board_t b_sflags.
*/
#define DR_BSLOCK 0x01 /* for blocking status (protected by b_slock) */
typedef const char *fn_t;
/*
* Unsafe devices based on dr.conf prop "unsupported-io-drivers"
*/
typedef struct {
char **devnames;
uint_t ndevs;
} dr_unsafe_devs_t;
/*
* Device states.
* PARTIAL state is really only relevant for board state.
*/
typedef enum {
DR_STATE_EMPTY = 0,
DR_STATE_OCCUPIED,
DR_STATE_CONNECTED,
DR_STATE_UNCONFIGURED,
DR_STATE_PARTIAL, /* part connected, part configured */
DR_STATE_CONFIGURED,
DR_STATE_RELEASE,
DR_STATE_UNREFERENCED,
DR_STATE_FATAL,
DR_STATE_MAX
} dr_state_t;
typedef struct dr_handle {
struct dr_board *h_bd;
sbd_error_t *h_err;
int h_op_intr; /* nz if op interrupted */
dev_t h_dev; /* dev_t of opened device */
int h_cmd; /* PIM ioctl argument */
int h_mode; /* device open mode */
sbd_cmd_t h_sbdcmd; /* copied-in ioctl cmd struct */
sbd_ioctl_arg_t *h_iap; /* ptr to caller-space cmd struct */
dr_devset_t h_devset; /* based on h_dev */
uint_t h_ndi;
drmach_opts_t h_opts; /* command-line platform options */
} dr_handle_t;
typedef struct dr_common_unit {
dr_state_t sbdev_state;
sbd_state_t sbdev_ostate;
sbd_cond_t sbdev_cond;
time_t sbdev_time;
int sbdev_busy;
struct dr_board *sbdev_bp;
int sbdev_unum;
sbd_comp_type_t sbdev_type;
drmachid_t sbdev_id;
char sbdev_path[MAXNAMELEN];
sbd_error_t *sbdev_error;
} dr_common_unit_t;
typedef struct dr_mem_unit {
dr_common_unit_t sbm_cm; /* mem-unit state */
uint_t sbm_flags;
pfn_t sbm_basepfn;
pgcnt_t sbm_npages;
pgcnt_t sbm_pageslost;
struct memlist *sbm_dyn_segs; /* kphysm_add_dynamic segs */
/*
* The following fields are used during
* the memory detach process only. sbm_mlist
* will be used to store the board memlist
* following a detach. The memlist will be
* used to re-attach the board when configuring
* the unit directly after an unconfigure.
*/
struct dr_mem_unit *sbm_peer;
struct memlist *sbm_mlist;
struct memlist *sbm_del_mlist;
memhandle_t sbm_memhandle;
uint64_t sbm_alignment_mask;
uint64_t sbm_slice_base;
uint64_t sbm_slice_top;
uint64_t sbm_slice_size;
} dr_mem_unit_t;
/*
* Currently only maintain state information for individual
* components.
*/
typedef struct dr_cpu_unit {
dr_common_unit_t sbc_cm; /* cpu-unit state */
processorid_t sbc_cpu_id;
cpu_flag_t sbc_cpu_flags; /* snapshot of CPU flags */
ushort_t sbc_pad1; /* padded for compatibility */
int sbc_speed;
int sbc_ecache;
int sbc_cpu_impl;
} dr_cpu_unit_t;
typedef struct dr_io_unit {
dr_common_unit_t sbi_cm; /* io-unit state */
} dr_io_unit_t;
typedef union {
dr_common_unit_t du_common;
dr_mem_unit_t du_mem;
dr_cpu_unit_t du_cpu;
dr_io_unit_t du_io;
} dr_dev_unit_t;
typedef struct dr_board {
kmutex_t b_lock; /* lock for this board struct */
kmutex_t b_slock; /* lock for status on the board */
kcondvar_t b_scv; /* condvar for status on the board */
int b_sflags; /* for serializing status */
sbd_state_t b_rstate; /* board's cfgadm receptacle state */
sbd_state_t b_ostate; /* board's cfgadm occupant state */
sbd_cond_t b_cond; /* cfgadm condition */
int b_busy;
int b_assigned;
time_t b_time; /* time of last board operation */
char b_type[MAXNAMELEN];
drmachid_t b_id;
int b_num; /* board number */
int b_ndev; /* # of devices on board */
dev_info_t *b_dip; /* dip for make-nodes */
dr_state_t b_state; /* board DR state */
dr_devset_t b_dev_present; /* present mask */
dr_devset_t b_dev_attached; /* attached mask */
dr_devset_t b_dev_released; /* released mask */
dr_devset_t b_dev_unreferenced; /* unreferenced mask */
char b_path[MAXNAMELEN];
dr_dev_unit_t *b_dev[DR_MAXNUM_NT];
} dr_board_t;
/*
* dr_quiesce.c interfaces
*/
struct dr_sr_handle;
typedef struct dr_sr_handle dr_sr_handle_t;
extern dr_sr_handle_t *dr_get_sr_handle(dr_handle_t *handle);
extern void dr_release_sr_handle(dr_sr_handle_t *srh);
extern int dr_suspend(dr_sr_handle_t *srh);
extern void dr_resume(dr_sr_handle_t *srh);
extern void dr_check_devices(dev_info_t *dip, int *refcount,
dr_handle_t *handle, uint64_t *arr, int *idx,
int len, int *refcount_non_gldv3);
extern int dr_pt_test_suspend(dr_handle_t *hp);
/*
* dr_cpu.c interface
*/
extern void dr_init_cpu_unit(dr_cpu_unit_t *cp);
extern int dr_pre_attach_cpu(dr_handle_t *hp,
dr_common_unit_t **devlist, int devnum);
extern void dr_attach_cpu(dr_handle_t *hp, dr_common_unit_t *cp);
extern int dr_post_attach_cpu(dr_handle_t *hp,
dr_common_unit_t **devlist, int devnum);
extern int dr_pre_release_cpu(dr_handle_t *hp,
dr_common_unit_t **devlist, int devnum);
extern int dr_pre_detach_cpu(dr_handle_t *hp,
dr_common_unit_t **devlist, int devnum);
extern void dr_detach_cpu(dr_handle_t *hp, dr_common_unit_t *cp);
extern int dr_post_detach_cpu(dr_handle_t *hp,
dr_common_unit_t **devlist, int devnum);
extern int dr_cpu_status(dr_handle_t *hp, dr_devset_t devset,
sbd_dev_stat_t *dsp);
extern int dr_cancel_cpu(dr_cpu_unit_t *cp);
extern int dr_disconnect_cpu(dr_cpu_unit_t *cp);
/*
* dr_mem.c interface
*/
extern void dr_init_mem_unit(dr_mem_unit_t *mp);
extern int dr_pre_attach_mem(dr_handle_t *hp,
dr_common_unit_t **devlist, int devnum);
extern void dr_attach_mem(dr_handle_t *hp, dr_common_unit_t *cp);
extern int dr_post_attach_mem(dr_handle_t *hp,
dr_common_unit_t **devlist, int devnum);
extern int dr_pre_release_mem(dr_handle_t *hp,
dr_common_unit_t **devlist, int devnum);
extern void dr_release_mem(dr_common_unit_t *cp);
extern void dr_release_mem_done(dr_common_unit_t *cp);
extern int dr_pre_detach_mem(dr_handle_t *hp,
dr_common_unit_t **devlist, int devnum);
extern void dr_detach_mem(dr_handle_t *, dr_common_unit_t *);
extern int dr_post_detach_mem(dr_handle_t *hp,
dr_common_unit_t **devlist, int devnum);
extern int dr_mem_status(dr_handle_t *hp, dr_devset_t devset,
sbd_dev_stat_t *dsp);
extern int dr_cancel_mem(dr_mem_unit_t *mp);
extern int dr_disconnect_mem(dr_mem_unit_t *mp);
/*
* dr_io.c interface
*/
extern void dr_init_io_unit(dr_io_unit_t *io);
extern int dr_pre_attach_io(dr_handle_t *hp,
dr_common_unit_t **devlist, int devnum);
extern void dr_attach_io(dr_handle_t *hp, dr_common_unit_t *cp);
extern int dr_post_attach_io(dr_handle_t *hp,
dr_common_unit_t **devlist, int devnum);
extern int dr_pre_release_io(dr_handle_t *hp,
dr_common_unit_t **devlist, int devnum);
extern int dr_pre_detach_io(dr_handle_t *hp,
dr_common_unit_t **devlist, int devnum);
extern void dr_detach_io(dr_handle_t *hp, dr_common_unit_t *cp);
extern int dr_post_detach_io(dr_handle_t *hp,
dr_common_unit_t **devlist, int devnum);
extern int dr_io_status(dr_handle_t *hp, dr_devset_t devset,
sbd_dev_stat_t *dsp);
extern int dr_disconnect_io(dr_io_unit_t *ip);
/*
* dr.c interface
*/
extern void dr_op_err(int ce, dr_handle_t *hp, int code, char *fmt, ...);
extern void dr_dev_err(int ce, dr_common_unit_t *cp, int code);
extern dr_cpu_unit_t *dr_get_cpu_unit(dr_board_t *bp, int unit_num);
extern dr_mem_unit_t *dr_get_mem_unit(dr_board_t *bp, int unit_num);
extern dr_io_unit_t *dr_get_io_unit(dr_board_t *bp, int unit_num);
extern dr_board_t *dr_lookup_board(int board_num);
extern int dr_release_dev_done(dr_common_unit_t *cp);
extern char *dr_nt_to_dev_type(int type);
extern void dr_device_transition(dr_common_unit_t *cp,
dr_state_t new_state);
extern void dr_lock_status(dr_board_t *bp);
extern void dr_unlock_status(dr_board_t *bp);
extern int dr_cmd_flags(dr_handle_t *hp);
#ifdef __cplusplus
}
#endif
#endif /* _SYS_DR_H */
|