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.
26 * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
30 * sunpm.c builds sunpm.o "power management framework"
31 * kernel-resident power management code. Implements power management
33 * Assumes: all backwards compat. device components wake up on &
34 * the pm_info pointer in dev_info is initially NULL
36 * PM - (device) Power Management
38 * Each device may have 0 or more components. If a device has no components,
39 * then it can't be power managed. Each component has 2 or more
42 * "Backwards Compatible" (bc) devices:
43 * There are two different types of devices from the point of view of this
44 * code. The original type, left over from the original PM implementation on
45 * the voyager platform are known in this code as "backwards compatible"
46 * devices (PM_ISBC(dip) returns true).
47 * They are recognized by the pm code by the lack of a pm-components property
48 * and a call made by the driver to pm_create_components(9F).
49 * For these devices, component 0 is special, and represents the power state
50 * of the device. If component 0 is to be set to power level 0 (off), then
51 * the framework must first call into the driver's detach(9E) routine with
52 * DDI_PM_SUSPEND, to get the driver to save the hardware state of the device.
53 * After setting component 0 from 0 to a non-zero power level, a call must be
54 * made into the driver's attach(9E) routine with DDI_PM_RESUME.
56 * Currently, the only way to get a bc device power managed is via a set of
57 * ioctls (PM_DIRECT_PM, PM_SET_CURRENT_POWER) issued to /dev/pm.
59 * For non-bc devices, the driver describes the components by exporting a
60 * pm-components(9P) property that tells how many components there are,
61 * tells what each component's power state values are, and provides human
62 * readable strings (currently unused) for each component name and power state.
63 * Devices which export pm-components(9P) are automatically power managed
64 * whenever autopm is enabled (via PM_START_PM ioctl issued by pmconfig(1M)
65 * after parsing power.conf(4)). The exception to this rule is that power
66 * manageable CPU devices may be automatically managed independently of autopm
67 * by either enabling or disabling (via PM_START_CPUPM and PM_STOP_CPUPM
68 * ioctls) cpupm. If the CPU devices are not managed independently, then they
69 * are managed by autopm. In either case, for automatically power managed
70 * devices, all components are considered independent of each other, and it is
71 * up to the driver to decide when a transition requires saving or restoring
74 * Each device component also has a threshold time associated with each power
75 * transition (see power.conf(4)), and a busy/idle state maintained by the
76 * driver calling pm_idle_component(9F) and pm_busy_component(9F).
77 * Components are created idle.
79 * The PM framework provides several functions:
80 * -implement PM policy as described in power.conf(4)
81 * Policy is set by pmconfig(1M) issuing pm ioctls based on power.conf(4).
82 * Policies consist of:
83 * -set threshold values (defaults if none provided by pmconfig)
84 * -set dependencies among devices
85 * -enable/disable autopm
86 * -enable/disable cpupm
87 * -turn down idle components based on thresholds (if autopm or cpupm is
88 * enabled) (aka scanning)
89 * -maintain power states based on dependencies among devices
90 * -upon request, or when the frame buffer powers off, attempt to turn off
91 * all components that are idle or become idle over the next (10 sec)
92 * period in an attempt to get down to an EnergyStar compliant state
93 * -prevent powering off of a device which exported the
94 * pm-no-involuntary-power-cycles property without active involvement of
95 * the device's driver (so no removing power when the device driver is
97 * -provide a mechanism for a device driver to request that a device's component
98 * be brought back to the power level necessary for the use of the device
99 * -allow a process to directly control the power levels of device components
100 * (via ioctls issued to /dev/pm--see usr/src/uts/common/io/pm.c)
101 * -ensure that the console frame buffer is powered up before being referenced
102 * via prom_printf() or other prom calls that might generate console output
103 * -maintain implicit dependencies (e.g. parent must be powered up if child is)
104 * -provide "backwards compatible" behavior for devices without pm-components
108 * Whenever autopm or cpupm is enabled, the framework attempts to bring each
109 * component of each managed device to its lowest power based on the threshold
110 * of idleness associated with each transition and the busy/idle state of the
113 * The actual work of this is done by pm_scan_dev(), which cycles through each
114 * component of a device, checking its idleness against its current threshold,
115 * and calling pm_set_power() as appropriate to change the power level.
116 * This function also indicates when it would next be profitable to scan the
117 * device again, and a new scan is scheduled after that time.
120 * It is possible to establish a dependency between the power states of two
121 * otherwise unrelated devices. This is currently done to ensure that the
122 * cdrom is always up whenever the console framebuffer is up, so that the user
123 * can insert a cdrom and see a popup as a result.
125 * The dependency terminology used in power.conf(4) is not easy to understand,
126 * so we've adopted a different terminology in the implementation. We write
127 * of a "keeps up" and a "kept up" device. A relationship can be established
128 * where one device keeps up another. That means that if the keepsup device
129 * has any component that is at a non-zero power level, all components of the
130 * "kept up" device must be brought to full power. This relationship is
131 * asynchronous. When the keeping device is powered up, a request is queued
132 * to a worker thread to bring up the kept device. The caller does not wait.
133 * Scan will not turn down a kept up device.
136 * A device may be directly power managed by a process. If a device is
137 * directly pm'd, then it will not be scanned, and dependencies will not be
138 * enforced. * If a directly pm'd device's driver requests a power change (via
139 * pm_raise_power(9F)), then the request is blocked and notification is sent
140 * to the controlling process, which must issue the requested power change for
141 * the driver to proceed.
145 #include <sys/types.h>
146 #include <sys/errno.h>
147 #include <sys/callb.h> /* callback registration during CPR */
148 #include <sys/conf.h> /* driver flags and functions */
149 #include <sys/open.h> /* OTYP_CHR definition */
150 #include <sys/stat.h> /* S_IFCHR definition */
151 #include <sys/pathname.h> /* name -> dev_info xlation */
152 #include <sys/ddi_impldefs.h> /* dev_info node fields */
153 #include <sys/kmem.h> /* memory alloc stuff */
154 #include <sys/debug.h>
155 #include <sys/archsystm.h>
158 #include <sys/sunddi.h>
159 #include <sys/sunndi.h>
160 #include <sys/sunpm.h>
163 #include <sys/mode.h>
164 #include <sys/mkdev.h>
165 #include <sys/promif.h>
166 #include <sys/consdev.h>
167 #include <sys/esunddi.h>
168 #include <sys/modctl.h>
169 #include <sys/fs/ufs_fs.h>
170 #include <sys/note.h>
171 #include <sys/taskq.h>
172 #include <sys/bootconf.h>
173 #include <sys/reboot.h>
175 #include <sys/disp.h>
176 #include <sys/sobject.h>
177 #include <sys/sunmdi.h>
178 #include <sys/systm.h>
179 #include <sys/cpuvar.h>
180 #include <sys/cyclic.h>
181 #include <sys/uadmin.h>
188 * Global pm mutex locks.
191 * It protects the timeout id of the scan thread, and the value
192 * of autopm_enabled and cpupm. This lock is not held
193 * concurrently with any other PM locks.
195 * pm_clone_lock: Protects the clone list and count of poll events
196 * pending for the pm driver.
198 * pm_clone_lock -> pm_pscc_interest_rwlock,
199 * pm_clone_lock -> pm_pscc_direct_rwlock.
202 * Used to synchronize the data structures used for processes
203 * to rendezvous with state change information when doing
206 * pm_rsvp_lock -> pm_pscc_interest_rwlock,
207 * pm_rsvp_lock -> pm_pscc_direct_rwlock,
208 * pm_rsvp_lock -> pm_clone_lock.
210 * ppm_lock: protects the list of registered ppm drivers
212 * ppm_lock -> ppm driver unit_lock
215 * Protects count of components that are not at their lowest
218 * pm_compcnt_lock -> ppm_lock.
220 * pm_dep_thread_lock:
221 * Protects work list for pm_dep_thread. Not taken concurrently
222 * with any other pm lock.
225 * Serializes the operation of removing noinvol data structure
226 * entries for a branch of the tree when a driver has been
227 * removed from the system (modctl_rem_major).
229 * pm_remdrv_lock -> pm_noinvol_rwlock.
231 * pm_cfb_lock: (High level spin lock)
232 * Protects the count of how many components of the console
233 * frame buffer are off (so we know if we have to bring up the
234 * console as a result of a prom_printf, etc.
235 * No other locks are taken while holding this lock.
238 * Protects the lock_loan list. List is used to record that one
239 * thread has acquired a power lock but has launched another thread
240 * to complete its processing. An entry in the list indicates that
241 * the worker thread can borrow the lock held by the other thread,
242 * which must block on the completion of the worker. Use is
243 * specific to module loading.
244 * No other locks are taken while holding this lock.
249 * Protects the list of thresholds recorded for future use (when
252 * pm_thresh_rwlock -> devi_pm_lock
255 * Protects list of detached nodes that had noinvol registered.
256 * No other PM locks are taken while holding pm_noinvol_rwlock.
258 * pm_pscc_direct_rwlock:
259 * Protects the list that maps devices being directly power
260 * managed to the processes that manage them.
262 * pm_pscc_direct_rwlock -> psce_lock
264 * pm_pscc_interest_rwlock;
265 * Protects the list that maps state change events to processes
266 * that want to know about them.
268 * pm_pscc_interest_rwlock -> psce_lock
272 * Each node has these per-dip locks, which are only used if the device is
273 * a candidate for power management (e.g. has pm components)
276 * Protects all power management state of the node except for
277 * power level, which is protected by ndi_devi_enter().
278 * Encapsulated in macros PM_LOCK_DIP()/PM_UNLOCK_DIP().
280 * devi_pm_lock -> pm_rsvp_lock,
281 * devi_pm_lock -> pm_dep_thread_lock,
282 * devi_pm_lock -> pm_noinvol_rwlock,
283 * devi_pm_lock -> power lock
285 * power lock (ndi_devi_enter()):
286 * Since changing power level is possibly a slow operation (30
287 * seconds to spin up a disk drive), this is locked separately.
288 * Since a call into the driver to change the power level of one
289 * component may result in a call back into the framework to change
290 * the power level of another, this lock allows re-entrancy by
291 * the same thread (ndi_devi_enter is used for this because
292 * the USB framework uses ndi_devi_enter in its power entry point,
293 * and use of any other lock would produce a deadlock.
296 * This lock protects the integrity of the busy count. It is
297 * only taken by pm_busy_component() and pm_idle_component and
298 * some code that adjust the busy time after the timer gets set
299 * up or after a CPR operation. It is per-dip to keep from
300 * single-threading all the disk drivers on a system.
301 * It could be per component instead, but most devices have
302 * only one component.
303 * No other PM locks are taken while holding this lock.
307 static int stdout_is_framebuffer
;
308 static kmutex_t e_pm_power_lock
;
309 static kmutex_t pm_loan_lock
;
310 kmutex_t pm_scan_lock
;
311 callb_id_t pm_cpr_cb_id
;
312 callb_id_t pm_panic_cb_id
;
313 callb_id_t pm_halt_cb_id
;
314 int pm_comps_notlowest
; /* no. of comps not at lowest power */
315 int pm_powering_down
; /* cpr is source of DDI_SUSPEND calls */
317 clock_t pm_id_ticks
= 5; /* ticks to wait before scan during idle-down */
318 clock_t pm_default_min_scan
= PM_DEFAULT_MIN_SCAN
;
319 clock_t pm_cpu_min_scan
= PM_CPU_MIN_SCAN
;
321 #define PM_MIN_SCAN(dip) (PM_ISCPU(dip) ? pm_cpu_min_scan : \
324 static int pm_busop_set_power(dev_info_t
*,
325 void *, pm_bus_power_op_t
, void *, void *);
326 static int pm_busop_match_request(dev_info_t
*, void *);
327 static int pm_all_to_normal_nexus(dev_info_t
*, pm_canblock_t
);
328 static void e_pm_set_max_power(dev_info_t
*, int, int);
329 static int e_pm_get_max_power(dev_info_t
*, int);
332 * Dependency Processing is done thru a seperate thread.
334 kmutex_t pm_dep_thread_lock
;
335 kcondvar_t pm_dep_thread_cv
;
336 pm_dep_wk_t
*pm_dep_thread_workq
= NULL
;
337 pm_dep_wk_t
*pm_dep_thread_tail
= NULL
;
340 * Autopm must be turned on by a PM_START_PM ioctl, so we don't end up
341 * power managing things in single user mode that have been suppressed via
342 * power.conf entries. Protected by pm_scan_lock.
347 * cpupm is turned on and off, by the PM_START_CPUPM and PM_STOP_CPUPM ioctls,
348 * to define the power management behavior of CPU devices separate from
349 * autopm. Protected by pm_scan_lock.
351 pm_cpupm_t cpupm
= PM_CPUPM_NOTSET
;
354 * Defines the default mode of operation for CPU power management,
355 * either the polling implementation, or the event based dispatcher driven
358 pm_cpupm_t cpupm_default_mode
= PM_CPUPM_EVENT
;
361 * AutoS3 depends on autopm being enabled, and must be enabled by
362 * PM_START_AUTOS3 command.
366 #if !defined(__sparc)
368 * on sparc these live in fillsysinfo.c
370 * If this variable is non-zero, cpr should return "not supported" when
371 * it is queried even though it would normally be supported on this platform.
373 int cpr_supported_override
;
376 * Some platforms may need to support CPR even in the absence of
377 * having the correct platform id information. If this
378 * variable is non-zero, cpr should proceed even in the absence
379 * of otherwise being qualified.
381 int cpr_platform_enable
= 0;
386 * pm_S3_enabled indicates that we believe the platform can support S3,
387 * which we get from pmconfig(1M)
392 * This flag is true while processes are stopped for a checkpoint/resume.
393 * Controlling processes of direct pm'd devices are not available to
394 * participate in power level changes, so we bypass them when this is set.
396 static int pm_processes_stopped
;
401 * see common/sys/epm.h for PMD_* values
407 * If pm_divertdebug is set, then no prom_printf calls will be made by
408 * PMD(), which will prevent debug output from bringing up the console
409 * frame buffer. Clearing this variable before setting pm_debug will result
410 * in PMD output going to the console.
412 * pm_divertdebug is incremented in pm_set_power() if dip == cfb_dip to avoid
413 * deadlocks and decremented at the end of pm_set_power()
415 uint_t pm_divertdebug
= 1;
416 volatile uint_t pm_debug_to_console
= 0;
417 kmutex_t pm_debug_lock
; /* protects pm_divertdebug */
425 * List of recorded thresholds and dependencies
427 pm_thresh_rec_t
*pm_thresh_head
;
428 krwlock_t pm_thresh_rwlock
;
430 pm_pdr_t
*pm_dep_head
;
431 static int pm_unresolved_deps
= 0;
432 static int pm_prop_deps
= 0;
435 * List of devices that exported no-involuntary-power-cycles property
437 pm_noinvol_t
*pm_noinvol_head
;
440 * Locks used in noinvol processing
442 krwlock_t pm_noinvol_rwlock
;
443 kmutex_t pm_remdrv_lock
;
445 int pm_default_idle_threshold
= PM_DEFAULT_SYS_IDLENESS
;
446 int pm_system_idle_threshold
;
447 int pm_cpu_idle_threshold
;
450 * By default nexus has 0 threshold, and depends on its children to keep it up
452 int pm_default_nexus_threshold
= 0;
455 * Data structures shared with common/io/pm.c
457 kmutex_t pm_clone_lock
;
458 kcondvar_t pm_clones_cv
[PM_MAX_CLONE
];
459 uint_t pm_poll_cnt
[PM_MAX_CLONE
]; /* count of events for poll */
460 unsigned char pm_interest
[PM_MAX_CLONE
];
461 struct pollhead pm_pollhead
;
464 * Data structures shared with common/io/srn.c
466 kmutex_t srn_clone_lock
; /* protects srn_signal, srn_inuse */
467 void (*srn_signal
)(int type
, int event
);
468 int srn_inuse
; /* stop srn detach */
471 extern char *platform_module_list
[];
474 * Wrappers for use in ddi_walk_devs
477 static int pm_set_dev_thr_walk(dev_info_t
*, void *);
478 static int pm_restore_direct_lvl_walk(dev_info_t
*, void *);
479 static int pm_save_direct_lvl_walk(dev_info_t
*, void *);
480 static int pm_discard_dep_walk(dev_info_t
*, void *);
482 static int pm_desc_pwrchk_walk(dev_info_t
*, void *);
486 * Routines for managing noinvol devices
488 int pm_noinvol_update(int, int, int, char *, dev_info_t
*);
489 void pm_noinvol_update_node(dev_info_t
*,
490 pm_bp_noinvol_t
*req
);
492 kmutex_t pm_rsvp_lock
;
493 kmutex_t pm_compcnt_lock
;
494 krwlock_t pm_pscc_direct_rwlock
;
495 krwlock_t pm_pscc_interest_rwlock
;
497 #define PSC_INTEREST 0 /* belongs to interest psc list */
498 #define PSC_DIRECT 1 /* belongs to direct psc list */
500 pscc_t
*pm_pscc_interest
;
501 pscc_t
*pm_pscc_direct
;
503 #define PM_MAJOR(dip) ddi_driver_major(dip)
504 #define PM_IS_NEXUS(dip) ((PM_MAJOR(dip) == DDI_MAJOR_T_NONE) ? 0 : \
505 NEXUS_DRV(devopsp[PM_MAJOR(dip)]))
506 #define POWERING_ON(old, new) ((old) == 0 && (new) != 0)
507 #define POWERING_OFF(old, new) ((old) != 0 && (new) == 0)
509 #define PM_INCR_NOTLOWEST(dip) { \
510 mutex_enter(&pm_compcnt_lock); \
511 if (!PM_IS_NEXUS(dip) || \
512 (DEVI(dip)->devi_pm_flags & (PMC_DEV_THRESH|PMC_COMP_THRESH))) {\
513 if (pm_comps_notlowest == 0) \
514 pm_ppm_notify_all_lowest(dip, PM_NOT_ALL_LOWEST);\
515 pm_comps_notlowest++; \
516 PMD(PMD_LEVEL, ("%s: %s@%s(%s#%d) incr notlowest->%d\n",\
517 pmf, PM_DEVICE(dip), pm_comps_notlowest)) \
519 mutex_exit(&pm_compcnt_lock); \
521 #define PM_DECR_NOTLOWEST(dip) { \
522 mutex_enter(&pm_compcnt_lock); \
523 if (!PM_IS_NEXUS(dip) || \
524 (DEVI(dip)->devi_pm_flags & (PMC_DEV_THRESH|PMC_COMP_THRESH))) {\
525 ASSERT(pm_comps_notlowest); \
526 pm_comps_notlowest--; \
527 PMD(PMD_LEVEL, ("%s: %s@%s(%s#%d) decr notlowest to " \
528 "%d\n", pmf, PM_DEVICE(dip), pm_comps_notlowest))\
529 if (pm_comps_notlowest == 0) \
530 pm_ppm_notify_all_lowest(dip, PM_ALL_LOWEST); \
532 mutex_exit(&pm_compcnt_lock); \
536 * console frame-buffer power-management is not enabled when
537 * debugging services are present. to override, set pm_cfb_override
540 uint_t pm_cfb_comps_off
= 0; /* PM_LEVEL_UNKNOWN is considered on */
541 kmutex_t pm_cfb_lock
;
542 int pm_cfb_enabled
= 1; /* non-zero allows pm of console frame buffer */
544 int pm_cfb_override
= 1; /* non-zero allows pm of cfb with debuggers */
546 int pm_cfb_override
= 0; /* non-zero allows pm of cfb with debuggers */
549 static dev_info_t
*cfb_dip
= 0;
550 static dev_info_t
*cfb_dip_detaching
= 0;
551 uint_t cfb_inuse
= 0;
552 static ddi_softintr_t pm_soft_id
;
553 static boolean_t pm_soft_pending
;
554 int pm_scans_disabled
= 0;
557 * A structure to record the fact that one thread has borrowed a lock held
558 * by another thread. The context requires that the lender block on the
559 * completion of the borrower.
561 typedef struct lock_loan
{
562 struct lock_loan
*pmlk_next
;
563 kthread_t
*pmlk_borrower
;
564 kthread_t
*pmlk_lender
;
565 dev_info_t
*pmlk_dip
;
567 static lock_loan_t lock_loan_head
; /* list head is a dummy element */
571 #define PMD_FUNC(func, name) char *(func) = (name);
572 #else /* !PMDDEBUG */
573 #define PMD_FUNC(func, name)
574 #endif /* PMDDEBUG */
576 #define PMD_FUNC(func, name)
581 * Must be called before first device (including pseudo) attach
586 mutex_init(&pm_scan_lock
, NULL
, MUTEX_DRIVER
, NULL
);
587 mutex_init(&pm_rsvp_lock
, NULL
, MUTEX_DRIVER
, NULL
);
588 mutex_init(&pm_compcnt_lock
, NULL
, MUTEX_DRIVER
, NULL
);
589 mutex_init(&pm_dep_thread_lock
, NULL
, MUTEX_DRIVER
, NULL
);
590 mutex_init(&pm_remdrv_lock
, NULL
, MUTEX_DRIVER
, NULL
);
591 mutex_init(&pm_loan_lock
, NULL
, MUTEX_DRIVER
, NULL
);
592 rw_init(&pm_thresh_rwlock
, NULL
, RW_DEFAULT
, NULL
);
593 rw_init(&pm_noinvol_rwlock
, NULL
, RW_DEFAULT
, NULL
);
594 cv_init(&pm_dep_thread_cv
, NULL
, CV_DEFAULT
, NULL
);
597 static int pm_reset_timestamps(dev_info_t
*, void *);
600 pm_cpr_callb(void *arg
, int code
)
602 _NOTE(ARGUNUSED(arg
))
603 static int auto_save
;
604 static pm_cpupm_t cpupm_save
;
607 case CB_CODE_CPR_CHKPT
:
609 * Cancel scan or wait for scan in progress to finish
610 * Other threads may be trying to restart the scan, so we
611 * have to keep at it unil it sticks
613 mutex_enter(&pm_scan_lock
);
614 ASSERT(!pm_scans_disabled
);
615 pm_scans_disabled
= 1;
616 auto_save
= autopm_enabled
;
619 cpupm
= PM_CPUPM_NOTSET
;
620 mutex_exit(&pm_scan_lock
);
621 ddi_walk_devs(ddi_root_node(), pm_scan_stop_walk
, NULL
);
624 case CB_CODE_CPR_RESUME
:
625 ASSERT(!autopm_enabled
);
626 ASSERT(cpupm
== PM_CPUPM_NOTSET
);
627 ASSERT(pm_scans_disabled
);
628 pm_scans_disabled
= 0;
630 * Call pm_reset_timestamps to reset timestamps of each
631 * device to the time when the system is resumed so that their
632 * idleness can be re-calculated. That's to avoid devices from
633 * being powered down right after resume if the system was in
634 * suspended mode long enough.
636 ddi_walk_devs(ddi_root_node(), pm_reset_timestamps
, NULL
);
638 autopm_enabled
= auto_save
;
641 * If there is any auto-pm device, get the scanning
642 * going. Otherwise don't bother.
644 ddi_walk_devs(ddi_root_node(), pm_rescan_walk
, NULL
);
651 * This callback routine is called when there is a system panic. This function
652 * exists for prototype matching.
655 pm_panic_callb(void *arg
, int code
)
657 _NOTE(ARGUNUSED(arg
, code
))
658 void pm_cfb_check_and_powerup(void);
659 PMD(PMD_CFB
, ("pm_panic_callb\n"))
660 pm_cfb_check_and_powerup();
665 pm_halt_callb(void *arg
, int code
)
667 _NOTE(ARGUNUSED(arg
, code
))
671 static void pm_dep_thread(void);
674 * This needs to be called after the root and platform drivers are loaded
675 * and be single-threaded with respect to driver attach/detach
680 PMD_FUNC(pmf
, "pm_init")
682 extern pri_t minclsyspri
;
684 pm_comps_notlowest
= 0;
685 pm_system_idle_threshold
= pm_default_idle_threshold
;
686 pm_cpu_idle_threshold
= 0;
688 pm_cpr_cb_id
= callb_add(pm_cpr_callb
, (void *)NULL
,
689 CB_CL_CPR_PM
, "pm_cpr");
690 pm_panic_cb_id
= callb_add(pm_panic_callb
, (void *)NULL
,
691 CB_CL_PANIC
, "pm_panic");
692 pm_halt_cb_id
= callb_add(pm_halt_callb
, (void *)NULL
,
693 CB_CL_HALT
, "pm_halt");
696 * Create a thread to do dependency processing.
698 (void) thread_create(NULL
, 0, (void (*)())pm_dep_thread
, NULL
, 0, &p0
,
699 TS_RUN
, minclsyspri
);
702 * loadrootmodules already loaded these ppm drivers, now get them
703 * attached so they can claim the root drivers as they attach
705 for (mod
= platform_module_list
; *mod
; mod
++) {
706 if (i_ddi_attach_hw_nodes(*mod
) != DDI_SUCCESS
) {
707 cmn_err(CE_WARN
, "!cannot load platform pm driver %s\n",
710 PMD(PMD_DHR
, ("%s: %s (%s)\n", pmf
, *mod
,
711 ddi_major_to_name(ddi_name_to_major(*mod
))))
717 * pm_scan_init - create pm scan data structure. Called (if autopm or cpupm
718 * enabled) when device becomes power managed or after a failed detach and
719 * when autopm is started via PM_START_PM or PM_START_CPUPM ioctls, and after
720 * a CPR resume to get all the devices scanning again.
723 pm_scan_init(dev_info_t
*dip
)
725 PMD_FUNC(pmf
, "scan_init")
728 ASSERT(!PM_ISBC(dip
));
731 scanp
= PM_GET_PM_SCAN(dip
);
733 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d): create scan data\n",
734 pmf
, PM_DEVICE(dip
)))
735 scanp
= kmem_zalloc(sizeof (pm_scan_t
), KM_SLEEP
);
736 DEVI(dip
)->devi_pm_scan
= scanp
;
737 } else if (scanp
->ps_scan_flags
& PM_SCAN_STOP
) {
738 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d): "
739 "clear PM_SCAN_STOP flag\n", pmf
, PM_DEVICE(dip
)))
740 scanp
->ps_scan_flags
&= ~PM_SCAN_STOP
;
746 * pm_scan_fini - remove pm scan data structure when stopping pm on the device
749 pm_scan_fini(dev_info_t
*dip
)
751 PMD_FUNC(pmf
, "scan_fini")
754 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d)\n", pmf
, PM_DEVICE(dip
)))
755 ASSERT(!PM_ISBC(dip
));
757 scanp
= PM_GET_PM_SCAN(dip
);
763 ASSERT(!scanp
->ps_scan_id
&& !(scanp
->ps_scan_flags
&
764 (PM_SCANNING
| PM_SCAN_DISPATCHED
| PM_SCAN_AGAIN
)));
766 kmem_free(scanp
, sizeof (pm_scan_t
));
767 DEVI(dip
)->devi_pm_scan
= NULL
;
772 * Given a pointer to a component struct, return the current power level
773 * (struct contains index unless it is a continuous level).
774 * Located here in hopes of getting both this and dev_is_needed into the
778 cur_power(pm_component_t
*cp
)
780 if (cp
->pmc_cur_pwr
== PM_LEVEL_UNKNOWN
)
781 return (cp
->pmc_cur_pwr
);
783 return (cp
->pmc_comp
.pmc_lvals
[cp
->pmc_cur_pwr
]);
787 pm_decode_direction(int direction
)
790 case PM_LEVEL_UPONLY
:
796 case PM_LEVEL_DOWNONLY
:
800 return ("INVALID DIRECTION");
805 pm_decode_op(pm_bus_power_op_t op
)
808 case BUS_POWER_CHILD_PWRCHG
:
809 return ("CHILD_PWRCHG");
810 case BUS_POWER_NEXUS_PWRUP
:
811 return ("NEXUS_PWRUP");
812 case BUS_POWER_PRE_NOTIFICATION
:
813 return ("PRE_NOTIFICATION");
814 case BUS_POWER_POST_NOTIFICATION
:
815 return ("POST_NOTIFICATION");
816 case BUS_POWER_HAS_CHANGED
:
817 return ("HAS_CHANGED");
818 case BUS_POWER_NOINVOL
:
821 return ("UNKNOWN OP");
826 * Returns true if level is a possible (valid) power level for component
829 e_pm_valid_power(dev_info_t
*dip
, int cmpt
, int level
)
831 PMD_FUNC(pmf
, "e_pm_valid_power")
832 pm_component_t
*cp
= PM_CP(dip
, cmpt
);
834 int *ip
= cp
->pmc_comp
.pmc_lvals
;
835 int limit
= cp
->pmc_comp
.pmc_numlevels
;
839 for (i
= 0; i
< limit
; i
++) {
844 if (pm_debug
& PMD_FAIL
) {
845 ip
= cp
->pmc_comp
.pmc_lvals
;
847 for (i
= 0; i
< limit
; i
++)
848 PMD(PMD_FAIL
, ("%s: index=%d, level=%d\n",
855 static int pm_start(dev_info_t
*dip
);
857 * Returns true if device is pm'd (after calling pm_start if need be)
860 e_pm_valid_info(dev_info_t
*dip
, pm_info_t
**infop
)
865 * Check if the device is power managed if not.
866 * To make the common case (device is power managed already)
867 * fast, we check without the lock. If device is not already
868 * power managed, then we take the lock and the long route through
869 * go get it managed. Devices never go unmanaged until they
872 info
= PM_GET_PM_INFO(dip
);
874 if (!DEVI_IS_ATTACHING(dip
)) {
877 if (pm_start(dip
) != DDI_SUCCESS
) {
880 info
= PM_GET_PM_INFO(dip
);
889 e_pm_valid_comp(dev_info_t
*dip
, int cmpt
, pm_component_t
**cpp
)
891 if (cmpt
>= 0 && cmpt
< PM_NUMCMPTS(dip
)) {
893 *cpp
= PM_CP(dip
, cmpt
);
901 * Internal guts of ddi_dev_is_needed and pm_raise/lower_power
904 dev_is_needed(dev_info_t
*dip
, int cmpt
, int level
, int direction
)
911 ASSERT(direction
== PM_LEVEL_UPONLY
|| direction
== PM_LEVEL_DOWNONLY
);
912 if (!e_pm_valid_info(dip
, NULL
) || !e_pm_valid_comp(dip
, cmpt
, &cp
) ||
913 !e_pm_valid_power(dip
, cmpt
, level
))
914 return (DDI_FAILURE
);
916 PMD(PMD_DIN
, ("%s: %s@%s(%s#%d) cmpt=%d, dir=%s, new=%d, cur=%d\n",
917 pmf
, PM_DEVICE(dip
), cmpt
, pm_decode_direction(direction
),
918 level
, cur_power(cp
)))
920 if (pm_set_power(dip
, cmpt
, level
, direction
,
921 PM_CANBLOCK_BLOCK
, 0, &result
) != DDI_SUCCESS
) {
922 if (direction
== PM_LEVEL_UPONLY
) {
923 pathbuf
= kmem_alloc(MAXPATHLEN
, KM_SLEEP
);
924 (void) ddi_pathname(dip
, pathbuf
);
925 cmn_err(CE_WARN
, "Device %s failed to power up.",
927 kmem_free(pathbuf
, MAXPATHLEN
);
929 PMD(PMD_DIN
| PMD_FAIL
, ("%s: %s@%s(%s#%d) [%d] %s->%d failed, "
930 "errno %d\n", pmf
, PM_DEVICE(dip
), cmpt
,
931 pm_decode_direction(direction
), level
, result
))
932 return (DDI_FAILURE
);
935 PMD(PMD_RESCAN
| PMD_DIN
, ("%s: pm_rescan %s@%s(%s#%d)\n", pmf
,
938 return (DDI_SUCCESS
);
942 * We can get multiple pm_rescan() threads, if one of them discovers
943 * that no scan is running at the moment, it kicks it into action.
944 * Otherwise, it tells the current scanning thread to scan again when
945 * it is done by asserting the PM_SCAN_AGAIN flag. The PM_SCANNING and
946 * PM_SCAN_AGAIN flags are used to regulate scan, to make sure only one
947 * thread at a time runs the pm_scan_dev() code.
952 PMD_FUNC(pmf
, "rescan")
953 dev_info_t
*dip
= (dev_info_t
*)arg
;
958 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d)\n", pmf
, PM_DEVICE(dip
)))
960 info
= PM_GET_PM_INFO(dip
);
961 scanp
= PM_GET_PM_SCAN(dip
);
962 if (pm_scans_disabled
|| !PM_SCANABLE(dip
) || !info
|| !scanp
||
963 (scanp
->ps_scan_flags
& PM_SCAN_STOP
)) {
967 if (scanp
->ps_scan_flags
& PM_SCANNING
) {
968 scanp
->ps_scan_flags
|= PM_SCAN_AGAIN
;
971 } else if (scanp
->ps_scan_id
) {
972 scanid
= scanp
->ps_scan_id
;
973 scanp
->ps_scan_id
= 0;
974 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d): cancel timeout scanid %lx\n",
975 pmf
, PM_DEVICE(dip
), (ulong_t
)scanid
))
977 (void) untimeout(scanid
);
982 * Dispatching pm_scan during attach time is risky due to the fact that
983 * attach might soon fail and dip dissolved, and panic may happen while
984 * attempting to stop scan. So schedule a pm_rescan instead.
985 * (Note that if either of the first two terms are true, taskq_dispatch
986 * will not be invoked).
988 * Multiple pm_scan dispatching is unecessary and costly to keep track
989 * of. The PM_SCAN_DISPATCHED flag is used between pm_rescan and pm_scan
990 * to regulate the dispatching.
992 * Scan is stopped before the device is detached (in pm_detaching())
993 * but it may get re-started during the post_detach processing if the
994 * driver fails to detach.
996 if (DEVI_IS_ATTACHING(dip
) ||
997 (scanp
->ps_scan_flags
& PM_SCAN_DISPATCHED
) ||
998 !taskq_dispatch(system_taskq
, pm_scan
, (void *)dip
, TQ_NOSLEEP
)) {
999 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d): attaching, pm_scan already "
1000 "dispatched or dispatching failed\n", pmf
, PM_DEVICE(dip
)))
1001 if (scanp
->ps_scan_id
) {
1002 scanid
= scanp
->ps_scan_id
;
1003 scanp
->ps_scan_id
= 0;
1005 (void) untimeout(scanid
);
1007 if (scanp
->ps_scan_id
) {
1008 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d): a competing "
1009 "thread scheduled pm_rescan, scanid %lx\n",
1010 pmf
, PM_DEVICE(dip
),
1011 (ulong_t
)scanp
->ps_scan_id
))
1016 scanp
->ps_scan_id
= timeout(pm_rescan
, (void *)dip
,
1017 (scanp
->ps_idle_down
? pm_id_ticks
:
1018 (PM_MIN_SCAN(dip
) * hz
)));
1019 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d): scheduled next pm_rescan, "
1020 "scanid %lx\n", pmf
, PM_DEVICE(dip
),
1021 (ulong_t
)scanp
->ps_scan_id
))
1023 PMD(PMD_SCAN
, ("%s: dispatched pm_scan for %s@%s(%s#%d)\n",
1024 pmf
, PM_DEVICE(dip
)))
1025 scanp
->ps_scan_flags
|= PM_SCAN_DISPATCHED
;
1033 PMD_FUNC(pmf
, "scan")
1034 dev_info_t
*dip
= (dev_info_t
*)arg
;
1038 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d)\n", pmf
, PM_DEVICE(dip
)))
1041 scanp
= PM_GET_PM_SCAN(dip
);
1042 ASSERT(scanp
&& PM_GET_PM_INFO(dip
));
1044 if (pm_scans_disabled
|| !PM_SCANABLE(dip
) ||
1045 (scanp
->ps_scan_flags
& PM_SCAN_STOP
)) {
1046 scanp
->ps_scan_flags
&= ~(PM_SCAN_AGAIN
| PM_SCAN_DISPATCHED
);
1051 if (scanp
->ps_idle_down
) {
1053 * make sure we remember idledown was in affect until
1054 * we've completed the scan
1056 PMID_SET_SCANS(scanp
->ps_idle_down
)
1057 PMD(PMD_IDLEDOWN
, ("%s: %s@%s(%s#%d): idledown starts "
1058 "(pmid %x)\n", pmf
, PM_DEVICE(dip
), scanp
->ps_idle_down
))
1061 /* possible having two threads running pm_scan() */
1062 if (scanp
->ps_scan_flags
& PM_SCANNING
) {
1063 scanp
->ps_scan_flags
|= PM_SCAN_AGAIN
;
1064 PMD(PMD_SCAN
, ("%s: scanning, will scan %s@%s(%s#%d) again\n",
1065 pmf
, PM_DEVICE(dip
)))
1066 scanp
->ps_scan_flags
&= ~PM_SCAN_DISPATCHED
;
1071 scanp
->ps_scan_flags
|= PM_SCANNING
;
1072 scanp
->ps_scan_flags
&= ~PM_SCAN_DISPATCHED
;
1074 scanp
->ps_scan_flags
&= ~PM_SCAN_AGAIN
;
1076 nextscan
= pm_scan_dev(dip
);
1078 } while (scanp
->ps_scan_flags
& PM_SCAN_AGAIN
);
1080 ASSERT(scanp
->ps_scan_flags
& PM_SCANNING
);
1081 scanp
->ps_scan_flags
&= ~PM_SCANNING
;
1083 if (scanp
->ps_idle_down
) {
1084 scanp
->ps_idle_down
&= ~PMID_SCANS
;
1085 PMD(PMD_IDLEDOWN
, ("%s: %s@%s(%s#%d): idledown ends "
1086 "(pmid %x)\n", pmf
, PM_DEVICE(dip
), scanp
->ps_idle_down
))
1089 /* schedule for next idle check */
1090 if (nextscan
!= LONG_MAX
) {
1091 if (nextscan
> (LONG_MAX
/ hz
))
1092 nextscan
= (LONG_MAX
- 1) / hz
;
1093 if (scanp
->ps_scan_id
) {
1094 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d): while scanning "
1095 "another rescan scheduled scanid(%lx)\n", pmf
,
1096 PM_DEVICE(dip
), (ulong_t
)scanp
->ps_scan_id
))
1099 } else if (!(scanp
->ps_scan_flags
& PM_SCAN_STOP
)) {
1100 scanp
->ps_scan_id
= timeout(pm_rescan
, (void *)dip
,
1101 (clock_t)(nextscan
* hz
));
1102 PMD(PMD_SCAN
, ("%s: nextscan for %s@%s(%s#%d) in "
1103 "%lx sec, scanid(%lx) \n", pmf
, PM_DEVICE(dip
),
1104 (ulong_t
)nextscan
, (ulong_t
)scanp
->ps_scan_id
))
1111 pm_get_timestamps(dev_info_t
*dip
, time_t *valuep
)
1113 int components
= PM_NUMCMPTS(dip
);
1116 ASSERT(components
> 0);
1117 PM_LOCK_BUSY(dip
); /* so we get a consistent view */
1118 for (i
= 0; i
< components
; i
++) {
1119 valuep
[i
] = PM_CP(dip
, i
)->pmc_timestamp
;
1121 PM_UNLOCK_BUSY(dip
);
1125 * Returns true if device needs to be kept up because it exported the
1126 * "no-involuntary-power-cycles" property or we're pretending it did (console
1127 * fb case) or it is an ancestor of such a device and has used up the "one
1128 * free cycle" allowed when all such leaf nodes have voluntarily powered down
1132 pm_noinvol(dev_info_t
*dip
)
1134 PMD_FUNC(pmf
, "noinvol")
1137 * This doesn't change over the life of a driver, so no locking needed
1139 if (PM_IS_CFB(dip
)) {
1140 PMD(PMD_NOINVOL
| PMD_CFB
, ("%s: inhibits CFB %s@%s(%s#%d)\n",
1141 pmf
, PM_DEVICE(dip
)))
1145 * Not an issue if no such kids
1147 if (DEVI(dip
)->devi_pm_noinvolpm
== 0) {
1149 if (DEVI(dip
)->devi_pm_volpmd
!= 0) {
1150 dev_info_t
*pdip
= dip
;
1152 PMD(PMD_NOINVOL
, ("%s: %s@%s(%s#%d) noinvol %d "
1153 "volpmd %d\n", pmf
, PM_DEVICE(pdip
),
1154 DEVI(pdip
)->devi_pm_noinvolpm
,
1155 DEVI(pdip
)->devi_pm_volpmd
))
1156 pdip
= ddi_get_parent(pdip
);
1160 ASSERT(DEVI(dip
)->devi_pm_volpmd
== 0);
1165 * Since we now maintain the counts correct at every node, we no longer
1166 * need to look up the tree. An ancestor cannot use up the free cycle
1167 * without the children getting their counts adjusted.
1171 if (DEVI(dip
)->devi_pm_noinvolpm
!= DEVI(dip
)->devi_pm_volpmd
)
1172 PMD(PMD_NOINVOL
, ("%s: (%d != %d) inhibits %s@%s(%s#%d)\n", pmf
,
1173 DEVI(dip
)->devi_pm_noinvolpm
, DEVI(dip
)->devi_pm_volpmd
,
1176 return (DEVI(dip
)->devi_pm_noinvolpm
!= DEVI(dip
)->devi_pm_volpmd
);
1179 static int cur_threshold(dev_info_t
*, int);
1180 static int pm_next_lower_power(pm_component_t
*, int);
1183 * This function performs the actual scanning of the device.
1184 * It attempts to power off the indicated device's components if they have
1185 * been idle and other restrictions are met.
1186 * pm_scan_dev calculates and returns when the next scan should happen for
1190 pm_scan_dev(dev_info_t
*dip
)
1192 PMD_FUNC(pmf
, "scan_dev")
1194 time_t *timestamp
, idletime
, now
, thresh
;
1195 time_t timeleft
= 0;
1199 int i
, nxtpwr
, pwrndx
, unused
;
1202 dev_info_t
*pdip
= ddi_get_parent(dip
);
1204 clock_t min_scan
= pm_default_min_scan
;
1207 * skip attaching device
1209 if (DEVI_IS_ATTACHING(dip
)) {
1210 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d) is attaching, timeleft(%lx)\n",
1211 pmf
, PM_DEVICE(dip
), min_scan
))
1216 scanp
= PM_GET_PM_SCAN(dip
);
1217 min_scan
= PM_MIN_SCAN(dip
);
1218 ASSERT(scanp
&& PM_GET_PM_INFO(dip
));
1220 PMD(PMD_SCAN
, ("%s: [BEGIN %s@%s(%s#%d)]\n", pmf
, PM_DEVICE(dip
)))
1221 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d): kuc is %d\n", pmf
, PM_DEVICE(dip
),
1224 /* no scan under the following conditions */
1225 if (pm_scans_disabled
|| !PM_SCANABLE(dip
) ||
1226 (scanp
->ps_scan_flags
& PM_SCAN_STOP
) ||
1227 (PM_KUC(dip
) != 0) ||
1228 PM_ISDIRECT(dip
) || pm_noinvol(dip
)) {
1230 PMD(PMD_SCAN
, ("%s: [END, %s@%s(%s#%d)] no scan, "
1231 "scan_disabled(%d), apm_enabled(%d), cpupm(%d), "
1232 "kuc(%d), %s directpm, %s pm_noinvol\n",
1233 pmf
, PM_DEVICE(dip
), pm_scans_disabled
, autopm_enabled
,
1235 PM_ISDIRECT(dip
) ? "is" : "is not",
1236 pm_noinvol(dip
) ? "is" : "is not"))
1241 if (!ndi_devi_tryenter(pdip
, &circ
)) {
1242 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d) can't hold pdip",
1243 pmf
, PM_DEVICE(pdip
)))
1246 now
= gethrestime_sec();
1247 size
= PM_NUMCMPTS(dip
) * sizeof (time_t);
1248 timestamp
= kmem_alloc(size
, KM_SLEEP
);
1249 pm_get_timestamps(dip
, timestamp
);
1252 * Since we removed support for backwards compatible devices,
1253 * (see big comment at top of file)
1254 * it is no longer required to deal with component 0 last.
1256 for (i
= 0; i
< PM_NUMCMPTS(dip
); i
++) {
1258 * If already off (an optimization, perhaps)
1261 pwrndx
= cp
->pmc_cur_pwr
;
1263 curpwr
= (pwrndx
== PM_LEVEL_UNKNOWN
) ?
1265 cp
->pmc_comp
.pmc_lvals
[pwrndx
];
1269 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d) comp %d off or "
1270 "lowest\n", pmf
, PM_DEVICE(dip
), i
))
1271 /* skip device if off or at its lowest */
1275 thresh
= cur_threshold(dip
, i
); /* comp i threshold */
1276 if ((timestamp
[i
] == 0) || (cp
->pmc_busycount
> 0)) {
1277 /* were busy or newly became busy by another thread */
1279 timeleft
= max(thresh
, min_scan
);
1282 timeleft
, max(thresh
, min_scan
));
1286 idletime
= now
- timestamp
[i
]; /* idle time */
1287 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d) comp %d idle time %lx\n",
1288 pmf
, PM_DEVICE(dip
), i
, idletime
))
1289 if (idletime
>= thresh
|| PM_IS_PID(dip
)) {
1290 nxtpwr
= pm_next_lower_power(cp
, pwrndx
);
1291 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d) comp %d, %d->%d\n",
1292 pmf
, PM_DEVICE(dip
), i
, curpwr
, nxtpwr
))
1293 if (pm_set_power(dip
, i
, nxtpwr
, PM_LEVEL_DOWNONLY
,
1294 PM_CANBLOCK_FAIL
, 1, &unused
) != DDI_SUCCESS
&&
1295 PM_CURPOWER(dip
, i
) != nxtpwr
) {
1296 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d) comp %d, "
1297 "%d->%d Failed\n", pmf
, PM_DEVICE(dip
),
1299 timeleft
= min_scan
;
1302 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d) comp %d, "
1303 "%d->%d, GOOD curpwr %d\n", pmf
,
1304 PM_DEVICE(dip
), i
, curpwr
, nxtpwr
,
1307 if (nxtpwr
== 0) /* component went off */
1311 * scan to next lower level
1315 1, cur_threshold(dip
, i
));
1317 timeleft
= min(timeleft
,
1318 max(1, cur_threshold(dip
, i
)));
1319 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d) comp %d, "
1320 "timeleft(%lx)\n", pmf
, PM_DEVICE(dip
),
1323 } else { /* comp not idle long enough */
1325 timeleft
= thresh
- idletime
;
1327 timeleft
= min(timeleft
, (thresh
- idletime
));
1328 PMD(PMD_SCAN
, ("%s: %s@%s(%s#%d) comp %d, timeleft="
1329 "%lx\n", pmf
, PM_DEVICE(dip
), i
, timeleft
))
1332 ndi_devi_exit(pdip
, circ
);
1333 kmem_free(timestamp
, size
);
1334 PMD(PMD_SCAN
, ("%s: [END %s@%s(%s#%d)] timeleft(%lx)\n", pmf
,
1335 PM_DEVICE(dip
), timeleft
))
1338 * if components are already at lowest level, timeleft is left 0
1340 return ((timeleft
== 0) ? LONG_MAX
: timeleft
);
1344 * pm_scan_stop - cancel scheduled pm_rescan,
1345 * wait for termination of dispatched pm_scan thread
1346 * and active pm_scan_dev thread.
1349 pm_scan_stop(dev_info_t
*dip
)
1351 PMD_FUNC(pmf
, "scan_stop")
1353 timeout_id_t scanid
;
1355 PMD(PMD_SCAN
, ("%s: [BEGIN %s@%s(%s#%d)]\n", pmf
, PM_DEVICE(dip
)))
1357 scanp
= PM_GET_PM_SCAN(dip
);
1359 PMD(PMD_SCAN
, ("%s: [END %s@%s(%s#%d)] scan not initialized\n",
1360 pmf
, PM_DEVICE(dip
)))
1364 scanp
->ps_scan_flags
|= PM_SCAN_STOP
;
1366 /* cancel scheduled scan taskq */
1367 while (scanp
->ps_scan_id
) {
1368 scanid
= scanp
->ps_scan_id
;
1369 scanp
->ps_scan_id
= 0;
1371 (void) untimeout(scanid
);
1375 while (scanp
->ps_scan_flags
& (PM_SCANNING
| PM_SCAN_DISPATCHED
)) {
1381 PMD(PMD_SCAN
, ("%s: [END %s@%s(%s#%d)]\n", pmf
, PM_DEVICE(dip
)))
1385 pm_scan_stop_walk(dev_info_t
*dip
, void *arg
)
1387 _NOTE(ARGUNUSED(arg
))
1389 if (!PM_GET_PM_SCAN(dip
))
1390 return (DDI_WALK_CONTINUE
);
1391 ASSERT(!PM_ISBC(dip
));
1393 return (DDI_WALK_CONTINUE
);
1397 * Converts a power level value to its index
1400 power_val_to_index(pm_component_t
*cp
, int val
)
1404 ASSERT(val
!= PM_LEVEL_UPONLY
&& val
!= PM_LEVEL_DOWNONLY
&&
1405 val
!= PM_LEVEL_EXACT
);
1406 /* convert power value into index (i) */
1407 limit
= cp
->pmc_comp
.pmc_numlevels
;
1408 ip
= cp
->pmc_comp
.pmc_lvals
;
1409 for (i
= 0; i
< limit
; i
++)
1416 * Converts a numeric power level to a printable string
1419 power_val_to_string(pm_component_t
*cp
, int val
)
1423 if (val
== PM_LEVEL_UPONLY
)
1424 return ("<UPONLY>");
1426 if (val
== PM_LEVEL_UNKNOWN
||
1427 (index
= power_val_to_index(cp
, val
)) == -1)
1428 return ("<LEVEL_UNKNOWN>");
1430 return (cp
->pmc_comp
.pmc_lnames
[index
]);
1434 * Return true if this node has been claimed by a ppm.
1437 pm_ppm_claimed(dev_info_t
*dip
)
1439 return (PPM(dip
) != NULL
);
1443 * A node which was voluntarily power managed has just used up its "free cycle"
1444 * and need is volpmd field cleared, and the same done to all its descendents
1447 pm_clear_volpm_dip(dev_info_t
*dip
)
1449 PMD_FUNC(pmf
, "clear_volpm_dip")
1453 PMD(PMD_NOINVOL
, ("%s: clear volpm from %s@%s(%s#%d)\n", pmf
,
1455 DEVI(dip
)->devi_pm_volpmd
= 0;
1456 for (dip
= ddi_get_child(dip
); dip
; dip
= ddi_get_next_sibling(dip
)) {
1457 pm_clear_volpm_dip(dip
);
1462 * A node which was voluntarily power managed has used up the "free cycles"
1463 * for the subtree that it is the root of. Scan through the list of detached
1464 * nodes and adjust the counts of any that are descendents of the node.
1467 pm_clear_volpm_list(dev_info_t
*dip
)
1469 PMD_FUNC(pmf
, "clear_volpm_list")
1474 pathbuf
= kmem_alloc(MAXPATHLEN
, KM_SLEEP
);
1475 (void) ddi_pathname(dip
, pathbuf
);
1476 len
= strlen(pathbuf
);
1477 PMD(PMD_NOINVOL
, ("%s: clear volpm list %s\n", pmf
, pathbuf
))
1478 rw_enter(&pm_noinvol_rwlock
, RW_WRITER
);
1479 for (ip
= pm_noinvol_head
; ip
; ip
= ip
->ni_next
) {
1480 PMD(PMD_NOINVOL
, ("%s: clear volpm: ni_path %s\n", pmf
,
1482 if (strncmp(pathbuf
, ip
->ni_path
, len
) == 0 &&
1483 ip
->ni_path
[len
] == '/') {
1484 PMD(PMD_NOINVOL
, ("%s: clear volpm: %s\n", pmf
,
1487 ip
->ni_wasvolpmd
= 0;
1490 kmem_free(pathbuf
, MAXPATHLEN
);
1491 rw_exit(&pm_noinvol_rwlock
);
1495 * Powers a device, suspending or resuming the driver if it is a backward
1496 * compatible device, calling into ppm to change power level.
1497 * Called with the component's power lock held.
1500 power_dev(dev_info_t
*dip
, int comp
, int level
, int old_level
,
1501 pm_canblock_t canblock
, pm_ppm_devlist_t
**devlist
)
1503 PMD_FUNC(pmf
, "power_dev")
1504 power_req_t power_req
;
1505 int power_op_ret
; /* DDI_SUCCESS or DDI_FAILURE */
1506 int resume_needed
= 0;
1510 struct pm_component
*cp
= PM_CP(dip
, comp
);
1512 int bc
= PM_ISBC(dip
);
1513 int pm_all_components_off(dev_info_t
*);
1514 int clearvolpmd
= 0;
1515 char pathbuf
[MAXNAMELEN
];
1517 char *ppmname
, *ppmaddr
;
1520 * If this is comp 0 of a backwards compat device and we are
1521 * going to take the power away, we need to detach it with
1522 * DDI_PM_SUSPEND command.
1524 if (bc
&& comp
== 0 && POWERING_OFF(old_level
, level
)) {
1525 if (devi_detach(dip
, DDI_PM_SUSPEND
) != DDI_SUCCESS
) {
1526 /* We could not suspend before turning cmpt zero off */
1527 PMD(PMD_ERROR
, ("%s: could not suspend %s@%s(%s#%d)\n",
1528 pmf
, PM_DEVICE(dip
)))
1529 return (DDI_FAILURE
);
1531 DEVI(dip
)->devi_pm_flags
|= PMC_SUSPENDED
;
1535 power_req
.request_type
= PMR_PPM_SET_POWER
;
1536 power_req
.req
.ppm_set_power_req
.who
= dip
;
1537 power_req
.req
.ppm_set_power_req
.cmpt
= comp
;
1538 power_req
.req
.ppm_set_power_req
.old_level
= old_level
;
1539 power_req
.req
.ppm_set_power_req
.new_level
= level
;
1540 power_req
.req
.ppm_set_power_req
.canblock
= canblock
;
1541 power_req
.req
.ppm_set_power_req
.cookie
= NULL
;
1543 if (pm_ppm_claimed(dip
)) {
1544 ppmname
= PM_NAME(PPM(dip
));
1545 ppmaddr
= PM_ADDR(PPM(dip
));
1551 PMD(PMD_PPM
, ("%s: %s@%s(%s#%d):%s[%d] %s (%d) -> %s (%d) via %s@%s\n",
1552 pmf
, PM_DEVICE(dip
), cp
->pmc_comp
.pmc_name
, comp
,
1553 power_val_to_string(cp
, old_level
), old_level
,
1554 power_val_to_string(cp
, level
), level
, ppmname
, ppmaddr
))
1557 * If non-bc noinvolpm device is turning first comp on, or noinvolpm
1558 * bc device comp 0 is powering on, then we count it as a power cycle
1559 * against its voluntary count.
1561 if (DEVI(dip
)->devi_pm_volpmd
&&
1562 (!bc
&& pm_all_components_off(dip
) && level
!= 0) ||
1563 (bc
&& comp
== 0 && POWERING_ON(old_level
, level
)))
1565 if ((power_op_ret
= pm_ctlops(PPM(dip
), dip
, DDI_CTLOPS_POWER
,
1566 &power_req
, &result
)) == DDI_SUCCESS
) {
1568 * Now do involuntary pm accounting; If we've just cycled power
1569 * on a voluntarily pm'd node, and by inference on its entire
1570 * subtree, we need to set the subtree (including those nodes
1571 * already detached) volpmd counts to 0, and subtract out the
1572 * value of the current node's volpmd count from the ancestors
1575 int volpmd
= DEVI(dip
)->devi_pm_volpmd
;
1576 pm_clear_volpm_dip(dip
);
1577 pm_clear_volpm_list(dip
);
1579 (void) ddi_pathname(dip
, pathbuf
);
1580 (void) pm_noinvol_update(PM_BP_NOINVOL_POWER
,
1581 volpmd
, 0, pathbuf
, dip
);
1585 PMD(PMD_FAIL
, ("%s: can't set comp %d (%s) of %s@%s(%s#%d) "
1586 "to level %d (%s)\n", pmf
, comp
, cp
->pmc_comp
.pmc_name
,
1587 PM_DEVICE(dip
), level
, power_val_to_string(cp
, level
)))
1590 * If some other devices were also powered up (e.g. other cpus in
1591 * the same domain) return a pointer to that list
1594 *devlist
= (pm_ppm_devlist_t
*)
1595 power_req
.req
.ppm_set_power_req
.cookie
;
1598 * We will have to resume the device if the device is backwards compat
1599 * device and either of the following is true:
1600 * -This is comp 0 and we have successfully powered it up
1601 * -This is comp 0 and we have failed to power it down. Resume is
1602 * needed because we have suspended it above
1605 if (bc
&& comp
== 0) {
1606 ASSERT(PM_ISDIRECT(dip
) || DEVI_IS_DETACHING(dip
));
1607 if (power_op_ret
== DDI_SUCCESS
) {
1608 if (POWERING_ON(old_level
, level
)) {
1610 * It must be either suspended or resumed
1611 * via pm_power_has_changed path
1613 ASSERT((DEVI(dip
)->devi_pm_flags
&
1615 (PM_CP(dip
, comp
)->pmc_flags
&
1616 PM_PHC_WHILE_SET_POWER
));
1618 resume_needed
= suspended
;
1621 if (POWERING_OFF(old_level
, level
)) {
1623 * It must be either suspended or resumed
1624 * via pm_power_has_changed path
1626 ASSERT((DEVI(dip
)->devi_pm_flags
&
1628 (PM_CP(dip
, comp
)->pmc_flags
&
1629 PM_PHC_WHILE_SET_POWER
));
1631 resume_needed
= suspended
;
1635 if (resume_needed
) {
1636 ASSERT(DEVI(dip
)->devi_pm_flags
& PMC_SUSPENDED
);
1637 /* ppm is not interested in DDI_PM_RESUME */
1638 if ((power_op_ret
= devi_attach(dip
, DDI_PM_RESUME
)) ==
1640 DEVI(dip
)->devi_pm_flags
&= ~PMC_SUSPENDED
;
1642 cmn_err(CE_WARN
, "!pm: Can't resume %s@%s(%s#%d)",
1645 return (power_op_ret
);
1649 * Return true if we are the owner or a borrower of the devi lock. See
1650 * pm_lock_power_single() about borrowing the lock.
1653 pm_devi_lock_held(dev_info_t
*dip
)
1657 if (DEVI_BUSY_OWNED(dip
))
1660 /* return false if no locks borrowed */
1661 if (lock_loan_head
.pmlk_next
== NULL
)
1664 mutex_enter(&pm_loan_lock
);
1665 /* see if our thread is registered as a lock borrower. */
1666 for (cur
= lock_loan_head
.pmlk_next
; cur
; cur
= cur
->pmlk_next
)
1667 if (cur
->pmlk_borrower
== curthread
)
1669 mutex_exit(&pm_loan_lock
);
1671 return (cur
!= NULL
&& cur
->pmlk_lender
== DEVI(dip
)->devi_busy_thread
);
1675 * pm_set_power: adjusts power level of device. Assumes device is power
1676 * manageable & component exists.
1678 * Cases which require us to bring up devices we keep up ("wekeepups") for
1679 * backwards compatible devices:
1680 * component 0 is off and we're bringing it up from 0
1681 * bring up wekeepup first
1682 * and recursively when component 0 is off and we bring some other
1683 * component up from 0
1684 * For devices which are not backward compatible, our dependency notion is much
1685 * simpler. Unless all components are off, then wekeeps must be on.
1686 * We don't treat component 0 differently.
1687 * Canblock tells how to deal with a direct pm'd device.
1688 * Scan arg tells us if we were called from scan, in which case we don't need
1689 * to go back to the root node and walk down to change power.
1692 pm_set_power(dev_info_t
*dip
, int comp
, int level
, int direction
,
1693 pm_canblock_t canblock
, int scan
, int *retp
)
1695 PMD_FUNC(pmf
, "set_power")
1697 pm_bp_child_pwrchg_t bpc
;
1699 int ret
= DDI_SUCCESS
;
1700 int unused
= DDI_SUCCESS
;
1701 dev_info_t
*pdip
= ddi_get_parent(dip
);
1707 * This prevents operations on the console from calling prom_printf and
1708 * either deadlocking or bringing up the console because of debug
1711 if (dip
== cfb_dip
) {
1713 mutex_enter(&pm_debug_lock
);
1715 mutex_exit(&pm_debug_lock
);
1718 ASSERT(direction
== PM_LEVEL_UPONLY
|| direction
== PM_LEVEL_DOWNONLY
||
1719 direction
== PM_LEVEL_EXACT
);
1720 PMD(PMD_SET
, ("%s: %s@%s(%s#%d), comp=%d, dir=%s, new=%d\n",
1721 pmf
, PM_DEVICE(dip
), comp
, pm_decode_direction(direction
), level
))
1722 pathbuf
= kmem_alloc(MAXPATHLEN
, KM_SLEEP
);
1723 (void) ddi_pathname(dip
, pathbuf
);
1725 bpc
.bpc_path
= pathbuf
;
1726 bpc
.bpc_comp
= comp
;
1727 bpc
.bpc_olevel
= PM_CURPOWER(dip
, comp
);
1728 bpc
.bpc_nlevel
= level
;
1729 pspm
.pspm_direction
= direction
;
1730 pspm
.pspm_errnop
= retp
;
1731 pspm
.pspm_canblock
= canblock
;
1732 pspm
.pspm_scan
= scan
;
1733 bpc
.bpc_private
= &pspm
;
1736 * If a config operation is being done (we've locked the parent) or
1737 * we already hold the power lock (we've locked the node)
1738 * then we can operate directly on the node because we have already
1739 * brought up all the ancestors, otherwise, we have to go back to the
1742 if (pm_devi_lock_held(pdip
) || pm_devi_lock_held(dip
))
1743 ret
= pm_busop_set_power(dip
, NULL
, BUS_POWER_CHILD_PWRCHG
,
1744 (void *)&bpc
, (void *)&unused
);
1746 ret
= pm_busop_bus_power(ddi_root_node(), NULL
,
1747 BUS_POWER_CHILD_PWRCHG
, (void *)&bpc
, (void *)&unused
);
1749 if (ret
!= DDI_SUCCESS
|| *retp
!= DDI_SUCCESS
) {
1750 PMD(PMD_ERROR
, ("%s: %s@%s(%s#%d) can't change power, ret=%d, "
1751 "errno=%d\n", pmf
, PM_DEVICE(dip
), ret
, *retp
))
1754 mutex_enter(&pm_debug_lock
);
1756 mutex_exit(&pm_debug_lock
);
1759 kmem_free(pathbuf
, MAXPATHLEN
);
1764 * If holddip is set, then if a dip is found we return with the node held.
1766 * This code uses the same locking scheme as e_ddi_hold_devi_by_path
1767 * (resolve_pathname), but it does not drive attach.
1770 pm_name_to_dip(char *pathname
, int holddip
)
1774 dev_info_t
*parent
, *child
;
1777 if ((pathname
== NULL
) || (*pathname
!= '/'))
1780 /* setup pathname and allocate component */
1781 if (pn_get(pathname
, UIO_SYSSPACE
, &pn
))
1783 component
= kmem_alloc(MAXNAMELEN
, KM_SLEEP
);
1785 /* start at top, process '/' component */
1786 parent
= child
= ddi_root_node();
1787 ndi_hold_devi(parent
);
1789 ASSERT(i_ddi_devi_attached(parent
));
1791 /* process components of pathname */
1792 while (pn_pathleft(&pn
)) {
1793 (void) pn_getcomponent(&pn
, component
);
1795 /* enter parent and search for component child */
1796 ndi_devi_enter(parent
, &circ
);
1797 child
= ndi_devi_findchild(parent
, component
);
1798 if ((child
== NULL
) || !i_ddi_devi_attached(child
)) {
1800 ndi_devi_exit(parent
, circ
);
1801 ndi_rele_devi(parent
);
1805 /* attached child found, hold child and release parent */
1806 ndi_hold_devi(child
);
1807 ndi_devi_exit(parent
, circ
);
1808 ndi_rele_devi(parent
);
1810 /* child becomes parent, and process next component */
1814 /* loop with active ndi_devi_hold of child->parent */
1819 kmem_free(component
, MAXNAMELEN
);
1821 /* if we are not asked to return with hold, drop current hold */
1822 if (child
&& !holddip
)
1823 ndi_rele_devi(child
);
1828 * Search for a dependency and mark it unsatisfied
1831 pm_unsatisfy(char *keeper
, char *kept
)
1833 PMD_FUNC(pmf
, "unsatisfy")
1836 PMD(PMD_KEEPS
, ("%s: keeper=%s, kept=%s\n", pmf
, keeper
, kept
))
1837 for (dp
= pm_dep_head
; dp
; dp
= dp
->pdr_next
) {
1838 if (!dp
->pdr_isprop
) {
1839 if (strcmp(dp
->pdr_keeper
, keeper
) == 0 &&
1840 (dp
->pdr_kept_count
> 0) &&
1841 strcmp(dp
->pdr_kept_paths
[0], kept
) == 0) {
1842 if (dp
->pdr_satisfied
) {
1843 dp
->pdr_satisfied
= 0;
1844 pm_unresolved_deps
++;
1845 PMD(PMD_KEEPS
, ("%s: clear satisfied, "
1846 "pm_unresolved_deps now %d\n", pmf
,
1847 pm_unresolved_deps
))
1855 * Device dip is being un power managed, it keeps up count other devices.
1856 * We need to release any hold we have on the kept devices, and also
1857 * mark the dependency no longer satisfied.
1860 pm_unkeeps(int count
, char *keeper
, char **keptpaths
, int pwr
)
1862 PMD_FUNC(pmf
, "unkeeps")
1866 struct pm_component
*cp
;
1867 int keeper_on
= 0, circ
;
1869 PMD(PMD_KEEPS
, ("%s: count=%d, keeper=%s, keptpaths=%p\n", pmf
, count
,
1870 keeper
, (void *)keptpaths
))
1872 * Try to grab keeper. Keeper may have gone away by now,
1873 * in this case, used the passed in value pwr
1875 dip
= pm_name_to_dip(keeper
, 1);
1876 for (i
= 0; i
< count
; i
++) {
1877 /* Release power hold */
1878 kept
= pm_name_to_dip(keptpaths
[i
], 1);
1880 PMD(PMD_KEEPS
, ("%s: %s@%s(%s#%d)[%d]\n", pmf
,
1881 PM_DEVICE(kept
), i
))
1883 * We need to check if we skipped a bringup here
1884 * because we could have failed the bringup
1885 * (ie DIRECT PM device) and have
1886 * not increment the count.
1888 if ((dip
!= NULL
) && (PM_GET_PM_INFO(dip
) != NULL
)) {
1890 PM_LOCK_POWER(dip
, &circ
);
1891 for (j
= 0; j
< PM_NUMCMPTS(dip
); j
++) {
1892 cp
= &DEVI(dip
)->devi_pm_components
[j
];
1893 if (cur_power(cp
)) {
1898 if (keeper_on
&& (PM_SKBU(kept
) == 0)) {
1899 pm_rele_power(kept
);
1900 DEVI(kept
)->devi_pm_flags
1901 &= ~PMC_SKIP_BRINGUP
;
1903 PM_UNLOCK_POWER(dip
, circ
);
1905 if (PM_SKBU(kept
) == 0) {
1906 pm_rele_power(kept
);
1907 DEVI(kept
)->devi_pm_flags
1908 &= ~PMC_SKIP_BRINGUP
;
1911 ddi_release_devi(kept
);
1914 * mark this dependency not satisfied
1916 pm_unsatisfy(keeper
, keptpaths
[i
]);
1919 ddi_release_devi(dip
);
1923 * Device kept is being un power managed, it is kept up by keeper.
1924 * We need to mark the dependency no longer satisfied.
1927 pm_unkepts(char *kept
, char *keeper
)
1929 PMD_FUNC(pmf
, "unkepts")
1930 PMD(PMD_KEEPS
, ("%s: kept=%s, keeper=%s\n", pmf
, kept
, keeper
))
1931 ASSERT(keeper
!= NULL
);
1933 * mark this dependency not satisfied
1935 pm_unsatisfy(keeper
, kept
);
1939 * Removes dependency information and hold on the kepts, if the path is a
1943 pm_free_keeper(char *path
, int pwr
)
1949 for (dp
= pm_dep_head
; dp
; dp
= dp
->pdr_next
) {
1950 if (strcmp(dp
->pdr_keeper
, path
) != 0)
1953 * Remove all our kept holds and the dependency records,
1954 * then free up the kept lists.
1956 pm_unkeeps(dp
->pdr_kept_count
, path
, dp
->pdr_kept_paths
, pwr
);
1957 if (dp
->pdr_kept_count
) {
1958 for (i
= 0; i
< dp
->pdr_kept_count
; i
++) {
1959 length
= strlen(dp
->pdr_kept_paths
[i
]);
1960 kmem_free(dp
->pdr_kept_paths
[i
], length
+ 1);
1962 kmem_free(dp
->pdr_kept_paths
,
1963 dp
->pdr_kept_count
* sizeof (char **));
1964 dp
->pdr_kept_paths
= NULL
;
1965 dp
->pdr_kept_count
= 0;
1971 * Removes the device represented by path from the list of kepts, if the
1972 * path is a path of a kept
1975 pm_free_kept(char *path
)
1983 for (dp
= pm_dep_head
; dp
; dp
= dp
->pdr_next
) {
1984 if (dp
->pdr_kept_count
== 0)
1986 count
= dp
->pdr_kept_count
;
1987 /* Remove this device from the kept path lists */
1988 for (i
= 0; i
< count
; i
++) {
1989 if (strcmp(dp
->pdr_kept_paths
[i
], path
) == 0) {
1990 pm_unkepts(path
, dp
->pdr_keeper
);
1991 length
= strlen(dp
->pdr_kept_paths
[i
]) + 1;
1992 kmem_free(dp
->pdr_kept_paths
[i
], length
);
1993 dp
->pdr_kept_paths
[i
] = NULL
;
1994 dp
->pdr_kept_count
--;
1997 /* Compact the kept paths array */
1998 if (dp
->pdr_kept_count
) {
1999 length
= dp
->pdr_kept_count
* sizeof (char **);
2000 paths
= kmem_zalloc(length
, KM_SLEEP
);
2002 for (i
= 0; i
< count
; i
++) {
2003 if (dp
->pdr_kept_paths
[i
] != NULL
) {
2004 paths
[j
] = dp
->pdr_kept_paths
[i
];
2008 ASSERT(j
== dp
->pdr_kept_count
);
2010 /* Now free the old array and point to the new one */
2011 kmem_free(dp
->pdr_kept_paths
, count
* sizeof (char **));
2012 if (dp
->pdr_kept_count
)
2013 dp
->pdr_kept_paths
= paths
;
2015 dp
->pdr_kept_paths
= NULL
;
2020 * Free the dependency information for a device.
2023 pm_free_keeps(char *path
, int pwr
)
2025 PMD_FUNC(pmf
, "free_keeps")
2029 void prdeps(char *);
2031 PMD(PMD_KEEPS
, ("%s: %s\n", pmf
, path
))
2032 if (pm_debug
& PMD_KEEPS
) {
2034 prdeps("pm_free_keeps before");
2038 * First assume we are a keeper and remove all our kepts.
2040 pm_free_keeper(path
, pwr
);
2042 * Now assume we a kept device, and remove all our records.
2047 prdeps("pm_free_keeps after");
2053 pm_is_kept(char *path
)
2058 for (dp
= pm_dep_head
; dp
; dp
= dp
->pdr_next
) {
2059 if (dp
->pdr_kept_count
== 0)
2061 for (i
= 0; i
< dp
->pdr_kept_count
; i
++) {
2062 if (strcmp(dp
->pdr_kept_paths
[i
], path
) == 0)
2070 e_pm_hold_rele_power(dev_info_t
*dip
, int cnt
)
2072 PMD_FUNC(pmf
, "hold_rele_power")
2075 if ((dip
== NULL
) ||
2076 (PM_GET_PM_INFO(dip
) == NULL
) || PM_ISBC(dip
))
2079 PM_LOCK_POWER(dip
, &circ
);
2080 ASSERT(cnt
>= 0 && PM_KUC(dip
) >= 0 || cnt
< 0 && PM_KUC(dip
) > 0);
2081 PMD(PMD_KIDSUP
, ("%s: kidsupcnt for %s@%s(%s#%d) %d->%d\n", pmf
,
2082 PM_DEVICE(dip
), PM_KUC(dip
), (PM_KUC(dip
) + cnt
)))
2086 ASSERT(PM_KUC(dip
) >= 0);
2087 PM_UNLOCK_POWER(dip
, circ
);
2089 if (cnt
< 0 && PM_KUC(dip
) == 0)
2093 #define MAX_PPM_HANDLERS 4
2095 kmutex_t ppm_lock
; /* in case we ever do multi-threaded startup */
2097 struct ppm_callbacks
{
2098 int (*ppmc_func
)(dev_info_t
*);
2099 dev_info_t
*ppmc_dip
;
2100 } ppm_callbacks
[MAX_PPM_HANDLERS
+ 1];
2104 * This routine calls into all the registered ppms to notify them
2105 * that either all components of power-managed devices are at their
2106 * lowest levels or no longer all are at their lowest levels.
2109 pm_ppm_notify_all_lowest(dev_info_t
*dip
, int mode
)
2111 struct ppm_callbacks
*ppmcp
;
2112 power_req_t power_req
;
2115 power_req
.request_type
= PMR_PPM_ALL_LOWEST
;
2116 power_req
.req
.ppm_all_lowest_req
.mode
= mode
;
2117 mutex_enter(&ppm_lock
);
2118 for (ppmcp
= ppm_callbacks
; ppmcp
->ppmc_func
; ppmcp
++)
2119 (void) pm_ctlops((dev_info_t
*)ppmcp
->ppmc_dip
, dip
,
2120 DDI_CTLOPS_POWER
, &power_req
, &result
);
2121 mutex_exit(&ppm_lock
);
2122 if (mode
== PM_ALL_LOWEST
) {
2123 if (autoS3_enabled
) {
2124 PMD(PMD_SX
, ("pm_ppm_notify_all_lowest triggering "
2126 mutex_enter(&srn_clone_lock
);
2129 PMD(PMD_SX
, ("(*srn_signal)(AUTOSX, 3)\n"))
2130 (*srn_signal
)(SRN_TYPE_AUTOSX
, 3);
2133 PMD(PMD_SX
, ("srn_signal NULL\n"))
2135 mutex_exit(&srn_clone_lock
);
2137 PMD(PMD_SX
, ("pm_ppm_notify_all_lowest autos3 "
2144 pm_set_pm_info(dev_info_t
*dip
, void *value
)
2146 DEVI(dip
)->devi_pm_info
= value
;
2149 pm_rsvp_t
*pm_blocked_list
;
2152 * Look up an entry in the blocked list by dip and component
2155 pm_rsvp_lookup(dev_info_t
*dip
, int comp
)
2158 ASSERT(MUTEX_HELD(&pm_rsvp_lock
));
2159 for (p
= pm_blocked_list
; p
; p
= p
->pr_next
)
2160 if (p
->pr_dip
== dip
&& p
->pr_comp
== comp
) {
2167 * Called when a device which is direct power managed (or the parent or
2168 * dependent of such a device) changes power, or when a pm clone is closed
2169 * that was direct power managing a device. This call results in pm_blocked()
2170 * (below) returning.
2173 pm_proceed(dev_info_t
*dip
, int cmd
, int comp
, int newlevel
)
2175 PMD_FUNC(pmf
, "proceed")
2176 pm_rsvp_t
*found
= NULL
;
2179 mutex_enter(&pm_rsvp_lock
);
2182 * we're giving up control, let any pending op continue
2185 for (p
= pm_blocked_list
; p
; p
= p
->pr_next
) {
2186 if (dip
== p
->pr_dip
) {
2187 p
->pr_retval
= PMP_RELEASE
;
2188 PMD(PMD_DPM
, ("%s: RELEASE %s@%s(%s#%d)\n",
2189 pmf
, PM_DEVICE(dip
)))
2190 cv_signal(&p
->pr_cv
);
2196 * process has done PM_SET_CURRENT_POWER; let a matching request
2197 * succeed and a non-matching request for the same device fail
2200 found
= pm_rsvp_lookup(dip
, comp
);
2201 if (!found
) /* if driver not waiting */
2204 * This cannot be pm_lower_power, since that can only happen
2205 * during detach or probe
2207 if (found
->pr_newlevel
<= newlevel
) {
2208 found
->pr_retval
= PMP_SUCCEED
;
2209 PMD(PMD_DPM
, ("%s: SUCCEED %s@%s(%s#%d)\n", pmf
,
2212 found
->pr_retval
= PMP_FAIL
;
2213 PMD(PMD_DPM
, ("%s: FAIL %s@%s(%s#%d)\n", pmf
,
2216 cv_signal(&found
->pr_cv
);
2220 panic("pm_proceed unknown cmd %d", cmd
);
2222 mutex_exit(&pm_rsvp_lock
);
2226 * This routine dispatches new work to the dependency thread. Caller must
2227 * be prepared to block for memory if necessary.
2230 pm_dispatch_to_dep_thread(int cmd
, char *keeper
, char *kept
, int wait
,
2231 int *res
, int cached_pwr
)
2233 pm_dep_wk_t
*new_work
;
2235 new_work
= kmem_zalloc(sizeof (pm_dep_wk_t
), KM_SLEEP
);
2236 new_work
->pdw_type
= cmd
;
2237 new_work
->pdw_wait
= wait
;
2238 new_work
->pdw_done
= 0;
2239 new_work
->pdw_ret
= 0;
2240 new_work
->pdw_pwr
= cached_pwr
;
2241 cv_init(&new_work
->pdw_cv
, NULL
, CV_DEFAULT
, NULL
);
2242 if (keeper
!= NULL
) {
2243 new_work
->pdw_keeper
= kmem_zalloc(strlen(keeper
) + 1,
2245 (void) strcpy(new_work
->pdw_keeper
, keeper
);
2248 new_work
->pdw_kept
= kmem_zalloc(strlen(kept
) + 1, KM_SLEEP
);
2249 (void) strcpy(new_work
->pdw_kept
, kept
);
2251 mutex_enter(&pm_dep_thread_lock
);
2252 if (pm_dep_thread_workq
== NULL
) {
2253 pm_dep_thread_workq
= new_work
;
2254 pm_dep_thread_tail
= new_work
;
2255 new_work
->pdw_next
= NULL
;
2257 pm_dep_thread_tail
->pdw_next
= new_work
;
2258 pm_dep_thread_tail
= new_work
;
2259 new_work
->pdw_next
= NULL
;
2261 cv_signal(&pm_dep_thread_cv
);
2262 /* If caller asked for it, wait till it is done. */
2264 while (!new_work
->pdw_done
)
2265 cv_wait(&new_work
->pdw_cv
, &pm_dep_thread_lock
);
2267 * Pass return status, if any, back.
2270 *res
= new_work
->pdw_ret
;
2272 * If we asked to wait, it is our job to free the request
2275 if (new_work
->pdw_keeper
)
2276 kmem_free(new_work
->pdw_keeper
,
2277 strlen(new_work
->pdw_keeper
) + 1);
2278 if (new_work
->pdw_kept
)
2279 kmem_free(new_work
->pdw_kept
,
2280 strlen(new_work
->pdw_kept
) + 1);
2281 kmem_free(new_work
, sizeof (pm_dep_wk_t
));
2283 mutex_exit(&pm_dep_thread_lock
);
2287 * Release the pm resource for this device.
2290 pm_rem_info(dev_info_t
*dip
)
2292 PMD_FUNC(pmf
, "rem_info")
2294 pm_info_t
*info
= PM_GET_PM_INFO(dip
);
2295 dev_info_t
*pdip
= ddi_get_parent(dip
);
2297 int work_type
= PM_DEP_WK_DETACH
;
2301 ASSERT(!PM_IAM_LOCKING_DIP(dip
));
2302 if (PM_ISDIRECT(dip
)) {
2303 info
->pmi_dev_pm_state
&= ~PM_DIRECT
;
2304 ASSERT(info
->pmi_clone
);
2305 info
->pmi_clone
= 0;
2306 pm_proceed(dip
, PMP_RELEASE
, -1, -1);
2308 ASSERT(!PM_GET_PM_SCAN(dip
));
2311 * Now adjust parent's kidsupcnt. BC nodes we check only comp 0,
2312 * Others we check all components. BC node that has already
2313 * called pm_destroy_components() has zero component count.
2314 * Parents that get notification are not adjusted because their
2315 * kidsupcnt is always 0 (or 1 during configuration).
2317 PMD(PMD_KEEPS
, ("%s: %s@%s(%s#%d) has %d components\n", pmf
,
2318 PM_DEVICE(dip
), PM_NUMCMPTS(dip
)))
2320 /* node is detached, so we can examine power without locking */
2322 count
= (PM_CURPOWER(dip
, 0) != 0);
2324 for (i
= 0; i
< PM_NUMCMPTS(dip
); i
++)
2325 count
+= (PM_CURPOWER(dip
, i
) != 0);
2328 if (PM_NUMCMPTS(dip
) && pdip
&& !PM_WANTS_NOTIFICATION(pdip
))
2329 e_pm_hold_rele_power(pdip
, -count
);
2331 /* Schedule a request to clean up dependency records */
2332 pathbuf
= kmem_zalloc(MAXPATHLEN
, KM_SLEEP
);
2333 (void) ddi_pathname(dip
, pathbuf
);
2334 pm_dispatch_to_dep_thread(work_type
, pathbuf
, pathbuf
,
2335 PM_DEP_NOWAIT
, NULL
, (count
> 0));
2336 kmem_free(pathbuf
, MAXPATHLEN
);
2339 * Adjust the pm_comps_notlowest count since this device is
2340 * not being power-managed anymore.
2342 for (i
= 0; i
< PM_NUMCMPTS(dip
); i
++) {
2343 pm_component_t
*cp
= PM_CP(dip
, i
);
2344 if (cp
->pmc_cur_pwr
!= 0)
2345 PM_DECR_NOTLOWEST(dip
)
2348 * Once we clear the info pointer, it looks like it is not power
2349 * managed to everybody else.
2351 pm_set_pm_info(dip
, NULL
);
2352 kmem_free(info
, sizeof (pm_info_t
));
2356 pm_get_norm_pwrs(dev_info_t
*dip
, int **valuep
, size_t *length
)
2358 int components
= PM_NUMCMPTS(dip
);
2363 if (components
<= 0) {
2364 cmn_err(CE_NOTE
, "!pm: %s@%s(%s#%d) has no components, "
2365 "can't get normal power values\n", PM_DEVICE(dip
));
2366 return (DDI_FAILURE
);
2368 size
= components
* sizeof (int);
2369 bufp
= kmem_alloc(size
, KM_SLEEP
);
2370 for (i
= 0; i
< components
; i
++) {
2371 bufp
[i
] = pm_get_normal_power(dip
, i
);
2376 return (DDI_SUCCESS
);
2380 pm_reset_timestamps(dev_info_t
*dip
, void *arg
)
2382 _NOTE(ARGUNUSED(arg
))
2387 if (!PM_GET_PM_INFO(dip
))
2388 return (DDI_WALK_CONTINUE
);
2389 components
= PM_NUMCMPTS(dip
);
2390 ASSERT(components
> 0);
2392 for (i
= 0; i
< components
; i
++) {
2393 struct pm_component
*cp
;
2395 * If the component was not marked as busy,
2396 * reset its timestamp to now.
2399 if (cp
->pmc_timestamp
)
2400 cp
->pmc_timestamp
= gethrestime_sec();
2402 PM_UNLOCK_BUSY(dip
);
2403 return (DDI_WALK_CONTINUE
);
2407 * Convert a power level to an index into the levels array (or
2408 * just PM_LEVEL_UNKNOWN in that special case).
2411 pm_level_to_index(dev_info_t
*dip
, pm_component_t
*cp
, int level
)
2413 PMD_FUNC(pmf
, "level_to_index")
2415 int limit
= cp
->pmc_comp
.pmc_numlevels
;
2416 int *ip
= cp
->pmc_comp
.pmc_lvals
;
2418 if (level
== PM_LEVEL_UNKNOWN
)
2421 for (i
= 0; i
< limit
; i
++) {
2422 if (level
== *ip
++) {
2423 PMD(PMD_LEVEL
, ("%s: %s@%s(%s#%d)[%d] to %x\n",
2424 pmf
, PM_DEVICE(dip
),
2425 (int)(cp
- DEVI(dip
)->devi_pm_components
), level
))
2429 panic("pm_level_to_index: level %d not found for device "
2430 "%s@%s(%s#%d)", level
, PM_DEVICE(dip
));
2435 * Internal function to set current power level
2438 e_pm_set_cur_pwr(dev_info_t
*dip
, pm_component_t
*cp
, int level
)
2440 PMD_FUNC(pmf
, "set_cur_pwr")
2441 int curpwr
= (cp
->pmc_flags
& PM_PHC_WHILE_SET_POWER
?
2442 cp
->pmc_phc_pwr
: cp
->pmc_cur_pwr
);
2445 * Nothing to adjust if current & new levels are the same.
2447 if (curpwr
!= PM_LEVEL_UNKNOWN
&&
2448 level
== cp
->pmc_comp
.pmc_lvals
[curpwr
])
2452 * Keep the count for comps doing transition to/from lowest
2456 PM_INCR_NOTLOWEST(dip
);
2457 } else if (level
== cp
->pmc_comp
.pmc_lvals
[0]) {
2458 PM_DECR_NOTLOWEST(dip
);
2460 cp
->pmc_phc_pwr
= PM_LEVEL_UNKNOWN
;
2461 cp
->pmc_cur_pwr
= pm_level_to_index(dip
, cp
, level
);
2464 static int pm_phc_impl(dev_info_t
*, int, int, int);
2467 * This is the default method of setting the power of a device if no ppm
2468 * driver has claimed it.
2471 pm_power(dev_info_t
*dip
, int comp
, int level
)
2473 PMD_FUNC(pmf
, "power")
2474 struct dev_ops
*ops
;
2475 int (*fn
)(dev_info_t
*, int, int);
2476 struct pm_component
*cp
= PM_CP(dip
, comp
);
2478 pm_info_t
*info
= PM_GET_PM_INFO(dip
);
2480 PMD(PMD_KIDSUP
, ("%s: %s@%s(%s#%d), comp=%d, level=%d\n", pmf
,
2481 PM_DEVICE(dip
), comp
, level
))
2482 if (!(ops
= ddi_get_driver(dip
))) {
2483 PMD(PMD_FAIL
, ("%s: %s@%s(%s#%d) has no ops\n", pmf
,
2485 return (DDI_FAILURE
);
2487 if ((ops
->devo_rev
< 2) || !(fn
= ops
->devo_power
)) {
2488 PMD(PMD_FAIL
, ("%s: %s%s\n", pmf
,
2489 (ops
->devo_rev
< 2 ? " wrong devo_rev" : ""),
2490 (!fn
? " devo_power NULL" : "")))
2491 return (DDI_FAILURE
);
2493 cp
->pmc_flags
|= PM_POWER_OP
;
2494 retval
= (*fn
)(dip
, comp
, level
);
2495 cp
->pmc_flags
&= ~PM_POWER_OP
;
2496 if (retval
== DDI_SUCCESS
) {
2497 e_pm_set_cur_pwr(dip
, PM_CP(dip
, comp
), level
);
2498 return (DDI_SUCCESS
);
2502 * If pm_power_has_changed() detected a deadlock with pm_power() it
2503 * updated only the power level of the component. If our attempt to
2504 * set the device new to a power level above has failed we sync the
2505 * total power state via phc code now.
2507 if (cp
->pmc_flags
& PM_PHC_WHILE_SET_POWER
) {
2509 cp
->pmc_comp
.pmc_lvals
[cp
->pmc_cur_pwr
];
2512 (void) pm_phc_impl(dip
, comp
, phc_lvl
, 0);
2513 PMD(PMD_PHC
, ("%s: phc %s@%s(%s#%d) comp=%d level=%d\n",
2514 pmf
, PM_DEVICE(dip
), comp
, phc_lvl
))
2517 PMD(PMD_FAIL
, ("%s: can't set comp=%d (%s) of %s@%s(%s#%d) to "
2518 "level=%d (%s)\n", pmf
, comp
, cp
->pmc_comp
.pmc_name
, PM_DEVICE(dip
),
2519 level
, power_val_to_string(cp
, level
)));
2520 return (DDI_FAILURE
);
2524 pm_unmanage(dev_info_t
*dip
)
2526 PMD_FUNC(pmf
, "unmanage")
2527 power_req_t power_req
;
2528 int result
, retval
= 0;
2530 ASSERT(!PM_IAM_LOCKING_DIP(dip
));
2531 PMD(PMD_REMDEV
| PMD_KIDSUP
, ("%s: %s@%s(%s#%d)\n", pmf
,
2533 power_req
.request_type
= PMR_PPM_UNMANAGE
;
2534 power_req
.req
.ppm_config_req
.who
= dip
;
2535 if (pm_ppm_claimed(dip
))
2536 retval
= pm_ctlops(PPM(dip
), dip
, DDI_CTLOPS_POWER
,
2537 &power_req
, &result
);
2540 retval
= pm_ctlops(PPM(dip
), dip
, DDI_CTLOPS_POWER
,
2541 &power_req
, &result
);
2543 ASSERT(retval
== DDI_SUCCESS
);
2549 pm_raise_power(dev_info_t
*dip
, int comp
, int level
)
2552 return (DDI_FAILURE
);
2553 if (!e_pm_valid_info(dip
, NULL
) || !e_pm_valid_comp(dip
, comp
, NULL
) ||
2554 !e_pm_valid_power(dip
, comp
, level
))
2555 return (DDI_FAILURE
);
2557 return (dev_is_needed(dip
, comp
, level
, PM_LEVEL_UPONLY
));
2561 pm_lower_power(dev_info_t
*dip
, int comp
, int level
)
2563 PMD_FUNC(pmf
, "pm_lower_power")
2565 if (!e_pm_valid_info(dip
, NULL
) || !e_pm_valid_comp(dip
, comp
, NULL
) ||
2566 !e_pm_valid_power(dip
, comp
, level
)) {
2567 PMD(PMD_FAIL
, ("%s: validation checks failed for %s@%s(%s#%d) "
2568 "comp=%d level=%d\n", pmf
, PM_DEVICE(dip
), comp
, level
))
2569 return (DDI_FAILURE
);
2572 if (!DEVI_IS_DETACHING(dip
)) {
2573 PMD(PMD_FAIL
, ("%s: %s@%s(%s#%d) not detaching\n",
2574 pmf
, PM_DEVICE(dip
)))
2575 return (DDI_FAILURE
);
2579 * If we don't care about saving power, or we're treating this node
2580 * specially, then this is a no-op
2582 if (!PM_SCANABLE(dip
) || pm_noinvol(dip
)) {
2583 PMD(PMD_FAIL
, ("%s: %s@%s(%s#%d) %s%s%s%s\n",
2584 pmf
, PM_DEVICE(dip
),
2585 !autopm_enabled
? "!autopm_enabled " : "",
2586 !PM_POLLING_CPUPM
? "!cpupm_polling " : "",
2587 PM_CPUPM_DISABLED
? "cpupm_disabled " : "",
2588 pm_noinvol(dip
) ? "pm_noinvol()" : ""))
2589 return (DDI_SUCCESS
);
2592 if (dev_is_needed(dip
, comp
, level
, PM_LEVEL_DOWNONLY
) != DDI_SUCCESS
) {
2593 PMD(PMD_FAIL
, ("%s: %s@%s(%s#%d) dev_is_needed failed\n", pmf
,
2595 return (DDI_FAILURE
);
2597 return (DDI_SUCCESS
);
2601 * Find the entries struct for a given dip in the blocked list, return it locked
2604 pm_psc_dip_to_direct(dev_info_t
*dip
, pscc_t
**psccp
)
2609 rw_enter(&pm_pscc_direct_rwlock
, RW_READER
);
2610 for (p
= pm_pscc_direct
; p
; p
= p
->pscc_next
) {
2611 if (p
->pscc_dip
== dip
) {
2613 psce
= p
->pscc_entries
;
2614 mutex_enter(&psce
->psce_lock
);
2616 rw_exit(&pm_pscc_direct_rwlock
);
2620 rw_exit(&pm_pscc_direct_rwlock
);
2621 panic("sunpm: no entry for dip %p in direct list", (void *)dip
);
2626 * Write an entry indicating a power level change (to be passed to a process
2627 * later) in the given psce.
2628 * If we were called in the path that brings up the console fb in the
2629 * case of entering the prom, we don't want to sleep. If the alloc fails, then
2630 * we create a record that has a size of -1, a physaddr of NULL, and that
2631 * has the overflow flag set.
2634 psc_entry(ushort_t event
, psce_t
*psce
, dev_info_t
*dip
, int comp
, int new,
2635 int old
, int which
, pm_canblock_t canblock
)
2637 char buf
[MAXNAMELEN
];
2638 pm_state_change_t
*p
;
2640 caddr_t physpath
= NULL
;
2643 ASSERT(MUTEX_HELD(&psce
->psce_lock
));
2644 (void) ddi_pathname(dip
, buf
);
2645 size
= strlen(buf
) + 1;
2647 if (canblock
== PM_CANBLOCK_BYPASS
) {
2648 physpath
= kmem_alloc(size
, KM_NOSLEEP
);
2649 if (physpath
== NULL
) {
2651 * mark current entry as overrun
2653 p
->flags
|= PSC_EVENT_LOST
;
2657 physpath
= kmem_alloc(size
, KM_SLEEP
);
2658 if (p
->size
) { /* overflow; mark the next entry */
2659 if (p
->size
!= (size_t)-1)
2660 kmem_free(p
->physpath
, p
->size
);
2661 ASSERT(psce
->psce_out
== p
);
2662 if (p
== psce
->psce_last
) {
2663 psce
->psce_first
->flags
|= PSC_EVENT_LOST
;
2664 psce
->psce_out
= psce
->psce_first
;
2666 (p
+ 1)->flags
|= PSC_EVENT_LOST
;
2667 psce
->psce_out
= (p
+ 1);
2670 } else if (physpath
== NULL
) { /* alloc failed, mark this entry */
2671 p
->flags
|= PSC_EVENT_LOST
;
2675 if (which
== PSC_INTEREST
) {
2676 mutex_enter(&pm_compcnt_lock
);
2677 if (pm_comps_notlowest
== 0)
2678 p
->flags
|= PSC_ALL_LOWEST
;
2680 p
->flags
&= ~PSC_ALL_LOWEST
;
2681 mutex_exit(&pm_compcnt_lock
);
2684 p
->timestamp
= gethrestime_sec();
2685 p
->component
= comp
;
2688 p
->physpath
= physpath
;
2690 if (physpath
!= NULL
)
2691 (void) strcpy(p
->physpath
, buf
);
2692 if (p
== psce
->psce_last
)
2693 psce
->psce_in
= psce
->psce_first
;
2695 psce
->psce_in
= ++p
;
2696 mutex_exit(&psce
->psce_lock
);
2701 * Find the next entry on the interest list. We keep a pointer to the item we
2702 * last returned in the user's cooke. Returns a locked entries struct.
2705 psc_interest(void **cookie
, pscc_t
**psccp
)
2708 pscc_t
**cookiep
= (pscc_t
**)cookie
;
2710 if (*cookiep
== NULL
)
2711 pscc
= pm_pscc_interest
;
2713 pscc
= (*cookiep
)->pscc_next
;
2717 mutex_enter(&pscc
->pscc_entries
->psce_lock
);
2718 return (pscc
->pscc_entries
);
2725 * Create an entry for a process to pick up indicating a power level change.
2728 pm_enqueue_notify(ushort_t cmd
, dev_info_t
*dip
, int comp
,
2729 int newlevel
, int oldlevel
, pm_canblock_t canblock
)
2731 PMD_FUNC(pmf
, "enqueue_notify")
2734 void *cookie
= NULL
;
2737 ASSERT(MUTEX_HELD(&pm_rsvp_lock
));
2739 case PSC_PENDING_CHANGE
: /* only for controlling process */
2740 PMD(PMD_DPM
, ("%s: PENDING %s@%s(%s#%d), comp %d, %d -> %d\n",
2741 pmf
, PM_DEVICE(dip
), comp
, oldlevel
, newlevel
))
2742 psce
= pm_psc_dip_to_direct(dip
, &pscc
);
2744 PMD(PMD_IOCTL
, ("%s: PENDING: %s@%s(%s#%d) pm_poll_cnt[%d] "
2745 "%d\n", pmf
, PM_DEVICE(dip
), pscc
->pscc_clone
,
2746 pm_poll_cnt
[pscc
->pscc_clone
]))
2747 overrun
= psc_entry(cmd
, psce
, dip
, comp
, newlevel
, oldlevel
,
2748 PSC_DIRECT
, canblock
);
2749 PMD(PMD_DPM
, ("%s: sig %d\n", pmf
, pscc
->pscc_clone
))
2750 mutex_enter(&pm_clone_lock
);
2752 pm_poll_cnt
[pscc
->pscc_clone
]++;
2753 cv_signal(&pm_clones_cv
[pscc
->pscc_clone
]);
2754 pollwakeup(&pm_pollhead
, (POLLRDNORM
| POLLIN
));
2755 mutex_exit(&pm_clone_lock
);
2757 case PSC_HAS_CHANGED
:
2758 PMD(PMD_DPM
, ("%s: HAS %s@%s(%s#%d), comp %d, %d -> %d\n",
2759 pmf
, PM_DEVICE(dip
), comp
, oldlevel
, newlevel
))
2760 if (PM_ISDIRECT(dip
) && canblock
!= PM_CANBLOCK_BYPASS
) {
2761 psce
= pm_psc_dip_to_direct(dip
, &pscc
);
2762 PMD(PMD_IOCTL
, ("%s: HAS: %s@%s(%s#%d) pm_poll_cnt[%d] "
2763 "%d\n", pmf
, PM_DEVICE(dip
), pscc
->pscc_clone
,
2764 pm_poll_cnt
[pscc
->pscc_clone
]))
2765 overrun
= psc_entry(cmd
, psce
, dip
, comp
, newlevel
,
2766 oldlevel
, PSC_DIRECT
, canblock
);
2767 PMD(PMD_DPM
, ("%s: sig %d\n", pmf
, pscc
->pscc_clone
))
2768 mutex_enter(&pm_clone_lock
);
2770 pm_poll_cnt
[pscc
->pscc_clone
]++;
2771 cv_signal(&pm_clones_cv
[pscc
->pscc_clone
]);
2772 pollwakeup(&pm_pollhead
, (POLLRDNORM
| POLLIN
));
2773 mutex_exit(&pm_clone_lock
);
2775 mutex_enter(&pm_clone_lock
);
2776 rw_enter(&pm_pscc_interest_rwlock
, RW_READER
);
2777 while ((psce
= psc_interest(&cookie
, &pscc
)) != NULL
) {
2778 (void) psc_entry(cmd
, psce
, dip
, comp
, newlevel
,
2779 oldlevel
, PSC_INTEREST
, canblock
);
2780 cv_signal(&pm_clones_cv
[pscc
->pscc_clone
]);
2782 rw_exit(&pm_pscc_interest_rwlock
);
2783 mutex_exit(&pm_clone_lock
);
2793 pm_enqueue_notify_others(pm_ppm_devlist_t
**listp
, pm_canblock_t canblock
)
2796 pm_ppm_devlist_t
*p
, *next
= NULL
;
2798 for (p
= *listp
; p
; p
= next
) {
2800 pm_enqueue_notify(PSC_HAS_CHANGED
, p
->ppd_who
,
2801 p
->ppd_cmpt
, p
->ppd_new_level
, p
->ppd_old_level
,
2803 kmem_free(p
, sizeof (pm_ppm_devlist_t
));
2810 * Try to get the power locks of the parent node and target (child)
2811 * node. Return true if successful (with both locks held) or false
2812 * (with no locks held).
2815 pm_try_parent_child_locks(dev_info_t
*pdip
,
2816 dev_info_t
*dip
, int *pcircp
, int *circp
)
2818 if (ndi_devi_tryenter(pdip
, pcircp
))
2819 if (PM_TRY_LOCK_POWER(dip
, circp
)) {
2822 ndi_devi_exit(pdip
, *pcircp
);
2828 * Determine if the power lock owner is blocked by current thread.
2830 * 1 - If the thread owning the effective power lock (the first lock on
2831 * which a thread blocks when it does PM_LOCK_POWER) is blocked by
2832 * a mutex held by the current thread.
2836 * Note : This function is called by pm_power_has_changed to determine whether
2837 * it is executing in parallel with pm_set_power.
2840 pm_blocked_by_us(dev_info_t
*dip
)
2842 power_req_t power_req
;
2846 dev_info_t
*ppm
= (dev_info_t
*)DEVI(dip
)->devi_pm_ppm
;
2848 power_req
.request_type
= PMR_PPM_POWER_LOCK_OWNER
;
2849 power_req
.req
.ppm_power_lock_owner_req
.who
= dip
;
2850 if (pm_ctlops(ppm
, dip
, DDI_CTLOPS_POWER
, &power_req
, &result
) !=
2853 * It is assumed that if the device is claimed by ppm, ppm
2854 * will always implement this request type and it'll always
2855 * return success. We panic here, if it fails.
2857 panic("pm: Can't determine power lock owner of %s@%s(%s#%d)\n",
2862 if ((owner
= power_req
.req
.ppm_power_lock_owner_req
.owner
) != NULL
&&
2863 owner
->t_state
== TS_SLEEP
&&
2864 owner
->t_sobj_ops
&&
2865 SOBJ_TYPE(owner
->t_sobj_ops
) == SOBJ_MUTEX
&&
2866 (mp
= (kmutex_t
*)owner
->t_wchan
) &&
2867 mutex_owner(mp
) == curthread
)
2874 * Notify parent which wants to hear about a child's power changes.
2877 pm_notify_parent(dev_info_t
*dip
,
2878 dev_info_t
*pdip
, int comp
, int old_level
, int level
)
2880 pm_bp_has_changed_t bphc
;
2882 char *pathbuf
= kmem_alloc(MAXPATHLEN
, KM_SLEEP
);
2883 int result
= DDI_SUCCESS
;
2885 bphc
.bphc_dip
= dip
;
2886 bphc
.bphc_path
= ddi_pathname(dip
, pathbuf
);
2887 bphc
.bphc_comp
= comp
;
2888 bphc
.bphc_olevel
= old_level
;
2889 bphc
.bphc_nlevel
= level
;
2890 pspm
.pspm_canblock
= PM_CANBLOCK_BLOCK
;
2892 bphc
.bphc_private
= &pspm
;
2893 (void) (*PM_BUS_POWER_FUNC(pdip
))(pdip
, NULL
,
2894 BUS_POWER_HAS_CHANGED
, (void *)&bphc
, (void *)&result
);
2895 kmem_free(pathbuf
, MAXPATHLEN
);
2899 * Check if we need to resume a BC device, and make the attach call as required.
2902 pm_check_and_resume(dev_info_t
*dip
, int comp
, int old_level
, int level
)
2904 int ret
= DDI_SUCCESS
;
2906 if (PM_ISBC(dip
) && comp
== 0 && old_level
== 0 && level
!= 0) {
2907 ASSERT(DEVI(dip
)->devi_pm_flags
& PMC_SUSPENDED
);
2908 /* ppm is not interested in DDI_PM_RESUME */
2909 if ((ret
= devi_attach(dip
, DDI_PM_RESUME
)) != DDI_SUCCESS
)
2910 /* XXX Should we mark it resumed, */
2911 /* even though it failed? */
2912 cmn_err(CE_WARN
, "!pm: Can't resume %s@%s",
2913 PM_NAME(dip
), PM_ADDR(dip
));
2914 DEVI(dip
)->devi_pm_flags
&= ~PMC_SUSPENDED
;
2921 * Tests outside the lock to see if we should bother to enqueue an entry
2922 * for any watching process. If yes, then caller will take the lock and
2923 * do the full protocol
2928 if (pm_processes_stopped
)
2930 return (pm_pscc_direct
|| pm_pscc_interest
);
2933 static int pm_phc_impl(dev_info_t
*, int, int, int);
2936 * A driver is reporting that the power of one of its device's components
2937 * has changed. Update the power state accordingly.
2940 pm_power_has_changed(dev_info_t
*dip
, int comp
, int level
)
2942 PMD_FUNC(pmf
, "pm_power_has_changed")
2944 dev_info_t
*pdip
= ddi_get_parent(dip
);
2945 struct pm_component
*cp
;
2946 int blocked
, circ
, pcirc
, old_level
;
2949 PMD(PMD_FAIL
, ("%s: %s@%s(%s#%d): bad level=%d\n", pmf
,
2950 PM_DEVICE(dip
), level
))
2951 return (DDI_FAILURE
);
2954 PMD(PMD_KIDSUP
| PMD_DEP
, ("%s: %s@%s(%s#%d), comp=%d, level=%d\n", pmf
,
2955 PM_DEVICE(dip
), comp
, level
))
2957 if (!e_pm_valid_info(dip
, NULL
) || !e_pm_valid_comp(dip
, comp
, &cp
) ||
2958 !e_pm_valid_power(dip
, comp
, level
))
2959 return (DDI_FAILURE
);
2962 * A driver thread calling pm_power_has_changed and another thread
2963 * calling pm_set_power can deadlock. The problem is not resolvable
2964 * by changing lock order, so we use pm_blocked_by_us() to detect
2965 * this specific deadlock. If we can't get the lock immediately
2966 * and we are deadlocked, just update the component's level, do
2967 * notifications, and return. We intend to update the total power
2968 * state later (if the other thread fails to set power to the
2969 * desired level). If we were called because of a power change on a
2970 * component that isn't involved in a set_power op, update all state
2973 cp
= PM_CP(dip
, comp
);
2974 while (!pm_try_parent_child_locks(pdip
, dip
, &pcirc
, &circ
)) {
2975 if (((blocked
= pm_blocked_by_us(dip
)) != 0) &&
2976 (cp
->pmc_flags
& PM_POWER_OP
)) {
2977 if (pm_watchers()) {
2978 mutex_enter(&pm_rsvp_lock
);
2979 pm_enqueue_notify(PSC_HAS_CHANGED
, dip
, comp
,
2980 level
, cur_power(cp
), PM_CANBLOCK_BLOCK
);
2981 mutex_exit(&pm_rsvp_lock
);
2983 if (pdip
&& PM_WANTS_NOTIFICATION(pdip
))
2984 pm_notify_parent(dip
,
2985 pdip
, comp
, cur_power(cp
), level
);
2986 (void) pm_check_and_resume(dip
,
2987 comp
, cur_power(cp
), level
);
2990 * Stash the old power index, update curpwr, and flag
2991 * that the total power state needs to be synched.
2993 cp
->pmc_flags
|= PM_PHC_WHILE_SET_POWER
;
2995 * Several pm_power_has_changed calls could arrive
2996 * while the set power path remains blocked. Keep the
2997 * oldest old power and the newest new power of any
2998 * sequence of phc calls which arrive during deadlock.
3000 if (cp
->pmc_phc_pwr
== PM_LEVEL_UNKNOWN
)
3001 cp
->pmc_phc_pwr
= cp
->pmc_cur_pwr
;
3003 pm_level_to_index(dip
, cp
, level
);
3004 PMD(PMD_PHC
, ("%s: deadlock for %s@%s(%s#%d), comp=%d, "
3005 "level=%d\n", pmf
, PM_DEVICE(dip
), comp
, level
))
3006 return (DDI_SUCCESS
);
3008 if (blocked
) { /* blocked, but different cmpt? */
3009 if (!ndi_devi_tryenter(pdip
, &pcirc
)) {
3011 "!pm: parent kuc not updated due "
3012 "to possible deadlock.\n");
3013 return (pm_phc_impl(dip
,
3016 old_level
= cur_power(cp
);
3017 if (pdip
&& !PM_WANTS_NOTIFICATION(pdip
) &&
3018 (!PM_ISBC(dip
) || comp
== 0) &&
3019 POWERING_ON(old_level
, level
))
3020 pm_hold_power(pdip
);
3021 ret
= pm_phc_impl(dip
, comp
, level
, 1);
3022 if (pdip
&& !PM_WANTS_NOTIFICATION(pdip
)) {
3023 if ((!PM_ISBC(dip
) ||
3024 comp
== 0) && level
== 0 &&
3025 old_level
!= PM_LEVEL_UNKNOWN
)
3026 pm_rele_power(pdip
);
3028 ndi_devi_exit(pdip
, pcirc
);
3029 /* child lock not held: deadlock */
3033 PMD(PMD_PHC
, ("%s: try lock again\n", pmf
))
3036 /* non-deadlock case */
3037 old_level
= cur_power(cp
);
3038 if (pdip
&& !PM_WANTS_NOTIFICATION(pdip
) &&
3039 (!PM_ISBC(dip
) || comp
== 0) && POWERING_ON(old_level
, level
))
3040 pm_hold_power(pdip
);
3041 ret
= pm_phc_impl(dip
, comp
, level
, 1);
3042 if (pdip
&& !PM_WANTS_NOTIFICATION(pdip
)) {
3043 if ((!PM_ISBC(dip
) || comp
== 0) && level
== 0 &&
3044 old_level
!= PM_LEVEL_UNKNOWN
)
3045 pm_rele_power(pdip
);
3047 PM_UNLOCK_POWER(dip
, circ
);
3048 ndi_devi_exit(pdip
, pcirc
);
3053 * Account for power changes to a component of the the console frame buffer.
3054 * If lowering power from full (or "unkown", which is treatd as full)
3055 * we will increment the "components off" count of the fb device.
3056 * Subsequent lowering of the same component doesn't affect the count. If
3057 * raising a component back to full power, we will decrement the count.
3059 * Return: the increment value for pm_cfb_comps_off (-1, 0, or 1)
3062 calc_cfb_comps_incr(dev_info_t
*dip
, int cmpt
, int old
, int new)
3064 struct pm_component
*cp
= PM_CP(dip
, cmpt
);
3065 int on
= (old
== PM_LEVEL_UNKNOWN
|| old
== cp
->pmc_norm_pwr
);
3066 int want_normal
= (new == cp
->pmc_norm_pwr
);
3069 if (on
&& !want_normal
)
3071 else if (!on
&& want_normal
)
3077 * Adjust the count of console frame buffer components < full power.
3080 update_comps_off(int incr
, dev_info_t
*dip
)
3082 mutex_enter(&pm_cfb_lock
);
3083 pm_cfb_comps_off
+= incr
;
3084 ASSERT(pm_cfb_comps_off
<= PM_NUMCMPTS(dip
));
3085 mutex_exit(&pm_cfb_lock
);
3089 * Update the power state in the framework (via the ppm). The 'notify'
3090 * argument tells whether to notify watchers. Power lock is already held.
3093 pm_phc_impl(dev_info_t
*dip
, int comp
, int level
, int notify
)
3095 PMD_FUNC(pmf
, "phc_impl")
3096 power_req_t power_req
;
3098 dev_info_t
*pdip
= ddi_get_parent(dip
);
3101 struct pm_component
*cp
;
3103 dev_info_t
*ppm
= (dev_info_t
*)DEVI(dip
)->devi_pm_ppm
;
3107 /* Must use "official" power level for this test. */
3108 cp
= PM_CP(dip
, comp
);
3109 old_level
= (cp
->pmc_flags
& PM_PHC_WHILE_SET_POWER
?
3110 cp
->pmc_phc_pwr
: cp
->pmc_cur_pwr
);
3111 if (old_level
!= PM_LEVEL_UNKNOWN
)
3112 old_level
= cp
->pmc_comp
.pmc_lvals
[old_level
];
3114 if (level
== old_level
) {
3115 PMD(PMD_SET
, ("%s: %s@%s(%s#%d), comp=%d is already at "
3116 "level=%d\n", pmf
, PM_DEVICE(dip
), comp
, level
))
3117 return (DDI_SUCCESS
);
3121 * Tell ppm about this.
3123 power_req
.request_type
= PMR_PPM_POWER_CHANGE_NOTIFY
;
3124 power_req
.req
.ppm_notify_level_req
.who
= dip
;
3125 power_req
.req
.ppm_notify_level_req
.cmpt
= comp
;
3126 power_req
.req
.ppm_notify_level_req
.new_level
= level
;
3127 power_req
.req
.ppm_notify_level_req
.old_level
= old_level
;
3128 if (pm_ctlops(ppm
, dip
, DDI_CTLOPS_POWER
, &power_req
,
3129 &result
) == DDI_FAILURE
) {
3130 PMD(PMD_FAIL
, ("%s: pm_ctlops %s@%s(%s#%d) to %d failed\n",
3131 pmf
, PM_DEVICE(dip
), level
))
3132 return (DDI_FAILURE
);
3135 if (PM_IS_CFB(dip
)) {
3136 incr
= calc_cfb_comps_incr(dip
, comp
, old_level
, level
);
3139 update_comps_off(incr
, dip
);
3140 PMD(PMD_CFB
, ("%s: %s@%s(%s#%d) comp=%d %d->%d "
3141 "cfb_comps_off->%d\n", pmf
, PM_DEVICE(dip
),
3142 comp
, old_level
, level
, pm_cfb_comps_off
))
3145 e_pm_set_cur_pwr(dip
, PM_CP(dip
, comp
), level
);
3146 result
= DDI_SUCCESS
;
3149 if (pdip
&& PM_WANTS_NOTIFICATION(pdip
))
3150 pm_notify_parent(dip
, pdip
, comp
, old_level
, level
);
3151 (void) pm_check_and_resume(dip
, comp
, old_level
, level
);
3155 * Decrement the dependency kidsup count if we turn a device
3158 if (POWERING_OFF(old_level
, level
)) {
3160 for (i
= 0; i
< PM_NUMCMPTS(dip
); i
++) {
3162 if (cur_power(cp
)) {
3168 work_type
= PM_DEP_WK_POWER_OFF
;
3172 * Increment if we turn it on. Check to see
3173 * if other comps are already on, if so,
3176 if (POWERING_ON(old_level
, level
)) {
3178 for (i
= 0; i
< PM_NUMCMPTS(dip
); i
++) {
3182 /* -1 also treated as 0 in this case */
3183 if (cur_power(cp
) > 0) {
3189 work_type
= PM_DEP_WK_POWER_ON
;
3193 pathbuf
= kmem_zalloc(MAXPATHLEN
, KM_SLEEP
);
3194 (void) ddi_pathname(dip
, pathbuf
);
3195 pm_dispatch_to_dep_thread(work_type
, pathbuf
, NULL
,
3196 PM_DEP_NOWAIT
, NULL
, 0);
3197 kmem_free(pathbuf
, MAXPATHLEN
);
3200 if (notify
&& (level
!= old_level
) && pm_watchers()) {
3201 mutex_enter(&pm_rsvp_lock
);
3202 pm_enqueue_notify(PSC_HAS_CHANGED
, dip
, comp
, level
, old_level
,
3204 mutex_exit(&pm_rsvp_lock
);
3207 PMD(PMD_RESCAN
, ("%s: %s@%s(%s#%d): pm_rescan\n", pmf
, PM_DEVICE(dip
)))
3209 return (DDI_SUCCESS
);
3213 * This function is called at startup time to notify pm of the existence
3214 * of any platform power managers for this platform. As a result of
3215 * this registration, each function provided will be called each time
3216 * a device node is attached, until one returns true, and it must claim the
3217 * device node (by returning non-zero) if it wants to be involved in the
3218 * node's power management. If it does claim the node, then it will
3219 * subsequently be notified of attach and detach events.
3224 pm_register_ppm(int (*func
)(dev_info_t
*), dev_info_t
*dip
)
3226 PMD_FUNC(pmf
, "register_ppm")
3227 struct ppm_callbacks
*ppmcp
;
3229 int i
, pwr
, result
, circ
;
3230 power_req_t power_req
;
3231 struct ppm_notify_level_req
*p
= &power_req
.req
.ppm_notify_level_req
;
3232 void pm_ppm_claim(dev_info_t
*);
3234 mutex_enter(&ppm_lock
);
3235 ppmcp
= ppm_callbacks
;
3236 for (i
= 0; i
< MAX_PPM_HANDLERS
; i
++, ppmcp
++) {
3237 if (ppmcp
->ppmc_func
== NULL
) {
3238 ppmcp
->ppmc_func
= func
;
3239 ppmcp
->ppmc_dip
= dip
;
3243 mutex_exit(&ppm_lock
);
3245 if (i
>= MAX_PPM_HANDLERS
)
3246 return (DDI_FAILURE
);
3247 while ((dip
= ddi_get_parent(dip
)) != NULL
) {
3248 if (dip
!= ddi_root_node() && PM_GET_PM_INFO(dip
) == NULL
)
3251 /* don't bother with the not power-manageable nodes */
3252 if (pm_ppm_claimed(dip
) && PM_GET_PM_INFO(dip
)) {
3254 * Tell ppm about this.
3256 power_req
.request_type
= PMR_PPM_POWER_CHANGE_NOTIFY
;
3257 p
->old_level
= PM_LEVEL_UNKNOWN
;
3259 PM_LOCK_POWER(dip
, &circ
);
3260 for (i
= 0; i
< PM_NUMCMPTS(dip
); i
++) {
3262 pwr
= cp
->pmc_cur_pwr
;
3263 if (pwr
!= PM_LEVEL_UNKNOWN
) {
3265 p
->new_level
= cur_power(cp
);
3266 p
->old_level
= PM_LEVEL_UNKNOWN
;
3267 if (pm_ctlops(PPM(dip
), dip
,
3268 DDI_CTLOPS_POWER
, &power_req
,
3269 &result
) == DDI_FAILURE
) {
3270 PMD(PMD_FAIL
, ("%s: pc "
3271 "%s@%s(%s#%d) to %d "
3273 PM_DEVICE(dip
), pwr
))
3277 PM_UNLOCK_POWER(dip
, circ
);
3280 return (DDI_SUCCESS
);
3284 * Call the ppm's that have registered and adjust the devinfo struct as
3285 * appropriate. First one to claim it gets it. The sets of devices claimed
3286 * by each ppm are assumed to be disjoint.
3289 pm_ppm_claim(dev_info_t
*dip
)
3291 struct ppm_callbacks
*ppmcp
;
3296 mutex_enter(&ppm_lock
);
3297 for (ppmcp
= ppm_callbacks
; ppmcp
->ppmc_func
; ppmcp
++) {
3298 if ((*ppmcp
->ppmc_func
)(dip
)) {
3299 DEVI(dip
)->devi_pm_ppm
=
3300 (struct dev_info
*)ppmcp
->ppmc_dip
;
3301 mutex_exit(&ppm_lock
);
3305 mutex_exit(&ppm_lock
);
3309 * Node is being detached so stop autopm until we see if it succeeds, in which
3310 * case pm_stop will be called. For backwards compatible devices we bring the
3311 * device up to full power on the assumption the detach will succeed.
3314 pm_detaching(dev_info_t
*dip
)
3316 PMD_FUNC(pmf
, "detaching")
3317 pm_info_t
*info
= PM_GET_PM_INFO(dip
);
3320 PMD(PMD_REMDEV
, ("%s: %s@%s(%s#%d), %d comps\n", pmf
, PM_DEVICE(dip
),
3324 ASSERT(DEVI_IS_DETACHING(dip
));
3326 info
->pmi_dev_pm_state
|= PM_DETACHING
;
3332 * console and old-style devices get brought up when detaching.
3334 iscons
= PM_IS_CFB(dip
);
3335 if (iscons
|| PM_ISBC(dip
)) {
3336 (void) pm_all_to_normal(dip
, PM_CANBLOCK_BYPASS
);
3338 mutex_enter(&pm_cfb_lock
);
3340 mutex_exit(&pm_cfb_lock
);
3341 PMD(PMD_CFB
, ("%s: delay; cfb_inuse\n", pmf
))
3343 mutex_enter(&pm_cfb_lock
);
3345 ASSERT(cfb_dip_detaching
== NULL
);
3347 cfb_dip_detaching
= cfb_dip
; /* case detach fails */
3349 mutex_exit(&pm_cfb_lock
);
3355 * Node failed to detach. If it used to be autopm'd, make it so again.
3358 pm_detach_failed(dev_info_t
*dip
)
3360 PMD_FUNC(pmf
, "detach_failed")
3361 pm_info_t
*info
= PM_GET_PM_INFO(dip
);
3362 int pm_all_at_normal(dev_info_t
*);
3366 ASSERT(DEVI_IS_DETACHING(dip
));
3367 if (info
->pmi_dev_pm_state
& PM_DETACHING
) {
3368 info
->pmi_dev_pm_state
&= ~PM_DETACHING
;
3369 if (info
->pmi_dev_pm_state
& PM_ALLNORM_DEFERRED
) {
3370 /* Make sure the operation is still needed */
3371 if (!pm_all_at_normal(dip
)) {
3372 if (pm_all_to_normal(dip
,
3373 PM_CANBLOCK_FAIL
) != DDI_SUCCESS
) {
3374 PMD(PMD_ERROR
, ("%s: could not bring "
3375 "%s@%s(%s#%d) to normal\n", pmf
,
3379 info
->pmi_dev_pm_state
&= ~PM_ALLNORM_DEFERRED
;
3382 if (!PM_ISBC(dip
)) {
3383 mutex_enter(&pm_scan_lock
);
3384 if (PM_SCANABLE(dip
))
3386 mutex_exit(&pm_scan_lock
);
3391 /* generic Backwards Compatible component */
3392 static char *bc_names
[] = {"off", "on"};
3394 static pm_comp_t bc_comp
= {"unknown", 2, NULL
, NULL
, &bc_names
[0]};
3397 e_pm_default_levels(dev_info_t
*dip
, pm_component_t
*cp
, int norm
)
3400 pmc
= &cp
->pmc_comp
;
3401 pmc
->pmc_numlevels
= 2;
3402 pmc
->pmc_lvals
[0] = 0;
3403 pmc
->pmc_lvals
[1] = norm
;
3404 e_pm_set_cur_pwr(dip
, cp
, norm
);
3408 e_pm_default_components(dev_info_t
*dip
, int cmpts
)
3411 pm_component_t
*p
= DEVI(dip
)->devi_pm_components
;
3413 p
= DEVI(dip
)->devi_pm_components
;
3414 for (i
= 0; i
< cmpts
; i
++, p
++) {
3415 p
->pmc_comp
= bc_comp
; /* struct assignment */
3416 p
->pmc_comp
.pmc_lvals
= kmem_zalloc(2 * sizeof (int),
3418 p
->pmc_comp
.pmc_thresh
= kmem_alloc(2 * sizeof (int),
3420 p
->pmc_comp
.pmc_numlevels
= 2;
3421 p
->pmc_comp
.pmc_thresh
[0] = INT_MAX
;
3422 p
->pmc_comp
.pmc_thresh
[1] = INT_MAX
;
3427 * Called from functions that require components to exist already to allow
3428 * for their creation by parsing the pm-components property.
3429 * Device will not be power managed as a result of this call
3430 * No locking needed because we're single threaded by the ndi_devi_enter
3431 * done while attaching, and the device isn't visible until after it has
3435 pm_premanage(dev_info_t
*dip
, int style
)
3437 PMD_FUNC(pmf
, "premanage")
3438 pm_comp_t
*pcp
, *compp
;
3439 int cmpts
, i
, norm
, error
;
3440 pm_component_t
*p
= DEVI(dip
)->devi_pm_components
;
3441 pm_comp_t
*pm_autoconfig(dev_info_t
*, int *);
3443 ASSERT(!PM_IAM_LOCKING_DIP(dip
));
3445 * If this dip has already been processed, don't mess with it
3447 if (DEVI(dip
)->devi_pm_flags
& PMC_COMPONENTS_DONE
)
3448 return (DDI_SUCCESS
);
3449 if (DEVI(dip
)->devi_pm_flags
& PMC_COMPONENTS_FAILED
) {
3450 return (DDI_FAILURE
);
3453 * Look up pm-components property and create components accordingly
3454 * If that fails, fall back to backwards compatibility
3456 if ((compp
= pm_autoconfig(dip
, &error
)) == NULL
) {
3458 * If error is set, the property existed but was not well formed
3460 if (error
|| (style
== PM_STYLE_NEW
)) {
3461 DEVI(dip
)->devi_pm_flags
|= PMC_COMPONENTS_FAILED
;
3462 return (DDI_FAILURE
);
3465 * If they don't have the pm-components property, then we
3466 * want the old "no pm until PM_SET_DEVICE_THRESHOLDS ioctl"
3467 * behavior driver must have called pm_create_components, and
3468 * we need to flesh out dummy components
3470 if ((cmpts
= PM_NUMCMPTS(dip
)) == 0) {
3472 * Not really failure, but we don't want the
3473 * caller to treat it as success
3475 return (DDI_FAILURE
);
3477 DEVI(dip
)->devi_pm_flags
|= PMC_BC
;
3478 e_pm_default_components(dip
, cmpts
);
3479 for (i
= 0; i
< cmpts
; i
++) {
3481 * if normal power not set yet, we don't really know
3482 * what *ANY* of the power values are. If normal
3483 * power is set, then we assume for this backwards
3484 * compatible case that the values are 0, normal power.
3486 norm
= pm_get_normal_power(dip
, i
);
3487 if (norm
== (uint_t
)-1) {
3488 PMD(PMD_ERROR
, ("%s: %s@%s(%s#%d)[%d]\n", pmf
,
3490 return (DDI_FAILURE
);
3493 * Components of BC devices start at their normal power,
3494 * so count them to be not at their lowest power.
3496 PM_INCR_NOTLOWEST(dip
);
3497 e_pm_default_levels(dip
, PM_CP(dip
, i
), norm
);
3501 * e_pm_create_components was called from pm_autoconfig(), it
3502 * creates components with no descriptions (or known levels)
3504 cmpts
= PM_NUMCMPTS(dip
);
3507 p
= DEVI(dip
)->devi_pm_components
;
3508 for (i
= 0; i
< cmpts
; i
++, p
++) {
3509 p
->pmc_comp
= *pcp
++; /* struct assignment */
3510 ASSERT(PM_CP(dip
, i
)->pmc_cur_pwr
== 0);
3511 e_pm_set_cur_pwr(dip
, PM_CP(dip
, i
), PM_LEVEL_UNKNOWN
);
3513 if (DEVI(dip
)->devi_pm_flags
& PMC_CPU_THRESH
)
3514 pm_set_device_threshold(dip
, pm_cpu_idle_threshold
,
3517 pm_set_device_threshold(dip
, pm_system_idle_threshold
,
3519 kmem_free(compp
, cmpts
* sizeof (pm_comp_t
));
3521 return (DDI_SUCCESS
);
3525 * Called from during or after the device's attach to let us know it is ready
3526 * to play autopm. Look up the pm model and manage the device accordingly.
3527 * Returns system call errno value.
3528 * If DDI_ATTACH and DDI_DETACH were in same namespace, this would be
3531 * Called with dip lock held, return with dip lock unheld.
3535 e_pm_manage(dev_info_t
*dip
, int style
)
3537 PMD_FUNC(pmf
, "e_manage")
3539 dev_info_t
*pdip
= ddi_get_parent(dip
);
3540 int pm_thresh_specd(dev_info_t
*);
3544 if (pm_premanage(dip
, style
) != DDI_SUCCESS
) {
3545 return (DDI_FAILURE
);
3547 PMD(PMD_KIDSUP
, ("%s: %s@%s(%s#%d)\n", pmf
, PM_DEVICE(dip
)))
3548 ASSERT(PM_GET_PM_INFO(dip
) == NULL
);
3549 info
= kmem_zalloc(sizeof (pm_info_t
), KM_SLEEP
);
3552 * Now set up parent's kidsupcnt. BC nodes are assumed to start
3553 * out at their normal power, so they are "up", others start out
3554 * unknown, which is effectively "up". Parent which want notification
3555 * get kidsupcnt of 0 always.
3557 count
= (PM_ISBC(dip
)) ? 1 : PM_NUMCMPTS(dip
);
3558 if (count
&& pdip
&& !PM_WANTS_NOTIFICATION(pdip
))
3559 e_pm_hold_rele_power(pdip
, count
);
3561 pm_set_pm_info(dip
, info
);
3563 * Apply any recorded thresholds
3565 (void) pm_thresh_specd(dip
);
3568 * Do dependency processing.
3570 pathbuf
= kmem_zalloc(MAXPATHLEN
, KM_SLEEP
);
3571 (void) ddi_pathname(dip
, pathbuf
);
3572 pm_dispatch_to_dep_thread(PM_DEP_WK_ATTACH
, pathbuf
, pathbuf
,
3573 PM_DEP_NOWAIT
, NULL
, 0);
3574 kmem_free(pathbuf
, MAXPATHLEN
);
3576 if (!PM_ISBC(dip
)) {
3577 mutex_enter(&pm_scan_lock
);
3578 if (PM_SCANABLE(dip
)) {
3580 mutex_exit(&pm_scan_lock
);
3583 mutex_exit(&pm_scan_lock
);
3590 * This is the obsolete exported interface for a driver to find out its
3591 * "normal" (max) power.
3592 * We only get components destroyed while no power management is
3593 * going on (and the device is detached), so we don't need a mutex here
3596 pm_get_normal_power(dev_info_t
*dip
, int comp
)
3599 if (comp
>= 0 && comp
< PM_NUMCMPTS(dip
)) {
3600 return (PM_CP(dip
, comp
)->pmc_norm_pwr
);
3602 return (DDI_FAILURE
);
3606 * Fetches the current power level. Return DDI_SUCCESS or DDI_FAILURE.
3609 pm_get_current_power(dev_info_t
*dip
, int comp
, int *levelp
)
3611 if (comp
>= 0 && comp
< PM_NUMCMPTS(dip
)) {
3612 *levelp
= PM_CURPOWER(dip
, comp
);
3613 return (DDI_SUCCESS
);
3615 return (DDI_FAILURE
);
3619 * Returns current threshold of indicated component
3622 cur_threshold(dev_info_t
*dip
, int comp
)
3624 pm_component_t
*cp
= PM_CP(dip
, comp
);
3629 * backwards compatible nodes only have one threshold
3631 return (cp
->pmc_comp
.pmc_thresh
[1]);
3633 pwr
= cp
->pmc_cur_pwr
;
3634 if (pwr
== PM_LEVEL_UNKNOWN
) {
3636 if (DEVI(dip
)->devi_pm_flags
& PMC_NEXDEF_THRESH
)
3637 thresh
= pm_default_nexus_threshold
;
3638 else if (DEVI(dip
)->devi_pm_flags
& PMC_CPU_THRESH
)
3639 thresh
= pm_cpu_idle_threshold
;
3641 thresh
= pm_system_idle_threshold
;
3644 ASSERT(cp
->pmc_comp
.pmc_thresh
);
3645 return (cp
->pmc_comp
.pmc_thresh
[pwr
]);
3649 * Compute next lower component power level given power index.
3652 pm_next_lower_power(pm_component_t
*cp
, int pwrndx
)
3656 if (pwrndx
== PM_LEVEL_UNKNOWN
) {
3657 nxt_pwr
= cp
->pmc_comp
.pmc_lvals
[0];
3660 ASSERT(pwrndx
>= 0);
3661 nxt_pwr
= cp
->pmc_comp
.pmc_lvals
[pwrndx
];
3667 * Update the maxpower (normal) power of a component. Note that the
3668 * component's power level is only changed if it's current power level
3669 * is higher than the new max power.
3672 pm_update_maxpower(dev_info_t
*dip
, int comp
, int level
)
3674 PMD_FUNC(pmf
, "update_maxpower")
3678 if (!e_pm_valid_info(dip
, NULL
) || !e_pm_valid_comp(dip
, comp
, NULL
) ||
3679 !e_pm_valid_power(dip
, comp
, level
)) {
3680 PMD(PMD_FAIL
, ("%s: validation checks failed for %s@%s(%s#%d) "
3681 "comp=%d level=%d\n", pmf
, PM_DEVICE(dip
), comp
, level
))
3682 return (DDI_FAILURE
);
3684 old
= e_pm_get_max_power(dip
, comp
);
3685 e_pm_set_max_power(dip
, comp
, level
);
3687 if (pm_set_power(dip
, comp
, level
, PM_LEVEL_DOWNONLY
,
3688 PM_CANBLOCK_BLOCK
, 0, &result
) != DDI_SUCCESS
) {
3689 e_pm_set_max_power(dip
, comp
, old
);
3690 PMD(PMD_FAIL
, ("%s: %s@%s(%s#%d) pm_set_power failed\n", pmf
,
3692 return (DDI_FAILURE
);
3694 return (DDI_SUCCESS
);
3698 * Bring all components of device to normal power
3701 pm_all_to_normal(dev_info_t
*dip
, pm_canblock_t canblock
)
3703 PMD_FUNC(pmf
, "all_to_normal")
3705 int i
, ncomps
, result
;
3707 int changefailed
= 0;
3709 PMD(PMD_ALLNORM
, ("%s: %s@%s(%s#%d)\n", pmf
, PM_DEVICE(dip
)))
3710 ASSERT(PM_GET_PM_INFO(dip
));
3711 if (pm_get_norm_pwrs(dip
, &normal
, &size
) != DDI_SUCCESS
) {
3712 PMD(PMD_ALLNORM
, ("%s: can't get norm pwrs for "
3713 "%s@%s(%s#%d)\n", pmf
, PM_DEVICE(dip
)))
3714 return (DDI_FAILURE
);
3716 ncomps
= PM_NUMCMPTS(dip
);
3717 for (i
= 0; i
< ncomps
; i
++) {
3718 if (pm_set_power(dip
, i
, normal
[i
],
3719 PM_LEVEL_UPONLY
, canblock
, 0, &result
) != DDI_SUCCESS
) {
3721 PMD(PMD_ALLNORM
| PMD_FAIL
, ("%s: failed to set "
3722 "%s@%s(%s#%d)[%d] to %d, errno %d\n", pmf
,
3723 PM_DEVICE(dip
), i
, normal
[i
], result
))
3726 kmem_free(normal
, size
);
3728 PMD(PMD_FAIL
, ("%s: failed to set %d comps %s@%s(%s#%d) "
3729 "to full power\n", pmf
, changefailed
, PM_DEVICE(dip
)))
3730 return (DDI_FAILURE
);
3732 return (DDI_SUCCESS
);
3736 * Returns true if all components of device are at normal power
3739 pm_all_at_normal(dev_info_t
*dip
)
3741 PMD_FUNC(pmf
, "all_at_normal")
3746 PMD(PMD_ALLNORM
, ("%s: %s@%s(%s#%d)\n", pmf
, PM_DEVICE(dip
)))
3747 if (pm_get_norm_pwrs(dip
, &normal
, &size
) != DDI_SUCCESS
) {
3748 PMD(PMD_ALLNORM
, ("%s: can't get normal power\n", pmf
))
3749 return (DDI_FAILURE
);
3751 for (i
= 0; i
< PM_NUMCMPTS(dip
); i
++) {
3752 int current
= PM_CURPOWER(dip
, i
);
3753 if (normal
[i
] > current
) {
3754 PMD(PMD_ALLNORM
, ("%s: %s@%s(%s#%d) comp=%d, "
3755 "norm=%d, cur=%d\n", pmf
, PM_DEVICE(dip
), i
,
3756 normal
[i
], current
))
3760 kmem_free(normal
, size
);
3761 if (i
!= PM_NUMCMPTS(dip
)) {
3767 static void bring_pmdep_up(dev_info_t
*, int);
3770 bring_wekeeps_up(char *keeper
)
3772 PMD_FUNC(pmf
, "bring_wekeeps_up")
3775 pm_info_t
*wku_info
;
3783 * We process the request even if the keeper detaches because
3784 * detach processing expects this to increment kidsupcnt of kept.
3786 PMD(PMD_BRING
, ("%s: keeper= %s\n", pmf
, keeper
))
3787 for (dp
= pm_dep_head
; dp
; dp
= dp
->pdr_next
) {
3788 if (strcmp(dp
->pdr_keeper
, keeper
) != 0)
3790 for (i
= 0; i
< dp
->pdr_kept_count
; i
++) {
3791 kept_path
= dp
->pdr_kept_paths
[i
];
3792 if (kept_path
== NULL
)
3794 ASSERT(kept_path
[0] != '\0');
3795 if ((kept
= pm_name_to_dip(kept_path
, 1)) == NULL
)
3797 wku_info
= PM_GET_PM_INFO(kept
);
3798 if (wku_info
== NULL
) {
3800 ddi_release_devi(kept
);
3804 * Don't mess with it if it is being detached, it isn't
3805 * safe to call its power entry point
3807 if (wku_info
->pmi_dev_pm_state
& PM_DETACHING
) {
3809 ddi_release_devi(kept
);
3812 bring_pmdep_up(kept
, 1);
3813 ddi_release_devi(kept
);
3819 * Bring up the 'kept' device passed as argument
3822 bring_pmdep_up(dev_info_t
*kept_dip
, int hold
)
3824 PMD_FUNC(pmf
, "bring_pmdep_up")
3825 int is_all_at_normal
= 0;
3828 * If the kept device has been unmanaged, do nothing.
3830 if (!PM_GET_PM_INFO(kept_dip
))
3833 /* Just ignore DIRECT PM device till they are released. */
3834 if (!pm_processes_stopped
&& PM_ISDIRECT(kept_dip
) &&
3835 !(is_all_at_normal
= pm_all_at_normal(kept_dip
))) {
3836 PMD(PMD_BRING
, ("%s: can't bring up PM_DIRECT %s@%s(%s#%d) "
3837 "controlling process did something else\n", pmf
,
3838 PM_DEVICE(kept_dip
)))
3839 DEVI(kept_dip
)->devi_pm_flags
|= PMC_SKIP_BRINGUP
;
3842 /* if we got here the keeper had a transition from OFF->ON */
3844 pm_hold_power(kept_dip
);
3846 if (!is_all_at_normal
)
3847 (void) pm_all_to_normal(kept_dip
, PM_CANBLOCK_FAIL
);
3851 * A bunch of stuff that belongs only to the next routine (or two)
3854 static const char namestr
[] = "NAME=";
3855 static const int nameln
= sizeof (namestr
) - 1;
3856 static const char pmcompstr
[] = "pm-components";
3858 struct pm_comp_pkg
{
3860 struct pm_comp_pkg
*next
;
3863 #define isdigit(ch) ((ch) >= '0' && (ch) <= '9')
3865 #define isxdigit(ch) (isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \
3866 ((ch) >= 'A' && (ch) <= 'F'))
3869 * Rather than duplicate this code ...
3870 * (this code excerpted from the function that follows it)
3872 #define FINISH_COMP { \
3874 compp->pmc_lnames_sz = size; \
3875 tp = compp->pmc_lname_buf = kmem_alloc(size, KM_SLEEP); \
3876 compp->pmc_numlevels = level; \
3877 compp->pmc_lnames = kmem_alloc(level * sizeof (char *), KM_SLEEP); \
3878 compp->pmc_lvals = kmem_alloc(level * sizeof (int), KM_SLEEP); \
3879 compp->pmc_thresh = kmem_alloc(level * sizeof (int), KM_SLEEP); \
3880 /* copy string out of prop array into buffer */ \
3881 for (j = 0; j < level; j++) { \
3882 compp->pmc_thresh[j] = INT_MAX; /* only [0] sticks */ \
3883 compp->pmc_lvals[j] = lvals[j]; \
3884 (void) strcpy(tp, lnames[j]); \
3885 compp->pmc_lnames[j] = tp; \
3888 ASSERT(tp > compp->pmc_lname_buf && tp <= \
3889 compp->pmc_lname_buf + compp->pmc_lnames_sz); \
3893 * Create (empty) component data structures.
3896 e_pm_create_components(dev_info_t
*dip
, int num_components
)
3898 struct pm_component
*compp
, *ocompp
;
3901 ASSERT(!PM_IAM_LOCKING_DIP(dip
));
3902 ASSERT(!DEVI(dip
)->devi_pm_components
);
3903 ASSERT(!(DEVI(dip
)->devi_pm_flags
& PMC_COMPONENTS_DONE
));
3904 size
= sizeof (struct pm_component
) * num_components
;
3906 compp
= kmem_zalloc(size
, KM_SLEEP
);
3908 DEVI(dip
)->devi_pm_comp_size
= size
;
3909 DEVI(dip
)->devi_pm_num_components
= num_components
;
3911 for (i
= 0; i
< num_components
; i
++) {
3912 compp
->pmc_timestamp
= gethrestime_sec();
3913 compp
->pmc_norm_pwr
= (uint_t
)-1;
3916 PM_UNLOCK_BUSY(dip
);
3917 DEVI(dip
)->devi_pm_components
= ocompp
;
3918 DEVI(dip
)->devi_pm_flags
|= PMC_COMPONENTS_DONE
;
3922 * Parse hex or decimal value from char string
3925 pm_parsenum(char *cp
, int *valp
)
3935 if ((ch
= *cp
++) == 'x' || ch
== 'X') {
3937 while (isxdigit(ch
)) {
3949 while (isdigit(ch
)) {
3961 for (np
= numbuf
; *np
; np
++) {
3962 if (*np
>= 'a' && *np
<= 'f')
3964 else if (*np
>= 'A' && *np
<= 'F')
3966 else if (*np
>= '0' && *np
<= '9')
3969 value
+= *np
- offset
;
3976 for (np
= numbuf
; *np
; np
++) {
3978 value
+= *np
- offset
;
3985 * Set max (previously documented as "normal") power.
3988 e_pm_set_max_power(dev_info_t
*dip
, int component_number
, int level
)
3990 PM_CP(dip
, component_number
)->pmc_norm_pwr
= level
;
3994 * Get max (previously documented as "normal") power.
3997 e_pm_get_max_power(dev_info_t
*dip
, int component_number
)
3999 return (PM_CP(dip
, component_number
)->pmc_norm_pwr
);
4003 * Internal routine for destroying components
4004 * It is called even when there might not be any, so it must be forgiving.
4007 e_pm_destroy_components(dev_info_t
*dip
)
4010 struct pm_component
*cp
;
4012 ASSERT(!PM_IAM_LOCKING_DIP(dip
));
4013 if (PM_NUMCMPTS(dip
) == 0)
4015 cp
= DEVI(dip
)->devi_pm_components
;
4017 for (i
= 0; i
< PM_NUMCMPTS(dip
); i
++, cp
++) {
4018 int nlevels
= cp
->pmc_comp
.pmc_numlevels
;
4019 kmem_free(cp
->pmc_comp
.pmc_lvals
, nlevels
* sizeof (int));
4020 kmem_free(cp
->pmc_comp
.pmc_thresh
, nlevels
* sizeof (int));
4022 * For BC nodes, the rest is static in bc_comp, so skip it
4026 kmem_free(cp
->pmc_comp
.pmc_name
, cp
->pmc_comp
.pmc_name_sz
);
4027 kmem_free(cp
->pmc_comp
.pmc_lnames
, nlevels
* sizeof (char *));
4028 kmem_free(cp
->pmc_comp
.pmc_lname_buf
,
4029 cp
->pmc_comp
.pmc_lnames_sz
);
4031 kmem_free(DEVI(dip
)->devi_pm_components
, DEVI(dip
)->devi_pm_comp_size
);
4032 DEVI(dip
)->devi_pm_components
= NULL
;
4033 DEVI(dip
)->devi_pm_num_components
= 0;
4034 DEVI(dip
)->devi_pm_flags
&=
4035 ~(PMC_COMPONENTS_DONE
| PMC_COMPONENTS_FAILED
);
4039 * Read the pm-components property (if there is one) and use it to set up
4040 * components. Returns a pointer to an array of component structures if
4041 * pm-components found and successfully parsed, else returns NULL.
4042 * Sets error return *errp to true to indicate a failure (as opposed to no
4043 * property being present).
4046 pm_autoconfig(dev_info_t
*dip
, int *errp
)
4048 PMD_FUNC(pmf
, "autoconfig")
4051 pm_comp_t
*compp
= NULL
;
4052 int i
, j
, level
, components
= 0;
4054 struct pm_comp_pkg
*p
, *ptail
;
4055 struct pm_comp_pkg
*phead
= NULL
;
4060 char **lnames
= NULL
;
4062 pm_comp_t
*ret
= NULL
;
4064 ASSERT(!PM_IAM_LOCKING_DIP(dip
));
4065 *errp
= 0; /* assume success */
4066 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
4067 (char *)pmcompstr
, &pp
, &nelems
) != DDI_PROP_SUCCESS
) {
4071 if (nelems
< 3) { /* need at least one name and two levels */
4076 * pm_create_components is no longer allowed
4078 if (PM_NUMCMPTS(dip
) != 0) {
4079 PMD(PMD_ERROR
, ("%s: %s@%s(%s#%d) has %d comps\n",
4080 pmf
, PM_DEVICE(dip
), PM_NUMCMPTS(dip
)))
4084 lvals
= kmem_alloc(nelems
* sizeof (int), KM_SLEEP
);
4085 lszs
= kmem_alloc(nelems
* sizeof (int), KM_SLEEP
);
4086 lnames
= kmem_alloc(nelems
* sizeof (char *), KM_SLEEP
);
4087 np
= kmem_alloc(nelems
* sizeof (int), KM_SLEEP
);
4091 for (i
= 0; i
< nelems
; i
++) {
4093 if (!isdigit(*cp
)) { /* must be name */
4094 if (strncmp(cp
, namestr
, nameln
) != 0) {
4098 if (level
== 0) { /* no level spec'd */
4099 PMD(PMD_ERROR
, ("%s: no level spec'd\n",
4103 np
[npi
++] = lvals
[level
- 1];
4104 /* finish up previous component levels */
4109 PMD(PMD_ERROR
, ("%s: nsa\n", pmf
))
4112 p
= kmem_zalloc(sizeof (*phead
), KM_SLEEP
);
4113 if (phead
== NULL
) {
4119 compp
= p
->comp
= kmem_zalloc(sizeof (pm_comp_t
),
4121 compp
->pmc_name_sz
= strlen(cp
) + 1;
4122 compp
->pmc_name
= kmem_zalloc(compp
->pmc_name_sz
,
4124 (void) strncpy(compp
->pmc_name
, cp
, compp
->pmc_name_sz
);
4127 } else { /* better be power level <num>=<name> */
4132 (cp
= pm_parsenum(cp
, &lvals
[level
])) == NULL
) {
4133 PMD(PMD_ERROR
, ("%s: parsenum(%s)\n", pmf
, tp
))
4139 if (*cp
++ != '=' || !*cp
) {
4140 PMD(PMD_ERROR
, ("%s: ex =, got %s\n", pmf
, tp
))
4144 lszs
[level
] = strlen(cp
) + 1;
4145 size
+= lszs
[level
];
4146 lnames
[level
] = cp
; /* points into prop string */
4150 np
[npi
++] = lvals
[level
- 1];
4151 if (level
== 0) { /* ended with a name */
4152 PMD(PMD_ERROR
, ("%s: ewn\n", pmf
))
4159 * Now we have a list of components--we have to return instead an
4160 * array of them, but we can just copy the top level and leave
4163 (void) e_pm_create_components(dip
, components
);
4164 for (i
= 0; i
< components
; i
++)
4165 e_pm_set_max_power(dip
, i
, np
[i
]);
4167 ret
= kmem_zalloc(components
* sizeof (pm_comp_t
), KM_SLEEP
);
4168 for (i
= 0, p
= phead
; i
< components
; i
++) {
4171 * Now sanity-check values: levels must be monotonically
4174 if (p
->comp
->pmc_numlevels
< 2) {
4175 PMD(PMD_ERROR
, ("%s: comp %s of %s@%s(%s#%d) only %d "
4177 p
->comp
->pmc_name
, PM_DEVICE(dip
),
4178 p
->comp
->pmc_numlevels
))
4181 for (j
= 0; j
< p
->comp
->pmc_numlevels
; j
++) {
4182 if ((p
->comp
->pmc_lvals
[j
] < 0) || ((j
> 0) &&
4183 (p
->comp
->pmc_lvals
[j
] <=
4184 p
->comp
->pmc_lvals
[j
- 1]))) {
4185 PMD(PMD_ERROR
, ("%s: comp %s of %s@%s(%s#%d) "
4186 "not mono. incr, %d follows %d\n", pmf
,
4187 p
->comp
->pmc_name
, PM_DEVICE(dip
),
4188 p
->comp
->pmc_lvals
[j
],
4189 p
->comp
->pmc_lvals
[j
- 1]))
4193 ret
[i
] = *p
->comp
; /* struct assignment */
4194 for (j
= 0; j
< i
; j
++) {
4196 * Test for unique component names
4198 if (strcmp(ret
[j
].pmc_name
, ret
[i
].pmc_name
) == 0) {
4199 PMD(PMD_ERROR
, ("%s: %s of %s@%s(%s#%d) not "
4200 "unique\n", pmf
, ret
[j
].pmc_name
,
4207 phead
= p
; /* errout depends on phead making sense */
4208 kmem_free(ptail
->comp
, sizeof (*ptail
->comp
));
4209 kmem_free(ptail
, sizeof (*ptail
));
4214 kmem_free(lvals
, nelems
* sizeof (int));
4216 kmem_free(lszs
, nelems
* sizeof (int));
4218 kmem_free(lnames
, nelems
* sizeof (char *));
4220 kmem_free(np
, nelems
* sizeof (int));
4224 e_pm_destroy_components(dip
);
4225 *errp
= 1; /* signal failure */
4226 cmn_err(CE_CONT
, "!pm: %s property ", pmcompstr
);
4227 for (i
= 0; i
< nelems
- 1; i
++)
4228 cmn_err(CE_CONT
, "!'%s', ", pp
[i
]);
4230 cmn_err(CE_CONT
, "!'%s'", pp
[nelems
- 1]);
4231 cmn_err(CE_CONT
, "! for %s@%s(%s#%d) is ill-formed.\n", PM_DEVICE(dip
));
4232 for (p
= phead
; p
; ) {
4238 * Free component data structures
4241 n
= pp
->pmc_numlevels
;
4242 if (pp
->pmc_name_sz
) {
4243 kmem_free(pp
->pmc_name
, pp
->pmc_name_sz
);
4245 if (pp
->pmc_lnames_sz
) {
4246 kmem_free(pp
->pmc_lname_buf
, pp
->pmc_lnames_sz
);
4248 if (pp
->pmc_lnames
) {
4249 kmem_free(pp
->pmc_lnames
, n
* (sizeof (char *)));
4251 if (pp
->pmc_thresh
) {
4252 kmem_free(pp
->pmc_thresh
, n
* (sizeof (int)));
4254 if (pp
->pmc_lvals
) {
4255 kmem_free(pp
->pmc_lvals
, n
* (sizeof (int)));
4258 kmem_free(ptail
, sizeof (*ptail
));
4261 kmem_free(ret
, components
* sizeof (pm_comp_t
));
4267 * Set threshold values for a devices components by dividing the target
4268 * threshold (base) by the number of transitions and assign each transition
4269 * that threshold. This will get the entire device down in the target time if
4270 * all components are idle and even if there are dependencies among components.
4272 * Devices may well get powered all the way down before the target time, but
4273 * at least the EPA will be happy.
4276 pm_set_device_threshold(dev_info_t
*dip
, int base
, int flag
)
4278 PMD_FUNC(pmf
, "set_device_threshold")
4279 int target_threshold
= (base
* 95) / 100;
4280 int level
, comp
; /* loop counters */
4281 int transitions
= 0;
4282 int ncomp
= PM_NUMCMPTS(dip
);
4288 ASSERT(!PM_IAM_LOCKING_DIP(dip
));
4291 * First we handle the easy one. If we're setting the default
4292 * threshold for a node with children, then we set it to the
4293 * default nexus threshold (currently 0) and mark it as default
4294 * nexus threshold instead
4296 if (PM_IS_NEXUS(dip
)) {
4297 if (flag
== PMC_DEF_THRESH
) {
4298 PMD(PMD_THRESH
, ("%s: [%s@%s(%s#%d) NEXDEF]\n", pmf
,
4300 thresh
= pm_default_nexus_threshold
;
4301 for (comp
= 0; comp
< ncomp
; comp
++) {
4302 pmc
= &PM_CP(dip
, comp
)->pmc_comp
;
4303 for (level
= 1; level
< pmc
->pmc_numlevels
;
4305 pmc
->pmc_thresh
[level
] = thresh
;
4308 DEVI(dip
)->devi_pm_dev_thresh
=
4309 pm_default_nexus_threshold
;
4311 * If the nexus node is being reconfigured back to
4312 * the default threshold, adjust the notlowest count.
4314 if (DEVI(dip
)->devi_pm_flags
&
4315 (PMC_DEV_THRESH
|PMC_COMP_THRESH
)) {
4316 PM_LOCK_POWER(dip
, &circ
);
4317 for (i
= 0; i
< PM_NUMCMPTS(dip
); i
++) {
4318 if (PM_CURPOWER(dip
, i
) == 0)
4320 mutex_enter(&pm_compcnt_lock
);
4321 ASSERT(pm_comps_notlowest
);
4322 pm_comps_notlowest
--;
4323 PMD(PMD_LEVEL
, ("%s: %s@%s(%s#%d) decr "
4324 "notlowest to %d\n", pmf
,
4325 PM_DEVICE(dip
), pm_comps_notlowest
))
4326 if (pm_comps_notlowest
== 0)
4327 pm_ppm_notify_all_lowest(dip
,
4329 mutex_exit(&pm_compcnt_lock
);
4331 PM_UNLOCK_POWER(dip
, circ
);
4333 DEVI(dip
)->devi_pm_flags
&= PMC_THRESH_NONE
;
4334 DEVI(dip
)->devi_pm_flags
|= PMC_NEXDEF_THRESH
;
4337 } else if (DEVI(dip
)->devi_pm_flags
& PMC_NEXDEF_THRESH
) {
4339 * If the nexus node is being configured for a
4340 * non-default threshold, include that node in
4341 * the notlowest accounting.
4343 PM_LOCK_POWER(dip
, &circ
);
4344 for (i
= 0; i
< PM_NUMCMPTS(dip
); i
++) {
4345 if (PM_CURPOWER(dip
, i
) == 0)
4347 mutex_enter(&pm_compcnt_lock
);
4348 if (pm_comps_notlowest
== 0)
4349 pm_ppm_notify_all_lowest(dip
,
4351 pm_comps_notlowest
++;
4352 PMD(PMD_LEVEL
, ("%s: %s@%s(%s#%d) incr "
4353 "notlowest to %d\n", pmf
,
4354 PM_DEVICE(dip
), pm_comps_notlowest
))
4355 mutex_exit(&pm_compcnt_lock
);
4357 PM_UNLOCK_POWER(dip
, circ
);
4361 * Compute the total number of transitions for all components
4362 * of the device. Distribute the threshold evenly over them
4364 for (comp
= 0; comp
< ncomp
; comp
++) {
4365 pmc
= &PM_CP(dip
, comp
)->pmc_comp
;
4366 ASSERT(pmc
->pmc_numlevels
> 1);
4367 transitions
+= pmc
->pmc_numlevels
- 1;
4369 ASSERT(transitions
);
4370 thresh
= target_threshold
/ transitions
;
4372 for (comp
= 0; comp
< ncomp
; comp
++) {
4373 pmc
= &PM_CP(dip
, comp
)->pmc_comp
;
4374 for (level
= 1; level
< pmc
->pmc_numlevels
; level
++) {
4375 pmc
->pmc_thresh
[level
] = thresh
;
4380 for (comp
= 0; comp
< ncomp
; comp
++) {
4381 pmc
= &PM_CP(dip
, comp
)->pmc_comp
;
4382 for (level
= 1; level
< pmc
->pmc_numlevels
; level
++) {
4383 PMD(PMD_THRESH
, ("%s: thresh before %s@%s(%s#%d) "
4384 "comp=%d, level=%d, %d\n", pmf
, PM_DEVICE(dip
),
4385 comp
, level
, pmc
->pmc_thresh
[level
]))
4390 * Distribute any remainder till they are all gone
4392 remainder
= target_threshold
- thresh
* transitions
;
4395 PMD(PMD_THRESH
, ("%s: remainder=%d target_threshold=%d thresh=%d "
4396 "trans=%d\n", pmf
, remainder
, target_threshold
, thresh
,
4399 while (remainder
> 0) {
4401 while (remainder
&& (comp
< ncomp
)) {
4402 pmc
= &PM_CP(dip
, comp
)->pmc_comp
;
4403 if (level
< pmc
->pmc_numlevels
) {
4404 pmc
->pmc_thresh
[level
] += 1;
4412 for (comp
= 0; comp
< ncomp
; comp
++) {
4413 pmc
= &PM_CP(dip
, comp
)->pmc_comp
;
4414 for (level
= 1; level
< pmc
->pmc_numlevels
; level
++) {
4415 PMD(PMD_THRESH
, ("%s: thresh after %s@%s(%s#%d) "
4416 "comp=%d level=%d, %d\n", pmf
, PM_DEVICE(dip
),
4417 comp
, level
, pmc
->pmc_thresh
[level
]))
4421 ASSERT(PM_IAM_LOCKING_DIP(dip
));
4422 DEVI(dip
)->devi_pm_dev_thresh
= base
;
4423 DEVI(dip
)->devi_pm_flags
&= PMC_THRESH_NONE
;
4424 DEVI(dip
)->devi_pm_flags
|= flag
;
4429 * Called when there is no old-style platform power management driver
4432 ddi_no_platform_power(power_req_t
*req
)
4434 _NOTE(ARGUNUSED(req
))
4435 return (DDI_FAILURE
);
4439 * This function calls the entry point supplied by the platform-specific
4440 * pm driver to bring the device component 'pm_cmpt' to power level 'pm_level'.
4441 * The use of global for getting the function name from platform-specific
4442 * pm driver is not ideal, but it is simple and efficient.
4443 * The previous property lookup was being done in the idle loop on swift
4444 * systems without pmc chips and hurt deskbench performance as well as
4445 * violating scheduler locking rules
4447 int (*pm_platform_power
)(power_req_t
*) = ddi_no_platform_power
;
4450 * Old obsolete interface for a device to request a power change (but only
4451 * an increase in power)
4454 ddi_dev_is_needed(dev_info_t
*dip
, int cmpt
, int level
)
4456 return (pm_raise_power(dip
, cmpt
, level
));
4460 * The old obsolete interface to platform power management. Only used by
4461 * Gypsy platform and APM on X86.
4464 ddi_power(dev_info_t
*dip
, int pm_cmpt
, int pm_level
)
4466 power_req_t request
;
4468 request
.request_type
= PMR_SET_POWER
;
4469 request
.req
.set_power_req
.who
= dip
;
4470 request
.req
.set_power_req
.cmpt
= pm_cmpt
;
4471 request
.req
.set_power_req
.level
= pm_level
;
4472 return (ddi_ctlops(dip
, dip
, DDI_CTLOPS_POWER
, &request
, NULL
));
4476 * A driver can invoke this from its detach routine when DDI_SUSPEND is
4477 * passed. Returns true if subsequent processing could result in power being
4478 * removed from the device. The arg is not currently used because it is
4479 * implicit in the operation of cpr/DR.
4482 ddi_removing_power(dev_info_t
*dip
)
4484 _NOTE(ARGUNUSED(dip
))
4485 return (pm_powering_down
);
4489 * Returns true if a device indicates that its parent handles suspend/resume
4490 * processing for it.
4493 e_ddi_parental_suspend_resume(dev_info_t
*dip
)
4495 return (DEVI(dip
)->devi_pm_flags
& PMC_PARENTAL_SR
);
4499 * Called for devices which indicate that their parent does suspend/resume
4503 e_ddi_suspend(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
4505 power_req_t request
;
4506 request
.request_type
= PMR_SUSPEND
;
4507 request
.req
.suspend_req
.who
= dip
;
4508 request
.req
.suspend_req
.cmd
= cmd
;
4509 return (ddi_ctlops(dip
, dip
, DDI_CTLOPS_POWER
, &request
, NULL
));
4513 * Called for devices which indicate that their parent does suspend/resume
4517 e_ddi_resume(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
4519 power_req_t request
;
4520 request
.request_type
= PMR_RESUME
;
4521 request
.req
.resume_req
.who
= dip
;
4522 request
.req
.resume_req
.cmd
= cmd
;
4523 return (ddi_ctlops(dip
, dip
, DDI_CTLOPS_POWER
, &request
, NULL
));
4527 * Old obsolete exported interface for drivers to create components.
4528 * This is now handled by exporting the pm-components property.
4531 pm_create_components(dev_info_t
*dip
, int num_components
)
4533 PMD_FUNC(pmf
, "pm_create_components")
4535 if (num_components
< 1)
4536 return (DDI_FAILURE
);
4538 if (!DEVI_IS_ATTACHING(dip
)) {
4539 return (DDI_FAILURE
);
4542 /* don't need to lock dip because attach is single threaded */
4543 if (DEVI(dip
)->devi_pm_components
) {
4544 PMD(PMD_ERROR
, ("%s: %s@%s(%s#%d) already has %d\n", pmf
,
4545 PM_DEVICE(dip
), PM_NUMCMPTS(dip
)))
4546 return (DDI_FAILURE
);
4548 e_pm_create_components(dip
, num_components
);
4549 DEVI(dip
)->devi_pm_flags
|= PMC_BC
;
4550 e_pm_default_components(dip
, num_components
);
4551 return (DDI_SUCCESS
);
4555 * Obsolete interface previously called by drivers to destroy their components
4556 * at detach time. This is now done automatically. However, we need to keep
4557 * this for the old drivers.
4560 pm_destroy_components(dev_info_t
*dip
)
4562 PMD_FUNC(pmf
, "pm_destroy_components")
4563 dev_info_t
*pdip
= ddi_get_parent(dip
);
4565 PMD(PMD_REMDEV
| PMD_KIDSUP
, ("%s: %s@%s(%s#%d)\n", pmf
,
4567 ASSERT(DEVI_IS_DETACHING(dip
));
4570 cmn_err(CE_WARN
, "!driver exporting pm-components property "
4571 "(%s@%s) calls pm_destroy_components", PM_NAME(dip
),
4575 * We ignore this unless this is an old-style driver, except for
4576 * printing the message above
4578 if (PM_NUMCMPTS(dip
) == 0 || !PM_ISBC(dip
)) {
4579 PMD(PMD_REMDEV
, ("%s: ignore %s@%s(%s#%d)\n", pmf
,
4583 ASSERT(PM_GET_PM_INFO(dip
));
4586 * pm_unmanage will clear info pointer later, after dealing with
4589 ASSERT(!PM_GET_PM_SCAN(dip
)); /* better be gone already */
4591 * Now adjust parent's kidsupcnt. We check only comp 0.
4592 * Parents that get notification are not adjusted because their
4593 * kidsupcnt is always 0 (or 1 during probe and attach).
4595 if ((PM_CURPOWER(dip
, 0) != 0) && pdip
&& !PM_WANTS_NOTIFICATION(pdip
))
4596 pm_rele_power(pdip
);
4599 PMD(PMD_KIDSUP
, ("%s: kuc stays %s@%s(%s#%d) comps gone\n",
4600 pmf
, PM_DEVICE(dip
)))
4603 e_pm_destroy_components(dip
);
4605 * Forget we ever knew anything about the components of this device
4607 DEVI(dip
)->devi_pm_flags
&=
4608 ~(PMC_BC
| PMC_COMPONENTS_DONE
| PMC_COMPONENTS_FAILED
);
4612 * Exported interface for a driver to set a component busy.
4615 pm_busy_component(dev_info_t
*dip
, int cmpt
)
4617 struct pm_component
*cp
;
4619 ASSERT(dip
!= NULL
);
4620 if (!e_pm_valid_info(dip
, NULL
) || !e_pm_valid_comp(dip
, cmpt
, &cp
))
4621 return (DDI_FAILURE
);
4623 cp
->pmc_busycount
++;
4624 cp
->pmc_timestamp
= 0;
4625 PM_UNLOCK_BUSY(dip
);
4626 return (DDI_SUCCESS
);
4630 * Exported interface for a driver to set a component idle.
4633 pm_idle_component(dev_info_t
*dip
, int cmpt
)
4635 PMD_FUNC(pmf
, "pm_idle_component")
4636 struct pm_component
*cp
;
4637 pm_scan_t
*scanp
= PM_GET_PM_SCAN(dip
);
4639 if (!e_pm_valid_info(dip
, NULL
) || !e_pm_valid_comp(dip
, cmpt
, &cp
))
4640 return (DDI_FAILURE
);
4643 if (cp
->pmc_busycount
) {
4644 if (--(cp
->pmc_busycount
) == 0)
4645 cp
->pmc_timestamp
= gethrestime_sec();
4647 cp
->pmc_timestamp
= gethrestime_sec();
4650 PM_UNLOCK_BUSY(dip
);
4653 * if device becomes idle during idle down period, try scan it down
4655 if (scanp
&& PM_IS_PID(dip
)) {
4656 PMD(PMD_IDLEDOWN
, ("%s: %s@%s(%s#%d) idle.\n", pmf
,
4659 return (DDI_SUCCESS
);
4663 * handle scan not running with nexus threshold == 0
4666 if (PM_IS_NEXUS(dip
) && (cp
->pmc_busycount
== 0)) {
4670 return (DDI_SUCCESS
);
4674 * This is the old obsolete interface called by drivers to set their normal
4675 * power. Thus we can't fix its behavior or return a value.
4676 * This functionality is replaced by the pm-component property.
4677 * We'll only get components destroyed while no power management is
4678 * going on (and the device is detached), so we don't need a mutex here
4681 pm_set_normal_power(dev_info_t
*dip
, int comp
, int level
)
4683 PMD_FUNC(pmf
, "set_normal_power")
4686 cmn_err(CE_WARN
, "!call to pm_set_normal_power() by %s@%s "
4687 "(driver exporting pm-components property) ignored",
4688 PM_NAME(dip
), PM_ADDR(dip
));
4691 PMD(PMD_NORM
, ("%s: %s@%s(%s#%d) set normal power comp=%d, "
4692 "level=%d\n", pmf
, PM_DEVICE(dip
), comp
, level
))
4693 e_pm_set_max_power(dip
, comp
, level
);
4694 e_pm_default_levels(dip
, PM_CP(dip
, comp
), level
);
4699 * Called on a successfully detached driver to free pm resources
4702 pm_stop(dev_info_t
*dip
)
4704 PMD_FUNC(pmf
, "stop")
4705 dev_info_t
*pdip
= ddi_get_parent(dip
);
4707 ASSERT(!PM_IAM_LOCKING_DIP(dip
));
4708 /* stopping scan, destroy scan data structure */
4709 if (!PM_ISBC(dip
)) {
4714 if (PM_GET_PM_INFO(dip
) != NULL
) {
4715 if (pm_unmanage(dip
) == DDI_SUCCESS
) {
4717 * Old style driver may have called
4718 * pm_destroy_components already, but just in case ...
4720 e_pm_destroy_components(dip
);
4722 PMD(PMD_FAIL
, ("%s: can't pm_unmanage %s@%s(%s#%d)\n",
4723 pmf
, PM_DEVICE(dip
)))
4726 if (PM_NUMCMPTS(dip
))
4727 e_pm_destroy_components(dip
);
4729 if (DEVI(dip
)->devi_pm_flags
& PMC_NOPMKID
) {
4730 DEVI(dip
)->devi_pm_flags
&= ~PMC_NOPMKID
;
4731 if (pdip
&& !PM_WANTS_NOTIFICATION(pdip
)) {
4732 pm_rele_power(pdip
);
4734 MDI_VHCI(pdip
) && MDI_CLIENT(dip
)) {
4735 (void) mdi_power(pdip
,
4737 (void *)dip
, NULL
, 0);
4745 * The node is the subject of a reparse pm props ioctl. Throw away the old
4746 * info and start over.
4749 e_new_pm_props(dev_info_t
*dip
)
4751 if (PM_GET_PM_INFO(dip
) != NULL
) {
4754 if (e_pm_manage(dip
, PM_STYLE_NEW
) != DDI_SUCCESS
) {
4755 return (DDI_FAILURE
);
4759 return (DDI_SUCCESS
);
4763 * Device has been attached, so process its pm properties
4766 e_pm_props(dev_info_t
*dip
)
4771 int propflag
= DDI_PROP_DONTPASS
|DDI_PROP_CANSLEEP
;
4774 * It doesn't matter if we do this more than once, we should always
4775 * get the same answers, and if not, then the last one in is the
4778 if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
, propflag
, "pm-hardware-state",
4779 (caddr_t
)&pp
, &len
) == DDI_PROP_SUCCESS
) {
4780 if (strcmp(pp
, "needs-suspend-resume") == 0) {
4781 flags
= PMC_NEEDS_SR
;
4782 } else if (strcmp(pp
, "no-suspend-resume") == 0) {
4784 } else if (strcmp(pp
, "parental-suspend-resume") == 0) {
4785 flags
= PMC_PARENTAL_SR
;
4787 cmn_err(CE_NOTE
, "!device %s@%s has unrecognized "
4788 "%s property value '%s'", PM_NAME(dip
),
4789 PM_ADDR(dip
), "pm-hardware-state", pp
);
4794 * This next segment (PMC_WANTS_NOTIFY) is in
4795 * support of nexus drivers which will want to be involved in
4796 * (or at least notified of) their child node's power level transitions.
4797 * "pm-want-child-notification?" is defined by the parent.
4799 if (ddi_prop_exists(DDI_DEV_T_ANY
, dip
, propflag
,
4800 "pm-want-child-notification?") && PM_HAS_BUS_POWER(dip
))
4801 flags
|= PMC_WANTS_NOTIFY
;
4802 ASSERT(PM_HAS_BUS_POWER(dip
) || !ddi_prop_exists(DDI_DEV_T_ANY
,
4803 dip
, propflag
, "pm-want-child-notification?"));
4804 if (ddi_prop_exists(DDI_DEV_T_ANY
, dip
, propflag
,
4805 "no-involuntary-power-cycles"))
4806 flags
|= PMC_NO_INVOL
;
4808 * Is the device a CPU device?
4810 if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
, propflag
, "pm-class",
4811 (caddr_t
)&pp
, &len
) == DDI_PROP_SUCCESS
) {
4812 if (strcmp(pp
, "CPU") == 0) {
4813 flags
|= PMC_CPU_DEVICE
;
4815 cmn_err(CE_NOTE
, "!device %s@%s has unrecognized "
4816 "%s property value '%s'", PM_NAME(dip
),
4817 PM_ADDR(dip
), "pm-class", pp
);
4821 /* devfs single threads us */
4822 DEVI(dip
)->devi_pm_flags
|= flags
;
4826 * This is the DDI_CTLOPS_POWER handler that is used when there is no ppm
4827 * driver which has claimed a node.
4828 * Sets old_power in arg struct.
4831 pm_default_ctlops(dev_info_t
*dip
, dev_info_t
*rdip
,
4832 ddi_ctl_enum_t ctlop
, void *arg
, void *result
)
4834 _NOTE(ARGUNUSED(dip
))
4835 PMD_FUNC(pmf
, "ctlops")
4836 power_req_t
*reqp
= (power_req_t
*)arg
;
4838 dev_info_t
*target_dip
;
4839 int new_level
, old_level
, cmpt
;
4845 * The interface for doing the actual power level changes is now
4846 * through the DDI_CTLOPS_POWER bus_ctl, so that we can plug in
4847 * different platform-specific power control drivers.
4849 * This driver implements the "default" version of this interface.
4850 * If no ppm driver has been installed then this interface is called
4853 ASSERT(dip
== NULL
);
4855 case DDI_CTLOPS_POWER
:
4856 switch (reqp
->request_type
) {
4857 case PMR_PPM_SET_POWER
:
4859 target_dip
= reqp
->req
.ppm_set_power_req
.who
;
4860 ASSERT(target_dip
== rdip
);
4861 new_level
= reqp
->req
.ppm_set_power_req
.new_level
;
4862 cmpt
= reqp
->req
.ppm_set_power_req
.cmpt
;
4863 /* pass back old power for the PM_LEVEL_UNKNOWN case */
4864 old_level
= PM_CURPOWER(target_dip
, cmpt
);
4865 reqp
->req
.ppm_set_power_req
.old_level
= old_level
;
4866 retval
= pm_power(target_dip
, cmpt
, new_level
);
4867 PMD(PMD_PPM
, ("%s: PPM_SET_POWER %s@%s(%s#%d)[%d] %d->"
4868 "%d %s\n", pmf
, PM_DEVICE(target_dip
), cmpt
,
4869 old_level
, new_level
, (retval
== DDI_SUCCESS
?
4874 case PMR_PPM_PRE_DETACH
:
4875 case PMR_PPM_POST_DETACH
:
4876 case PMR_PPM_PRE_ATTACH
:
4877 case PMR_PPM_POST_ATTACH
:
4878 case PMR_PPM_PRE_PROBE
:
4879 case PMR_PPM_POST_PROBE
:
4880 case PMR_PPM_PRE_RESUME
:
4881 case PMR_PPM_INIT_CHILD
:
4882 case PMR_PPM_UNINIT_CHILD
:
4884 switch (reqp
->request_type
) {
4885 case PMR_PPM_PRE_DETACH
:
4886 format
= "%s: PMR_PPM_PRE_DETACH "
4889 case PMR_PPM_POST_DETACH
:
4890 format
= "%s: PMR_PPM_POST_DETACH "
4891 "%s@%s(%s#%d) rets %d\n";
4893 case PMR_PPM_PRE_ATTACH
:
4894 format
= "%s: PMR_PPM_PRE_ATTACH "
4897 case PMR_PPM_POST_ATTACH
:
4898 format
= "%s: PMR_PPM_POST_ATTACH "
4899 "%s@%s(%s#%d) rets %d\n";
4901 case PMR_PPM_PRE_PROBE
:
4902 format
= "%s: PMR_PPM_PRE_PROBE "
4905 case PMR_PPM_POST_PROBE
:
4906 format
= "%s: PMR_PPM_POST_PROBE "
4907 "%s@%s(%s#%d) rets %d\n";
4909 case PMR_PPM_PRE_RESUME
:
4910 format
= "%s: PMR_PPM_PRE_RESUME "
4911 "%s@%s(%s#%d) rets %d\n";
4913 case PMR_PPM_INIT_CHILD
:
4914 format
= "%s: PMR_PPM_INIT_CHILD "
4917 case PMR_PPM_UNINIT_CHILD
:
4918 format
= "%s: PMR_PPM_UNINIT_CHILD "
4924 PMD(PMD_PPM
, (format
, pmf
, PM_DEVICE(rdip
),
4925 reqp
->req
.ppm_config_req
.result
))
4927 return (DDI_SUCCESS
);
4929 case PMR_PPM_POWER_CHANGE_NOTIFY
:
4931 * Nothing for us to do
4933 ASSERT(reqp
->req
.ppm_notify_level_req
.who
== rdip
);
4934 PMD(PMD_PPM
, ("%s: PMR_PPM_POWER_CHANGE_NOTIFY "
4935 "%s@%s(%s#%d)[%d] %d->%d\n", pmf
,
4936 PM_DEVICE(reqp
->req
.ppm_notify_level_req
.who
),
4937 reqp
->req
.ppm_notify_level_req
.cmpt
,
4938 PM_CURPOWER(reqp
->req
.ppm_notify_level_req
.who
,
4939 reqp
->req
.ppm_notify_level_req
.cmpt
),
4940 reqp
->req
.ppm_notify_level_req
.new_level
))
4941 return (DDI_SUCCESS
);
4943 case PMR_PPM_UNMANAGE
:
4944 PMD(PMD_PPM
, ("%s: PMR_PPM_UNMANAGE %s@%s(%s#%d)\n",
4945 pmf
, PM_DEVICE(rdip
)))
4946 return (DDI_SUCCESS
);
4948 case PMR_PPM_LOCK_POWER
:
4949 pm_lock_power_single(reqp
->req
.ppm_lock_power_req
.who
,
4950 reqp
->req
.ppm_lock_power_req
.circp
);
4951 return (DDI_SUCCESS
);
4953 case PMR_PPM_UNLOCK_POWER
:
4954 pm_unlock_power_single(
4955 reqp
->req
.ppm_unlock_power_req
.who
,
4956 reqp
->req
.ppm_unlock_power_req
.circ
);
4957 return (DDI_SUCCESS
);
4959 case PMR_PPM_TRY_LOCK_POWER
:
4960 *(int *)result
= pm_try_locking_power_single(
4961 reqp
->req
.ppm_lock_power_req
.who
,
4962 reqp
->req
.ppm_lock_power_req
.circp
);
4963 return (DDI_SUCCESS
);
4965 case PMR_PPM_POWER_LOCK_OWNER
:
4966 target_dip
= reqp
->req
.ppm_power_lock_owner_req
.who
;
4967 ASSERT(target_dip
== rdip
);
4968 reqp
->req
.ppm_power_lock_owner_req
.owner
=
4969 DEVI(rdip
)->devi_busy_thread
;
4970 return (DDI_SUCCESS
);
4972 PMD(PMD_ERROR
, ("%s: default!\n", pmf
))
4973 return (DDI_FAILURE
);
4977 PMD(PMD_ERROR
, ("%s: unknown\n", pmf
))
4978 return (DDI_FAILURE
);
4983 * We overload the bus_ctl ops here--perhaps we ought to have a distinct
4984 * power_ops struct for this functionality instead?
4985 * However, we only ever do this on a ppm driver.
4988 pm_ctlops(dev_info_t
*d
, dev_info_t
*r
, ddi_ctl_enum_t op
, void *a
, void *v
)
4992 /* if no ppm handler, call the default routine */
4994 return (pm_default_ctlops(d
, r
, op
, a
, v
));
4997 return (DDI_FAILURE
);
4998 ASSERT(DEVI(d
)->devi_ops
&& DEVI(d
)->devi_ops
->devo_bus_ops
&&
4999 DEVI(d
)->devi_ops
->devo_bus_ops
->bus_ctl
);
5001 fp
= DEVI(d
)->devi_ops
->devo_bus_ops
->bus_ctl
;
5002 return ((*fp
)(d
, r
, op
, a
, v
));
5006 * Called on a node when attach completes or the driver makes its first pm
5007 * call (whichever comes first).
5008 * In the attach case, device may not be power manageable at all.
5009 * Don't need to lock the dip because we're single threaded by the devfs code
5012 pm_start(dev_info_t
*dip
)
5014 PMD_FUNC(pmf
, "start")
5016 dev_info_t
*pdip
= ddi_get_parent(dip
);
5017 int e_pm_manage(dev_info_t
*, int);
5018 void pm_noinvol_specd(dev_info_t
*dip
);
5021 pm_noinvol_specd(dip
);
5023 * If this dip has already been processed, don't mess with it
5024 * (but decrement the speculative count we did above, as whatever
5025 * code put it under pm already will have dealt with it)
5027 if (PM_GET_PM_INFO(dip
)) {
5028 PMD(PMD_KIDSUP
, ("%s: pm already done for %s@%s(%s#%d)\n",
5029 pmf
, PM_DEVICE(dip
)))
5032 ret
= e_pm_manage(dip
, PM_STYLE_UNKNOWN
);
5034 if (PM_GET_PM_INFO(dip
) == NULL
) {
5036 * keep the kidsupcount increment as is
5038 DEVI(dip
)->devi_pm_flags
|= PMC_NOPMKID
;
5039 if (pdip
&& !PM_WANTS_NOTIFICATION(pdip
)) {
5040 pm_hold_power(pdip
);
5041 } else if (pdip
&& MDI_VHCI(pdip
) && MDI_CLIENT(dip
)) {
5042 (void) mdi_power(pdip
, MDI_PM_HOLD_POWER
,
5043 (void *)dip
, NULL
, 0);
5046 PMD(PMD_KIDSUP
, ("%s: pm of %s@%s(%s#%d) failed, parent "
5047 "left up\n", pmf
, PM_DEVICE(dip
)))
5054 * Keep a list of recorded thresholds. For now we just keep a list and
5055 * search it linearly. We don't expect too many entries. Can always hash it
5056 * later if we need to.
5059 pm_record_thresh(pm_thresh_rec_t
*rp
)
5061 pm_thresh_rec_t
*pptr
, *ptr
;
5063 ASSERT(*rp
->ptr_physpath
);
5064 rw_enter(&pm_thresh_rwlock
, RW_WRITER
);
5065 for (pptr
= NULL
, ptr
= pm_thresh_head
;
5066 ptr
; pptr
= ptr
, ptr
= ptr
->ptr_next
) {
5067 if (strcmp(rp
->ptr_physpath
, ptr
->ptr_physpath
) == 0) {
5068 /* replace this one */
5069 rp
->ptr_next
= ptr
->ptr_next
;
5071 pptr
->ptr_next
= rp
;
5073 pm_thresh_head
= rp
;
5075 rw_exit(&pm_thresh_rwlock
);
5076 kmem_free(ptr
, ptr
->ptr_size
);
5082 * There was not a match in the list, insert this one in front
5084 if (pm_thresh_head
) {
5085 rp
->ptr_next
= pm_thresh_head
;
5086 pm_thresh_head
= rp
;
5088 rp
->ptr_next
= NULL
;
5089 pm_thresh_head
= rp
;
5091 rw_exit(&pm_thresh_rwlock
);
5095 * Create a new dependency record and hang a new dependency entry off of it
5098 newpdr(char *kept
, char *keeps
, int isprop
)
5100 size_t size
= strlen(kept
) + strlen(keeps
) + 2 + sizeof (pm_pdr_t
);
5101 pm_pdr_t
*p
= kmem_zalloc(size
, KM_SLEEP
);
5103 p
->pdr_isprop
= isprop
;
5104 p
->pdr_kept_paths
= NULL
;
5105 p
->pdr_kept_count
= 0;
5106 p
->pdr_kept
= (char *)((intptr_t)p
+ sizeof (pm_pdr_t
));
5107 (void) strcpy(p
->pdr_kept
, kept
);
5108 p
->pdr_keeper
= (char *)((intptr_t)p
->pdr_kept
+ strlen(kept
) + 1);
5109 (void) strcpy(p
->pdr_keeper
, keeps
);
5110 ASSERT((intptr_t)p
->pdr_keeper
+ strlen(p
->pdr_keeper
) + 1 <=
5111 (intptr_t)p
+ size
);
5112 ASSERT((intptr_t)p
->pdr_kept
+ strlen(p
->pdr_kept
) + 1 <=
5113 (intptr_t)p
+ size
);
5118 * Keep a list of recorded dependencies. We only keep the
5119 * keeper -> kept list for simplification. At this point We do not
5120 * care about whether the devices are attached or not yet,
5121 * this would be done in pm_keeper() and pm_kept().
5122 * If a PM_RESET_PM happens, then we tear down and forget the dependencies,
5123 * and it is up to the user to issue the ioctl again if they want it
5125 * Returns true if dependency already exists in the list.
5128 pm_record_keeper(char *kept
, char *keeper
, int isprop
)
5130 PMD_FUNC(pmf
, "record_keeper")
5131 pm_pdr_t
*npdr
, *ppdr
, *pdr
;
5133 PMD(PMD_KEEPS
, ("%s: %s, %s\n", pmf
, kept
, keeper
))
5134 ASSERT(kept
&& keeper
);
5136 if (pm_debug
& PMD_KEEPS
)
5137 prdeps("pm_record_keeper entry");
5139 for (ppdr
= NULL
, pdr
= pm_dep_head
; pdr
;
5140 ppdr
= pdr
, pdr
= pdr
->pdr_next
) {
5141 PMD(PMD_KEEPS
, ("%s: check %s, %s\n", pmf
, pdr
->pdr_kept
,
5143 if (strcmp(kept
, pdr
->pdr_kept
) == 0 &&
5144 strcmp(keeper
, pdr
->pdr_keeper
) == 0) {
5145 PMD(PMD_KEEPS
, ("%s: match\n", pmf
))
5150 * We did not find any match, so we have to make an entry
5152 npdr
= newpdr(kept
, keeper
, isprop
);
5154 ASSERT(ppdr
->pdr_next
== NULL
);
5155 ppdr
->pdr_next
= npdr
;
5157 ASSERT(pm_dep_head
== NULL
);
5161 if (pm_debug
& PMD_KEEPS
)
5162 prdeps("pm_record_keeper after new record");
5165 pm_unresolved_deps
++;
5172 * Look up this device in the set of devices we've seen ioctls for
5173 * to see if we are holding a threshold spec for it. If so, make it so.
5174 * At ioctl time, we were given the physical path of the device.
5177 pm_thresh_specd(dev_info_t
*dip
)
5179 void pm_apply_recorded_thresh(dev_info_t
*, pm_thresh_rec_t
*);
5181 char pathbuf
[MAXNAMELEN
];
5182 pm_thresh_rec_t
*rp
;
5184 path
= ddi_pathname(dip
, pathbuf
);
5186 rw_enter(&pm_thresh_rwlock
, RW_READER
);
5187 for (rp
= pm_thresh_head
; rp
; rp
= rp
->ptr_next
) {
5188 if (strcmp(rp
->ptr_physpath
, path
) != 0)
5190 pm_apply_recorded_thresh(dip
, rp
);
5191 rw_exit(&pm_thresh_rwlock
);
5194 rw_exit(&pm_thresh_rwlock
);
5199 pm_set_keeping(dev_info_t
*keeper
, dev_info_t
*kept
)
5201 PMD_FUNC(pmf
, "set_keeping")
5202 int j
, up
= 0, circ
;
5203 void prdeps(char *);
5205 PMD(PMD_KEEPS
, ("%s: keeper=%s@%s(%s#%d), kept=%s@%s(%s#%d)\n", pmf
,
5206 PM_DEVICE(keeper
), PM_DEVICE(kept
)))
5208 if (pm_debug
& PMD_KEEPS
)
5209 prdeps("Before PAD\n");
5211 ASSERT(keeper
!= kept
);
5212 if (PM_GET_PM_INFO(keeper
) == NULL
) {
5213 cmn_err(CE_CONT
, "!device %s@%s(%s#%d) keeps up device "
5214 "%s@%s(%s#%d), but the former is not power managed",
5215 PM_DEVICE(keeper
), PM_DEVICE(kept
));
5216 PMD((PMD_FAIL
| PMD_KEEPS
), ("%s: keeper %s@%s(%s#%d) is not"
5217 "power managed\n", pmf
, PM_DEVICE(keeper
)))
5220 if (PM_GET_PM_INFO(kept
) == NULL
) {
5221 cmn_err(CE_CONT
, "!device %s@%s(%s#%d) keeps up device "
5222 "%s@%s(%s#%d), but the latter is not power managed",
5223 PM_DEVICE(keeper
), PM_DEVICE(kept
));
5224 PMD((PMD_FAIL
| PMD_KEEPS
), ("%s: kept %s@%s(%s#%d) is not"
5225 "power managed\n", pmf
, PM_DEVICE(kept
)))
5229 PM_LOCK_POWER(keeper
, &circ
);
5230 for (j
= 0; j
< PM_NUMCMPTS(keeper
); j
++) {
5231 if (PM_CURPOWER(keeper
, j
)) {
5237 /* Bringup and maintain a hold on the kept */
5238 PMD(PMD_KEEPS
, ("%s: place a hold on kept %s@%s(%s#%d)\n", pmf
,
5240 bring_pmdep_up(kept
, 1);
5242 PM_UNLOCK_POWER(keeper
, circ
);
5244 if (pm_debug
& PMD_KEEPS
)
5245 prdeps("After PAD\n");
5251 * Should this device keep up another device?
5252 * Look up this device in the set of devices we've seen ioctls for
5253 * to see if we are holding a dependency spec for it. If so, make it so.
5254 * Because we require the kept device to be attached already in order to
5255 * make the list entry (and hold it), we only need to look for keepers.
5256 * At ioctl time, we were given the physical path of the device.
5259 pm_keeper(char *keeper
)
5261 PMD_FUNC(pmf
, "keeper")
5262 int pm_apply_recorded_dep(dev_info_t
*, pm_pdr_t
*);
5265 dev_info_t
*kept
= NULL
;
5269 if (!pm_unresolved_deps
&& !pm_prop_deps
)
5271 ASSERT(keeper
!= NULL
);
5272 dip
= pm_name_to_dip(keeper
, 1);
5275 PMD(PMD_KEEPS
, ("%s: keeper=%s\n", pmf
, keeper
))
5276 for (dp
= pm_dep_head
; dp
; dp
= dp
->pdr_next
) {
5277 if (!dp
->pdr_isprop
) {
5278 if (!pm_unresolved_deps
)
5280 PMD(PMD_KEEPS
, ("%s: keeper %s\n", pmf
, dp
->pdr_keeper
))
5281 if (dp
->pdr_satisfied
) {
5282 PMD(PMD_KEEPS
, ("%s: satisfied\n", pmf
))
5285 if (strcmp(dp
->pdr_keeper
, keeper
) == 0) {
5286 ret
+= pm_apply_recorded_dep(dip
, dp
);
5289 if (strcmp(dp
->pdr_keeper
, keeper
) != 0)
5291 for (i
= 0; i
< dp
->pdr_kept_count
; i
++) {
5292 if (dp
->pdr_kept_paths
[i
] == NULL
)
5294 kept
= pm_name_to_dip(dp
->pdr_kept_paths
[i
], 1);
5297 ASSERT(ddi_prop_exists(DDI_DEV_T_ANY
, kept
,
5298 DDI_PROP_DONTPASS
, dp
->pdr_kept
));
5299 PMD(PMD_KEEPS
, ("%s: keeper=%s@%s(%s#%d), "
5300 "kept=%s@%s(%s#%d) keptcnt=%d\n",
5301 pmf
, PM_DEVICE(dip
), PM_DEVICE(kept
),
5302 dp
->pdr_kept_count
))
5304 ret
+= pm_set_keeping(dip
, kept
);
5306 ddi_release_devi(kept
);
5311 ddi_release_devi(dip
);
5316 * Should this device be kept up by another device?
5317 * Look up all dependency recorded from PM_ADD_DEPENDENT and
5318 * PM_ADD_DEPENDENT_PROPERTY ioctls. Record down on the keeper's
5319 * kept device lists.
5322 pm_kept(char *keptp
)
5324 PMD_FUNC(pmf
, "kept")
5335 ASSERT(keptp
!= NULL
);
5336 kept
= pm_name_to_dip(keptp
, 1);
5339 PMD(PMD_KEEPS
, ("%s: %s@%s(%s#%d)\n", pmf
, PM_DEVICE(kept
)))
5340 for (dp
= pm_dep_head
; dp
; dp
= dp
->pdr_next
) {
5341 if (dp
->pdr_isprop
) {
5342 PMD(PMD_KEEPS
, ("%s: property %s\n", pmf
, dp
->pdr_kept
))
5343 if (ddi_prop_exists(DDI_DEV_T_ANY
, kept
,
5344 DDI_PROP_DONTPASS
, dp
->pdr_kept
)) {
5346 * Dont allow self dependency.
5348 if (strcmp(dp
->pdr_keeper
, keptp
) == 0)
5350 keeper
= pm_name_to_dip(dp
->pdr_keeper
, 1);
5353 PMD(PMD_KEEPS
, ("%s: adding to kepts path list "
5354 "%p\n", pmf
, (void *)kept
))
5356 if (pm_debug
& PMD_DEP
)
5357 prdeps("Before Adding from pm_kept\n");
5360 * Add ourselves to the dip list.
5362 if (dp
->pdr_kept_count
== 0) {
5363 length
= strlen(keptp
) + 1;
5365 kmem_alloc(length
, KM_SLEEP
);
5366 paths
= kmem_alloc(sizeof (char **),
5368 (void) strcpy(path
, keptp
);
5370 dp
->pdr_kept_paths
= paths
;
5371 dp
->pdr_kept_count
++;
5373 /* Check to see if already on list */
5374 for (i
= 0; i
< dp
->pdr_kept_count
;
5377 dp
->pdr_kept_paths
[i
])
5384 ddi_release_devi(keeper
);
5387 length
= dp
->pdr_kept_count
*
5390 length
+ sizeof (char **),
5392 if (dp
->pdr_kept_count
) {
5393 bcopy(dp
->pdr_kept_paths
,
5395 kmem_free(dp
->pdr_kept_paths
,
5398 dp
->pdr_kept_paths
= paths
;
5399 length
= strlen(keptp
) + 1;
5401 kmem_alloc(length
, KM_SLEEP
);
5402 (void) strcpy(path
, keptp
);
5403 dp
->pdr_kept_paths
[i
] = path
;
5404 dp
->pdr_kept_count
++;
5407 if (pm_debug
& PMD_DEP
)
5408 prdeps("After from pm_kept\n");
5411 ret
+= pm_set_keeping(keeper
, kept
);
5412 ddi_release_devi(keeper
);
5417 * pm_keeper would be called later to do
5418 * the actual pm_set_keeping.
5420 PMD(PMD_KEEPS
, ("%s: adding to kepts path list %p\n",
5423 if (pm_debug
& PMD_DEP
)
5424 prdeps("Before Adding from pm_kept\n");
5426 if (strcmp(keptp
, dp
->pdr_kept
) == 0) {
5427 if (dp
->pdr_kept_paths
== NULL
) {
5428 length
= strlen(keptp
) + 1;
5430 kmem_alloc(length
, KM_SLEEP
);
5431 paths
= kmem_alloc(sizeof (char **),
5433 (void) strcpy(path
, keptp
);
5435 dp
->pdr_kept_paths
= paths
;
5436 dp
->pdr_kept_count
++;
5440 if (pm_debug
& PMD_DEP
)
5441 prdeps("After from pm_kept\n");
5445 ddi_release_devi(kept
);
5450 * Apply a recorded dependency. dp specifies the dependency, and
5451 * keeper is already known to be the device that keeps up the other (kept) one.
5452 * We have to the whole tree for the "kept" device, then apply
5453 * the dependency (which may already be applied).
5456 pm_apply_recorded_dep(dev_info_t
*keeper
, pm_pdr_t
*dp
)
5458 PMD_FUNC(pmf
, "apply_recorded_dep")
5459 dev_info_t
*kept
= NULL
;
5464 * Device to Device dependency can only be 1 to 1.
5466 if (dp
->pdr_kept_paths
== NULL
)
5468 keptp
= dp
->pdr_kept_paths
[0];
5471 ASSERT(*keptp
!= '\0');
5472 kept
= pm_name_to_dip(keptp
, 1);
5476 PMD(PMD_KEEPS
, ("%s: keeper=%s, kept=%s\n", pmf
,
5477 dp
->pdr_keeper
, keptp
))
5478 if (pm_set_keeping(keeper
, kept
)) {
5479 ASSERT(dp
->pdr_satisfied
== 0);
5480 dp
->pdr_satisfied
= 1;
5481 ASSERT(pm_unresolved_deps
);
5482 pm_unresolved_deps
--;
5486 ddi_release_devi(kept
);
5492 * Called from common/io/pm.c
5495 pm_cur_power(pm_component_t
*cp
)
5497 return (cur_power(cp
));
5501 * External interface to sanity-check a power level.
5504 pm_valid_power(dev_info_t
*dip
, int comp
, int level
)
5506 PMD_FUNC(pmf
, "valid_power")
5508 if (comp
>= 0 && comp
< PM_NUMCMPTS(dip
) && level
>= 0)
5509 return (e_pm_valid_power(dip
, comp
, level
));
5511 PMD(PMD_FAIL
, ("%s: comp=%d, ncomp=%d, level=%d\n",
5512 pmf
, comp
, PM_NUMCMPTS(dip
), level
))
5518 * Called when a device that is direct power managed needs to change state.
5519 * This routine arranges to block the request until the process managing
5520 * the device makes the change (or some other incompatible change) or
5521 * the process closes /dev/pm.
5524 pm_block(dev_info_t
*dip
, int comp
, int newpower
, int oldpower
)
5526 pm_rsvp_t
*new = kmem_zalloc(sizeof (*new), KM_SLEEP
);
5528 void pm_dequeue_blocked(pm_rsvp_t
*);
5529 void pm_enqueue_blocked(pm_rsvp_t
*);
5531 ASSERT(!pm_processes_stopped
);
5532 ASSERT(PM_IAM_LOCKING_DIP(dip
));
5534 new->pr_comp
= comp
;
5535 new->pr_newlevel
= newpower
;
5536 new->pr_oldlevel
= oldpower
;
5537 cv_init(&new->pr_cv
, NULL
, CV_DEFAULT
, NULL
);
5538 mutex_enter(&pm_rsvp_lock
);
5539 pm_enqueue_blocked(new);
5540 pm_enqueue_notify(PSC_PENDING_CHANGE
, dip
, comp
, newpower
, oldpower
,
5544 * truss may make the cv_wait_sig return prematurely
5548 * Normally there will be no user context involved, but if
5549 * there is (e.g. we are here via an ioctl call to a driver)
5550 * then we should allow the process to abort the request,
5551 * or we get an unkillable process if the same thread does
5552 * PM_DIRECT_PM and pm_raise_power
5554 if (cv_wait_sig(&new->pr_cv
, &pm_rsvp_lock
) == 0) {
5557 ret
= new->pr_retval
;
5560 pm_dequeue_blocked(new);
5561 mutex_exit(&pm_rsvp_lock
);
5562 cv_destroy(&new->pr_cv
);
5563 kmem_free(new, sizeof (*new));
5568 * Returns true if the process is interested in power level changes (has issued
5569 * PM_GET_STATE_CHANGE ioctl).
5572 pm_interest_registered(int clone
)
5574 ASSERT(clone
>= 0 && clone
< PM_MAX_CLONE
- 1);
5575 return (pm_interest
[clone
]);
5578 static void pm_enqueue_pscc(pscc_t
*, pscc_t
**);
5581 * Process with clone has just done PM_DIRECT_PM on dip, or has asked to
5582 * watch all state transitions (dip == NULL). Set up data
5583 * structs to communicate with process about state changes.
5586 pm_register_watcher(int clone
, dev_info_t
*dip
)
5592 * We definitely need a control struct, then we have to search to see
5593 * there is already an entries struct (in the dip != NULL case).
5595 pscc_t
*pscc
= kmem_zalloc(sizeof (*pscc
), KM_SLEEP
);
5596 pscc
->pscc_clone
= clone
;
5597 pscc
->pscc_dip
= dip
;
5601 rw_enter(&pm_pscc_direct_rwlock
, RW_WRITER
);
5602 for (p
= pm_pscc_direct
; p
; p
= p
->pscc_next
) {
5604 * Already an entry for this clone, so just use it
5605 * for the new one (for the case where a single
5606 * process is watching multiple devices)
5608 if (p
->pscc_clone
== clone
) {
5609 pscc
->pscc_entries
= p
->pscc_entries
;
5610 pscc
->pscc_entries
->psce_references
++;
5615 if (!found
) { /* create a new one */
5616 psce
= kmem_zalloc(sizeof (psce_t
), KM_SLEEP
);
5617 mutex_init(&psce
->psce_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
5619 kmem_zalloc(sizeof (pm_state_change_t
) * PSCCOUNT
,
5621 psce
->psce_in
= psce
->psce_out
= psce
->psce_first
;
5622 psce
->psce_last
= &psce
->psce_first
[PSCCOUNT
- 1];
5623 psce
->psce_references
= 1;
5624 pscc
->pscc_entries
= psce
;
5626 pm_enqueue_pscc(pscc
, &pm_pscc_direct
);
5627 rw_exit(&pm_pscc_direct_rwlock
);
5629 ASSERT(!pm_interest_registered(clone
));
5630 rw_enter(&pm_pscc_interest_rwlock
, RW_WRITER
);
5632 for (p
= pm_pscc_interest
; p
; p
= p
->pscc_next
) {
5634 * Should not be an entry for this clone!
5636 ASSERT(p
->pscc_clone
!= clone
);
5639 psce
= kmem_zalloc(sizeof (psce_t
), KM_SLEEP
);
5640 psce
->psce_first
= kmem_zalloc(sizeof (pm_state_change_t
) *
5641 PSCCOUNT
, KM_SLEEP
);
5642 psce
->psce_in
= psce
->psce_out
= psce
->psce_first
;
5643 psce
->psce_last
= &psce
->psce_first
[PSCCOUNT
- 1];
5644 psce
->psce_references
= 1;
5645 pscc
->pscc_entries
= psce
;
5646 pm_enqueue_pscc(pscc
, &pm_pscc_interest
);
5647 pm_interest
[clone
] = 1;
5648 rw_exit(&pm_pscc_interest_rwlock
);
5653 * Remove the given entry from the blocked list
5656 pm_dequeue_blocked(pm_rsvp_t
*p
)
5658 ASSERT(MUTEX_HELD(&pm_rsvp_lock
));
5659 if (pm_blocked_list
== p
) {
5660 ASSERT(p
->pr_prev
== NULL
);
5661 if (p
->pr_next
!= NULL
)
5662 p
->pr_next
->pr_prev
= NULL
;
5663 pm_blocked_list
= p
->pr_next
;
5665 ASSERT(p
->pr_prev
!= NULL
);
5666 p
->pr_prev
->pr_next
= p
->pr_next
;
5667 if (p
->pr_next
!= NULL
)
5668 p
->pr_next
->pr_prev
= p
->pr_prev
;
5673 * Remove the given control struct from the given list
5676 pm_dequeue_pscc(pscc_t
*p
, pscc_t
**list
)
5679 ASSERT(p
->pscc_prev
== NULL
);
5680 if (p
->pscc_next
!= NULL
)
5681 p
->pscc_next
->pscc_prev
= NULL
;
5682 *list
= p
->pscc_next
;
5684 ASSERT(p
->pscc_prev
!= NULL
);
5685 p
->pscc_prev
->pscc_next
= p
->pscc_next
;
5686 if (p
->pscc_next
!= NULL
)
5687 p
->pscc_next
->pscc_prev
= p
->pscc_prev
;
5692 * Stick the control struct specified on the front of the list
5695 pm_enqueue_pscc(pscc_t
*p
, pscc_t
**list
)
5697 pscc_t
*h
; /* entry at head of list */
5698 if ((h
= *list
) == NULL
) {
5700 ASSERT(p
->pscc_next
== NULL
);
5701 ASSERT(p
->pscc_prev
== NULL
);
5704 ASSERT(h
->pscc_prev
== NULL
);
5706 ASSERT(p
->pscc_prev
== NULL
);
5712 * If dip is NULL, process is closing "clone" clean up all its registrations.
5713 * Otherwise only clean up those for dip because process is just giving up
5714 * control of a direct device.
5717 pm_deregister_watcher(int clone
, dev_info_t
*dip
)
5724 rw_enter(&pm_pscc_interest_rwlock
, RW_WRITER
);
5725 for (p
= pm_pscc_interest
; p
; p
= pn
) {
5727 if (p
->pscc_clone
== clone
) {
5728 pm_dequeue_pscc(p
, &pm_pscc_interest
);
5729 psce
= p
->pscc_entries
;
5730 ASSERT(psce
->psce_references
== 1);
5731 mutex_destroy(&psce
->psce_lock
);
5732 kmem_free(psce
->psce_first
,
5733 sizeof (pm_state_change_t
) * PSCCOUNT
);
5734 kmem_free(psce
, sizeof (*psce
));
5735 kmem_free(p
, sizeof (*p
));
5738 pm_interest
[clone
] = 0;
5739 rw_exit(&pm_pscc_interest_rwlock
);
5742 rw_enter(&pm_pscc_direct_rwlock
, RW_WRITER
);
5743 for (p
= pm_pscc_direct
; p
; p
= pn
) {
5745 if ((dip
&& p
->pscc_dip
== dip
) ||
5746 (dip
== NULL
&& clone
== p
->pscc_clone
)) {
5747 ASSERT(clone
== p
->pscc_clone
);
5750 * Remove from control list
5752 pm_dequeue_pscc(p
, &pm_pscc_direct
);
5754 * If we're the last reference, free the
5757 psce
= p
->pscc_entries
;
5759 if (psce
->psce_references
== 1) {
5760 kmem_free(psce
->psce_first
,
5761 PSCCOUNT
* sizeof (pm_state_change_t
));
5762 kmem_free(psce
, sizeof (*psce
));
5764 psce
->psce_references
--;
5766 kmem_free(p
, sizeof (*p
));
5769 ASSERT(dip
== NULL
|| found
);
5770 rw_exit(&pm_pscc_direct_rwlock
);
5774 * Search the indicated list for an entry that matches clone, and return a
5775 * pointer to it. To be interesting, the entry must have something ready to
5776 * be passed up to the controlling process.
5777 * The returned entry will be locked upon return from this call.
5780 pm_psc_find_clone(int clone
, pscc_t
**list
, krwlock_t
*lock
)
5784 rw_enter(lock
, RW_READER
);
5785 for (p
= *list
; p
; p
= p
->pscc_next
) {
5786 if (clone
== p
->pscc_clone
) {
5787 psce
= p
->pscc_entries
;
5788 mutex_enter(&psce
->psce_lock
);
5789 if (psce
->psce_out
->size
) {
5793 mutex_exit(&psce
->psce_lock
);
5801 static psce_t
*pm_psc_find_clone(int, pscc_t
**, krwlock_t
*);
5803 * Find an entry for a particular clone in the direct list.
5806 pm_psc_clone_to_direct(int clone
)
5808 return (pm_psc_find_clone(clone
, &pm_pscc_direct
,
5809 &pm_pscc_direct_rwlock
));
5813 * Find an entry for a particular clone in the interest list.
5816 pm_psc_clone_to_interest(int clone
)
5818 return (pm_psc_find_clone(clone
, &pm_pscc_interest
,
5819 &pm_pscc_interest_rwlock
));
5823 * Put the given entry at the head of the blocked list
5826 pm_enqueue_blocked(pm_rsvp_t
*p
)
5828 ASSERT(MUTEX_HELD(&pm_rsvp_lock
));
5829 ASSERT(p
->pr_next
== NULL
);
5830 ASSERT(p
->pr_prev
== NULL
);
5831 if (pm_blocked_list
!= NULL
) {
5832 p
->pr_next
= pm_blocked_list
;
5833 ASSERT(pm_blocked_list
->pr_prev
== NULL
);
5834 pm_blocked_list
->pr_prev
= p
;
5835 pm_blocked_list
= p
;
5837 pm_blocked_list
= p
;
5842 * Sets every power managed device back to its default threshold
5845 pm_all_to_default_thresholds(void)
5847 ddi_walk_devs(ddi_root_node(), pm_set_dev_thr_walk
,
5848 (void *) &pm_system_idle_threshold
);
5852 pm_set_dev_thr_walk(dev_info_t
*dip
, void *arg
)
5854 int thr
= (int)(*(int *)arg
);
5856 if (!PM_GET_PM_INFO(dip
))
5857 return (DDI_WALK_CONTINUE
);
5858 pm_set_device_threshold(dip
, thr
, PMC_DEF_THRESH
);
5859 return (DDI_WALK_CONTINUE
);
5863 * Returns the current threshold value (in seconds) for the indicated component
5866 pm_current_threshold(dev_info_t
*dip
, int comp
, int *threshp
)
5868 if (comp
< 0 || comp
>= PM_NUMCMPTS(dip
)) {
5869 return (DDI_FAILURE
);
5871 *threshp
= cur_threshold(dip
, comp
);
5872 return (DDI_SUCCESS
);
5877 * To be called when changing the power level of a component of a device.
5878 * On some platforms, changing power on one device may require that power
5879 * be changed on other, related devices in the same transaction. Thus, we
5880 * always pass this request to the platform power manager so that all the
5881 * affected devices will be locked.
5884 pm_lock_power(dev_info_t
*dip
, int *circp
)
5886 power_req_t power_req
;
5889 power_req
.request_type
= PMR_PPM_LOCK_POWER
;
5890 power_req
.req
.ppm_lock_power_req
.who
= dip
;
5891 power_req
.req
.ppm_lock_power_req
.circp
= circp
;
5892 (void) pm_ctlops(PPM(dip
), dip
, DDI_CTLOPS_POWER
, &power_req
, &result
);
5896 * Release the lock (or locks) acquired to change the power of a device.
5897 * See comments for pm_lock_power.
5900 pm_unlock_power(dev_info_t
*dip
, int circ
)
5902 power_req_t power_req
;
5905 power_req
.request_type
= PMR_PPM_UNLOCK_POWER
;
5906 power_req
.req
.ppm_unlock_power_req
.who
= dip
;
5907 power_req
.req
.ppm_unlock_power_req
.circ
= circ
;
5908 (void) pm_ctlops(PPM(dip
), dip
, DDI_CTLOPS_POWER
, &power_req
, &result
);
5913 * Attempt (without blocking) to acquire the lock(s) needed to change the
5914 * power of a component of a device. See comments for pm_lock_power.
5916 * Return: 1 if lock(s) acquired, 0 if not.
5919 pm_try_locking_power(dev_info_t
*dip
, int *circp
)
5921 power_req_t power_req
;
5924 power_req
.request_type
= PMR_PPM_TRY_LOCK_POWER
;
5925 power_req
.req
.ppm_lock_power_req
.who
= dip
;
5926 power_req
.req
.ppm_lock_power_req
.circp
= circp
;
5927 (void) pm_ctlops(PPM(dip
), dip
, DDI_CTLOPS_POWER
, &power_req
, &result
);
5933 * Lock power state of a device.
5935 * The implementation handles a special case where another thread may have
5936 * acquired the lock and created/launched this thread to do the work. If
5937 * the lock cannot be acquired immediately, we check to see if this thread
5938 * is registered as a borrower of the lock. If so, we may proceed without
5939 * the lock. This assumes that the lending thread blocks on the completion
5942 * Note 1: for use by ppm only.
5944 * Note 2: On failing to get the lock immediately, we search lock_loan list
5945 * for curthread (as borrower of the lock). On a hit, we check that the
5946 * lending thread already owns the lock we want. It is safe to compare
5947 * devi_busy_thread and thread id of the lender because in the == case (the
5948 * only one we care about) we know that the owner is blocked. Similarly,
5949 * If we find that curthread isn't registered as a lock borrower, it is safe
5950 * to use the blocking call (ndi_devi_enter) because we know that if we
5951 * weren't already listed as a borrower (upstream on the call stack) we won't
5955 pm_lock_power_single(dev_info_t
*dip
, int *circp
)
5959 /* if the lock is available, we are done. */
5960 if (ndi_devi_tryenter(dip
, circp
))
5963 mutex_enter(&pm_loan_lock
);
5964 /* see if our thread is registered as a lock borrower. */
5965 for (cur
= lock_loan_head
.pmlk_next
; cur
; cur
= cur
->pmlk_next
)
5966 if (cur
->pmlk_borrower
== curthread
)
5968 mutex_exit(&pm_loan_lock
);
5970 /* if this thread not already registered, it is safe to block */
5972 ndi_devi_enter(dip
, circp
);
5974 /* registered: does lender own the lock we want? */
5975 if (cur
->pmlk_lender
== DEVI(dip
)->devi_busy_thread
) {
5976 ASSERT(cur
->pmlk_dip
== NULL
|| cur
->pmlk_dip
== dip
);
5977 cur
->pmlk_dip
= dip
;
5978 } else /* no: just block for it */
5979 ndi_devi_enter(dip
, circp
);
5985 * Drop the lock on the device's power state. See comment for
5986 * pm_lock_power_single() for special implementation considerations.
5988 * Note: for use by ppm only.
5991 pm_unlock_power_single(dev_info_t
*dip
, int circ
)
5995 /* optimization: mutex not needed to check empty list */
5996 if (lock_loan_head
.pmlk_next
== NULL
) {
5997 ndi_devi_exit(dip
, circ
);
6001 mutex_enter(&pm_loan_lock
);
6002 /* see if our thread is registered as a lock borrower. */
6003 for (cur
= lock_loan_head
.pmlk_next
; cur
; cur
= cur
->pmlk_next
)
6004 if (cur
->pmlk_borrower
== curthread
)
6006 mutex_exit(&pm_loan_lock
);
6008 if (cur
== NULL
|| cur
->pmlk_dip
!= dip
)
6009 /* we acquired the lock directly, so return it */
6010 ndi_devi_exit(dip
, circ
);
6014 * Try to take the lock for changing the power level of a component.
6016 * Note: for use by ppm only.
6019 pm_try_locking_power_single(dev_info_t
*dip
, int *circp
)
6021 return (ndi_devi_tryenter(dip
, circp
));
6026 * The following are used only to print out data structures for debugging
6035 pm_log("pm_dep_head %s %p\n", msg
, (void *)pm_dep_head
);
6036 for (rp
= pm_dep_head
; rp
; rp
= rp
->pdr_next
) {
6037 pm_log("%p: %s keeper %s, kept %s, kept count %d, next %p\n",
6038 (void *)rp
, (rp
->pdr_isprop
? "property" : "device"),
6039 rp
->pdr_keeper
, rp
->pdr_kept
, rp
->pdr_kept_count
,
6040 (void *)rp
->pdr_next
);
6041 if (rp
->pdr_kept_count
!= 0) {
6042 pm_log("kept list = ");
6044 while (i
< rp
->pdr_kept_count
) {
6045 pm_log("%s ", rp
->pdr_kept_paths
[i
]);
6054 pr_noinvol(char *hdr
)
6058 pm_log("%s\n", hdr
);
6059 rw_enter(&pm_noinvol_rwlock
, RW_READER
);
6060 for (ip
= pm_noinvol_head
; ip
; ip
= ip
->ni_next
)
6061 pm_log("\tmaj %d, flags %x, noinvolpm %d %s\n",
6062 ip
->ni_major
, ip
->ni_flags
, ip
->ni_noinvolpm
, ip
->ni_path
);
6063 rw_exit(&pm_noinvol_rwlock
);
6068 * Attempt to apply the thresholds indicated by rp to the node specified by
6072 pm_apply_recorded_thresh(dev_info_t
*dip
, pm_thresh_rec_t
*rp
)
6074 PMD_FUNC(pmf
, "apply_recorded_thresh")
6076 int comps
= PM_NUMCMPTS(dip
);
6077 struct pm_component
*cp
;
6079 int pm_valid_thresh(dev_info_t
*, pm_thresh_rec_t
*);
6081 PMD(PMD_THRESH
, ("%s: part: %s@%s(%s#%d), rp %p, %s\n", pmf
,
6082 PM_DEVICE(dip
), (void *)rp
, rp
->ptr_physpath
))
6084 if (!PM_GET_PM_INFO(dip
) || PM_ISBC(dip
) || !pm_valid_thresh(dip
, rp
)) {
6085 PMD(PMD_FAIL
, ("%s: part: %s@%s(%s#%d) PM_GET_PM_INFO %p\n",
6086 pmf
, PM_DEVICE(dip
), (void*)PM_GET_PM_INFO(dip
)))
6087 PMD(PMD_FAIL
, ("%s: part: %s@%s(%s#%d) PM_ISBC %d\n",
6088 pmf
, PM_DEVICE(dip
), PM_ISBC(dip
)))
6089 PMD(PMD_FAIL
, ("%s: part: %s@%s(%s#%d) pm_valid_thresh %d\n",
6090 pmf
, PM_DEVICE(dip
), pm_valid_thresh(dip
, rp
)))
6095 ep
= rp
->ptr_entries
;
6097 * Here we do the special case of a device threshold
6099 if (rp
->ptr_numcomps
== 0) { /* PM_SET_DEVICE_THRESHOLD product */
6100 ASSERT(ep
&& ep
->pte_numthresh
== 1);
6101 PMD(PMD_THRESH
, ("%s: set dev thr %s@%s(%s#%d) to 0x%x\n",
6102 pmf
, PM_DEVICE(dip
), ep
->pte_thresh
[0]))
6104 pm_set_device_threshold(dip
, ep
->pte_thresh
[0], PMC_DEV_THRESH
);
6105 if (PM_SCANABLE(dip
))
6109 for (i
= 0; i
< comps
; i
++) {
6111 for (j
= 0; j
< ep
->pte_numthresh
; j
++) {
6112 PMD(PMD_THRESH
, ("%s: set thr %d for %s@%s(%s#%d)[%d] "
6113 "to %x\n", pmf
, j
, PM_DEVICE(dip
),
6114 i
, ep
->pte_thresh
[j
]))
6115 cp
->pmc_comp
.pmc_thresh
[j
+ 1] = ep
->pte_thresh
[j
];
6119 DEVI(dip
)->devi_pm_flags
&= PMC_THRESH_NONE
;
6120 DEVI(dip
)->devi_pm_flags
|= PMC_COMP_THRESH
;
6123 if (PM_SCANABLE(dip
))
6128 * Returns true if the threshold specified by rp could be applied to dip
6129 * (that is, the number of components and transitions are the same)
6132 pm_valid_thresh(dev_info_t
*dip
, pm_thresh_rec_t
*rp
)
6134 PMD_FUNC(pmf
, "valid_thresh")
6139 if (!PM_GET_PM_INFO(dip
) || PM_ISBC(dip
)) {
6140 PMD(PMD_ERROR
, ("%s: %s: no pm_info or BC\n", pmf
,
6145 * Special case: we represent the PM_SET_DEVICE_THRESHOLD case by
6146 * an entry with numcomps == 0, (since we don't know how many
6147 * components there are in advance). This is always a valid
6150 if (rp
->ptr_numcomps
== 0) {
6151 ASSERT(rp
->ptr_entries
&& rp
->ptr_entries
->pte_numthresh
== 1);
6154 if (rp
->ptr_numcomps
!= (comps
= PM_NUMCMPTS(dip
))) {
6155 PMD(PMD_ERROR
, ("%s: comp # mm (dip %d cmd %d) for %s\n",
6156 pmf
, PM_NUMCMPTS(dip
), rp
->ptr_numcomps
, rp
->ptr_physpath
))
6159 ep
= rp
->ptr_entries
;
6160 for (i
= 0; i
< comps
; i
++) {
6162 if ((ep
+ i
)->pte_numthresh
!=
6163 cp
->pmc_comp
.pmc_numlevels
- 1) {
6164 PMD(PMD_ERROR
, ("%s: %s[%d]: thresh=%d, record=%d\n",
6165 pmf
, rp
->ptr_physpath
, i
,
6166 cp
->pmc_comp
.pmc_numlevels
- 1,
6167 (ep
+ i
)->pte_numthresh
))
6175 * Remove any recorded threshold for device physpath
6176 * We know there will be at most one.
6179 pm_unrecord_threshold(char *physpath
)
6181 pm_thresh_rec_t
*pptr
, *ptr
;
6183 rw_enter(&pm_thresh_rwlock
, RW_WRITER
);
6184 for (pptr
= NULL
, ptr
= pm_thresh_head
; ptr
; ptr
= ptr
->ptr_next
) {
6185 if (strcmp(physpath
, ptr
->ptr_physpath
) == 0) {
6187 pptr
->ptr_next
= ptr
->ptr_next
;
6189 ASSERT(pm_thresh_head
== ptr
);
6190 pm_thresh_head
= ptr
->ptr_next
;
6192 kmem_free(ptr
, ptr
->ptr_size
);
6197 rw_exit(&pm_thresh_rwlock
);
6201 * Discard all recorded thresholds. We are returning to the default pm state.
6204 pm_discard_thresholds(void)
6206 pm_thresh_rec_t
*rp
;
6207 rw_enter(&pm_thresh_rwlock
, RW_WRITER
);
6208 while (pm_thresh_head
) {
6209 rp
= pm_thresh_head
;
6210 pm_thresh_head
= rp
->ptr_next
;
6211 kmem_free(rp
, rp
->ptr_size
);
6213 rw_exit(&pm_thresh_rwlock
);
6217 * Discard all recorded dependencies. We are returning to the default pm state.
6220 pm_discard_dependencies(void)
6227 if (pm_debug
& PMD_DEP
)
6228 prdeps("Before discard\n");
6230 ddi_walk_devs(ddi_root_node(), pm_discard_dep_walk
, NULL
);
6233 if (pm_debug
& PMD_DEP
)
6234 prdeps("After discard\n");
6236 while (pm_dep_head
) {
6238 if (!rp
->pdr_isprop
) {
6239 ASSERT(rp
->pdr_satisfied
== 0);
6240 ASSERT(pm_unresolved_deps
);
6241 pm_unresolved_deps
--;
6243 ASSERT(pm_prop_deps
);
6246 pm_dep_head
= rp
->pdr_next
;
6247 if (rp
->pdr_kept_count
) {
6248 for (i
= 0; i
< rp
->pdr_kept_count
; i
++) {
6249 length
= strlen(rp
->pdr_kept_paths
[i
]) + 1;
6250 kmem_free(rp
->pdr_kept_paths
[i
], length
);
6252 kmem_free(rp
->pdr_kept_paths
,
6253 rp
->pdr_kept_count
* sizeof (char **));
6255 kmem_free(rp
, rp
->pdr_size
);
6261 pm_discard_dep_walk(dev_info_t
*dip
, void *arg
)
6263 _NOTE(ARGUNUSED(arg
))
6266 if (PM_GET_PM_INFO(dip
) == NULL
)
6267 return (DDI_WALK_CONTINUE
);
6268 pathbuf
= kmem_alloc(MAXPATHLEN
, KM_SLEEP
);
6269 (void) ddi_pathname(dip
, pathbuf
);
6270 pm_free_keeper(pathbuf
, 0);
6271 kmem_free(pathbuf
, MAXPATHLEN
);
6272 return (DDI_WALK_CONTINUE
);
6276 pm_kept_walk(dev_info_t
*dip
, void *arg
)
6278 _NOTE(ARGUNUSED(arg
))
6281 pathbuf
= kmem_alloc(MAXPATHLEN
, KM_SLEEP
);
6282 (void) ddi_pathname(dip
, pathbuf
);
6283 (void) pm_kept(pathbuf
);
6284 kmem_free(pathbuf
, MAXPATHLEN
);
6286 return (DDI_WALK_CONTINUE
);
6290 pm_keeper_walk(dev_info_t
*dip
, void *arg
)
6292 _NOTE(ARGUNUSED(arg
))
6295 pathbuf
= kmem_alloc(MAXPATHLEN
, KM_SLEEP
);
6296 (void) ddi_pathname(dip
, pathbuf
);
6297 (void) pm_keeper(pathbuf
);
6298 kmem_free(pathbuf
, MAXPATHLEN
);
6300 return (DDI_WALK_CONTINUE
);
6304 pdw_type_decode(int type
)
6307 case PM_DEP_WK_POWER_ON
:
6308 return ("power on");
6309 case PM_DEP_WK_POWER_OFF
:
6310 return ("power off");
6311 case PM_DEP_WK_DETACH
:
6313 case PM_DEP_WK_REMOVE_DEP
:
6314 return ("remove dep");
6315 case PM_DEP_WK_BRINGUP_SELF
:
6316 return ("bringup self");
6317 case PM_DEP_WK_RECORD_KEEPER
:
6318 return ("add dependent");
6319 case PM_DEP_WK_RECORD_KEEPER_PROP
:
6320 return ("add dependent property");
6321 case PM_DEP_WK_KEPT
:
6323 case PM_DEP_WK_KEEPER
:
6325 case PM_DEP_WK_ATTACH
:
6327 case PM_DEP_WK_CHECK_KEPT
:
6328 return ("check kept");
6329 case PM_DEP_WK_CPR_SUSPEND
:
6331 case PM_DEP_WK_CPR_RESUME
:
6340 pm_rele_dep(char *keeper
)
6342 PMD_FUNC(pmf
, "rele_dep")
6344 char *kept_path
= NULL
;
6345 dev_info_t
*kept
= NULL
;
6348 for (dp
= pm_dep_head
; dp
; dp
= dp
->pdr_next
) {
6349 if (strcmp(dp
->pdr_keeper
, keeper
) != 0)
6351 for (count
= 0; count
< dp
->pdr_kept_count
; count
++) {
6352 kept_path
= dp
->pdr_kept_paths
[count
];
6353 if (kept_path
== NULL
)
6355 kept
= pm_name_to_dip(kept_path
, 1);
6357 PMD(PMD_KEEPS
, ("%s: release kept=%s@%s(%s#%d) "
6358 "of keeper=%s\n", pmf
, PM_DEVICE(kept
),
6360 ASSERT(DEVI(kept
)->devi_pm_kidsupcnt
> 0);
6361 pm_rele_power(kept
);
6362 ddi_release_devi(kept
);
6369 * Called when we are just released from direct PM. Bring ourself up
6370 * if our keeper is up since dependency is not honored while a kept
6371 * device is under direct PM.
6374 pm_bring_self_up(char *keptpath
)
6376 PMD_FUNC(pmf
, "bring_self_up")
6383 kept
= pm_name_to_dip(keptpath
, 1);
6386 PMD(PMD_KEEPS
, ("%s: kept=%s@%s(%s#%d)\n", pmf
, PM_DEVICE(kept
)))
6387 for (dp
= pm_dep_head
; dp
; dp
= dp
->pdr_next
) {
6388 if (dp
->pdr_kept_count
== 0)
6390 for (i
= 0; i
< dp
->pdr_kept_count
; i
++) {
6391 if (strcmp(dp
->pdr_kept_paths
[i
], keptpath
) != 0)
6393 keeper
= pm_name_to_dip(dp
->pdr_keeper
, 1);
6395 PMD(PMD_KEEPS
, ("%s: keeper=%s@%s(%s#%d)\n",
6396 pmf
, PM_DEVICE(keeper
)))
6397 PM_LOCK_POWER(keeper
, &circ
);
6398 for (j
= 0; j
< PM_NUMCMPTS(keeper
);
6400 if (PM_CURPOWER(keeper
, j
)) {
6401 PMD(PMD_KEEPS
, ("%s: comp="
6402 "%d is up\n", pmf
, j
))
6408 DEVI(kept
)->devi_pm_flags
&=
6410 bring_pmdep_up(kept
, 1);
6412 PM_UNLOCK_POWER(keeper
, circ
);
6413 ddi_release_devi(keeper
);
6417 ddi_release_devi(kept
);
6421 pm_process_dep_request(pm_dep_wk_t
*work
)
6423 PMD_FUNC(pmf
, "dep_req")
6426 PMD(PMD_DEP
, ("%s: work=%s\n", pmf
,
6427 pdw_type_decode(work
->pdw_type
)))
6428 PMD(PMD_DEP
, ("%s: keeper=%s, kept=%s\n", pmf
,
6429 (work
->pdw_keeper
? work
->pdw_keeper
: "NULL"),
6430 (work
->pdw_kept
? work
->pdw_kept
: "NULL")))
6432 switch (work
->pdw_type
) {
6433 case PM_DEP_WK_POWER_ON
:
6434 /* Bring up the kept devices and put a hold on them */
6435 bring_wekeeps_up(work
->pdw_keeper
);
6437 case PM_DEP_WK_POWER_OFF
:
6438 /* Release the kept devices */
6439 pm_rele_dep(work
->pdw_keeper
);
6441 case PM_DEP_WK_DETACH
:
6442 pm_free_keeps(work
->pdw_keeper
, work
->pdw_pwr
);
6444 case PM_DEP_WK_REMOVE_DEP
:
6445 pm_discard_dependencies();
6447 case PM_DEP_WK_BRINGUP_SELF
:
6449 * We deferred satisfying our dependency till now, so satisfy
6450 * it again and bring ourselves up.
6452 pm_bring_self_up(work
->pdw_kept
);
6454 case PM_DEP_WK_RECORD_KEEPER
:
6455 (void) pm_record_keeper(work
->pdw_kept
, work
->pdw_keeper
, 0);
6456 ddi_walk_devs(ddi_root_node(), pm_kept_walk
, NULL
);
6457 ddi_walk_devs(ddi_root_node(), pm_keeper_walk
, NULL
);
6459 case PM_DEP_WK_RECORD_KEEPER_PROP
:
6460 (void) pm_record_keeper(work
->pdw_kept
, work
->pdw_keeper
, 1);
6461 ddi_walk_devs(ddi_root_node(), pm_keeper_walk
, NULL
);
6462 ddi_walk_devs(ddi_root_node(), pm_kept_walk
, NULL
);
6464 case PM_DEP_WK_KEPT
:
6465 ret
= pm_kept(work
->pdw_kept
);
6466 PMD(PMD_DEP
, ("%s: PM_DEP_WK_KEPT: pm_kept returns %d\n", pmf
,
6469 case PM_DEP_WK_KEEPER
:
6470 ret
= pm_keeper(work
->pdw_keeper
);
6471 PMD(PMD_DEP
, ("%s: PM_DEP_WK_KEEPER: pm_keeper returns %d\n",
6474 case PM_DEP_WK_ATTACH
:
6475 ret
= pm_keeper(work
->pdw_keeper
);
6476 PMD(PMD_DEP
, ("%s: PM_DEP_WK_ATTACH: pm_keeper returns %d\n",
6478 ret
= pm_kept(work
->pdw_kept
);
6479 PMD(PMD_DEP
, ("%s: PM_DEP_WK_ATTACH: pm_kept returns %d\n",
6482 case PM_DEP_WK_CHECK_KEPT
:
6483 ret
= pm_is_kept(work
->pdw_kept
);
6484 PMD(PMD_DEP
, ("%s: PM_DEP_WK_CHECK_KEPT: kept=%s, ret=%d\n",
6485 pmf
, work
->pdw_kept
, ret
))
6487 case PM_DEP_WK_CPR_SUSPEND
:
6488 pm_discard_dependencies();
6490 case PM_DEP_WK_CPR_RESUME
:
6491 ddi_walk_devs(ddi_root_node(), pm_kept_walk
, NULL
);
6492 ddi_walk_devs(ddi_root_node(), pm_keeper_walk
, NULL
);
6499 * Free the work structure if the requester is not waiting
6500 * Otherwise it is the requester's responsiblity to free it.
6502 if (!work
->pdw_wait
) {
6503 if (work
->pdw_keeper
)
6504 kmem_free(work
->pdw_keeper
,
6505 strlen(work
->pdw_keeper
) + 1);
6507 kmem_free(work
->pdw_kept
, strlen(work
->pdw_kept
) + 1);
6508 kmem_free(work
, sizeof (pm_dep_wk_t
));
6511 * Notify requester if it is waiting for it.
6513 work
->pdw_ret
= ret
;
6515 cv_signal(&work
->pdw_cv
);
6520 * Process PM dependency requests.
6526 callb_cpr_t cprinfo
;
6528 CALLB_CPR_INIT(&cprinfo
, &pm_dep_thread_lock
, callb_generic_cpr
,
6531 mutex_enter(&pm_dep_thread_lock
);
6532 if (pm_dep_thread_workq
== NULL
) {
6533 CALLB_CPR_SAFE_BEGIN(&cprinfo
);
6534 cv_wait(&pm_dep_thread_cv
, &pm_dep_thread_lock
);
6535 CALLB_CPR_SAFE_END(&cprinfo
, &pm_dep_thread_lock
);
6537 work
= pm_dep_thread_workq
;
6538 pm_dep_thread_workq
= work
->pdw_next
;
6539 if (pm_dep_thread_tail
== work
)
6540 pm_dep_thread_tail
= work
->pdw_next
;
6541 mutex_exit(&pm_dep_thread_lock
);
6542 pm_process_dep_request(work
);
6549 * Set the power level of the indicated device to unknown (if it is not a
6550 * backwards compatible device), as it has just been resumed, and it won't
6551 * know if the power was removed or not. Adjust parent's kidsupcnt if necessary.
6554 pm_forget_power_level(dev_info_t
*dip
)
6556 dev_info_t
*pdip
= ddi_get_parent(dip
);
6559 if (!PM_ISBC(dip
)) {
6560 for (i
= 0; i
< PM_NUMCMPTS(dip
); i
++)
6561 count
+= (PM_CURPOWER(dip
, i
) == 0);
6563 if (count
&& pdip
&& !PM_WANTS_NOTIFICATION(pdip
))
6564 e_pm_hold_rele_power(pdip
, count
);
6567 * Count this as a power cycle if we care
6569 if (DEVI(dip
)->devi_pm_volpmd
&&
6570 PM_CP(dip
, 0)->pmc_cur_pwr
== 0)
6571 DEVI(dip
)->devi_pm_volpmd
= 0;
6572 for (i
= 0; i
< PM_NUMCMPTS(dip
); i
++)
6573 e_pm_set_cur_pwr(dip
, PM_CP(dip
, i
), PM_LEVEL_UNKNOWN
);
6578 * This function advises the caller whether it should make a power-off
6579 * transition at this time or not. If the transition is not advised
6580 * at this time, the time that the next power-off transition can
6581 * be made from now is returned through "intervalp" pointer.
6582 * This function returns:
6584 * 1 power-off advised
6585 * 0 power-off not advised, intervalp will point to seconds from
6586 * now that a power-off is advised. If it is passed the number
6587 * of years that policy specifies the device should last,
6588 * a large number is returned as the time interval.
6592 pm_trans_check(struct pm_trans_data
*datap
, time_t *intervalp
)
6594 PMD_FUNC(pmf
, "pm_trans_check")
6595 char dbuf
[DC_SCSI_MFR_LEN
];
6596 struct pm_scsi_cycles
*scp
;
6597 int service_years
, service_weeks
, full_years
;
6598 time_t now
, service_seconds
, tdiff
;
6599 time_t within_year
, when_allowed
;
6601 int lower_bound_cycles
, upper_bound_cycles
, cycles_allowed
;
6602 int cycles_diff
, cycles_over
;
6603 struct pm_smart_count
*smart_p
;
6605 if (datap
== NULL
) {
6606 PMD(PMD_TCHECK
, ("%s: NULL data pointer!\n", pmf
))
6610 if (datap
->format
== DC_SCSI_FORMAT
) {
6612 * Power cycles of the scsi drives are distributed
6613 * over 5 years with the following percentage ratio:
6615 * 30%, 25%, 20%, 15%, and 10%
6617 * The power cycle quota for each year is distributed
6618 * linearly through out the year. The equation for
6619 * determining the expected cycles is:
6623 * e = expected cycles
6624 * a = allocated cycles for this year
6625 * n = number of seconds since beginning of this year
6626 * y = number of seconds in a year
6628 * Note that beginning of the year starts the day that
6629 * the drive has been put on service.
6631 * If the drive has passed its expected cycles, we
6632 * can determine when it can start to power cycle
6633 * again to keep it on track to meet the 5-year
6634 * life expectancy. The equation for determining
6635 * when to power cycle is:
6639 * w = when it can power cycle again
6640 * y = number of seconds in a year
6641 * c = current number of cycles
6642 * a = allocated cycles for the year
6645 char pcnt
[DC_SCSI_NPY
] = { 30, 55, 75, 90, 100 };
6647 scp
= &datap
->un
.scsi_cycles
;
6648 PMD(PMD_TCHECK
, ("%s: format=%d, lifemax=%d, ncycles=%d, "
6649 "svc_date=%s, svc_flag=%d\n", pmf
, datap
->format
,
6650 scp
->lifemax
, scp
->ncycles
, scp
->svc_date
, scp
->flag
))
6651 if (scp
->ncycles
< 0 || scp
->flag
!= 0) {
6652 PMD(PMD_TCHECK
, ("%s: ncycles < 0 || flag != 0\n", pmf
))
6656 if (scp
->ncycles
> scp
->lifemax
) {
6657 *intervalp
= (LONG_MAX
/ hz
);
6662 * convert service date to time_t
6664 bcopy(scp
->svc_date
, dbuf
, DC_SCSI_YEAR_LEN
);
6665 dbuf
[DC_SCSI_YEAR_LEN
] = '\0';
6667 service_years
= stoi(&ptr
) - EPOCH_YEAR
;
6668 bcopy(&scp
->svc_date
[DC_SCSI_YEAR_LEN
], dbuf
,
6670 dbuf
[DC_SCSI_WEEK_LEN
] = '\0';
6673 * scsi standard does not specify WW data,
6674 * could be (00-51) or (01-52)
6677 service_weeks
= stoi(&ptr
);
6678 if (service_years
< 0 ||
6679 service_weeks
< 0 || service_weeks
> 52) {
6680 PMD(PMD_TCHECK
, ("%s: service year %d and week %d\n",
6681 pmf
, service_years
, service_weeks
))
6686 * calculate service date in seconds-since-epoch,
6687 * adding one day for each leap-year.
6689 * (years-since-epoch + 2) fixes integer truncation,
6690 * example: (8) leap-years during [1972, 2000]
6691 * (2000 - 1970) = 30; and (30 + 2) / 4 = 8;
6693 service_seconds
= (service_years
* DC_SPY
) +
6694 (service_weeks
* DC_SPW
) +
6695 (((service_years
+ 2) / 4) * DC_SPD
);
6697 now
= gethrestime_sec();
6699 * since the granularity of 'svc_date' is day not second,
6700 * 'now' should be rounded up to full day.
6702 now
= ((now
+ DC_SPD
-1) / DC_SPD
) * DC_SPD
;
6703 if (service_seconds
> now
) {
6704 PMD(PMD_TCHECK
, ("%s: service date (%ld) later "
6705 "than now (%ld)!\n", pmf
, service_seconds
, now
))
6709 tdiff
= now
- service_seconds
;
6710 PMD(PMD_TCHECK
, ("%s: age is %ld sec\n", pmf
, tdiff
))
6713 * NOTE - Leap years are not considered in the calculations
6716 full_years
= (tdiff
/ DC_SPY
);
6717 if ((full_years
>= DC_SCSI_NPY
) &&
6718 (scp
->ncycles
<= scp
->lifemax
))
6722 * Determine what is the normal cycle usage for the
6723 * device at the beginning and the end of this year.
6725 lower_bound_cycles
= (!full_years
) ? 0 :
6726 ((scp
->lifemax
* pcnt
[full_years
- 1]) / 100);
6727 upper_bound_cycles
= (scp
->lifemax
* pcnt
[full_years
]) / 100;
6729 if (scp
->ncycles
<= lower_bound_cycles
)
6733 * The linear slope that determines how many cycles
6734 * are allowed this year is number of seconds
6735 * passed this year over total number of seconds in a year.
6737 cycles_diff
= (upper_bound_cycles
- lower_bound_cycles
);
6738 within_year
= (tdiff
% DC_SPY
);
6739 cycles_allowed
= lower_bound_cycles
+
6740 (((uint64_t)cycles_diff
* (uint64_t)within_year
) / DC_SPY
);
6741 PMD(PMD_TCHECK
, ("%s: lived %d yrs and %ld secs\n", pmf
,
6742 full_years
, within_year
))
6743 PMD(PMD_TCHECK
, ("%s: # of cycles allowed %d\n", pmf
,
6746 if (scp
->ncycles
<= cycles_allowed
)
6750 * The transition is not advised now but we can
6751 * determine when the next transition can be made.
6753 * Depending on how many cycles the device has been
6754 * over-used, we may need to skip years with
6755 * different percentage quota in order to determine
6756 * when the next transition can be made.
6758 cycles_over
= (scp
->ncycles
- lower_bound_cycles
);
6759 while (cycles_over
> cycles_diff
) {
6761 if (full_years
>= DC_SCSI_NPY
) {
6762 *intervalp
= (LONG_MAX
/ hz
);
6765 cycles_over
-= cycles_diff
;
6766 lower_bound_cycles
= upper_bound_cycles
;
6767 upper_bound_cycles
=
6768 (scp
->lifemax
* pcnt
[full_years
]) / 100;
6769 cycles_diff
= (upper_bound_cycles
- lower_bound_cycles
);
6773 * The linear slope that determines when the next transition
6774 * can be made is the relative position of used cycles within a
6775 * year over total number of cycles within that year.
6777 when_allowed
= service_seconds
+ (full_years
* DC_SPY
) +
6778 (((uint64_t)DC_SPY
* (uint64_t)cycles_over
) / cycles_diff
);
6779 *intervalp
= (when_allowed
- now
);
6780 if (*intervalp
> (LONG_MAX
/ hz
))
6781 *intervalp
= (LONG_MAX
/ hz
);
6782 PMD(PMD_TCHECK
, ("%s: no cycle is allowed in %ld secs\n", pmf
,
6785 } else if (datap
->format
== DC_SMART_FORMAT
) {
6787 * power cycles of SATA disks are reported from SMART
6790 smart_p
= &datap
->un
.smart_count
;
6791 if (smart_p
->consumed
>= smart_p
->allowed
) {
6792 *intervalp
= (LONG_MAX
/ hz
);
6793 PMD(PMD_TCHECK
, ("%s: exceeded lifemax cycles.\n", pmf
))
6799 PMD(PMD_TCHECK
, ("%s: unknown format!\n", pmf
))
6804 * Nexus drivers call into pm framework to indicate which child driver is about
6805 * to be installed. In some platforms, ppm may need to configure the hardware
6806 * for successful installation of a driver.
6809 pm_init_child(dev_info_t
*dip
)
6811 power_req_t power_req
;
6813 ASSERT(ddi_binding_name(dip
));
6814 ASSERT(ddi_get_name_addr(dip
));
6816 if (pm_ppm_claimed(dip
)) { /* if ppm driver claims the node */
6817 power_req
.request_type
= PMR_PPM_INIT_CHILD
;
6818 power_req
.req
.ppm_config_req
.who
= dip
;
6819 ASSERT(PPM(dip
) != NULL
);
6820 return (pm_ctlops(PPM(dip
), dip
, DDI_CTLOPS_POWER
, &power_req
,
6824 /* pass it to the default handler so we can debug things */
6825 power_req
.request_type
= PMR_PPM_INIT_CHILD
;
6826 power_req
.req
.ppm_config_req
.who
= dip
;
6827 (void) pm_ctlops(NULL
, dip
,
6828 DDI_CTLOPS_POWER
, &power_req
, NULL
);
6831 return (DDI_SUCCESS
);
6835 * Bring parent of a node that is about to be probed up to full power, and
6836 * arrange for it to stay up until pm_post_probe() or pm_post_attach() decide
6837 * it is time to let it go down again
6840 pm_pre_probe(dev_info_t
*dip
, pm_ppm_cookie_t
*cp
)
6843 power_req_t power_req
;
6845 bzero(cp
, sizeof (*cp
));
6849 if (pm_ppm_claimed(dip
)) { /* if ppm driver claims the node */
6850 power_req
.request_type
= PMR_PPM_PRE_PROBE
;
6851 power_req
.req
.ppm_config_req
.who
= dip
;
6852 ASSERT(PPM(dip
) != NULL
);
6853 (void) pm_ctlops(PPM(dip
), dip
,
6854 DDI_CTLOPS_POWER
, &power_req
, &result
);
6855 cp
->ppc_ppm
= PPM(dip
);
6858 /* pass it to the default handler so we can debug things */
6859 power_req
.request_type
= PMR_PPM_PRE_PROBE
;
6860 power_req
.req
.ppm_config_req
.who
= dip
;
6861 (void) pm_ctlops(NULL
, dip
,
6862 DDI_CTLOPS_POWER
, &power_req
, &result
);
6869 pm_pre_config(dev_info_t
*dip
, char *devnm
)
6871 PMD_FUNC(pmf
, "pre_config")
6874 if (MDI_VHCI(dip
)) {
6875 PMD(PMD_SET
, ("%s: %s@%s(%s#%d)\n", pmf
, PM_DEVICE(dip
)))
6876 ret
= mdi_power(dip
, MDI_PM_PRE_CONFIG
, NULL
, devnm
, 0);
6877 return (ret
== MDI_SUCCESS
? DDI_SUCCESS
: DDI_FAILURE
);
6878 } else if (!PM_GET_PM_INFO(dip
))
6879 return (DDI_SUCCESS
);
6881 PMD(PMD_SET
, ("%s: %s@%s(%s#%d)\n", pmf
, PM_DEVICE(dip
)))
6883 ret
= pm_all_to_normal(dip
, PM_CANBLOCK_BLOCK
);
6884 if (ret
!= DDI_SUCCESS
)
6890 * This routine is called by devfs during its walk to unconfigue a node.
6891 * If the call is due to auto mod_unloads and the dip is not at its
6892 * full power, we return DDI_FAILURE to terminate the walk, otherwise
6893 * return DDI_SUCCESS.
6896 pm_pre_unconfig(dev_info_t
*dip
, int flags
, int *held
, char *devnm
)
6898 PMD_FUNC(pmf
, "pre_unconfig")
6901 if (MDI_VHCI(dip
)) {
6902 PMD(PMD_SET
, ("%s: %s@%s(%s#%d), flags=%x\n", pmf
,
6903 PM_DEVICE(dip
), flags
))
6904 ret
= mdi_power(dip
, MDI_PM_PRE_UNCONFIG
, held
, devnm
, flags
);
6905 return (ret
== MDI_SUCCESS
? DDI_SUCCESS
: DDI_FAILURE
);
6906 } else if (!PM_GET_PM_INFO(dip
))
6907 return (DDI_SUCCESS
);
6909 PMD(PMD_SET
, ("%s: %s@%s(%s#%d), flags=%x\n", pmf
, PM_DEVICE(dip
),
6914 * If the dip is a leaf node, don't power it up.
6916 if (!ddi_get_child(dip
))
6917 return (DDI_SUCCESS
);
6920 * Do not power up the node if it is called due to auto-modunload.
6922 if ((flags
& NDI_AUTODETACH
) && !pm_all_at_normal(dip
))
6923 return (DDI_FAILURE
);
6927 ret
= pm_all_to_normal(dip
, PM_CANBLOCK_BLOCK
);
6928 if (ret
!= DDI_SUCCESS
) {
6936 * Notify ppm of attach action. Parent is already held at full power by
6940 pm_pre_attach(dev_info_t
*dip
, pm_ppm_cookie_t
*cp
, ddi_attach_cmd_t cmd
)
6942 static char *me
= "pm_pre_attach";
6943 power_req_t power_req
;
6947 * Initialize and fill in the PPM cookie
6949 bzero(cp
, sizeof (*cp
));
6950 cp
->ppc_cmd
= (int)cmd
;
6951 cp
->ppc_ppm
= PPM(dip
);
6955 * DDI_ATTACH and DDI_RESUME cmds need to call platform specific
6956 * Power Management stuff. DDI_RESUME also has to purge it's
6957 * powerlevel information.
6961 if (cp
->ppc_ppm
) { /* if ppm driver claims the node */
6962 power_req
.request_type
= PMR_PPM_PRE_ATTACH
;
6963 power_req
.req
.ppm_config_req
.who
= dip
;
6965 (void) pm_ctlops(cp
->ppc_ppm
, dip
, DDI_CTLOPS_POWER
,
6966 &power_req
, &result
);
6970 power_req
.request_type
= PMR_PPM_PRE_ATTACH
;
6971 power_req
.req
.ppm_config_req
.who
= dip
;
6972 (void) pm_ctlops(NULL
, dip
,
6973 DDI_CTLOPS_POWER
, &power_req
, &result
);
6978 pm_forget_power_level(dip
);
6980 if (cp
->ppc_ppm
) { /* if ppm driver claims the node */
6981 power_req
.request_type
= PMR_PPM_PRE_RESUME
;
6982 power_req
.req
.resume_req
.who
= cp
->ppc_dip
;
6983 power_req
.req
.resume_req
.cmd
=
6984 (ddi_attach_cmd_t
)cp
->ppc_cmd
;
6985 ASSERT(PPM(cp
->ppc_dip
) == cp
->ppc_ppm
);
6986 (void) pm_ctlops(cp
->ppc_ppm
, cp
->ppc_dip
,
6987 DDI_CTLOPS_POWER
, &power_req
, &result
);
6991 power_req
.request_type
= PMR_PPM_PRE_RESUME
;
6992 power_req
.req
.resume_req
.who
= cp
->ppc_dip
;
6993 power_req
.req
.resume_req
.cmd
=
6994 (ddi_attach_cmd_t
)cp
->ppc_cmd
;
6995 (void) pm_ctlops(NULL
, cp
->ppc_dip
,
6996 DDI_CTLOPS_POWER
, &power_req
, &result
);
7010 * Nexus drivers call into pm framework to indicate which child driver is
7011 * being uninstalled. In some platforms, ppm may need to reconfigure the
7012 * hardware since the device driver is no longer installed.
7015 pm_uninit_child(dev_info_t
*dip
)
7017 power_req_t power_req
;
7019 ASSERT(ddi_binding_name(dip
));
7020 ASSERT(ddi_get_name_addr(dip
));
7022 if (pm_ppm_claimed(dip
)) { /* if ppm driver claims the node */
7023 power_req
.request_type
= PMR_PPM_UNINIT_CHILD
;
7024 power_req
.req
.ppm_config_req
.who
= dip
;
7026 return (pm_ctlops(PPM(dip
), dip
, DDI_CTLOPS_POWER
, &power_req
,
7030 /* pass it to the default handler so we can debug things */
7031 power_req
.request_type
= PMR_PPM_UNINIT_CHILD
;
7032 power_req
.req
.ppm_config_req
.who
= dip
;
7033 (void) pm_ctlops(NULL
, dip
, DDI_CTLOPS_POWER
, &power_req
, NULL
);
7036 return (DDI_SUCCESS
);
7039 * Decrement kidsupcnt so scan can turn the parent back off if it is idle
7040 * Also notify ppm of result of probe if there is a ppm that cares
7043 pm_post_probe(pm_ppm_cookie_t
*cp
, int ret
, int probe_failed
)
7045 _NOTE(ARGUNUSED(probe_failed
))
7047 power_req_t power_req
;
7049 if (cp
->ppc_ppm
) { /* if ppm driver claims the node */
7050 power_req
.request_type
= PMR_PPM_POST_PROBE
;
7051 power_req
.req
.ppm_config_req
.who
= cp
->ppc_dip
;
7052 power_req
.req
.ppm_config_req
.result
= ret
;
7053 ASSERT(PPM(cp
->ppc_dip
) == cp
->ppc_ppm
);
7054 (void) pm_ctlops(cp
->ppc_ppm
, cp
->ppc_dip
, DDI_CTLOPS_POWER
,
7055 &power_req
, &result
);
7059 power_req
.request_type
= PMR_PPM_POST_PROBE
;
7060 power_req
.req
.ppm_config_req
.who
= cp
->ppc_dip
;
7061 power_req
.req
.ppm_config_req
.result
= ret
;
7062 (void) pm_ctlops(NULL
, cp
->ppc_dip
, DDI_CTLOPS_POWER
,
7063 &power_req
, &result
);
7069 pm_post_config(dev_info_t
*dip
, char *devnm
)
7071 PMD_FUNC(pmf
, "post_config")
7073 if (MDI_VHCI(dip
)) {
7074 PMD(PMD_SET
, ("%s: %s@%s(%s#%d)\n", pmf
, PM_DEVICE(dip
)))
7075 (void) mdi_power(dip
, MDI_PM_POST_CONFIG
, NULL
, devnm
, 0);
7077 } else if (!PM_GET_PM_INFO(dip
))
7080 PMD(PMD_SET
, ("%s: %s@%s(%s#%d)\n", pmf
, PM_DEVICE(dip
)))
7085 pm_post_unconfig(dev_info_t
*dip
, int held
, char *devnm
)
7087 PMD_FUNC(pmf
, "post_unconfig")
7089 if (MDI_VHCI(dip
)) {
7090 PMD(PMD_SET
, ("%s: %s@%s(%s#%d), held = %d\n", pmf
,
7091 PM_DEVICE(dip
), held
))
7092 (void) mdi_power(dip
, MDI_PM_POST_UNCONFIG
, &held
, devnm
, 0);
7094 } else if (!PM_GET_PM_INFO(dip
))
7097 PMD(PMD_SET
, ("%s: %s@%s(%s#%d), held = %d\n", pmf
, PM_DEVICE(dip
),
7102 * We have held power in pre_unconfig, release it here.
7108 * Notify ppm of result of attach if there is a ppm that cares
7111 pm_post_attach(pm_ppm_cookie_t
*cp
, int ret
)
7114 power_req_t power_req
;
7117 if (cp
->ppc_cmd
!= DDI_ATTACH
)
7122 if (ret
== DDI_SUCCESS
) {
7124 * Attach succeeded, so proceed to doing post-attach pm tasks
7126 if (PM_GET_PM_INFO(dip
) == NULL
)
7127 (void) pm_start(dip
);
7130 * Attach may have got pm started before failing
7135 if (cp
->ppc_ppm
) { /* if ppm driver claims the node */
7136 power_req
.request_type
= PMR_PPM_POST_ATTACH
;
7137 power_req
.req
.ppm_config_req
.who
= cp
->ppc_dip
;
7138 power_req
.req
.ppm_config_req
.result
= ret
;
7139 ASSERT(PPM(cp
->ppc_dip
) == cp
->ppc_ppm
);
7140 (void) pm_ctlops(cp
->ppc_ppm
, cp
->ppc_dip
,
7141 DDI_CTLOPS_POWER
, &power_req
, &result
);
7145 power_req
.request_type
= PMR_PPM_POST_ATTACH
;
7146 power_req
.req
.ppm_config_req
.who
= cp
->ppc_dip
;
7147 power_req
.req
.ppm_config_req
.result
= ret
;
7148 (void) pm_ctlops(NULL
, cp
->ppc_dip
,
7149 DDI_CTLOPS_POWER
, &power_req
, &result
);
7155 * Notify ppm of attach action. Parent is already held at full power by
7159 pm_pre_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
, pm_ppm_cookie_t
*cp
)
7162 power_req_t power_req
;
7164 bzero(cp
, sizeof (*cp
));
7166 cp
->ppc_cmd
= (int)cmd
;
7170 pm_detaching(dip
); /* suspend pm while detaching */
7171 if (pm_ppm_claimed(dip
)) { /* if ppm driver claims node */
7172 power_req
.request_type
= PMR_PPM_PRE_DETACH
;
7173 power_req
.req
.ppm_config_req
.who
= dip
;
7175 (void) pm_ctlops(PPM(dip
), dip
, DDI_CTLOPS_POWER
,
7176 &power_req
, &result
);
7177 cp
->ppc_ppm
= PPM(dip
);
7180 /* pass to the default handler so we can debug things */
7181 power_req
.request_type
= PMR_PPM_PRE_DETACH
;
7182 power_req
.req
.ppm_config_req
.who
= dip
;
7183 (void) pm_ctlops(NULL
, dip
,
7184 DDI_CTLOPS_POWER
, &power_req
, &result
);
7196 * Dip is either a leaf node that exported "no-involuntary-power-cycles" prop.,
7197 * (if devi_pm_noinvol count is 0) or an ancestor of such a node. We need to
7198 * make an entry to record the details, which includes certain flag settings.
7201 pm_record_invol_path(char *path
, int flags
, int noinvolpm
, int volpmd
,
7202 int wasvolpmd
, major_t major
)
7204 PMD_FUNC(pmf
, "record_invol_path")
7205 major_t
pm_path_to_major(char *);
7207 pm_noinvol_t
*ip
, *np
, *pp
;
7210 plen
= strlen(path
) + 1;
7211 np
= kmem_zalloc(sizeof (*np
), KM_SLEEP
);
7213 np
->ni_path
= kmem_alloc(plen
, KM_SLEEP
);
7214 np
->ni_noinvolpm
= noinvolpm
;
7215 np
->ni_volpmd
= volpmd
;
7216 np
->ni_wasvolpmd
= wasvolpmd
;
7217 np
->ni_flags
= flags
;
7218 (void) strcpy(np
->ni_path
, path
);
7220 * If we haven't actually seen the node attached, it is hard to figure
7221 * out its major. If we could hold the node by path, we would be much
7224 if (major
== DDI_MAJOR_T_NONE
) {
7225 np
->ni_major
= pm_path_to_major(path
);
7227 np
->ni_major
= major
;
7229 rw_enter(&pm_noinvol_rwlock
, RW_WRITER
);
7230 for (ip
= pm_noinvol_head
; ip
; pp
= ip
, ip
= ip
->ni_next
) {
7231 int comp
= strcmp(path
, ip
->ni_path
);
7233 PMD(PMD_NOINVOL
, ("%s: %s insert before %s\n",
7234 pmf
, path
, ip
->ni_path
))
7235 /* insert before current entry */
7240 pm_noinvol_head
= np
;
7242 rw_exit(&pm_noinvol_rwlock
);
7244 if (pm_debug
& PMD_NOINVOL
)
7245 pr_noinvol("record_invol_path exit0");
7248 } else if (comp
== 0) {
7249 panic("%s already in pm_noinvol list", path
);
7253 * If we did not find an entry in the list that this should go before,
7254 * then it must go at the end
7257 PMD(PMD_NOINVOL
, ("%s: %s append after %s\n", pmf
, path
,
7259 ASSERT(pp
->ni_next
== 0);
7262 PMD(PMD_NOINVOL
, ("%s: %s added to end-of-list\n", pmf
, path
))
7263 ASSERT(!pm_noinvol_head
);
7264 pm_noinvol_head
= np
;
7266 rw_exit(&pm_noinvol_rwlock
);
7268 if (pm_debug
& PMD_NOINVOL
)
7269 pr_noinvol("record_invol_path exit");
7274 pm_record_invol(dev_info_t
*dip
)
7277 int pm_all_components_off(dev_info_t
*);
7278 int volpmd
= (PM_NUMCMPTS(dip
) > 0) && pm_all_components_off(dip
);
7280 pathbuf
= kmem_alloc(MAXPATHLEN
, KM_SLEEP
);
7281 (void) ddi_pathname(dip
, pathbuf
);
7283 pm_record_invol_path(pathbuf
, (DEVI(dip
)->devi_pm_flags
&
7284 (PMC_NO_INVOL
| PMC_CONSOLE_FB
)), DEVI(dip
)->devi_pm_noinvolpm
,
7285 DEVI(dip
)->devi_pm_volpmd
, volpmd
, PM_MAJOR(dip
));
7288 * If this child's detach will be holding up its ancestors, then we
7289 * allow for an exception to that if all children of this type have
7290 * gone down voluntarily.
7291 * Now walk down the tree incrementing devi_pm_noinvolpm
7293 (void) pm_noinvol_update(PM_BP_NOINVOL_DETACH
, 0, volpmd
, pathbuf
,
7295 kmem_free(pathbuf
, MAXPATHLEN
);
7299 pm_post_detach(pm_ppm_cookie_t
*cp
, int ret
)
7301 dev_info_t
*dip
= cp
->ppc_dip
;
7303 power_req_t power_req
;
7305 switch (cp
->ppc_cmd
) {
7307 if (cp
->ppc_ppm
) { /* if ppm driver claims the node */
7308 power_req
.request_type
= PMR_PPM_POST_DETACH
;
7309 power_req
.req
.ppm_config_req
.who
= cp
->ppc_dip
;
7310 power_req
.req
.ppm_config_req
.result
= ret
;
7311 ASSERT(PPM(cp
->ppc_dip
) == cp
->ppc_ppm
);
7312 (void) pm_ctlops(cp
->ppc_ppm
, cp
->ppc_dip
,
7313 DDI_CTLOPS_POWER
, &power_req
, &result
);
7317 power_req
.request_type
= PMR_PPM_POST_DETACH
;
7318 power_req
.req
.ppm_config_req
.who
= cp
->ppc_dip
;
7319 power_req
.req
.ppm_config_req
.result
= ret
;
7320 (void) pm_ctlops(NULL
, cp
->ppc_dip
,
7321 DDI_CTLOPS_POWER
, &power_req
, &result
);
7324 if (ret
== DDI_SUCCESS
) {
7326 * For hotplug detach we assume it is *really* gone
7328 if (cp
->ppc_cmd
== DDI_DETACH
&&
7329 ((DEVI(dip
)->devi_pm_flags
&
7330 (PMC_NO_INVOL
| PMC_CONSOLE_FB
)) ||
7331 DEVI(dip
)->devi_pm_noinvolpm
))
7332 pm_record_invol(dip
);
7333 DEVI(dip
)->devi_pm_flags
&=
7334 ~(PMC_NO_INVOL
| PMC_NOINVOL_DONE
);
7337 * If console fb is detaching, then we don't need to
7338 * worry any more about it going off (pm_detaching has
7339 * brought up all components)
7341 if (PM_IS_CFB(dip
)) {
7342 mutex_enter(&pm_cfb_lock
);
7343 ASSERT(cfb_dip_detaching
);
7344 ASSERT(cfb_dip
== NULL
);
7345 ASSERT(pm_cfb_comps_off
== 0);
7346 cfb_dip_detaching
= NULL
;
7347 mutex_exit(&pm_cfb_lock
);
7349 pm_stop(dip
); /* make it permanent */
7351 if (PM_IS_CFB(dip
)) {
7352 mutex_enter(&pm_cfb_lock
);
7353 ASSERT(cfb_dip_detaching
);
7354 ASSERT(cfb_dip
== NULL
);
7355 ASSERT(pm_cfb_comps_off
== 0);
7356 cfb_dip
= cfb_dip_detaching
;
7357 cfb_dip_detaching
= NULL
;
7358 mutex_exit(&pm_cfb_lock
);
7360 pm_detach_failed(dip
); /* resume power management */
7363 case DDI_PM_SUSPEND
:
7366 break; /* legal, but nothing to do */
7369 panic("pm_post_detach: unrecognized cmd %d for detach",
7379 * Called after vfs_mountroot has got the clock started to fix up timestamps
7380 * that were set when root bush drivers attached. hresttime was 0 then, so the
7381 * devices look busy but have a 0 busycnt
7384 pm_adjust_timestamps(dev_info_t
*dip
, void *arg
)
7386 _NOTE(ARGUNUSED(arg
))
7388 pm_info_t
*info
= PM_GET_PM_INFO(dip
);
7389 struct pm_component
*cp
;
7393 return (DDI_WALK_CONTINUE
);
7395 for (i
= 0; i
< PM_NUMCMPTS(dip
); i
++) {
7397 if (cp
->pmc_timestamp
== 0 && cp
->pmc_busycount
== 0)
7398 cp
->pmc_timestamp
= gethrestime_sec();
7400 PM_UNLOCK_BUSY(dip
);
7401 return (DDI_WALK_CONTINUE
);
7405 * Called at attach time to see if the device being attached has a record in
7406 * the no involuntary power cycles list. If so, we do some bookkeeping on the
7407 * parents and set a flag in the dip
7410 pm_noinvol_specd(dev_info_t
*dip
)
7412 PMD_FUNC(pmf
, "noinvol_specd")
7414 pm_noinvol_t
*ip
, *pp
= NULL
;
7418 if (DEVI(dip
)->devi_pm_flags
& PMC_NOINVOL_DONE
)
7420 DEVI(dip
)->devi_pm_flags
|= PMC_NOINVOL_DONE
;
7421 pathbuf
= kmem_alloc(MAXPATHLEN
, KM_SLEEP
);
7422 (void) ddi_pathname(dip
, pathbuf
);
7425 DEVI(dip
)->devi_pm_volpmd
= 0;
7426 DEVI(dip
)->devi_pm_noinvolpm
= 0;
7427 rw_enter(&pm_noinvol_rwlock
, RW_READER
);
7428 for (ip
= pm_noinvol_head
; ip
; pp
= ip
, ip
= ip
->ni_next
) {
7429 PMD(PMD_NOINVOL
, ("%s: comparing '%s' to '%s'\n",
7430 pmf
, pathbuf
, ip
->ni_path
))
7431 if (strcmp(pathbuf
, ip
->ni_path
) == 0) {
7436 rw_exit(&pm_noinvol_rwlock
);
7439 kmem_free(pathbuf
, MAXPATHLEN
);
7442 rw_enter(&pm_noinvol_rwlock
, RW_WRITER
);
7444 for (ip
= pm_noinvol_head
; ip
; pp
= ip
, ip
= ip
->ni_next
) {
7445 PMD(PMD_NOINVOL
, ("%s: comparing '%s' to '%s'\n",
7446 pmf
, pathbuf
, ip
->ni_path
))
7447 if (strcmp(pathbuf
, ip
->ni_path
) == 0) {
7448 ip
->ni_flags
&= ~PMC_DRIVER_REMOVED
;
7449 DEVI(dip
)->devi_pm_flags
|= ip
->ni_flags
;
7451 * Handle special case of console fb
7453 if (PM_IS_CFB(dip
)) {
7454 mutex_enter(&pm_cfb_lock
);
7456 PMD(PMD_CFB
, ("%s: %s@%s(%s#%d) setting "
7457 "cfb_dip\n", pmf
, PM_DEVICE(dip
)))
7458 mutex_exit(&pm_cfb_lock
);
7460 DEVI(dip
)->devi_pm_noinvolpm
= ip
->ni_noinvolpm
;
7461 ASSERT((DEVI(dip
)->devi_pm_flags
&
7462 (PMC_NO_INVOL
| PMC_CONSOLE_FB
)) ||
7463 DEVI(dip
)->devi_pm_noinvolpm
);
7464 DEVI(dip
)->devi_pm_volpmd
= ip
->ni_volpmd
;
7465 PMD(PMD_NOINVOL
, ("%s: noinvol=%d, volpmd=%d, "
7466 "wasvolpmd=%d, flags=%x, path=%s\n", pmf
,
7467 ip
->ni_noinvolpm
, ip
->ni_volpmd
,
7468 ip
->ni_wasvolpmd
, ip
->ni_flags
, ip
->ni_path
))
7470 * free the entry in hopes the list will now be empty
7471 * and we won't have to search it any more until the
7475 PMD(PMD_NOINVOL
, ("%s: free %s, prev %s\n",
7476 pmf
, ip
->ni_path
, pp
->ni_path
))
7477 pp
->ni_next
= ip
->ni_next
;
7479 PMD(PMD_NOINVOL
, ("%s: free %s head\n",
7481 ASSERT(pm_noinvol_head
== ip
);
7482 pm_noinvol_head
= ip
->ni_next
;
7485 wasvolpmd
= ip
->ni_wasvolpmd
;
7486 rw_exit(&pm_noinvol_rwlock
);
7487 kmem_free(ip
->ni_path
, ip
->ni_size
);
7488 kmem_free(ip
, sizeof (*ip
));
7490 * Now walk up the tree decrementing devi_pm_noinvolpm
7491 * (and volpmd if appropriate)
7493 (void) pm_noinvol_update(PM_BP_NOINVOL_ATTACH
, 0,
7494 wasvolpmd
, pathbuf
, dip
);
7496 if (pm_debug
& PMD_NOINVOL
)
7497 pr_noinvol("noinvol_specd exit");
7499 kmem_free(pathbuf
, MAXPATHLEN
);
7503 kmem_free(pathbuf
, MAXPATHLEN
);
7504 rw_exit(&pm_noinvol_rwlock
);
7509 pm_all_components_off(dev_info_t
*dip
)
7514 for (i
= 0; i
< PM_NUMCMPTS(dip
); i
++) {
7516 if (cp
->pmc_cur_pwr
== PM_LEVEL_UNKNOWN
||
7517 cp
->pmc_comp
.pmc_lvals
[cp
->pmc_cur_pwr
])
7520 return (1); /* all off */
7524 * Make sure that all "no involuntary power cycles" devices are attached.
7525 * Called before doing a cpr suspend to make sure the driver has a say about
7529 pm_reattach_noinvol(void)
7531 PMD_FUNC(pmf
, "reattach_noinvol")
7537 * Prevent the modunload thread from unloading any modules until we
7538 * have completely stopped all kernel threads.
7540 modunload_disable();
7541 for (ip
= pm_noinvol_head
; ip
; ip
= ip
->ni_next
) {
7543 * Forget we'v ever seen any entry
7545 ip
->ni_persistent
= 0;
7548 rw_enter(&pm_noinvol_rwlock
, RW_READER
);
7549 for (ip
= pm_noinvol_head
; ip
; ip
= ip
->ni_next
) {
7555 if (path
!= NULL
&& !(ip
->ni_flags
& PMC_DRIVER_REMOVED
)) {
7556 if (ip
->ni_persistent
) {
7558 * If we weren't able to make this entry
7559 * go away, then we give up, as
7560 * holding/attaching the driver ought to have
7561 * resulted in this entry being deleted
7563 PMD(PMD_NOINVOL
, ("%s: can't reattach %s "
7564 "(%s|%d)\n", pmf
, ip
->ni_path
,
7565 ddi_major_to_name(maj
), (int)maj
))
7566 cmn_err(CE_WARN
, "cpr: unable to reattach %s ",
7569 rw_exit(&pm_noinvol_rwlock
);
7572 ip
->ni_persistent
++;
7573 rw_exit(&pm_noinvol_rwlock
);
7574 PMD(PMD_NOINVOL
, ("%s: holding %s\n", pmf
, path
))
7575 dip
= e_ddi_hold_devi_by_path(path
, 0);
7577 PMD(PMD_NOINVOL
, ("%s: can't hold (%s|%d)\n",
7578 pmf
, path
, (int)maj
))
7579 cmn_err(CE_WARN
, "cpr: unable to hold %s "
7584 PMD(PMD_DHR
, ("%s: release %s\n", pmf
, path
))
7586 * Since the modunload thread is stopped, we
7587 * don't have to keep the driver held, which
7588 * saves a ton of bookkeeping
7590 ddi_release_devi(dip
);
7594 PMD(PMD_NOINVOL
, ("%s: skip %s; unknown major\n",
7599 rw_exit(&pm_noinvol_rwlock
);
7604 pm_reattach_noinvol_fini(void)
7610 * Display pm support code
7615 * console frame-buffer power-mgmt gets enabled when debugging
7616 * services are not present or console fbpm override is set
7619 pm_cfb_setup(const char *stdout_path
)
7621 PMD_FUNC(pmf
, "cfb_setup")
7622 extern int obpdebug
;
7626 extern dev_info_t
*fbdip
;
7629 * By virtue of this function being called (from consconfig),
7630 * we know stdout is a framebuffer.
7632 stdout_is_framebuffer
= 1;
7634 if (obpdebug
|| (boothowto
& RB_DEBUG
)) {
7635 if (pm_cfb_override
== 0) {
7637 * Console is frame buffer, but we want to suppress
7638 * pm on it because of debugging setup
7641 cmn_err(CE_NOTE
, "Kernel debugger present: disabling "
7642 "console power management.");
7644 * however, we still need to know which is the console
7645 * fb in order to suppress pm on it
7648 cmn_err(CE_WARN
, "Kernel debugger present: see "
7649 "kmdb(1M) for interaction with power management.");
7654 * IF console is fb and is power managed, don't do prom_printfs from
7657 if (pm_cfb_enabled
&& !pm_debug_to_console
) {
7659 prom_printf("pm debug output will be to log only\n");
7663 devname
= i_ddi_strdup((char *)stdout_path
, KM_SLEEP
);
7664 devname_len
= strlen(devname
) + 1;
7665 PMD(PMD_CFB
, ("%s: stripped %s\n", pmf
, devname
))
7666 /* if the driver is attached */
7667 if ((dip
= fbdip
) != NULL
) {
7668 PMD(PMD_CFB
, ("%s: attached: %s@%s(%s#%d)\n", pmf
,
7671 * We set up here as if the driver were power manageable in case
7672 * we get a later attach of a pm'able driver (which would result
7676 DEVI(dip
)->devi_pm_flags
|= (PMC_CONSOLE_FB
| PMC_NO_INVOL
);
7677 PMD(PMD_CFB
, ("%s: cfb_dip -> %s@%s(%s#%d)\n", pmf
,
7680 if (!(PM_GET_PM_INFO(dip
) != NULL
&& PM_NUMCMPTS(dip
))) {
7681 PMD(PMD_CFB
, ("%s: %s@%s(%s#%d) not power-managed\n",
7682 pmf
, PM_DEVICE(dip
)))
7687 PMD(PMD_CFB
, ("%s: pntd %s failed\n", pmf
, devname
))
7688 pm_record_invol_path(devname
,
7689 (PMC_CONSOLE_FB
| PMC_NO_INVOL
), 1, 0, 0,
7691 for (ep
= strrchr(devname
, '/'); ep
!= devname
;
7692 ep
= strrchr(devname
, '/')) {
7693 PMD(PMD_CFB
, ("%s: devname %s\n", pmf
, devname
))
7695 dip
= pm_name_to_dip(devname
, 0);
7698 * Walk up the tree incrementing
7701 (void) pm_noinvol_update(PM_BP_NOINVOL_CFB
,
7702 0, 0, devname
, dip
);
7705 pm_record_invol_path(devname
,
7706 PMC_NO_INVOL
, 1, 0, 0, DDI_MAJOR_T_NONE
);
7710 kmem_free(devname
, devname_len
);
7716 mutex_enter(&pm_cfb_lock
);
7718 * this call isn't using the console any more, it is ok to take it
7719 * down if the count goes to 0
7722 mutex_exit(&pm_cfb_lock
);
7726 * software interrupt handler for fbpm; this function exists because we can't
7727 * bring up the frame buffer power from above lock level. So if we need to,
7728 * we instead schedule a softint that runs this routine and takes us into
7729 * debug_enter (a bit delayed from the original request, but avoiding a panic).
7732 pm_cfb_softint(caddr_t int_handler_arg
)
7734 _NOTE(ARGUNUSED(int_handler_arg
))
7735 int rval
= DDI_INTR_UNCLAIMED
;
7737 mutex_enter(&pm_cfb_lock
);
7738 if (pm_soft_pending
) {
7739 mutex_exit(&pm_cfb_lock
);
7740 debug_enter((char *)NULL
);
7741 /* acquired in debug_enter before calling pm_cfb_trigger */
7743 mutex_enter(&pm_cfb_lock
);
7744 pm_soft_pending
= B_FALSE
;
7745 mutex_exit(&pm_cfb_lock
);
7746 rval
= DDI_INTR_CLAIMED
;
7748 mutex_exit(&pm_cfb_lock
);
7754 pm_cfb_setup_intr(void)
7756 PMD_FUNC(pmf
, "cfb_setup_intr")
7757 extern void prom_set_outfuncs(void (*)(void), void (*)(void));
7758 void pm_cfb_check_and_powerup(void);
7760 mutex_init(&pm_cfb_lock
, NULL
, MUTEX_SPIN
, (void *)ipltospl(SPL8
));
7762 mutex_init(&pm_debug_lock
, NULL
, MUTEX_SPIN
, (void *)ipltospl(SPL8
));
7765 if (!stdout_is_framebuffer
) {
7766 PMD(PMD_CFB
, ("%s: console not fb\n", pmf
))
7771 * setup software interrupt handler
7773 if (ddi_add_softintr(ddi_root_node(), DDI_SOFTINT_HIGH
, &pm_soft_id
,
7774 NULL
, NULL
, pm_cfb_softint
, NULL
) != DDI_SUCCESS
)
7775 panic("pm: unable to register soft intr.");
7777 prom_set_outfuncs(pm_cfb_check_and_powerup
, pm_cfb_rele
);
7781 * Checks to see if it is safe to write to the console wrt power management
7782 * (i.e. if the console is a framebuffer, then it must be at full power)
7783 * returns 1 when power is off (power-up is needed)
7784 * returns 0 when power is on (power-up not needed)
7787 pm_cfb_check_and_hold(void)
7790 * cfb_dip is set iff console is a power manageable frame buffer
7793 extern int modrootloaded
;
7795 mutex_enter(&pm_cfb_lock
);
7797 ASSERT(cfb_inuse
); /* wrap? */
7798 if (modrootloaded
&& cfb_dip
) {
7800 * don't power down the frame buffer, the prom is using it
7802 if (pm_cfb_comps_off
) {
7803 mutex_exit(&pm_cfb_lock
);
7807 mutex_exit(&pm_cfb_lock
);
7812 * turn on cfb power (which is known to be off).
7813 * Must be called below lock level!
7816 pm_cfb_powerup(void)
7824 * Can't reenter prom_prekern, so suppress pm debug messages
7825 * (still go to circular buffer).
7827 mutex_enter(&pm_debug_lock
);
7829 mutex_exit(&pm_debug_lock
);
7831 info
= PM_GET_PM_INFO(cfb_dip
);
7834 ccount
= PM_NUMCMPTS(cfb_dip
);
7835 for (ci
= 0; ci
< ccount
; ci
++) {
7836 norm
= pm_get_normal_power(cfb_dip
, ci
);
7837 (void) pm_set_power(cfb_dip
, ci
, norm
, PM_LEVEL_UPONLY
,
7838 PM_CANBLOCK_BYPASS
, 0, &unused
);
7841 mutex_enter(&pm_debug_lock
);
7843 mutex_exit(&pm_debug_lock
);
7848 * Check if the console framebuffer is powered up. If not power it up.
7849 * Note: Calling pm_cfb_check_and_hold has put a hold on the power state which
7850 * must be released by calling pm_cfb_rele when the console fb operation
7854 pm_cfb_check_and_powerup(void)
7856 if (pm_cfb_check_and_hold())
7861 * Trigger a low level interrupt to power up console frame buffer.
7864 pm_cfb_trigger(void)
7866 if (cfb_dip
== NULL
)
7869 mutex_enter(&pm_cfb_lock
);
7871 * If the machine appears to be hung, pulling the keyboard connector of
7872 * the console will cause a high level interrupt and go to debug_enter.
7873 * But, if the fb is powered down, this routine will be called to bring
7874 * it up (by generating a softint to do the work). If a second attempt
7875 * at triggering this softint happens before the first one completes,
7876 * we panic as softints are most likely not being handled.
7878 if (pm_soft_pending
) {
7879 panicstr
= "pm_cfb_trigger: failed to enter the debugger";
7880 panic(panicstr
); /* does a power up at any intr level */
7883 pm_soft_pending
= B_TRUE
;
7884 mutex_exit(&pm_cfb_lock
);
7885 ddi_trigger_softintr(pm_soft_id
);
7888 static major_t
i_path_to_major(char *, char *);
7891 pm_path_to_major(char *path
)
7893 PMD_FUNC(pmf
, "path_to_major")
7898 PMD(PMD_NOINVOL
, ("%s: %s\n", pmf
, path
))
7900 np
= strrchr(path
, '/');
7905 len
= strlen(np
) + 1;
7906 bp
= kmem_alloc(len
, KM_SLEEP
);
7907 (void) strcpy(bp
, np
);
7908 if ((ap
= strchr(bp
, '@')) != NULL
) {
7911 PMD(PMD_NOINVOL
, ("%s: %d\n", pmf
, ddi_name_to_major(np
)))
7912 ret
= i_path_to_major(path
, np
);
7919 clock_t pt_sleep
= 1;
7924 char *pm_msgbuf
= NULL
;
7925 int pm_logpages
= 0x100;
7926 #include <sys/sunldi.h>
7927 #include <sys/uio.h>
7928 clock_t pm_log_sleep
= 1000;
7929 int pm_extra_cr
= 1;
7930 volatile int pm_tty
= 1;
7932 #define PMLOGPGS pm_logpages
7935 void pm_printf(char *s
);
7940 pm_log(const char *fmt
, ...)
7945 mutex_enter(&pm_debug_lock
);
7946 if (pm_msgbuf
== NULL
) {
7947 pm_msgbuf
= kmem_zalloc(mmu_ptob(PMLOGPGS
), KM_SLEEP
);
7948 pm_bufend
= pm_msgbuf
+ mmu_ptob(PMLOGPGS
) - 1;
7949 pm_msgp
= pm_msgbuf
;
7952 size
= vsnprintf(NULL
, 0, fmt
, adx
) + 1;
7955 if (size
> (pm_bufend
- pm_msgp
)) { /* wraps */
7956 bzero(pm_msgp
, pm_bufend
- pm_msgp
);
7957 (void) vsnprintf(pm_msgbuf
, size
, fmt
, adx
);
7958 if (!pm_divertdebug
)
7959 prom_printf("%s", pm_msgp
);
7967 pm_msgp
= pm_msgbuf
+ size
;
7969 (void) vsnprintf(pm_msgp
, size
, fmt
, adx
);
7977 if (!pm_divertdebug
)
7978 prom_printf("%s", pm_msgp
);
7982 mutex_exit(&pm_debug_lock
);
7983 drv_usecwait((clock_t)pm_log_sleep
);
7988 * We want to save the state of any directly pm'd devices over the suspend/
7989 * resume process so that we can put them back the way the controlling
7990 * process left them.
7993 pm_save_direct_levels(void)
7995 pm_processes_stopped
= 1;
7996 ddi_walk_devs(ddi_root_node(), pm_save_direct_lvl_walk
, 0);
8000 pm_save_direct_lvl_walk(dev_info_t
*dip
, void *arg
)
8002 _NOTE(ARGUNUSED(arg
))
8005 pm_info_t
*info
= PM_GET_PM_INFO(dip
);
8008 return (DDI_WALK_CONTINUE
);
8010 if (PM_ISDIRECT(dip
) && !PM_ISBC(dip
)) {
8011 if (PM_NUMCMPTS(dip
) > 2) {
8012 info
->pmi_lp
= kmem_alloc(PM_NUMCMPTS(dip
) *
8013 sizeof (int), KM_SLEEP
);
8016 ip
= info
->pmi_levels
;
8018 /* autopm and processes are stopped, ok not to lock power */
8019 for (i
= 0; i
< PM_NUMCMPTS(dip
); i
++)
8020 *ip
++ = PM_CURPOWER(dip
, i
);
8022 * There is a small window between stopping the
8023 * processes and setting pm_processes_stopped where
8024 * a driver could get hung up in a pm_raise_power()
8025 * call. Free any such driver now.
8027 pm_proceed(dip
, PMP_RELEASE
, -1, -1);
8030 return (DDI_WALK_CONTINUE
);
8034 pm_restore_direct_levels(void)
8037 * If cpr didn't call pm_save_direct_levels, (because stopping user
8038 * threads failed) then we don't want to try to restore them
8040 if (!pm_processes_stopped
)
8043 ddi_walk_devs(ddi_root_node(), pm_restore_direct_lvl_walk
, 0);
8044 pm_processes_stopped
= 0;
8048 pm_restore_direct_lvl_walk(dev_info_t
*dip
, void *arg
)
8050 _NOTE(ARGUNUSED(arg
))
8051 PMD_FUNC(pmf
, "restore_direct_lvl_walk")
8055 pm_info_t
*info
= PM_GET_PM_INFO(dip
);
8057 return (DDI_WALK_CONTINUE
);
8059 if (PM_ISDIRECT(dip
) && !PM_ISBC(dip
)) {
8060 if ((nc
= PM_NUMCMPTS(dip
)) > 2) {
8061 ip
= &info
->pmi_lp
[nc
- 1];
8063 ip
= &info
->pmi_levels
[nc
- 1];
8066 * Because fb drivers fail attempts to turn off the
8067 * fb when the monitor is on, but treat a request to
8068 * turn on the monitor as a request to turn on the
8069 * fb too, we process components in descending order
8070 * Because autopm is disabled and processes aren't
8071 * running, it is ok to examine current power outside
8074 for (i
= nc
- 1; i
>= 0; i
--, ip
--) {
8075 if (PM_CURPOWER(dip
, i
) == *ip
)
8077 if (pm_set_power(dip
, i
, *ip
, PM_LEVEL_EXACT
,
8078 PM_CANBLOCK_BYPASS
, 0, &result
) != DDI_SUCCESS
) {
8079 cmn_err(CE_WARN
, "cpr: unable "
8080 "to restore power level of "
8081 "component %d of directly "
8082 "power manged device %s@%s"
8086 PMD(PMD_FAIL
, ("%s: failed to restore "
8087 "%s@%s(%s#%d)[%d] exact(%d)->%d, "
8088 "errno %d\n", pmf
, PM_DEVICE(dip
), i
,
8089 PM_CURPOWER(dip
, i
), *ip
, result
))
8093 kmem_free(info
->pmi_lp
, nc
* sizeof (int));
8094 info
->pmi_lp
= NULL
;
8097 return (DDI_WALK_CONTINUE
);
8101 * Stolen from the bootdev module
8102 * attempt to convert a path to a major number
8105 i_path_to_major(char *path
, char *leaf_name
)
8107 extern major_t
path_to_major(char *pathname
);
8110 if ((maj
= path_to_major(path
)) == DDI_MAJOR_T_NONE
) {
8111 maj
= ddi_name_to_major(leaf_name
);
8117 static void i_pm_driver_removed(major_t major
);
8120 * When user calls rem_drv, we need to forget no-involuntary-power-cycles state
8121 * An entry in the list means that the device is detached, so we need to
8122 * adjust its ancestors as if they had just seen this attach, and any detached
8123 * ancestors need to have their list entries adjusted.
8126 pm_driver_removed(major_t major
)
8130 * Serialize removal of drivers. This is to keep ancestors of
8131 * a node that is being deleted from getting deleted and added back
8132 * with different counters.
8134 mutex_enter(&pm_remdrv_lock
);
8135 i_pm_driver_removed(major
);
8136 mutex_exit(&pm_remdrv_lock
);
8139 static void adjust_ancestors(char *, int);
8140 static int pm_is_noinvol_ancestor(pm_noinvol_t
*);
8141 static void pm_noinvol_process_ancestors(char *);
8144 * This routine is called recursively by pm_noinvol_process_ancestors()
8147 i_pm_driver_removed(major_t major
)
8149 PMD_FUNC(pmf
, "driver_removed")
8150 pm_noinvol_t
*ip
, *pp
= NULL
;
8152 ASSERT(major
!= DDI_MAJOR_T_NONE
);
8153 PMD(PMD_NOINVOL
, ("%s: %s\n", pmf
, ddi_major_to_name(major
)))
8155 rw_enter(&pm_noinvol_rwlock
, RW_WRITER
);
8156 for (ip
= pm_noinvol_head
; ip
; pp
= ip
, ip
= ip
->ni_next
) {
8157 if (major
!= ip
->ni_major
)
8160 * If it is an ancestor of no-invol node, which is
8161 * not removed, skip it. This is to cover the case of
8162 * ancestor removed without removing its descendants.
8164 if (pm_is_noinvol_ancestor(ip
)) {
8165 ip
->ni_flags
|= PMC_DRIVER_REMOVED
;
8168 wasvolpmd
= ip
->ni_wasvolpmd
;
8170 * remove the entry from the list
8173 PMD(PMD_NOINVOL
, ("%s: freeing %s, prev is %s\n",
8174 pmf
, ip
->ni_path
, pp
->ni_path
))
8175 pp
->ni_next
= ip
->ni_next
;
8177 PMD(PMD_NOINVOL
, ("%s: free %s head\n", pmf
,
8179 ASSERT(pm_noinvol_head
== ip
);
8180 pm_noinvol_head
= ip
->ni_next
;
8182 rw_exit(&pm_noinvol_rwlock
);
8183 adjust_ancestors(ip
->ni_path
, wasvolpmd
);
8185 * Had an ancestor been removed before this node, it would have
8186 * been skipped. Adjust the no-invol counters for such skipped
8189 pm_noinvol_process_ancestors(ip
->ni_path
);
8190 kmem_free(ip
->ni_path
, ip
->ni_size
);
8191 kmem_free(ip
, sizeof (*ip
));
8194 rw_exit(&pm_noinvol_rwlock
);
8198 * returns 1, if *aip is a ancestor of a no-invol node
8202 pm_is_noinvol_ancestor(pm_noinvol_t
*aip
)
8206 ASSERT(strlen(aip
->ni_path
) != 0);
8207 for (ip
= pm_noinvol_head
; ip
; ip
= ip
->ni_next
) {
8211 * To be an ancestor, the path must be an initial substring of
8212 * the descendent, and end just before a '/' in the
8213 * descendent's path.
8215 if ((strstr(ip
->ni_path
, aip
->ni_path
) == ip
->ni_path
) &&
8216 (ip
->ni_path
[strlen(aip
->ni_path
)] == '/'))
8223 * scan through the pm_noinvolpm list adjusting ancestors of the current
8224 * node; Modifies string *path.
8227 adjust_ancestors(char *path
, int wasvolpmd
)
8229 PMD_FUNC(pmf
, "adjust_ancestors")
8232 pm_noinvol_t
*pp
= NULL
;
8233 major_t locked
= DDI_MAJOR_T_NONE
;
8236 size_t pathbuflen
= strlen(path
) + 1;
8239 * First we look up the ancestor's dip. If we find it, then we
8240 * adjust counts up the tree
8242 PMD(PMD_NOINVOL
, ("%s: %s wasvolpmd %d\n", pmf
, path
, wasvolpmd
))
8243 pathbuf
= kmem_alloc(pathbuflen
, KM_SLEEP
);
8244 (void) strcpy(pathbuf
, path
);
8245 cp
= strrchr(pathbuf
, '/');
8247 /* if no ancestors, then nothing to do */
8248 kmem_free(pathbuf
, pathbuflen
);
8252 dip
= pm_name_to_dip(pathbuf
, 1);
8254 locked
= PM_MAJOR(dip
);
8256 (void) pm_noinvol_update(PM_BP_NOINVOL_REMDRV
, 0, wasvolpmd
,
8259 if (locked
!= DDI_MAJOR_T_NONE
)
8260 ddi_release_devi(dip
);
8263 size_t len
= strlen(pathbuf
) + 1;
8267 * Now check for ancestors that exist only in the list
8269 apath
= kmem_alloc(len
, KM_SLEEP
);
8270 (void) strcpy(apath
, pathbuf
);
8271 rw_enter(&pm_noinvol_rwlock
, RW_WRITER
);
8272 for (lp
= pm_noinvol_head
; lp
; pp
= lp
, lp
= lp
->ni_next
) {
8274 * This can only happen once. Since we have to drop
8275 * the lock, we need to extract the relevant info.
8277 if (strcmp(pathbuf
, lp
->ni_path
) == 0) {
8278 PMD(PMD_NOINVOL
, ("%s: %s no %d -> %d\n", pmf
,
8279 lp
->ni_path
, lp
->ni_noinvolpm
,
8280 lp
->ni_noinvolpm
- 1))
8282 if (wasvolpmd
&& lp
->ni_volpmd
) {
8283 PMD(PMD_NOINVOL
, ("%s: %s vol %d -> "
8284 "%d\n", pmf
, lp
->ni_path
,
8285 lp
->ni_volpmd
, lp
->ni_volpmd
- 1))
8289 * remove the entry from the list, if there
8290 * are no more no-invol descendants and node
8291 * itself is not a no-invol node.
8293 if (!(lp
->ni_noinvolpm
||
8294 (lp
->ni_flags
& PMC_NO_INVOL
))) {
8295 ASSERT(lp
->ni_volpmd
== 0);
8297 PMD(PMD_NOINVOL
, ("%s: freeing "
8298 "%s, prev is %s\n", pmf
,
8299 lp
->ni_path
, pp
->ni_path
))
8300 pp
->ni_next
= lp
->ni_next
;
8302 PMD(PMD_NOINVOL
, ("%s: free %s "
8303 "head\n", pmf
, lp
->ni_path
))
8304 ASSERT(pm_noinvol_head
== lp
);
8305 pm_noinvol_head
= lp
->ni_next
;
8308 rw_exit(&pm_noinvol_rwlock
);
8309 adjust_ancestors(apath
, wasvolpmd
);
8311 (void) strcpy(apath
, pathbuf
);
8312 kmem_free(lp
->ni_path
, lp
->ni_size
);
8313 kmem_free(lp
, sizeof (*lp
));
8319 rw_exit(&pm_noinvol_rwlock
);
8320 adjust_ancestors(apath
, wasvolpmd
);
8321 kmem_free(apath
, len
);
8323 kmem_free(pathbuf
, pathbuflen
);
8327 * Do no-invol processing for any ancestors i.e. adjust counters of ancestors,
8328 * which were skipped even though their drivers were removed.
8331 pm_noinvol_process_ancestors(char *path
)
8335 rw_enter(&pm_noinvol_rwlock
, RW_READER
);
8336 for (lp
= pm_noinvol_head
; lp
; lp
= lp
->ni_next
) {
8337 if (strstr(path
, lp
->ni_path
) &&
8338 (lp
->ni_flags
& PMC_DRIVER_REMOVED
)) {
8339 rw_exit(&pm_noinvol_rwlock
);
8340 i_pm_driver_removed(lp
->ni_major
);
8344 rw_exit(&pm_noinvol_rwlock
);
8348 * Returns true if (detached) device needs to be kept up because it exported the
8349 * "no-involuntary-power-cycles" property or we're pretending it did (console
8350 * fb case) or it is an ancestor of such a device and has used up the "one
8351 * free cycle" allowed when all such leaf nodes have voluntarily powered down
8352 * upon detach. In any event, we need an exact hit on the path or we return
8356 pm_noinvol_detached(char *path
)
8358 PMD_FUNC(pmf
, "noinvol_detached")
8362 rw_enter(&pm_noinvol_rwlock
, RW_READER
);
8363 for (ip
= pm_noinvol_head
; ip
; ip
= ip
->ni_next
) {
8364 if (strcmp(path
, ip
->ni_path
) == 0) {
8365 if (ip
->ni_flags
& PMC_CONSOLE_FB
) {
8366 PMD(PMD_NOINVOL
| PMD_CFB
, ("%s: inhibits CFB "
8372 if (ip
->ni_noinvolpm
!= ip
->ni_volpmd
)
8373 PMD(PMD_NOINVOL
, ("%s: (%d != %d) inhibits %s"
8374 "\n", pmf
, ip
->ni_noinvolpm
, ip
->ni_volpmd
,
8377 ret
= (ip
->ni_noinvolpm
!= ip
->ni_volpmd
);
8381 rw_exit(&pm_noinvol_rwlock
);
8386 pm_is_cfb(dev_info_t
*dip
)
8388 return (dip
== cfb_dip
);
8393 * Return true if all components of the console frame buffer are at
8394 * "normal" power, i.e., fully on. For the case where the console is not
8395 * a framebuffer, we also return true
8400 return (pm_cfb_comps_off
== 0);
8405 * Preventing scan from powering down the node by incrementing the
8409 pm_hold_power(dev_info_t
*dip
)
8411 e_pm_hold_rele_power(dip
, 1);
8415 * Releasing the hold by decrementing the kidsupcnt allowing scan
8416 * to power down the node if all conditions are met.
8419 pm_rele_power(dev_info_t
*dip
)
8421 e_pm_hold_rele_power(dip
, -1);
8425 * A wrapper of pm_all_to_normal() to power up a dip
8426 * to its normal level
8429 pm_powerup(dev_info_t
*dip
)
8431 PMD_FUNC(pmf
, "pm_powerup")
8433 PMD(PMD_ALLNORM
, ("%s: %s@%s(%s#%d)\n", pmf
, PM_DEVICE(dip
)))
8434 ASSERT(!(servicing_interrupt()));
8437 * in case this node is not already participating pm
8439 if (!PM_GET_PM_INFO(dip
)) {
8440 if (!DEVI_IS_ATTACHING(dip
))
8441 return (DDI_SUCCESS
);
8442 if (pm_start(dip
) != DDI_SUCCESS
)
8443 return (DDI_FAILURE
);
8444 if (!PM_GET_PM_INFO(dip
))
8445 return (DDI_SUCCESS
);
8448 return (pm_all_to_normal(dip
, PM_CANBLOCK_BLOCK
));
8452 pm_rescan_walk(dev_info_t
*dip
, void *arg
)
8454 _NOTE(ARGUNUSED(arg
))
8456 if (!PM_GET_PM_INFO(dip
) || PM_ISBC(dip
))
8457 return (DDI_WALK_CONTINUE
);
8460 * Currently pm_cpr_callb/resume code is the only caller
8461 * and it needs to make sure that stopped scan get
8462 * reactivated. Otherwise, rescan walk needn't reactive
8467 (void) pm_rescan(dip
);
8468 return (DDI_WALK_CONTINUE
);
8472 pm_get_next_descendent(dev_info_t
*dip
, dev_info_t
*tdip
)
8474 dev_info_t
*wdip
, *pdip
;
8476 for (wdip
= tdip
; wdip
!= dip
; wdip
= pdip
) {
8477 pdip
= ddi_get_parent(wdip
);
8485 pm_busop_bus_power(dev_info_t
*dip
, void *impl_arg
, pm_bus_power_op_t op
,
8486 void *arg
, void *result
)
8488 PMD_FUNC(pmf
, "bp_bus_power")
8491 pm_bp_child_pwrchg_t
*bpc
;
8493 pm_bp_nexus_pwrup_t
*bpn
;
8494 pm_bp_child_pwrchg_t new_bpc
;
8495 pm_bp_noinvol_t
*bpi
;
8498 int ret
= DDI_SUCCESS
;
8502 PMD(PMD_SET
, ("%s: %s@%s(%s#%d) %s\n", pmf
, PM_DEVICE(dip
),
8505 case BUS_POWER_CHILD_PWRCHG
:
8506 bpc
= (pm_bp_child_pwrchg_t
*)arg
;
8507 pspm
= (pm_sp_misc_t
*)bpc
->bpc_private
;
8508 tdip
= bpc
->bpc_dip
;
8509 cdip
= pm_get_next_descendent(dip
, tdip
);
8510 cinfo
= PM_GET_PM_INFO(cdip
);
8513 * If the node is an involved parent, it needs to
8514 * power up the node as it is needed. There is nothing
8515 * else the framework can do here.
8517 if (PM_WANTS_NOTIFICATION(cdip
)) {
8518 PMD(PMD_SET
, ("%s: call bus_power for "
8519 "%s@%s(%s#%d)\n", pmf
, PM_DEVICE(cdip
)))
8520 return ((*PM_BUS_POWER_FUNC(cdip
))(cdip
,
8521 impl_arg
, op
, arg
, result
));
8523 ASSERT(pspm
->pspm_direction
== PM_LEVEL_UPONLY
||
8524 pspm
->pspm_direction
== PM_LEVEL_DOWNONLY
||
8525 pspm
->pspm_direction
== PM_LEVEL_EXACT
);
8527 * we presume that the parent needs to be up in
8528 * order for the child to change state (either
8529 * because it must already be on if the child is on
8530 * (and the pm_all_to_normal_nexus() will be a nop)
8531 * or because it will need to be on for the child
8532 * to come on; so we make the call regardless
8534 pm_hold_power(cdip
);
8536 pm_canblock_t canblock
= pspm
->pspm_canblock
;
8537 ret
= pm_all_to_normal_nexus(cdip
, canblock
);
8538 if (ret
!= DDI_SUCCESS
) {
8539 pm_rele_power(cdip
);
8543 PMD(PMD_SET
, ("%s: walk down to %s@%s(%s#%d)\n", pmf
,
8545 ret
= pm_busop_bus_power(cdip
, impl_arg
, op
, arg
,
8547 pm_rele_power(cdip
);
8549 ret
= pm_busop_set_power(cdip
, impl_arg
, op
, arg
,
8554 case BUS_POWER_NEXUS_PWRUP
:
8555 bpn
= (pm_bp_nexus_pwrup_t
*)arg
;
8556 pspm
= (pm_sp_misc_t
*)bpn
->bpn_private
;
8558 if (!e_pm_valid_info(dip
, NULL
) ||
8559 !e_pm_valid_comp(dip
, bpn
->bpn_comp
, &cp
) ||
8560 !e_pm_valid_power(dip
, bpn
->bpn_comp
, bpn
->bpn_level
)) {
8561 PMD(PMD_SET
, ("%s: %s@%s(%s#%d) has no pm info; EIO\n",
8562 pmf
, PM_DEVICE(dip
)))
8563 *pspm
->pspm_errnop
= EIO
;
8564 *(int *)result
= DDI_FAILURE
;
8565 return (DDI_FAILURE
);
8568 ASSERT(bpn
->bpn_dip
== dip
);
8569 PMD(PMD_SET
, ("%s: nexus powerup for %s@%s(%s#%d)\n", pmf
,
8571 new_bpc
.bpc_dip
= dip
;
8572 pathbuf
= kmem_alloc(MAXPATHLEN
, KM_SLEEP
);
8573 new_bpc
.bpc_path
= ddi_pathname(dip
, pathbuf
);
8574 new_bpc
.bpc_comp
= bpn
->bpn_comp
;
8575 new_bpc
.bpc_olevel
= PM_CURPOWER(dip
, bpn
->bpn_comp
);
8576 new_bpc
.bpc_nlevel
= bpn
->bpn_level
;
8577 new_bpc
.bpc_private
= bpn
->bpn_private
;
8578 ((pm_sp_misc_t
*)(new_bpc
.bpc_private
))->pspm_direction
=
8580 ((pm_sp_misc_t
*)(new_bpc
.bpc_private
))->pspm_errnop
=
8582 ret
= pm_busop_set_power(dip
, impl_arg
, BUS_POWER_CHILD_PWRCHG
,
8583 (void *)&new_bpc
, result
);
8584 kmem_free(pathbuf
, MAXPATHLEN
);
8587 case BUS_POWER_NOINVOL
:
8588 bpi
= (pm_bp_noinvol_t
*)arg
;
8589 tdip
= bpi
->bpni_dip
;
8590 cdip
= pm_get_next_descendent(dip
, tdip
);
8592 /* In case of rem_drv, the leaf node has been removed */
8594 return (DDI_SUCCESS
);
8596 cinfo
= PM_GET_PM_INFO(cdip
);
8598 if (PM_WANTS_NOTIFICATION(cdip
)) {
8600 ("%s: call bus_power for %s@%s(%s#%d)\n",
8601 pmf
, PM_DEVICE(cdip
)))
8602 ret
= (*PM_BUS_POWER_FUNC(cdip
))
8603 (cdip
, NULL
, op
, arg
, result
);
8604 if ((cinfo
) && (ret
== DDI_SUCCESS
))
8605 (void) pm_noinvol_update_node(cdip
,
8610 ("%s: walk down to %s@%s(%s#%d)\n", pmf
,
8612 ret
= pm_busop_bus_power(cdip
, NULL
, op
,
8615 * Update the current node.
8617 if ((cinfo
) && (ret
== DDI_SUCCESS
))
8618 (void) pm_noinvol_update_node(cdip
,
8624 * For attach, detach, power up:
8625 * Do nothing for leaf node since its
8626 * counts are already updated.
8627 * For CFB and driver removal, since the
8628 * path and the target dip passed in is up to and incl.
8629 * the immediate ancestor, need to do the update.
8631 PMD(PMD_NOINVOL
, ("%s: target %s@%s(%s#%d) is "
8632 "reached\n", pmf
, PM_DEVICE(cdip
)))
8633 if (cinfo
&& ((bpi
->bpni_cmd
== PM_BP_NOINVOL_REMDRV
) ||
8634 (bpi
->bpni_cmd
== PM_BP_NOINVOL_CFB
)))
8635 (void) pm_noinvol_update_node(cdip
, bpi
);
8636 return (DDI_SUCCESS
);
8640 PMD(PMD_SET
, ("%s: operation %d is not supported!\n", pmf
, op
))
8641 return (DDI_FAILURE
);
8646 pm_busop_set_power(dev_info_t
*dip
, void *impl_arg
, pm_bus_power_op_t op
,
8647 void *arg
, void *resultp
)
8649 _NOTE(ARGUNUSED(impl_arg
))
8650 PMD_FUNC(pmf
, "bp_set_power")
8651 pm_ppm_devlist_t
*devl
= NULL
;
8654 int circ_db
, ccirc_db
;
8656 int ret
= DDI_SUCCESS
;
8658 pm_bp_child_pwrchg_t
*bpc
= (pm_bp_child_pwrchg_t
*)arg
;
8659 pm_sp_misc_t
*pspm
= (pm_sp_misc_t
*)bpc
->bpc_private
;
8660 pm_canblock_t canblock
= pspm
->pspm_canblock
;
8661 int scan
= pspm
->pspm_scan
;
8662 int comp
= bpc
->bpc_comp
;
8663 int olevel
= bpc
->bpc_olevel
;
8664 int nlevel
= bpc
->bpc_nlevel
;
8665 int comps_off_incr
= 0;
8666 dev_info_t
*pdip
= ddi_get_parent(dip
);
8668 int direction
= pspm
->pspm_direction
;
8669 int *errnop
= pspm
->pspm_errnop
;
8671 char *dir
= pm_decode_direction(direction
);
8673 int *iresp
= (int *)resultp
;
8674 time_t idletime
, thresh
;
8675 pm_component_t
*cp
= PM_CP(dip
, comp
);
8678 *iresp
= DDI_SUCCESS
;
8680 ASSERT(op
== BUS_POWER_CHILD_PWRCHG
);
8681 PMD(PMD_SET
, ("%s: %s@%s(%s#%d) %s\n", pmf
, PM_DEVICE(dip
),
8685 * The following set of conditions indicate we are here to handle a
8686 * driver's pm_[raise|lower]_power request, but the device is being
8687 * power managed (PM_DIRECT_PM) by a user process. For that case
8688 * we want to pm_block and pass a status back to the caller based
8689 * on whether the controlling process's next activity on the device
8690 * matches the current request or not. This distinction tells
8691 * downstream functions to avoid calling into a driver or changing
8692 * the framework's power state. To actually block, we need:
8695 * no reason to block unless a process is directly controlling dev
8696 * direction != PM_LEVEL_EXACT
8697 * EXACT is used by controlling proc's PM_SET_CURRENT_POWER ioctl
8698 * !pm_processes_stopped
8699 * don't block if controlling proc already be stopped for cpr
8700 * canblock != PM_CANBLOCK_BYPASS
8701 * our caller must not have explicitly prevented blocking
8703 if (direction
!= PM_LEVEL_EXACT
&& canblock
!= PM_CANBLOCK_BYPASS
) {
8705 while (PM_ISDIRECT(dip
) && !pm_processes_stopped
) {
8706 /* releases dip lock */
8707 ret
= pm_busop_match_request(dip
, bpc
);
8708 if (ret
== EAGAIN
) {
8712 return (*iresp
= ret
);
8716 /* BC device is never scanned, so power will stick until we are done */
8717 if (PM_ISBC(dip
) && comp
!= 0 && nlevel
!= 0 &&
8718 direction
!= PM_LEVEL_DOWNONLY
) {
8719 int nrmpwr0
= pm_get_normal_power(dip
, 0);
8720 if (pm_set_power(dip
, 0, nrmpwr0
, direction
,
8721 canblock
, 0, resultp
) != DDI_SUCCESS
) {
8722 /* *resultp set by pm_set_power */
8723 return (DDI_FAILURE
);
8726 if (PM_WANTS_NOTIFICATION(pdip
)) {
8727 PMD(PMD_SET
, ("%s: pre_notify %s@%s(%s#%d) for child "
8728 "%s@%s(%s#%d)\n", pmf
, PM_DEVICE(pdip
), PM_DEVICE(dip
)))
8729 ret
= (*PM_BUS_POWER_FUNC(pdip
))(pdip
, NULL
,
8730 BUS_POWER_PRE_NOTIFICATION
, bpc
, resultp
);
8731 if (ret
!= DDI_SUCCESS
) {
8732 PMD(PMD_SET
, ("%s: failed to pre_notify %s@%s(%s#%d)\n",
8733 pmf
, PM_DEVICE(pdip
)))
8734 return (DDI_FAILURE
);
8738 * Since we don't know what the actual power level is,
8739 * we place a power hold on the parent no matter what
8740 * component and level is changing.
8742 pm_hold_power(pdip
);
8744 PM_LOCK_POWER(dip
, &circ
);
8745 clevel
= PM_CURPOWER(dip
, comp
);
8747 * It's possible that a call was made to pm_update_maxpower()
8748 * on another thread before we took the lock above. So, we need to
8749 * make sure that this request isn't processed after the
8750 * change of power executed on behalf of pm_update_maxpower().
8752 if (nlevel
> pm_get_normal_power(dip
, comp
)) {
8753 PMD(PMD_SET
, ("%s: requested level is higher than normal.\n",
8756 *iresp
= DDI_FAILURE
;
8759 PMD(PMD_SET
, ("%s: %s@%s(%s#%d), cmp=%d, olvl=%d, nlvl=%d, clvl=%d, "
8760 "dir=%s\n", pmf
, PM_DEVICE(dip
), comp
, bpc
->bpc_olevel
, nlevel
,
8762 switch (direction
) {
8763 case PM_LEVEL_UPONLY
:
8765 if (clevel
>= nlevel
) {
8766 PMD(PMD_SET
, ("%s: current level is already "
8767 "at or above the requested level.\n", pmf
))
8768 *iresp
= DDI_SUCCESS
;
8773 case PM_LEVEL_EXACT
:
8774 /* specific level request */
8775 if (clevel
== nlevel
&& !PM_ISBC(dip
)) {
8776 PMD(PMD_SET
, ("%s: current level is already "
8777 "at the requested level.\n", pmf
))
8778 *iresp
= DDI_SUCCESS
;
8781 } else if (PM_IS_CFB(dip
) && (nlevel
< clevel
)) {
8782 PMD(PMD_CFB
, ("%s: powerdown of console\n", pmf
))
8783 if (!pm_cfb_enabled
) {
8784 PMD(PMD_ERROR
| PMD_CFB
,
8785 ("%s: !pm_cfb_enabled, fails\n", pmf
))
8787 *iresp
= DDI_FAILURE
;
8791 mutex_enter(&pm_cfb_lock
);
8793 mutex_exit(&pm_cfb_lock
);
8794 if (delay_sig(1) == EINTR
) {
8796 *iresp
= DDI_FAILURE
;
8800 mutex_enter(&pm_cfb_lock
);
8802 mutex_exit(&pm_cfb_lock
);
8805 case PM_LEVEL_DOWNONLY
:
8807 thresh
= cur_threshold(dip
, comp
);
8808 idletime
= gethrestime_sec() - cp
->pmc_timestamp
;
8809 if (scan
&& ((PM_KUC(dip
) != 0) ||
8810 (cp
->pmc_busycount
> 0) ||
8811 ((idletime
< thresh
) && !PM_IS_PID(dip
)))) {
8813 if (DEVI(dip
)->devi_pm_kidsupcnt
!= 0)
8814 PMD(PMD_SET
, ("%s: scan failed: "
8815 "kidsupcnt != 0\n", pmf
))
8816 if (cp
->pmc_busycount
> 0)
8817 PMD(PMD_SET
, ("%s: scan failed: "
8818 "device become busy\n", pmf
))
8819 if (idletime
< thresh
)
8820 PMD(PMD_SET
, ("%s: scan failed: device "
8821 "hasn't been idle long enough\n", pmf
))
8823 *iresp
= DDI_FAILURE
;
8827 } else if (clevel
!= PM_LEVEL_UNKNOWN
&& clevel
<= nlevel
) {
8828 PMD(PMD_SET
, ("%s: current level is already at "
8829 "or below the requested level.\n", pmf
))
8830 *iresp
= DDI_SUCCESS
;
8837 if (PM_IS_CFB(dip
) && (comps_off_incr
=
8838 calc_cfb_comps_incr(dip
, comp
, clevel
, nlevel
)) > 0) {
8840 * Pre-adjust pm_cfb_comps_off if lowering a console fb
8841 * component from full power. Remember that we tried to
8842 * lower power in case it fails and we need to back out
8845 update_comps_off(comps_off_incr
, dip
);
8846 PMD(PMD_CFB
, ("%s: %s@%s(%s#%d)[%d] %d->%d cfb_comps_off->%d\n",
8847 pmf
, PM_DEVICE(dip
), comp
, clevel
, nlevel
,
8851 if ((*iresp
= power_dev(dip
,
8852 comp
, nlevel
, clevel
, canblock
, &devl
)) == DDI_SUCCESS
) {
8855 * All descendents of this node should already be powered off.
8857 if (PM_CURPOWER(dip
, comp
) == 0) {
8858 pm_desc_pwrchk_t pdpchk
;
8859 pdpchk
.pdpc_dip
= dip
;
8860 pdpchk
.pdpc_par_involved
= PM_WANTS_NOTIFICATION(dip
);
8861 ndi_devi_enter(dip
, &circ_db
);
8862 for (cdip
= ddi_get_child(dip
); cdip
!= NULL
;
8863 cdip
= ddi_get_next_sibling(cdip
)) {
8864 ndi_devi_enter(cdip
, &ccirc_db
);
8865 ddi_walk_devs(cdip
, pm_desc_pwrchk_walk
,
8867 ndi_devi_exit(cdip
, ccirc_db
);
8869 ndi_devi_exit(dip
, circ_db
);
8873 * Post-adjust pm_cfb_comps_off if we brought an fb component
8874 * back up to full power.
8876 if (PM_IS_CFB(dip
) && comps_off_incr
< 0) {
8877 update_comps_off(comps_off_incr
, dip
);
8878 PMD(PMD_CFB
, ("%s: %s@%s(%s#%d)[%d] %d->%d "
8879 "cfb_comps_off->%d\n", pmf
, PM_DEVICE(dip
),
8880 comp
, clevel
, nlevel
, pm_cfb_comps_off
))
8883 if (POWERING_OFF(clevel
, nlevel
)) {
8885 dodeps
= (comp
== 0);
8889 for (i
= 0; i
< PM_NUMCMPTS(dip
); i
++) {
8890 /* if some component still on */
8891 if (PM_CURPOWER(dip
, i
)) {
8898 work_type
= PM_DEP_WK_POWER_OFF
;
8899 } else if (POWERING_ON(clevel
, nlevel
)) {
8901 dodeps
= (comp
== 0);
8905 for (i
= 0; i
< PM_NUMCMPTS(dip
); i
++) {
8908 if (PM_CURPOWER(dip
, i
) > 0) {
8915 work_type
= PM_DEP_WK_POWER_ON
;
8919 char *pathbuf
= kmem_alloc(MAXPATHLEN
, KM_SLEEP
);
8921 (void) ddi_pathname(dip
, pathbuf
);
8922 pm_dispatch_to_dep_thread(work_type
, pathbuf
, NULL
,
8923 PM_DEP_NOWAIT
, NULL
, 0);
8924 kmem_free(pathbuf
, MAXPATHLEN
);
8926 if ((PM_CURPOWER(dip
, comp
) == nlevel
) && pm_watchers()) {
8929 /* If old power cached during deadlock, use it. */
8930 old
= (cp
->pmc_flags
& PM_PHC_WHILE_SET_POWER
?
8931 cp
->pmc_phc_pwr
: olevel
);
8932 mutex_enter(&pm_rsvp_lock
);
8933 pm_enqueue_notify(PSC_HAS_CHANGED
, dip
, comp
, nlevel
,
8935 pm_enqueue_notify_others(&devl
, canblock
);
8936 mutex_exit(&pm_rsvp_lock
);
8938 pm_ppm_devlist_t
*p
;
8939 pm_ppm_devlist_t
*next
;
8940 for (p
= devl
; p
!= NULL
; p
= next
) {
8942 kmem_free(p
, sizeof (pm_ppm_devlist_t
));
8948 * If we are coming from a scan, don't do it again,
8949 * else we can have infinite loops.
8954 /* if we incremented pm_comps_off_count, but failed */
8955 if (comps_off_incr
> 0) {
8956 update_comps_off(-comps_off_incr
, dip
);
8957 PMD(PMD_CFB
, ("%s: %s@%s(%s#%d)[%d] %d->%d "
8958 "cfb_comps_off->%d\n", pmf
, PM_DEVICE(dip
),
8959 comp
, clevel
, nlevel
, pm_cfb_comps_off
))
8966 * This thread may have been in deadlock with pm_power_has_changed.
8967 * Before releasing power lock, clear the flag which marks this
8970 cp
->pmc_flags
&= ~PM_PHC_WHILE_SET_POWER
;
8973 * Update the old power level in the bus power structure with the
8974 * actual power level before the transition was made to the new level.
8975 * Some involved parents depend on this information to keep track of
8976 * their children's power transition.
8978 if (*iresp
!= DDI_FAILURE
)
8979 bpc
->bpc_olevel
= clevel
;
8981 if (PM_WANTS_NOTIFICATION(pdip
)) {
8982 ret
= (*PM_BUS_POWER_FUNC(pdip
))(pdip
, NULL
,
8983 BUS_POWER_POST_NOTIFICATION
, bpc
, resultp
);
8984 PM_UNLOCK_POWER(dip
, circ
);
8985 PMD(PMD_SET
, ("%s: post_notify %s@%s(%s#%d) for "
8986 "child %s@%s(%s#%d), ret=%d\n", pmf
, PM_DEVICE(pdip
),
8987 PM_DEVICE(dip
), ret
))
8989 nlevel
= cur_power(cp
); /* in case phc deadlock updated pwr */
8990 PM_UNLOCK_POWER(dip
, circ
);
8992 * Now that we know what power transition has occurred
8993 * (if any), release the power hold. Leave the hold
8994 * in effect in the case of OFF->ON transition.
8996 if (!(clevel
== 0 && nlevel
> 0 &&
8997 (!PM_ISBC(dip
) || comp
== 0)))
8998 pm_rele_power(pdip
);
9000 * If the power transition was an ON->OFF transition,
9001 * remove the power hold from the parent.
9003 if ((clevel
> 0 || clevel
== PM_LEVEL_UNKNOWN
) &&
9004 nlevel
== 0 && (!PM_ISBC(dip
) || comp
== 0))
9005 pm_rele_power(pdip
);
9007 if (*iresp
!= DDI_SUCCESS
|| ret
!= DDI_SUCCESS
)
9008 return (DDI_FAILURE
);
9010 return (DDI_SUCCESS
);
9014 * If an app (SunVTS or Xsun) has taken control, then block until it
9015 * gives it up or makes the requested power level change, unless
9016 * we have other instructions about blocking. Returns DDI_SUCCESS,
9017 * DDI_FAILURE or EAGAIN (owner released device from directpm).
9020 pm_busop_match_request(dev_info_t
*dip
, void *arg
)
9022 PMD_FUNC(pmf
, "bp_match_request")
9023 pm_bp_child_pwrchg_t
*bpc
= (pm_bp_child_pwrchg_t
*)arg
;
9024 pm_sp_misc_t
*pspm
= (pm_sp_misc_t
*)bpc
->bpc_private
;
9025 int comp
= bpc
->bpc_comp
;
9026 int nlevel
= bpc
->bpc_nlevel
;
9027 pm_canblock_t canblock
= pspm
->pspm_canblock
;
9028 int direction
= pspm
->pspm_direction
;
9031 ASSERT(PM_IAM_LOCKING_DIP(dip
));
9032 PM_LOCK_POWER(dip
, &circ
);
9033 clevel
= PM_CURPOWER(dip
, comp
);
9034 PMD(PMD_SET
, ("%s: %s@%s(%s#%d), cmp=%d, nlvl=%d, clvl=%d\n",
9035 pmf
, PM_DEVICE(dip
), comp
, nlevel
, clevel
))
9036 if (direction
== PM_LEVEL_UPONLY
) {
9037 if (clevel
>= nlevel
) {
9038 PM_UNLOCK_POWER(dip
, circ
);
9040 return (DDI_SUCCESS
);
9042 } else if (clevel
== nlevel
) {
9043 PM_UNLOCK_POWER(dip
, circ
);
9045 return (DDI_SUCCESS
);
9047 if (canblock
== PM_CANBLOCK_FAIL
) {
9048 PM_UNLOCK_POWER(dip
, circ
);
9050 return (DDI_FAILURE
);
9052 if (canblock
== PM_CANBLOCK_BLOCK
) {
9054 * To avoid a deadlock, we must not hold the
9055 * power lock when we pm_block.
9057 PM_UNLOCK_POWER(dip
, circ
);
9058 PMD(PMD_SET
, ("%s: blocking\n", pmf
))
9059 /* pm_block releases dip lock */
9060 switch (pm_block(dip
, comp
, nlevel
, clevel
)) {
9064 return (DDI_SUCCESS
);
9066 return (DDI_FAILURE
);
9072 return (DDI_FAILURE
); /* keep gcc happy */
9076 pm_all_to_normal_nexus(dev_info_t
*dip
, pm_canblock_t canblock
)
9078 PMD_FUNC(pmf
, "all_to_normal_nexus")
9082 int changefailed
= 0;
9083 int ret
, result
= DDI_SUCCESS
;
9084 pm_bp_nexus_pwrup_t bpn
;
9087 ASSERT(PM_GET_PM_INFO(dip
));
9088 PMD(PMD_ALLNORM
, ("%s: %s@%s(%s#%d)\n", pmf
, PM_DEVICE(dip
)))
9089 if (pm_get_norm_pwrs(dip
, &normal
, &size
) != DDI_SUCCESS
) {
9090 PMD(PMD_ALLNORM
, ("%s: can't get norm pwrs\n", pmf
))
9091 return (DDI_FAILURE
);
9093 ncomps
= PM_NUMCMPTS(dip
);
9094 for (i
= 0; i
< ncomps
; i
++) {
9097 bpn
.bpn_level
= normal
[i
];
9098 pspm
.pspm_canblock
= canblock
;
9100 bpn
.bpn_private
= &pspm
;
9101 ret
= pm_busop_bus_power(dip
, NULL
, BUS_POWER_NEXUS_PWRUP
,
9102 (void *)&bpn
, (void *)&result
);
9103 if (ret
!= DDI_SUCCESS
|| result
!= DDI_SUCCESS
) {
9104 PMD(PMD_FAIL
| PMD_ALLNORM
, ("%s: %s@%s(%s#%d)[%d] "
9105 "->%d failure result %d\n", pmf
, PM_DEVICE(dip
),
9106 i
, normal
[i
], result
))
9110 kmem_free(normal
, size
);
9112 PMD(PMD_FAIL
, ("%s: failed to set %d comps %s@%s(%s#%d) "
9113 "full power\n", pmf
, changefailed
, PM_DEVICE(dip
)))
9114 return (DDI_FAILURE
);
9116 return (DDI_SUCCESS
);
9120 pm_noinvol_update(int subcmd
, int volpmd
, int wasvolpmd
, char *path
,
9123 PMD_FUNC(pmf
, "noinvol_update")
9124 pm_bp_noinvol_t args
;
9126 int result
= DDI_SUCCESS
;
9128 args
.bpni_path
= path
;
9129 args
.bpni_dip
= tdip
;
9130 args
.bpni_cmd
= subcmd
;
9131 args
.bpni_wasvolpmd
= wasvolpmd
;
9132 args
.bpni_volpmd
= volpmd
;
9133 PMD(PMD_NOINVOL
, ("%s: update for path %s tdip %p subcmd %d "
9134 "volpmd %d wasvolpmd %d\n", pmf
,
9135 path
, (void *)tdip
, subcmd
, wasvolpmd
, volpmd
))
9136 ret
= pm_busop_bus_power(ddi_root_node(), NULL
, BUS_POWER_NOINVOL
,
9142 pm_noinvol_update_node(dev_info_t
*dip
, pm_bp_noinvol_t
*req
)
9144 PMD_FUNC(pmf
, "noinvol_update_node")
9146 PMD(PMD_NOINVOL
, ("%s: %s@%s(%s#%d)\n", pmf
, PM_DEVICE(dip
)))
9147 switch (req
->bpni_cmd
) {
9148 case PM_BP_NOINVOL_ATTACH
:
9149 PMD(PMD_NOINVOL
, ("%s: PM_PB_NOINVOL_ATTACH %s@%s(%s#%d) "
9150 "noinvol %d->%d\n", pmf
, PM_DEVICE(dip
),
9151 DEVI(dip
)->devi_pm_noinvolpm
,
9152 DEVI(dip
)->devi_pm_noinvolpm
- 1))
9153 ASSERT(DEVI(dip
)->devi_pm_noinvolpm
);
9155 DEVI(dip
)->devi_pm_noinvolpm
--;
9156 if (req
->bpni_wasvolpmd
) {
9157 PMD(PMD_NOINVOL
, ("%s: PM_BP_NOINVOL_ATTACH "
9158 "%s@%s(%s#%d) volpmd %d->%d\n", pmf
,
9159 PM_DEVICE(dip
), DEVI(dip
)->devi_pm_volpmd
,
9160 DEVI(dip
)->devi_pm_volpmd
- 1))
9161 if (DEVI(dip
)->devi_pm_volpmd
)
9162 DEVI(dip
)->devi_pm_volpmd
--;
9167 case PM_BP_NOINVOL_DETACH
:
9168 PMD(PMD_NOINVOL
, ("%s: PM_BP_NOINVOL_DETACH %s@%s(%s#%d) "
9169 "noinvolpm %d->%d\n", pmf
, PM_DEVICE(dip
),
9170 DEVI(dip
)->devi_pm_noinvolpm
,
9171 DEVI(dip
)->devi_pm_noinvolpm
+ 1))
9173 DEVI(dip
)->devi_pm_noinvolpm
++;
9174 if (req
->bpni_wasvolpmd
) {
9175 PMD(PMD_NOINVOL
, ("%s: PM_BP_NOINVOL_DETACH "
9176 "%s@%s(%s#%d) volpmd %d->%d\n", pmf
,
9177 PM_DEVICE(dip
), DEVI(dip
)->devi_pm_volpmd
,
9178 DEVI(dip
)->devi_pm_volpmd
+ 1))
9179 DEVI(dip
)->devi_pm_volpmd
++;
9184 case PM_BP_NOINVOL_REMDRV
:
9185 PMD(PMD_NOINVOL
, ("%s: PM_BP_NOINVOL_REMDRV %s@%s(%s#%d) "
9186 "noinvol %d->%d\n", pmf
, PM_DEVICE(dip
),
9187 DEVI(dip
)->devi_pm_noinvolpm
,
9188 DEVI(dip
)->devi_pm_noinvolpm
- 1))
9189 ASSERT(DEVI(dip
)->devi_pm_noinvolpm
);
9191 DEVI(dip
)->devi_pm_noinvolpm
--;
9192 if (req
->bpni_wasvolpmd
) {
9194 ("%s: PM_BP_NOINVOL_REMDRV %s@%s(%s#%d) "
9195 "volpmd %d->%d\n", pmf
, PM_DEVICE(dip
),
9196 DEVI(dip
)->devi_pm_volpmd
,
9197 DEVI(dip
)->devi_pm_volpmd
- 1))
9199 * A power up could come in between and
9200 * clear the volpmd, if that's the case,
9201 * volpmd would be clear.
9203 if (DEVI(dip
)->devi_pm_volpmd
)
9204 DEVI(dip
)->devi_pm_volpmd
--;
9209 case PM_BP_NOINVOL_CFB
:
9211 ("%s: PM_BP_NOIVOL_CFB %s@%s(%s#%d) noinvol %d->%d\n",
9212 pmf
, PM_DEVICE(dip
), DEVI(dip
)->devi_pm_noinvolpm
,
9213 DEVI(dip
)->devi_pm_noinvolpm
+ 1))
9215 DEVI(dip
)->devi_pm_noinvolpm
++;
9219 case PM_BP_NOINVOL_POWER
:
9221 ("%s: PM_BP_NOIVOL_PWR %s@%s(%s#%d) volpmd %d->%d\n",
9222 pmf
, PM_DEVICE(dip
),
9223 DEVI(dip
)->devi_pm_volpmd
, DEVI(dip
)->devi_pm_volpmd
-
9226 DEVI(dip
)->devi_pm_volpmd
-= req
->bpni_volpmd
;
9238 pm_desc_pwrchk_walk(dev_info_t
*dip
, void *arg
)
9240 PMD_FUNC(pmf
, "desc_pwrchk")
9241 pm_desc_pwrchk_t
*pdpchk
= (pm_desc_pwrchk_t
*)arg
;
9242 pm_info_t
*info
= PM_GET_PM_INFO(dip
);
9245 int curpwr
, ce_level
;
9248 return (DDI_WALK_CONTINUE
);
9250 PMD(PMD_SET
, ("%s: %s@%s(%s#%d)\n", pmf
, PM_DEVICE(dip
)))
9251 for (i
= 0; i
< PM_NUMCMPTS(dip
); i
++) {
9253 if ((curpwr
= PM_CURPOWER(dip
, i
)) == 0)
9255 /* E_FUNC_SET_NOT_USED */
9256 ce_level
= (pdpchk
->pdpc_par_involved
== 0) ? CE_PANIC
:
9258 PMD(PMD_SET
, ("%s: %s@%s(%s#%d) is powered off while desc "
9259 "%s@%s(%s#%d)[%d] is at %d\n", pmf
,
9260 PM_DEVICE(pdpchk
->pdpc_dip
), PM_DEVICE(dip
), i
, curpwr
))
9261 cmn_err(ce_level
, "!device %s@%s(%s#%d) is powered on, "
9262 "while its ancestor, %s@%s(%s#%d), is powering off!",
9263 PM_DEVICE(dip
), PM_DEVICE(pdpchk
->pdpc_dip
));
9265 return (DDI_WALK_CONTINUE
);
9270 * Record the fact that one thread is borrowing the lock on a device node.
9271 * Use is restricted to the case where the lending thread will block until
9272 * the borrowing thread (always curthread) completes.
9275 pm_borrow_lock(kthread_t
*lender
)
9277 lock_loan_t
*prev
= &lock_loan_head
;
9278 lock_loan_t
*cur
= (lock_loan_t
*)kmem_zalloc(sizeof (*cur
), KM_SLEEP
);
9280 cur
->pmlk_borrower
= curthread
;
9281 cur
->pmlk_lender
= lender
;
9282 mutex_enter(&pm_loan_lock
);
9283 cur
->pmlk_next
= prev
->pmlk_next
;
9284 prev
->pmlk_next
= cur
;
9285 mutex_exit(&pm_loan_lock
);
9289 * Return the borrowed lock. A thread can borrow only one.
9292 pm_return_lock(void)
9295 lock_loan_t
*prev
= &lock_loan_head
;
9297 mutex_enter(&pm_loan_lock
);
9298 ASSERT(prev
->pmlk_next
!= NULL
);
9299 for (cur
= prev
->pmlk_next
; cur
; prev
= cur
, cur
= cur
->pmlk_next
)
9300 if (cur
->pmlk_borrower
== curthread
)
9303 ASSERT(cur
!= NULL
);
9304 prev
->pmlk_next
= cur
->pmlk_next
;
9305 mutex_exit(&pm_loan_lock
);
9306 kmem_free(cur
, sizeof (*cur
));
9312 #define CPR_TXR 0x20
9313 #define CPR_DATAREG 0x3f8
9314 #define CPR_LSTAT 0x3fd
9315 #define CPR_INTRCTL 0x3f9
9320 while ((inb(CPR_LSTAT
) & CPR_RXR
) != CPR_RXR
)
9323 return (inb(CPR_DATAREG
));
9330 while ((inb(CPR_LSTAT
) & CPR_TXR
) == 0)
9333 outb(CPR_DATAREG
, c
);
9347 pm_ppm_searchlist(pm_searchargs_t
*sp
)
9349 power_req_t power_req
;
9354 power_req
.request_type
= PMR_PPM_SEARCH_LIST
;
9355 power_req
.req
.ppm_search_list_req
.searchlist
= sp
;
9356 ASSERT(DEVI(ddi_root_node())->devi_pm_ppm
);
9357 ret
= pm_ctlops((dev_info_t
*)DEVI(ddi_root_node())->devi_pm_ppm
,
9358 ddi_root_node(), DDI_CTLOPS_POWER
, &power_req
, &result
);
9359 PMD(PMD_SX
, ("pm_ppm_searchlist returns %d, result %d\n",