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