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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
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>
38 * Do we really need this include? It may be leftover from early CPUPM code.
39 * #include <sys/processor.h>
49 * epm.h: Function prototypes and data structs for kernel pm functions.
52 void e_pm_props(dev_info_t
*);
53 int e_new_pm_props(dev_info_t
*);
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 */
60 * Values used by e_pm_props and friends, found in devi_pm_flags
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 */
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
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 */
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)
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 */
100 * One of these is attached to each devinfo that is autopm'd.
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 */
109 * ps_scan_flags may take the following values, plus possibly
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
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 */
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.
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.
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 */
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.
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 */
151 * Here we have the rest of what we need to know about a component.
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 */
164 * All members of this struct are protected by PM_LOCK_DIP(dip).
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.
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 */
183 * Work request structure for the dependency processing thread.
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 */
198 * Types of work, depends on when it gets called:
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 */
215 * Wait for dependency work to finish or not.
217 #define PM_DEP_WAIT 1
218 #define PM_DEP_NOWAIT 0
220 typedef enum pm_canblock
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 */
227 typedef enum pm_cpupm
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 */
235 #define PPM(dip) ((dev_info_t *)DEVI(dip)->devi_pm_ppm)
238 * The power request struct uses for the DDI_CTLOPS_POWER busctl.
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.
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 */
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
283 typedef struct power_req
{
284 pm_request_type request_type
;
287 * PMR_SET_POWER (obsolete)
289 struct set_power_req
{
299 ddi_detach_cmd_t cmd
;
302 * PMR_PPM_PRE_RESUME or PMR_RESUME
306 ddi_attach_cmd_t cmd
;
311 struct pre_set_power_req
{
320 struct post_set_power_req
{
325 int result
; /* driver's return */
326 } post_set_power_req
;
330 struct ppm_set_power_req
{
335 pm_canblock_t canblock
;
339 * PMR_PPM_POWER_CHANGE_NOTIFY
341 struct ppm_notify_level_req
{
346 } ppm_notify_level_req
;
350 struct report_pmcap_req
{
358 struct changed_power_req
{
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
370 struct ppm_config_req
{
372 int result
; /* post only */
377 struct ppm_all_lowest_req
{
379 } ppm_all_lowest_req
;
381 * PMR_PPM_LOCK_POWER, PMR_PPM_TRY_LOCK_POWER
383 struct ppm_lock_power_req
{
386 } ppm_lock_power_req
;
388 * PMR_PPM_UNLOCK_POWER
390 struct ppm_unlock_power_req
{
393 } ppm_unlock_power_req
;
395 * PMR_PPM_POWER_LOCK_OWNER
397 struct ppm_power_lock_owner_req
{
400 } ppm_power_lock_owner_req
;
402 * PMR_PPM_POWER_ENTER_SX
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
;
411 * PMR_PPM_SEARCH_LIST
413 struct ppm_search_list
{
414 pm_searchargs_t
*searchlist
;
416 } ppm_search_list_req
;
423 extern int cpr_test_point
;
424 extern major_t cpr_device
;
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
433 * Struct passed as arg to appm_ioctl
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 */
443 * Structure used by the following bus_power operations:
445 * BUS_POWER_PRE_NOTIFICATION
446 * BUS_POWER_POST_NOTIFICATION
447 * BUS_POWER_CHILD_PWRCHG
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
;
459 * Structure used by the BUS_POWER_NEXUS_PWRUP operation
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
;
469 * Structure used by the BUS_POWER_HAS_CHANGED operation
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
;
481 * Commands indicating which activity is requiring an
482 * update to the noinvol counters.
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
491 * Structure used by the BUS_POWER_NOINVOL operation.
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 */
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
508 typedef struct pm_ppm_devlist
{
513 struct pm_ppm_devlist
*ppd_next
;
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())
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 */
528 * This struct records one dependency (a device keeps another or others up)
529 * pdr_size includes size of strings.
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) */
545 * This struct records threshold information about a single component
547 typedef struct pm_thresh_entry
{
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
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
;
566 * pmi_dev_pm_state state bits:
570 * a direct-pm device, not scanned, but controlled by a process
572 #define PM_DIRECT 0x1
574 * autopm is suspended while waiting to see if detach succeeds
576 #define PM_DETACHING 0x2
579 * An all_to_normal operation for an autopm device that is detaching, is
580 * deferred in case the detach fails.
582 #define PM_ALLNORM_DEFERRED 0x4
584 #define PM_GET_PM_INFO(dip) (DEVI(dip)->devi_pm_info)
585 #define PM_GET_PM_SCAN(dip) (DEVI(dip)->devi_pm_scan)
587 #define PM_NUMCMPTS(dip) (DEVI(dip)->devi_pm_num_components)
588 #define PM_CP(dip, comp) (&DEVI(dip)->devi_pm_components[comp])
591 * Returns true if the device specified by dip is directly power managed
593 #define PM_ISDIRECT(dip) \
594 (((pm_info_t *)PM_GET_PM_INFO(dip))->pmi_dev_pm_state & PM_DIRECT)
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).
600 #define PM_ISBC(dip) (DEVI(dip)->devi_pm_flags & PMC_BC)
603 * Returns true if we have skipped a dependency bringup on this dip.
605 #define PM_SKBU(dip) (DEVI(dip)->devi_pm_flags & PMC_SKIP_BRINGUP)
608 * Returns true if device specified by dip is a power manageable CPU.
610 #define PM_ISCPU(dip) (DEVI(dip)->devi_pm_flags & PMC_CPU_DEVICE)
613 * Returns true if cpupm is enabled in event driven mode.
615 #define PM_EVENT_CPUPM (cpupm == PM_CPUPM_EVENT)
618 * Returns true if cpupm is enabled in polling mode.
620 #define PM_POLLING_CPUPM (cpupm == PM_CPUPM_POLLING)
623 * Returns true if cpupm operating using the default mode.
625 #define PM_DEFAULT_CPUPM (cpupm == cpupm_default_mode)
628 * Returns true if is disabled.
630 #define PM_CPUPM_DISABLED (cpupm == PM_CPUPM_DISABLE)
633 * If ((autopm is enabled and
634 * (CPUPM is not disabled and we're not in event mode, or it isn't a cpu))
636 * (CPUPM are enabled and it is one))
638 #define PM_SCANABLE(dip) ((autopm_enabled && \
639 ((!PM_CPUPM_DISABLED && !PM_EVENT_CPUPM) || !PM_ISCPU(dip))) || \
640 (PM_POLLING_CPUPM && PM_ISCPU(dip)))
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 */
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)
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.
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 */
692 extern uint_t pm_debug
;
693 extern uint_t pm_divertdebug
;
695 extern void pm_log(const char *fmt
, ...) __KPRINTFLIKE(1);
697 #if !defined(__sparc)
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.
703 #endif /* !__sparc */
706 #define PMD(level, arglist) { \
707 if (pm_debug & (level)) { \
711 #else /* !PMDDEBUG */
712 #define PMD(level, arglist) ((void)0);
713 #endif /* PMDDEBUG */
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); }
722 #define PMD(level, arglist)
726 * Code Value Indication
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 */
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
,
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
*);
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,
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
*,
816 extern void pm_pre_detach(dev_info_t
*, ddi_detach_cmd_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
*);
844 extern int pm_cfb_is_up(void);
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); }
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)
862 * These are the same DEBUG or not
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))
871 #define PM_DEFAULT_SYS_IDLENESS 1800 /* 30 minutes */
874 * Codes put into the pr_retval field of pm_rsvp_t that tell pm_block()
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 */
882 * Values of "style" for e_pm_manage and pm_premanage
884 #define PM_STYLE_NEW 0
885 #define PM_STYLE_UNKNOWN 1
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
891 #define PMP_SETPOWER 0x4
893 #define PM_MAX_CLONE 256
895 typedef struct pm_rsvp
{
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
;
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
;
916 typedef struct pscc
{ /* pm_state_change_control */
918 dev_info_t
*pscc_dip
;
919 psce_t
*pscc_entries
;
920 struct pscc
*pscc_next
;
921 struct pscc
*pscc_prev
;
924 #define PSCCOUNT 128 /* number of state change entries kept per process */
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.
931 typedef struct pm_noinvol
{
932 struct pm_noinvol
*ni_next
;
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 */
940 int ni_persistent
; /* still around */
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 */
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) << \
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))
965 #define PM_WANTS_NOTIFICATION(dip) \
966 (DEVI(dip)->devi_pm_flags & PMC_WANTS_NOTIFY)
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))
973 #define PM_BUS_POWER_FUNC(dip) \
974 DEVI(dip)->devi_ops->devo_bus_ops->bus_power
977 * Structure used to pass down sunpm's private data variables
978 * through the bus_power bus_op calls
980 typedef struct pm_sp_misc
{
981 pm_canblock_t pspm_canblock
;
988 * This structure is used in validating that the power level
989 * of the descendents are off, while a device is powered off.
991 typedef struct pm_desc_pwrchk
{
992 dev_info_t
*pdpc_dip
;
993 int pdpc_par_involved
;
998 * These defines are used by pm_trans_check() to calculate time.
999 * Mostly copied from "tzfile.h".
1001 #define DC_SPY (SECSPERDAY * DAYSPERNYEAR)
1002 #define DC_SPW (SECSPERDAY * DAYSPERWEEK)
1003 #define DC_SPD SECSPERDAY
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 */
1009 #endif /* _KERNEL */
1015 #endif /* _SYS_EPM_H */