xref: /illumos-gate/usr/src/uts/common/sys/epm.h (revision 0e751525)
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	_SYS_EPM_H
27 #define	_SYS_EPM_H
28 
29 #include <sys/pm.h>
30 #include <sys/dditypes.h>
31 #include <sys/devops.h>
32 #include <sys/ddi_impldefs.h>
33 #include <sys/taskq.h>
34 #include <sys/tzfile.h>
35 
36 /*
37  * XXXX
38  * Do we really need this include?  It may be leftover from early CPUPM code.
39  * #include <sys/processor.h>
40  */
41 
42 #ifdef	__cplusplus
43 extern "C" {
44 #endif
45 
46 #ifdef	_KERNEL
47 
48 /*
49  * epm.h:	Function prototypes and data structs for kernel pm functions.
50  */
51 
52 void e_pm_props(dev_info_t *);
53 int e_new_pm_props(dev_info_t *);
54 
55 #define	PM_LEVEL_UPONLY (-2)	/* only raise power level */
56 #define	PM_LEVEL_DOWNONLY (-3)	/* only lower power level */
57 #define	PM_LEVEL_EXACT (-4)	/* wants exact power level */
58 
59 /*
60  * Values used by e_pm_props and friends, found in devi_pm_flags
61  */
62 #define	PMC_NEEDS_SR		0x00001	/* do suspend/resume despite no "reg" */
63 #define	PMC_NO_SR		0x00002	/* don't suspend/resume despite "reg" */
64 #define	PMC_PARENTAL_SR		0x00004	/* call up tree to suspend/resume */
65 #define	PMC_WANTS_NOTIFY	0x00008	/* notify if child pwr level changes */
66 #define	PMC_BC			0x00010	/* no pm-components, backwards compat */
67 #define	PMC_COMPONENTS_DONE	0x00020 /* parsed pm-components */
68 #define	PMC_COMPONENTS_FAILED	0x00040 /* failed parsing pm-components */
69 #define	PMC_SUSPENDED		0x00080 /* device has been suspended */
70 #define	PMC_DEF_THRESH		0x00100 /* thresholds are default */
71 #define	PMC_DEV_THRESH		0x00200 /* SET_THRESHOLD ioctl seen */
72 #define	PMC_COMP_THRESH		0x00400 /* relative threshold set */
73 #define	PMC_NEXDEF_THRESH	0x00800 /* relative threshold set for nexus */
74 #define	PMC_NOPMKID		0x01000 /* non-pm'd child of pm'd parent */
75 #define	PMC_NO_INVOL		0x02000 /* no pm without driver's consent */
76 #define	PMC_VOLPMD		0x04000 /* went down voluntarily */
77 #define	PMC_SKIP_BRINGUP	0x08000 /* Skipped a dependency bringup */
78 
79 /*
80  * A node which is the console frame buffer, and should not be powered down
81  * automatically because the OBP driver doesn't know how to power it back up
82  * before using it  (can remove this when prom calls back into kernel to do
83  * io to console).
84  */
85 #define	PMC_CONSOLE_FB		0x10000	/* console framebuffer */
86 #define	PMC_NOINVOL_DONE	0x20000 /* processed by pm_noinvol_specd() */
87 #define	PMC_DRIVER_REMOVED	0x40000 /* driver is removed	*/
88 #define	PMC_CPU_DEVICE		0x80000 /* device is a power manageable CPU */
89 #define	PMC_CPU_THRESH		0x100000 /* cpu threshold set */
90 
91 #define	PMC_THRESH_ALL	(PMC_DEF_THRESH | PMC_DEV_THRESH | \
92     PMC_COMP_THRESH | PMC_NEXDEF_THRESH | PMC_CPU_THRESH)
93 #define	PMC_THRESH_NONE	~(PMC_THRESH_ALL)
94 
95 /* Flags for the component */
96 #define	PM_POWER_OP		0x00001	/* set power in process */
97 #define	PM_PHC_WHILE_SET_POWER	0x00002	/* phc and set power deadlock */
98 
99 /*
100  * One of these is attached to each devinfo that is autopm'd.
101  */
102 typedef struct pm_scan {
103 	int		ps_idle_down;	/* PMID_XXX flags */
104 	int		ps_scan_flags;	/* scan flags, defined below */
105 	timeout_id_t	ps_scan_id;	/* per dip scan timeout id */
106 } pm_scan_t;
107 
108 /*
109  * ps_scan_flags may take the following values, plus possibly
110  * more defined.
111  */
112 #define	PM_SCANNING		0x100	/* scanning: pm_scan_dev is active */
113 #define	PM_SCAN_AGAIN		0x200
114 #define	PM_SCAN_STOP		0x400
115 #define	PM_SCAN_DISPATCHED	0x800
116 
117 #define	PM_DEFAULT_MIN_SCAN	((clock_t)15) /* Minimum scan interval in sec */
118 #define	PM_CPU_MIN_SCAN		((clock_t)1) /* Minimum interval for CPUs */
119 
120 /*
121  * Power management component definitions, used for tracking idleness of
122  * devices.  An array of these hangs off the devi_pm_components member of the
123  * dev_info struct (if initialized by driver and/or auto-pm)
124  * The array of these structs is followed in the same kmem_zalloc'd chunk by
125  * the names pointed to by the structs.
126  */
127 
128 /*
129  * This (sub-)struct contains all the info extracted from the pm-components
130  * property for each component (name of component, names and values of power
131  * levels supported).  It is in a separate structure to allow it to be handled
132  * as a struct assignment.
133  */
134 typedef struct pm_comp {
135 	char 	*pmc_name;		/* name of component */
136 	int	pmc_numlevels;		/* number of power levels supported */
137 	int	*pmc_lvals;		/* numerical values of levels */
138 	int	*pmc_thresh;		/* thresholds in secs, last INT_MAX */
139 	char	**pmc_lnames;		/* human readable names of levels */
140 	/*
141 	 * This part is just bookkeeping for the storage space involved above
142 	 * used for copying and freeing the struct members.  This because C
143 	 * is really an assembler at heart.
144 	 */
145 	size_t	pmc_name_sz;		/* size of name string		*/
146 	char	*pmc_lname_buf;		/* buffer holding *pmc_lnames	*/
147 	size_t	pmc_lnames_sz;		/* total size of pmc_lname_buf	*/
148 } pm_comp_t;
149 
150 /*
151  * Here we have the rest of what we need to know about a component.
152  */
153 typedef struct pm_component {
154 	uint_t pmc_flags;		/* flags this component */
155 	uint_t pmc_busycount;		/* for nesting busy calls */
156 	time_t pmc_timestamp;		/* timestamp */
157 	uint_t pmc_norm_pwr;		/* normal power index (or value) */
158 	int pmc_cur_pwr;		/* current power index (or value)  */
159 	int pmc_phc_pwr;		/* prev. value of curpwr (deadlock) */
160 	pm_comp_t pmc_comp;		/* component description */
161 } pm_component_t;
162 
163 /*
164  * All members of this struct are protected by PM_LOCK_DIP(dip).
165  *
166  * kidsupcnt counts (the number of components of new-style children at non-zero
167  * level (unknown counts as non-zero)) + (the number of old-style children with
168  * component 0 at non-zero level) for parents that have not asked for
169  * notification.  When kidsupcnt is 0 for a nexus node, then pm scans it,
170  * otherwise it leaves it alone.
171  * Parents that ask for notification always get get scanned,
172  * so we keep their kidsupcnt at zero.
173  */
174 typedef struct pm_info {
175 	uint_t		pmi_dev_pm_state; /* PM state of a device */
176 	int		pmi_clone;	/* owner for direct pm'd devs */
177 	int		pmi_levels[2];	/* storage space for 2 levels */
178 	int		*pmi_lp;	/* storage space for >2 levels */
179 	kcondvar_t	pmi_cv;		/* condvar for direct PM access */
180 } pm_info_t;
181 
182 /*
183  * Work request structure for the dependency processing thread.
184  */
185 typedef struct pm_dep_wk {
186 	int		pdw_type;		/* Type of request */
187 	int		pdw_wait;		/* caller waits for result */
188 	int		pdw_done;		/* set when req is done */
189 	int		pdw_ret;		/* return value to caller */
190 	int		pdw_pwr;		/* pwr level of keeper */
191 	kcondvar_t	pdw_cv;			/* cv to wake up caller */
192 	struct		pm_dep_wk *pdw_next;	/* next element */
193 	char		*pdw_keeper;
194 	char		*pdw_kept;
195 } pm_dep_wk_t;
196 
197 /*
198  * Types of work, depends on when it gets called:
199  */
200 #define	PM_DEP_WK_POWER_ON		1	/* power on */
201 #define	PM_DEP_WK_POWER_OFF		2	/* power off */
202 #define	PM_DEP_WK_DETACH		3	/* detach */
203 #define	PM_DEP_WK_REMOVE_DEP		4	/* dependency removed */
204 #define	PM_DEP_WK_BRINGUP_SELF		5	/* released from direct PM */
205 #define	PM_DEP_WK_RECORD_KEEPER		6	/* PM_ADD_DEPENDENT */
206 #define	PM_DEP_WK_RECORD_KEEPER_PROP	7	/* PM_ADD_DEPENDENT_PROP */
207 #define	PM_DEP_WK_KEPT			8	/* dep. work as a kept */
208 #define	PM_DEP_WK_KEEPER		9	/* dep. work as a keeper */
209 #define	PM_DEP_WK_ATTACH		10	/* when dip is attached */
210 #define	PM_DEP_WK_CHECK_KEPT		11	/* check if this is a kept */
211 #define	PM_DEP_WK_CPR_SUSPEND		12	/* Suspend dep. during CPR */
212 #define	PM_DEP_WK_CPR_RESUME		13	/* Resume dep. after CPR */
213 
214 /*
215  * Wait for dependency work to finish or not.
216  */
217 #define	PM_DEP_WAIT	1
218 #define	PM_DEP_NOWAIT	0
219 
220 typedef enum pm_canblock
221 {
222 	PM_CANBLOCK_BLOCK,	/* wait for controlling process action */
223 	PM_CANBLOCK_FAIL,	/* don't wait, fail request */
224 	PM_CANBLOCK_BYPASS	/* don't wait, ignore controlling process */
225 } pm_canblock_t;
226 
227 typedef enum pm_cpupm
228 {
229 	PM_CPUPM_NOTSET,	/* no specific treatment of CPU devices */
230 	PM_CPUPM_POLLING,	/* CPUPM enabled: polling mode */
231 	PM_CPUPM_EVENT,		/* CPUPM enabled: event driven mode */
232 	PM_CPUPM_DISABLE	/* do not power manage CPU devices */
233 } pm_cpupm_t;
234 
235 #define	PPM(dip) ((dev_info_t *)DEVI(dip)->devi_pm_ppm)
236 
237 /*
238  * The power request struct uses for the DDI_CTLOPS_POWER busctl.
239  *
240  * Note: When changing this enum it is necessary to maintain binary
241  * compatibility with older versions.  To insure that, add new values only
242  * at the end and refrain from deleting any existing values.
243  */
244 typedef enum {
245 	PMR_SET_POWER = 1,		/* called ddi_power (obsolete)	*/
246 	PMR_SUSPEND,			/* parental suspend		*/
247 	PMR_RESUME,			/* parental resume		*/
248 	PMR_PRE_SET_POWER,		/* parent's "pre" notification	*/
249 	PMR_POST_SET_POWER,		/* parent's "post" notification	*/
250 	PMR_PPM_SET_POWER,		/* platform pm set power	*/
251 	PMR_PPM_ATTACH,			/* ppm attach notify - unused	*/
252 	PMR_PPM_DETACH,			/* ppm detach notify - unused   */
253 	PMR_PPM_POWER_CHANGE_NOTIFY,	/* ppm level change notify	*/
254 	PMR_REPORT_PMCAP,		/* report pm capability		*/
255 	PMR_CHANGED_POWER,		/* parent's power_has_changed notif. */
256 	PMR_PPM_PRE_PROBE,		/* ppm pre probe notify		*/
257 	PMR_PPM_POST_PROBE,		/* ppm post probe notify	*/
258 	PMR_PPM_PRE_ATTACH,		/* ppm pre attach notify	*/
259 	PMR_PPM_POST_ATTACH,		/* ppm post pm attach notify	*/
260 	PMR_PPM_PRE_DETACH,		/* ppm pre pm detach notify	*/
261 	PMR_PPM_POST_DETACH,		/* ppm post pm detach notify	*/
262 	PMR_PPM_UNMANAGE,		/* device being unmanaged	*/
263 	PMR_PPM_PRE_RESUME,		/* ppm resume notify		*/
264 	PMR_PPM_ALL_LOWEST,		/* ppm all lowest power notify	*/
265 	PMR_PPM_LOCK_POWER,		/* ppm lock power		*/
266 	PMR_PPM_UNLOCK_POWER,		/* ppm unlock power		*/
267 	PMR_PPM_TRY_LOCK_POWER,		/* ppm try lock power		*/
268 	PMR_PPM_INIT_CHILD,		/* ppm init child notify	*/
269 	PMR_PPM_UNINIT_CHILD,		/* ppm uninit child notify	*/
270 	PMR_PPM_POWER_LOCK_OWNER,	/* ppm power lock owner's address */
271 	PMR_PPM_ENTER_SX,		/* ppm: enter ACPI S[2-4] state	*/
272 	PMR_PPM_EXIT_SX,		/* ppm: enter ACPI S[2-4] state	*/
273 	PMR_PPM_SEARCH_LIST		/* ppm: search tuple list	*/
274 } pm_request_type;
275 
276 /*
277  * When changing the elements of the union below it is necessary to
278  * maintain binary compatibility with older versions.  Refrain from
279  * deleting existing elements of the union or modifying their contents.
280  * Avoid increasing the total size of this structure if new elements
281  * must be added.
282  */
283 typedef struct power_req {
284 	pm_request_type request_type;
285 	union req {
286 		/*
287 		 * PMR_SET_POWER (obsolete)
288 		 */
289 		struct set_power_req {
290 			dev_info_t	*who;
291 			int		cmpt;
292 			int		level;
293 		} set_power_req;
294 		/*
295 		 * PMR_SUSPEND
296 		 */
297 		struct suspend_req {
298 			dev_info_t	*who;
299 			ddi_detach_cmd_t cmd;
300 		} suspend_req;
301 		/*
302 		 * PMR_PPM_PRE_RESUME or PMR_RESUME
303 		 */
304 		struct resume_req {
305 			dev_info_t	*who;
306 			ddi_attach_cmd_t cmd;
307 		} resume_req;
308 		/*
309 		 * PMR_PRE_SET_POWER
310 		 */
311 		struct pre_set_power_req {
312 			dev_info_t	*who;
313 			int		cmpt;
314 			int		old_level;
315 			int		new_level;
316 		} pre_set_power_req;
317 		/*
318 		 * PMR_POST_SET_POWER
319 		 */
320 		struct post_set_power_req {
321 			dev_info_t	*who;
322 			int		cmpt;
323 			int		old_level;
324 			int		new_level;
325 			int		result;		/* driver's return */
326 		} post_set_power_req;
327 		/*
328 		 * PMR_PPM_SET_POWER
329 		 */
330 		struct ppm_set_power_req {
331 			dev_info_t	*who;
332 			int		cmpt;
333 			int		old_level;
334 			int		new_level;
335 			pm_canblock_t	canblock;
336 			void		*cookie;
337 		} ppm_set_power_req;
338 		/*
339 		 * PMR_PPM_POWER_CHANGE_NOTIFY
340 		 */
341 		struct ppm_notify_level_req {
342 			dev_info_t	*who;
343 			int		cmpt;
344 			int		old_level;
345 			int		new_level;
346 		} ppm_notify_level_req;
347 		/*
348 		 * PMR_REPORT_PMCAP
349 		 */
350 		struct report_pmcap_req {
351 			dev_info_t	*who;
352 			int		cap;
353 			void 		*arg;
354 		} report_pmcap_req;
355 		/*
356 		 * PMR_CHANGED_POWER
357 		 */
358 		struct changed_power_req {
359 			dev_info_t	*who;
360 			int		cmpt;
361 			int		old_level;
362 			int		new_level;
363 			int		result;
364 		} changed_power_req;
365 		/*
366 		 * PMR_PPM_PRE_PROBE, PMR_PPM_POST_PROBE, PMR_PPM_PRE_ATTACH,
367 		 * PMR_PPM_POST_ATTACH, PMR_PPM_PRE_DETACH, PMR_PPM_POST_DETACH
368 		 * PMR_PPM_INIT_CHILD, PMR_PPM_UNINIT_CHILD, or PMR_PPM_UNMANAGE
369 		 */
370 		struct ppm_config_req {
371 			dev_info_t	*who;
372 			int		result;		/* post only */
373 		} ppm_config_req;
374 		/*
375 		 * PMR_PPM_ALL_LOWEST
376 		 */
377 		struct ppm_all_lowest_req {
378 			int		mode;
379 		} ppm_all_lowest_req;
380 		/*
381 		 * PMR_PPM_LOCK_POWER, PMR_PPM_TRY_LOCK_POWER
382 		 */
383 		struct ppm_lock_power_req {
384 			dev_info_t	*who;
385 			int		*circp;
386 		} ppm_lock_power_req;
387 		/*
388 		 * PMR_PPM_UNLOCK_POWER
389 		 */
390 		struct ppm_unlock_power_req {
391 			dev_info_t	*who;
392 			int		circ;
393 		} ppm_unlock_power_req;
394 		/*
395 		 * PMR_PPM_POWER_LOCK_OWNER
396 		 */
397 		struct ppm_power_lock_owner_req {
398 			dev_info_t	*who;
399 			kthread_t	*owner;
400 		} ppm_power_lock_owner_req;
401 		/*
402 		 * PMR_PPM_POWER_ENTER_SX
403 		 */
404 		struct ppm_power_enter_sx_req {
405 			int	sx_state;	/* S3, S4 */
406 			int	test_point;	/* test point */
407 			uint64_t wakephys;	/* restart vector phys addr */
408 			void *psr;		/* PSM (apic) state buffer */
409 		} ppm_power_enter_sx_req;
410 		/*
411 		 * PMR_PPM_SEARCH_LIST
412 		 */
413 		struct ppm_search_list {
414 			pm_searchargs_t *searchlist;
415 			int		result;
416 		} ppm_search_list_req;
417 	} req;
418 } power_req_t;
419 
420 #define	S3	3
421 #define	S4	4
422 
423 extern int cpr_test_point;
424 extern major_t cpr_device;
425 
426 #define	LOOP_BACK_NONE	0
427 #define	LOOP_BACK_PASS	1
428 #define	LOOP_BACK_FAIL	2
429 #define	FORCE_SUSPEND_TO_RAM	3
430 #define	DEVICE_SUSPEND_TO_RAM	4
431 
432 /*
433  * Struct passed as arg to appm_ioctl
434  */
435 typedef struct s3_args {
436 	int		s3a_state;	/* S3, S4 */
437 	int		s3a_test_point;	/* test point */
438 	uint64_t	s3a_wakephys;	/* restart vector physical addr */
439 	void		*s3a_psr;	/* apic state save buffer */
440 } s3a_t;
441 
442 /*
443  * Structure used by the following bus_power operations:
444  *
445  *	BUS_POWER_PRE_NOTIFICATION
446  *	BUS_POWER_POST_NOTIFICATION
447  *	BUS_POWER_CHILD_PWRCHG
448  */
449 typedef struct pm_bp_child_pwrchg {
450 	dev_info_t	*bpc_dip;	/* dip of the target device */
451 	char		*bpc_path;	/* path to the target device */
452 	int		bpc_comp;	/* component changing power */
453 	int		bpc_olevel;	/* old power level */
454 	int		bpc_nlevel;	/* new power level */
455 	void		*bpc_private;	/* PM framework private */
456 } pm_bp_child_pwrchg_t;
457 
458 /*
459  * Structure used by the BUS_POWER_NEXUS_PWRUP operation
460  */
461 typedef struct pm_bp_nexus_pwrup {
462 	dev_info_t	*bpn_dip;	/* dip of the nexus device */
463 	int		bpn_comp;	/* component powering up */
464 	int		bpn_level;	/* new power level */
465 	void		*bpn_private;	/* PM framework private */
466 } pm_bp_nexus_pwrup_t;
467 
468 /*
469  * Structure used by the BUS_POWER_HAS_CHANGED operation
470  */
471 typedef struct pm_bp_has_changed {
472 	dev_info_t	*bphc_dip;	/* dip of the target device */
473 	char		*bphc_path;	/* path to the target device */
474 	int		bphc_comp;	/* component changing power */
475 	int		bphc_olevel;	/* old power level */
476 	int		bphc_nlevel;	/* new power level */
477 	void		*bphc_private;	/* PM framework private */
478 } pm_bp_has_changed_t;
479 
480 /*
481  * Commands indicating which activity is requiring an
482  * update to the noinvol counters.
483  */
484 #define	PM_BP_NOINVOL_ATTACH	1
485 #define	PM_BP_NOINVOL_DETACH	2
486 #define	PM_BP_NOINVOL_REMDRV	3
487 #define	PM_BP_NOINVOL_CFB	4
488 #define	PM_BP_NOINVOL_POWER	5
489 
490 /*
491  * Structure used by the BUS_POWER_NOINVOL operation.
492  */
493 typedef struct pm_bp_noinvol {
494 	dev_info_t	*bpni_dip;	/* dip of the target device */
495 	char		*bpni_path;	/* path to the target device */
496 	int		bpni_cmd;	/* how to update the counters */
497 	int		bpni_volpmd;	/* volpmd of target device */
498 	int		bpni_wasvolpmd;	/* whether to update volpmd */
499 	void		*bpni_private;	/* PM framework private */
500 } pm_bp_noinvol_t;
501 
502 /*
503  * This struct is used by the code that makes a PMR_PPM_SET_POWER request
504  * to ppm. Devices that changed power other than the primary device (which
505  * was requested) are passed back to the pm framework through this
506  * structure.
507  */
508 typedef struct pm_ppm_devlist {
509 	dev_info_t	*ppd_who;
510 	int		ppd_cmpt;
511 	int		ppd_old_level;
512 	int		ppd_new_level;
513 	struct pm_ppm_devlist	*ppd_next;
514 } pm_ppm_devlist_t;
515 
516 /*
517  * This struct is used by the code that brings up parents and notifies
518  * ppm drivers across probe/attach/detach (pm_pre/post_probe/attach/detach())
519  */
520 typedef struct pm_ppm_cookie {
521 	dev_info_t		*ppc_dip;	/* dip of target node */
522 	dev_info_t		*ppc_pdip;	/* parent's dip */
523 	dev_info_t		*ppc_ppm;	/* interested ppm driver */
524 	int			ppc_cmd;	/* attach/detach cmd */
525 } pm_ppm_cookie_t;
526 
527 /*
528  * This struct records one dependency (a device keeps another or others up)
529  * pdr_size includes size of strings.
530  */
531 typedef struct pm_dep_rec {
532 	char *pdr_keeper;		/* physpath of device keeping up */
533 	char *pdr_kept;			/* physpath or property name */
534 	char **pdr_kept_paths;		/* array of kept devices' paths */
535 	struct pm_dep_rec *pdr_next;	/* next dependency device */
536 	size_t pdr_size;		/* size to kmem_free */
537 	major_t pdr_major;		/* major of kept driver (not props) */
538 	int pdr_isprop;			/* true if kept is property name */
539 	int pdr_kept_count;		/* how many kept altogether */
540 	int pdr_satisfied;		/* true if in force (not properties) */
541 } pm_pdr_t;
542 
543 
544 /*
545  * This struct records threshold information about a single component
546  */
547 typedef struct pm_thresh_entry {
548 	int pte_numthresh;
549 	int *pte_thresh;
550 } pm_pte_t;
551 
552 /*
553  * Note that this header and its array of entry structs with their arrays
554  * of thresholds and string storage for physpath are all kmem_alloced in one
555  * chunk for easy freeing ptr_size is the size of that chunk
556  */
557 typedef struct pm_thresh_rec {
558 	char			*ptr_physpath;	/* identifies node */
559 	struct pm_thresh_rec	*ptr_next;
560 	int			ptr_numcomps;	/* number of components */
561 	size_t			ptr_size;	/* total size for kmem_free */
562 	pm_pte_t 		*ptr_entries;
563 } pm_thresh_rec_t;
564 
565 /*
566  * pmi_dev_pm_state state bits:
567  */
568 
569 /*
570  * a direct-pm device, not scanned, but controlled by a process
571  */
572 #define	PM_DIRECT	0x1
573 /*
574  * autopm is suspended while waiting to see if detach succeeds
575  */
576 #define	PM_DETACHING	0x2
577 
578 /*
579  * An all_to_normal operation for an autopm device that is detaching, is
580  * deferred in case the detach fails.
581  */
582 #define	PM_ALLNORM_DEFERRED	0x4
583 
584 #define	PM_GET_PM_INFO(dip) (DEVI(dip)->devi_pm_info)
585 #define	PM_GET_PM_SCAN(dip) (DEVI(dip)->devi_pm_scan)
586 
587 #define	PM_NUMCMPTS(dip) (DEVI(dip)->devi_pm_num_components)
588 #define	PM_CP(dip, comp) (&DEVI(dip)->devi_pm_components[comp])
589 
590 /*
591  * Returns true if the device specified by dip is directly power managed
592  */
593 #define	PM_ISDIRECT(dip) \
594 	(((pm_info_t *)PM_GET_PM_INFO(dip))->pmi_dev_pm_state & PM_DIRECT)
595 
596 /*
597  * Returns true if the device specified by dip is an old node for which we
598  * provide backwards compatible behavior (e.g. no pm-components property).
599  */
600 #define	PM_ISBC(dip) (DEVI(dip)->devi_pm_flags & PMC_BC)
601 
602 /*
603  * Returns true if we have skipped a dependency bringup on this dip.
604  */
605 #define	PM_SKBU(dip) (DEVI(dip)->devi_pm_flags & PMC_SKIP_BRINGUP)
606 
607 /*
608  * Returns true if device specified by dip is a power manageable CPU.
609  */
610 #define	PM_ISCPU(dip) (DEVI(dip)->devi_pm_flags & PMC_CPU_DEVICE)
611 
612 /*
613  * Returns true if cpupm is enabled in event driven mode.
614  */
615 #define	PM_EVENT_CPUPM (cpupm == PM_CPUPM_EVENT)
616 
617 /*
618  * Returns true if cpupm is enabled in polling mode.
619  */
620 #define	PM_POLLING_CPUPM (cpupm == PM_CPUPM_POLLING)
621 
622 /*
623  * Returns true if cpupm operating using the default mode.
624  */
625 #define	PM_DEFAULT_CPUPM (cpupm == cpupm_default_mode)
626 
627 /*
628  * Returns true if is disabled.
629  */
630 #define	PM_CPUPM_DISABLED (cpupm == PM_CPUPM_DISABLE)
631 
632 /*
633  * If ((autopm is enabled and
634  *	(CPUPM is not disabled and we're not in event mode, or it isn't a cpu))
635  *	  OR
636  *	(CPUPM are enabled and it is one))
637  */
638 #define	PM_SCANABLE(dip) ((autopm_enabled && \
639 	((!PM_CPUPM_DISABLED && !PM_EVENT_CPUPM) || !PM_ISCPU(dip))) || \
640 	(PM_POLLING_CPUPM && PM_ISCPU(dip)))
641 
642 #define	PM_NOT_ALL_LOWEST	0x0	/* not all components are at lowest */
643 #define	PM_ALL_LOWEST		0x1	/* all components are at lowest lvl */
644 
645 #define	PM_ADDR(dip)	(ddi_get_name_addr(dip) ? ddi_get_name_addr(dip) : "")
646 #define	PM_NAME(dip)	(ddi_binding_name(dip))
647 #define	PM_NODE(dip)	(ddi_node_name(dip))
648 #define	PM_INST(dip)	(ddi_get_instance(dip))
649 #define	PM_DEVICE(dip)	PM_NAME(dip), PM_ADDR(dip), PM_NODE(dip), PM_INST(dip)
650 
651 #ifdef	DEBUG
652 /*
653  * Flags passed to PMD to enable debug printfs.  If the same flag is set in
654  * pm_debug below then the message is printed.  The most generally useful
655  * ones are the first 3 or 4.
656  */
657 #define	PMD_ERROR	0x0000001
658 #define	PMD_FAIL	0x0000002
659 #define	PMD_IOCTL	0x0000004
660 #define	PMD_SCAN	0x0000008
661 #define	PMD_RESCAN	0x0000010
662 #define	PMD_REMINFO	0x0000020
663 #define	PMD_NAMETODIP	0x0000040
664 #define	PMD_CLOSE	0x0000080
665 #define	PMD_DIN		0x0000100	/* Dev Is Needed */
666 #define	PMD_PMC		0x0000200	/* for testing with sun4m pmc driver */
667 #define	PMD_PPM		0x0000400
668 #define	PMD_DEP		0x0000800	/* dependency processing */
669 #define	PMD_IDLEDOWN	0x0001000
670 #define	PMD_SET		0x0002000
671 #define	PMD_BRING	0x0004000
672 #define	PMD_ALLNORM	0x0008000
673 #define	PMD_REMDEV	0x0010000
674 #define	PMD_LEVEL	0x0020000
675 #define	PMD_THRESH	0x0040000
676 #define	PMD_DPM		0x0080000	/* Direct Power Management */
677 #define	PMD_NORM	0x0100000
678 #define	PMD_STATS	0x0200000
679 #define	PMD_DEREG	0x0400000
680 #define	PMD_KEEPS	0x0800000
681 #define	PMD_KIDSUP	0x1000000
682 #define	PMD_TCHECK	0x2000000
683 #define	PMD_NOINVOL	0x4000000
684 #define	PMD_CFB		0x8000000	/* console fb pm */
685 #define	PMD_DHR		0x10000000	/* driver hold/rele changes */
686 #define	PMD_PIL		0x20000000	/* print out PIL when calling power */
687 #define	PMD_PHC		0x40000000	/* pm_power_has_changed messages */
688 #define	PMD_LOCK	0x80000000
689 #define	PMD_SX		0x80000000	/* ACPI S[1234] states */
690 #define	PMD_PROTO	PMD_SX		/* and other Prototype stuff */
691 
692 extern uint_t	pm_debug;
693 extern uint_t	pm_divertdebug;
694 /*PRINTFLIKE1*/
695 extern void	pm_log(const char *fmt, ...) __KPRINTFLIKE(1);
696 
697 #if !defined(__sparc)
698 /*
699  * On non-sparc machines, PMDDEBUG isn't as big a deal as Sparc, so we
700  * define PMDDEUG here for use on non-sparc platforms.
701  */
702 #define	PMDDEBUG
703 #endif /* !__sparc */
704 
705 #ifdef PMDDEBUG
706 #define	PMD(level, arglist) { 			\
707 	if (pm_debug & (level)) {		\
708 		pm_log arglist;			\
709 	}					\
710 }
711 #else /* !PMDDEBUG */
712 #define	PMD(level, arglist)	((void)0);
713 #endif /* PMDDEBUG */
714 #ifndef	sparc
715 extern clock_t pt_sleep;
716 /* code is char hex number to display on POST LED */
717 #define	PT(code) {outb(0x80, (char)code); drv_usecwait(pt_sleep); }
718 #else
719 #define	PT(code)
720 #endif
721 #else
722 #define	PMD(level, arglist)
723 #define	PT(code)
724 #endif
725 /*
726  * Code	Value	Indication
727  *
728  */
729 #define	PT_SPL7		0x01	/* pm_suspend spl7 */
730 #define	PT_PMSRET	0x02	/* pm_suspend returns */
731 #define	PT_PPMCTLOP	0x03	/* invoking ppm_ctlops */
732 #define	PT_ACPISDEV	0x04	/* acpi suspend devices */
733 #define	PT_IC		0x05	/* acpi intr_clear */
734 #define	PT_1to1		0x06	/* 1:1 mapping */
735 #define	PT_SC		0x07	/* save context */
736 #define	PT_SWV		0x08	/* set waking vector */
737 #define	PT_SWV_FAIL	0x09	/* set waking vector failed */
738 #define	PT_EWE		0x0a	/* enable wake events */
739 #define	PT_EWE_FAIL	0x0b	/* enable wake events failed */
740 #define	PT_RTCW		0x0c	/* setting rtc wakeup */
741 #define	PT_RTCW_FAIL	0x0d	/* setting rtc wakeup failed */
742 #define	PT_TOD		0x0e	/* setting tod */
743 #define	PT_SXP		0x0f	/* sx prep */
744 #define	PT_SXE		0x10	/* sx enter */
745 #define	PT_SXE_FAIL	0x11	/* sx enter failed */
746 #define	PT_INSOM	0x12	/* insomnia label */
747 #define	PT_WOKE		0x20	/* woke up */
748 #define	PT_UNDO1to1	0x21	/* Undo 1:1 mapping */
749 #define	PT_LSS		0x22	/* leave sleep state */
750 #define	PT_LSS_FAIL	0x23	/* leave sleep state failed */
751 #define	PT_CPB		0x24	/* clear power button event */
752 #define	PT_CPB_FAIL	0x25	/* clear power button event failed */
753 #define	PT_DRTC_FAIL	0x26	/* disable rtc fails */
754 #define	PT_ACPIREINIT	0x27	/* reinit apic */
755 #define	PT_ACPIRESTORE	0x28	/* restore apic */
756 #define	PT_INTRRESTORE	0x28	/* restore interrupts */
757 #define	PT_RESDEV	0x2a	/* ressume acpi devices */
758 #define	PT_CPU		0x2b	/* init_cpu_syscall */
759 #define	PT_PRESUME	0x30	/* pm_resume entered */
760 #define	PT_RSUS		0x31	/* pm_resume "suspended" */
761 #define	PT_RKERN	0x32	/* pm_resume "kernel" */
762 #define	PT_RDRV		0x33	/* pm_resume "driver" */
763 #define	PT_RDRV_FAIL	0x34	/* pm_resume "driver" failed */
764 #define	PT_RRNOINVOL	0x35	/* pm_resume "reattach_noinvol" */
765 #define	PT_RUSER	0x36	/* pm_resume "user" */
766 #define	PT_RAPMSIG	0x37	/* pm_resume APM/SRN signal */
767 #define	PT_RMPO		0x38	/* pm_resume "mp_online" */
768 #define	PT_RDONE	0x39	/* pm_resume done */
769 
770 extern void	pm_detaching(dev_info_t *);
771 extern void	pm_detach_failed(dev_info_t *);
772 extern int	pm_power(dev_info_t *, int, int);
773 extern int	pm_unmanage(dev_info_t *);
774 extern void	pm_rem_info(dev_info_t *);
775 extern int	pm_get_norm_pwrs(dev_info_t *, int **, size_t *);
776 extern dev_info_t *pm_name_to_dip(char *, int);
777 extern int	pm_power_up(dev_info_t *, int, int, int, pm_info_t *);
778 extern int	pm_default_idle_threshold;
779 extern void	pm_set_device_threshold(dev_info_t *, int, int);
780 extern int	pm_valid_power(dev_info_t *, int, int);
781 extern void	pm_lock_power(dev_info_t *, int *);
782 extern void	pm_unlock_power(dev_info_t *, int);
783 extern int	pm_try_locking_power(dev_info_t *, int *);
784 extern void	pm_lock_power_single(dev_info_t *, int *);
785 extern void	pm_unlock_power_single(dev_info_t *, int);
786 extern int	pm_try_locking_power_single(dev_info_t *, int *);
787 extern int	pm_isbc(dev_info_t *dip);
788 extern int	pm_isdirect(dev_info_t *dip);
789 extern int	pm_ctlops(dev_info_t *d, dev_info_t *r, ddi_ctl_enum_t o,
790 			void *a, void *v);
791 extern int	pm_noinvol_detached(char *);
792 extern int	pm_init_child(dev_info_t *);
793 extern int	pm_uninit_child(dev_info_t *);
794 
795 extern int	pm_all_to_normal(dev_info_t *, pm_canblock_t);
796 extern int	pm_set_power(dev_info_t *, int, int, int, pm_canblock_t, int,
797 			int *);
798 extern void	pm_scan_init(dev_info_t *dip);
799 extern void	pm_scan_fini(dev_info_t *dip);
800 extern void	pm_scan_stop(dev_info_t *dip);
801 extern int	pm_scan_stop_walk(dev_info_t *dip, void *);
802 extern void	pm_scan(void *);
803 extern time_t	pm_scan_dev(dev_info_t *dip);
804 extern void	pm_rescan(void *);
805 extern int	pm_rescan_walk(dev_info_t *, void *);
806 extern void	pm_forget_power_level(dev_info_t *);
807 extern int	pm_pre_config(dev_info_t *, char *);
808 extern int	pm_pre_unconfig(dev_info_t *, int, int *, char *);
809 extern void	pm_post_config(dev_info_t *, char *);
810 extern void	pm_post_unconfig(dev_info_t *, int, char *);
811 extern void	pm_pre_probe(dev_info_t *, pm_ppm_cookie_t *);
812 extern void	pm_post_probe(pm_ppm_cookie_t *, int, int);
813 extern void	pm_post_attach(pm_ppm_cookie_t *, int);
814 extern void	pm_pre_attach(dev_info_t *, pm_ppm_cookie_t *,
815 			ddi_attach_cmd_t);
816 extern void	pm_pre_detach(dev_info_t *, ddi_detach_cmd_t,
817 			pm_ppm_cookie_t *);
818 extern void	pm_post_detach(pm_ppm_cookie_t *, int);
819 extern int	pm_powerup(dev_info_t *);
820 extern int	pm_all_at_normal(dev_info_t *);
821 extern int	pm_busop_bus_power(dev_info_t *, void *,
822 		    pm_bus_power_op_t, void *, void *);
823 extern void	pm_hold_power(dev_info_t *);
824 extern void	pm_rele_power(dev_info_t *);
825 extern void	pm_driver_removed(major_t);
826 extern void	pm_borrow_lock(kthread_t *);
827 extern void	pm_return_lock(void);
828 extern int	pm_reattach_noinvol(void);
829 extern void	pm_reattach_noinvol_fini();
830 extern void	pm_restore_direct_levels(void);
831 extern void	pm_save_direct_levels(void);
832 extern void	pm_cfb_setup(const char *);
833 extern void	pm_proceed(dev_info_t *, int, int, int);
834 extern void	pm_get_timestamps(dev_info_t *, time_t *);
835 extern void	pm_deregister_watcher(int, dev_info_t *);
836 extern void	pm_dispatch_to_dep_thread(int, char *, char *, int, int *, int);
837 extern int	e_pm_valid_comp(dev_info_t *, int, pm_component_t **);
838 extern int	e_pm_valid_info(dev_info_t *, pm_info_t **);
839 extern int	e_pm_valid_power(dev_info_t *, int, int);
840 extern void	pm_init_locks(void);
841 extern int	pm_register_ppm(int (*)(dev_info_t *), dev_info_t *);
842 extern int	pm_is_cfb(dev_info_t *);
843 #ifdef	DEBUG
844 extern int	pm_cfb_is_up(void);
845 #endif
846 
847 #ifdef DIPLOCKDEBUG
848 #define	PM_LOCK_DIP(dip)	{ PMD(PMD_LOCK, ("dip lock %s@%s(%s#%d) " \
849 				    "%s %d\n", PM_DEVICE(dip),		  \
850 				    __FILE__, __LINE__)) 		  \
851 				    mutex_enter(&DEVI(dip)->devi_pm_lock); }
852 #define	PM_UNLOCK_DIP(dip)	{ PMD(PMD_LOCK, ("dip unlock %s@%s(%s#%d) " \
853 				    "%s %d\n", PM_DEVICE(dip),		    \
854 				    __FILE__, __LINE__))		    \
855 				    mutex_exit(&DEVI(dip)->devi_pm_lock); }
856 #else
857 #define	PM_LOCK_DIP(dip)	mutex_enter(&DEVI(dip)->devi_pm_lock)
858 #define	PM_UNLOCK_DIP(dip)	mutex_exit(&DEVI(dip)->devi_pm_lock)
859 #endif
860 
861 /*
862  * These are the same DEBUG or not
863  */
864 #define	PM_LOCK_BUSY(dip)	mutex_enter(&DEVI(dip)->devi_pm_busy_lock)
865 #define	PM_UNLOCK_BUSY(dip)	mutex_exit(&DEVI(dip)->devi_pm_busy_lock)
866 #define	PM_LOCK_POWER(dip, circp)	pm_lock_power(dip, circp)
867 #define	PM_UNLOCK_POWER(dip, circ)	pm_unlock_power(dip, circ)
868 #define	PM_TRY_LOCK_POWER(dip, circp)	pm_try_locking_power(dip, circp)
869 #define	PM_IAM_LOCKING_DIP(dip)	(mutex_owned(&DEVI(dip)->devi_pm_lock))
870 
871 #define	PM_DEFAULT_SYS_IDLENESS	1800	/* 30 minutes */
872 
873 /*
874  * Codes put into the pr_retval field of pm_rsvp_t that tell pm_block()
875  * how to proceed
876  */
877 #define	PMP_SUCCEED	0x1	/* return success, the process did it */
878 #define	PMP_FAIL	0x2	/* return fail, process did something else */
879 #define	PMP_RELEASE	0x3	/* let it go, the process has lost interest */
880 				/* also arg to pm_proceed to signal this */
881 /*
882  * Values of "style" for e_pm_manage and pm_premanage
883  */
884 #define	PM_STYLE_NEW		0
885 #define	PM_STYLE_UNKNOWN	1
886 
887 /*
888  * Arg passed to pm_proceed that results in PMP_SUCCEED or PMP_FAIL being set
889  * in pr_retval depending on what is pending
890  */
891 #define	PMP_SETPOWER	0x4
892 
893 #define	PM_MAX_CLONE	256
894 
895 typedef struct pm_rsvp {
896 	dev_info_t	*pr_dip;
897 	int		pr_comp;
898 	int		pr_newlevel;
899 	int		pr_oldlevel;
900 	kcondvar_t	pr_cv;		/* a place to sleep */
901 	int		pr_retval;	/* what to do when you wake up */
902 	struct pm_rsvp	*pr_next;
903 	struct pm_rsvp	*pr_prev;
904 } pm_rsvp_t;
905 
906 typedef struct psce {	/* pm_state_change_entries */
907 	struct pm_state_change		*psce_first;
908 	struct pm_state_change		*psce_in;
909 	struct pm_state_change		*psce_out;
910 	struct pm_state_change		*psce_last;
911 	int				psce_overruns;
912 	int				psce_references;
913 	kmutex_t			psce_lock;
914 } psce_t;
915 
916 typedef struct pscc {			/* pm_state_change_control */
917 	int		pscc_clone;
918 	dev_info_t	*pscc_dip;
919 	psce_t		*pscc_entries;
920 	struct pscc	*pscc_next;
921 	struct pscc	*pscc_prev;
922 } pscc_t;
923 
924 #define	PSCCOUNT 128	/* number of state change entries kept per process */
925 
926 /*
927  * Struct used to track the existence of devices exporting the
928  * no-involuntary-power-cycles property, and remember things from their
929  * devinfo node for later attach.
930  */
931 typedef struct pm_noinvol {
932 	struct pm_noinvol	*ni_next;
933 	char			*ni_path;
934 	major_t			ni_major;	/* for attaching at cpr time */
935 	uint_t			ni_flags;	/* selected PMC_* values */
936 	uint_t			ni_noinvolpm;	/* saved noinvolpm count */
937 	uint_t			ni_volpmd;	/* saved volpmd count */
938 	uint_t			ni_wasvolpmd;	/* was vol pm'd at detach */
939 	size_t			ni_size;
940 	int			ni_persistent;	/* still around */
941 } pm_noinvol_t;
942 
943 #define	PMID_IOCTIMER		0x1		/* pm_ioctl sets during timer */
944 #define	PMID_CFBTIMER		0x2		/* cfb sets during timer */
945 #define	PMID_IOCSCAN		0x4		/* pm_ioctl sets during scan */
946 #define	PMID_CFBSCAN		0x8		/* cfb sets during scan */
947 
948 #define	PMID_IOC		(PMID_IOCTIMER | PMID_IOCSCAN)
949 #define	PMID_CFB		(PMID_CFBTIMER | PMID_CFBSCAN)
950 #define	PMID_TIMERS		(PMID_IOCTIMER | PMID_CFBTIMER)
951 #define	PMID_SCANS		(PMID_IOCSCAN | PMID_CFBSCAN)
952 #define	PMID_SCANS_SHIFT	2
953 #define	PMID_SET_SCANS(pmid)	(pmid) |= (((pmid) & PMID_TIMERS) <<	\
954 				    PMID_SCANS_SHIFT);
955 #define	PMID_IS_IOC(pmid)	((pmid) & PMID_IOC)
956 #define	PMID_IS_CFB(pmid, dip)	(((pmid) & PMID_CFB) &&			\
957 				    (DEVI(dip)->devi_pm_flags &		\
958 				    (PMC_DEF_THRESH | PMC_NEXDEF_THRESH)))
959 #define	PM_IS_PID(dip)	(PMID_IS_IOC(PM_GET_PM_SCAN(dip)->ps_idle_down) || \
960 	PMID_IS_CFB(PM_GET_PM_SCAN(dip)->ps_idle_down, dip))
961 #define	PM_IS_CFB(dip)		(DEVI(dip)->devi_pm_flags & PMC_CONSOLE_FB)
962 #define	PM_KUC(dip)		(DEVI(dip)->devi_pm_kidsupcnt)
963 #define	PM_CURPOWER(dip, comp)	cur_power(PM_CP(dip, comp))
964 
965 #define	PM_WANTS_NOTIFICATION(dip)					\
966 	(DEVI(dip)->devi_pm_flags & PMC_WANTS_NOTIFY)
967 
968 #define	PM_HAS_BUS_POWER(dip)						\
969 	((DEVI(dip)->devi_ops->devo_bus_ops != NULL) &&			\
970 	(DEVI(dip)->devi_ops->devo_bus_ops->busops_rev >= BUSO_REV_7) &&\
971 	(DEVI(dip)->devi_ops->devo_bus_ops->bus_power != NULL))
972 
973 #define	PM_BUS_POWER_FUNC(dip)						\
974 	DEVI(dip)->devi_ops->devo_bus_ops->bus_power
975 
976 /*
977  * Structure used to pass down sunpm's private data variables
978  * through the bus_power bus_op calls
979  */
980 typedef struct pm_sp_misc {
981 	pm_canblock_t   pspm_canblock;
982 	int pspm_scan;
983 	int *pspm_errnop;
984 	int pspm_direction;
985 } pm_sp_misc_t;
986 
987 /*
988  * This structure is used in validating that the power level
989  * of the descendents are off, while a device is powered off.
990  */
991 typedef struct pm_desc_pwrchk {
992 	dev_info_t *pdpc_dip;
993 	int pdpc_par_involved;
994 } pm_desc_pwrchk_t;
995 
996 
997 /*
998  * These defines are used by pm_trans_check() to calculate time.
999  * Mostly copied from "tzfile.h".
1000  */
1001 #define	DC_SPY			(SECSPERDAY * DAYSPERNYEAR)
1002 #define	DC_SPW			(SECSPERDAY * DAYSPERWEEK)
1003 #define	DC_SPD			SECSPERDAY
1004 
1005 #define	DC_SCSI_YEAR_LEN	4		/* YYYY */
1006 #define	DC_SCSI_WEEK_LEN	2		/* WW */
1007 #define	DC_SCSI_NPY		5		/* # power-cycle years */
1008 
1009 #endif	/* _KERNEL */
1010 
1011 #ifdef	__cplusplus
1012 }
1013 #endif
1014 
1015 #endif /* _SYS_EPM_H */
1016