1700 Add SCSI UNMAP support
[unleashed.git] / usr / src / uts / common / sys / epm.h
blob476b254d1a6a7c29508f2d2d4a24e3e18c1162d5
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #ifndef _SYS_EPM_H
27 #define _SYS_EPM_H
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>
37 * XXXX
38 * Do we really need this include? It may be leftover from early CPUPM code.
39 * #include <sys/processor.h>
42 #ifdef __cplusplus
43 extern "C" {
44 #endif
46 #ifdef _KERNEL
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
83 * io to console).
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 */
106 } pm_scan_t;
109 * ps_scan_flags may take the following values, plus possibly
110 * more defined.
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 */
148 } pm_comp_t;
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 */
161 } pm_component_t;
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 */
180 } pm_info_t;
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 */
193 char *pdw_keeper;
194 char *pdw_kept;
195 } pm_dep_wk_t;
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 */
225 } pm_canblock_t;
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 */
233 } pm_cpupm_t;
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.
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;
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.
283 typedef struct power_req {
284 pm_request_type request_type;
285 union req {
287 * PMR_SET_POWER (obsolete)
289 struct set_power_req {
290 dev_info_t *who;
291 int cmpt;
292 int level;
293 } set_power_req;
295 * PMR_SUSPEND
297 struct suspend_req {
298 dev_info_t *who;
299 ddi_detach_cmd_t cmd;
300 } suspend_req;
302 * PMR_PPM_PRE_RESUME or PMR_RESUME
304 struct resume_req {
305 dev_info_t *who;
306 ddi_attach_cmd_t cmd;
307 } resume_req;
309 * PMR_PRE_SET_POWER
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;
318 * PMR_POST_SET_POWER
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;
328 * PMR_PPM_SET_POWER
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;
339 * PMR_PPM_POWER_CHANGE_NOTIFY
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;
348 * PMR_REPORT_PMCAP
350 struct report_pmcap_req {
351 dev_info_t *who;
352 int cap;
353 void *arg;
354 } report_pmcap_req;
356 * PMR_CHANGED_POWER
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;
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 {
371 dev_info_t *who;
372 int result; /* post only */
373 } ppm_config_req;
375 * PMR_PPM_ALL_LOWEST
377 struct ppm_all_lowest_req {
378 int mode;
379 } ppm_all_lowest_req;
381 * PMR_PPM_LOCK_POWER, PMR_PPM_TRY_LOCK_POWER
383 struct ppm_lock_power_req {
384 dev_info_t *who;
385 int *circp;
386 } ppm_lock_power_req;
388 * PMR_PPM_UNLOCK_POWER
390 struct ppm_unlock_power_req {
391 dev_info_t *who;
392 int circ;
393 } ppm_unlock_power_req;
395 * PMR_PPM_POWER_LOCK_OWNER
397 struct ppm_power_lock_owner_req {
398 dev_info_t *who;
399 kthread_t *owner;
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;
415 int result;
416 } ppm_search_list_req;
417 } req;
418 } power_req_t;
420 #define S3 3
421 #define S4 4
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 */
440 } s3a_t;
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 */
500 } pm_bp_noinvol_t;
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.
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;
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 */
525 } pm_ppm_cookie_t;
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) */
541 } pm_pdr_t;
545 * This struct records threshold information about a single component
547 typedef struct pm_thresh_entry {
548 int pte_numthresh;
549 int *pte_thresh;
550 } pm_pte_t;
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;
563 } pm_thresh_rec_t;
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))
635 * OR
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)
651 #ifdef DEBUG
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;
694 /*PRINTFLIKE1*/
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.
702 #define PMDDEBUG
703 #endif /* !__sparc */
705 #ifdef PMDDEBUG
706 #define PMD(level, arglist) { \
707 if (pm_debug & (level)) { \
708 pm_log arglist; \
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
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,
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 *);
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
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
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()
875 * how to proceed
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 {
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;
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;
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;
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;
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;
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) << \
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))
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;
982 int pspm_scan;
983 int *pspm_errnop;
984 int pspm_direction;
985 } pm_sp_misc_t;
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;
994 } pm_desc_pwrchk_t;
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 */
1011 #ifdef __cplusplus
1013 #endif
1015 #endif /* _SYS_EPM_H */