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