uts: make emu10k non-verbose
[unleashed.git] / kernel / os / sunpm.c
blob72cf9f318329052bc42d4763b3b20c4b62fa7cb2
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 * 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
32 * policy
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
40 * power states.
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
72 * hardware state.
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
96 * not attached)
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
105 * property
107 * Scanning:
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
111 * component.
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.
119 * Dependencies:
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.
135 * Direct PM:
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>
156 #include <sys/pm.h>
157 #include <sys/ddi.h>
158 #include <sys/sunddi.h>
159 #include <sys/sunndi.h>
160 #include <sys/sunpm.h>
161 #include <sys/epm.h>
162 #include <sys/vfs.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>
174 #include <sys/spl.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>
182 #include <sys/srn.h>
186 * PM LOCKING
187 * The list of locks:
188 * Global pm mutex locks.
190 * pm_scan_lock:
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.
197 * Lock ordering:
198 * pm_clone_lock -> pm_pscc_interest_rwlock,
199 * pm_clone_lock -> pm_pscc_direct_rwlock.
201 * pm_rsvp_lock:
202 * Used to synchronize the data structures used for processes
203 * to rendezvous with state change information when doing
204 * direct PM.
205 * Lock ordering:
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
211 * Lock ordering:
212 * ppm_lock -> ppm driver unit_lock
214 * pm_compcnt_lock:
215 * Protects count of components that are not at their lowest
216 * power level.
217 * Lock ordering:
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.
224 * pm_remdrv_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).
228 * Lock ordering:
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.
237 * pm_loan_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.
246 * Global PM rwlocks
248 * pm_thresh_rwlock:
249 * Protects the list of thresholds recorded for future use (when
250 * devices attach).
251 * Lock ordering:
252 * pm_thresh_rwlock -> devi_pm_lock
254 * pm_noinvol_rwlock:
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.
261 * Lock ordering:
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.
267 * Lock ordering:
268 * pm_pscc_interest_rwlock -> psce_lock
270 * per-dip locks:
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)
275 * devi_pm_lock:
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().
279 * Lock ordering:
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.
295 * devi_pm_busy_lock:
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 : \
322 pm_default_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.
344 int autopm_enabled;
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
356 * implementation.
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.
364 int autoS3_enabled;
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;
383 #endif
386 * pm_S3_enabled indicates that we believe the platform can support S3,
387 * which we get from pmconfig(1M)
389 int pm_S3_enabled;
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;
398 #ifdef DEBUG
401 * see include/sys/epm.h for PMD_* values
404 uint_t pm_debug = 0;
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 */
419 void prdeps(char *);
420 #endif
422 /* Globals */
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 */
470 extern int hz;
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 *);
481 #ifdef DEBUG
482 static int pm_desc_pwrchk_walk(dev_info_t *, void *);
483 #endif
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
538 * to non-zero.
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 */
543 #ifdef DEBUG
544 int pm_cfb_override = 1; /* non-zero allows pm of cfb with debuggers */
545 #else
546 int pm_cfb_override = 0; /* non-zero allows pm of cfb with debuggers */
547 #endif
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;
566 } lock_loan_t;
567 static lock_loan_t lock_loan_head; /* list head is a dummy element */
569 #ifdef DEBUG
570 #ifdef PMDDEBUG
571 #define PMD_FUNC(func, name) char *(func) = (name);
572 #else /* !PMDDEBUG */
573 #define PMD_FUNC(func, name)
574 #endif /* PMDDEBUG */
575 #else /* !DEBUG */
576 #define PMD_FUNC(func, name)
577 #endif /* DEBUG */
581 * Must be called before first device (including pseudo) attach
583 void
584 pm_init_locks(void)
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 *);
599 static boolean_t
600 pm_cpr_callb(void *arg, int code)
602 _NOTE(ARGUNUSED(arg))
603 static int auto_save;
604 static pm_cpupm_t cpupm_save;
606 switch (code) {
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;
617 autopm_enabled = 0;
618 cpupm_save = cpupm;
619 cpupm = PM_CPUPM_NOTSET;
620 mutex_exit(&pm_scan_lock);
621 ddi_walk_devs(ddi_root_node(), pm_scan_stop_walk, NULL);
622 break;
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;
639 cpupm = cpupm_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);
645 break;
647 return (B_TRUE);
651 * This callback routine is called when there is a system panic. This function
652 * exists for prototype matching.
654 static boolean_t
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();
661 return (B_TRUE);
664 static boolean_t
665 pm_halt_callb(void *arg, int code)
667 _NOTE(ARGUNUSED(arg, code))
668 return (B_TRUE);
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
677 void
678 pm_init(void)
680 PMD_FUNC(pmf, "pm_init")
681 char **mod;
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, NULL, CB_CL_CPR_PM, "pm_cpr");
689 pm_panic_cb_id = callb_add(pm_panic_callb, NULL, CB_CL_PANIC,
690 "pm_panic");
691 pm_halt_cb_id = callb_add(pm_halt_callb, NULL, CB_CL_HALT, "pm_halt");
694 * Create a thread to do dependency processing.
696 (void) thread_create(NULL, 0, (void (*)())pm_dep_thread, NULL, 0, &p0,
697 TS_RUN, minclsyspri);
700 * loadrootmodules already loaded these ppm drivers, now get them
701 * attached so they can claim the root drivers as they attach
703 for (mod = platform_module_list; *mod; mod++) {
704 if (i_ddi_attach_hw_nodes(*mod) != DDI_SUCCESS) {
705 cmn_err(CE_WARN, "!cannot load platform pm driver %s\n",
706 *mod);
707 } else {
708 PMD(PMD_DHR, ("%s: %s (%s)\n", pmf, *mod,
709 ddi_major_to_name(ddi_name_to_major(*mod))))
715 * pm_scan_init - create pm scan data structure. Called (if autopm or cpupm
716 * enabled) when device becomes power managed or after a failed detach and
717 * when autopm is started via PM_START_PM or PM_START_CPUPM ioctls, and after
718 * a CPR resume to get all the devices scanning again.
720 void
721 pm_scan_init(dev_info_t *dip)
723 PMD_FUNC(pmf, "scan_init")
724 pm_scan_t *scanp;
726 ASSERT(!PM_ISBC(dip));
728 PM_LOCK_DIP(dip);
729 scanp = PM_GET_PM_SCAN(dip);
730 if (!scanp) {
731 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): create scan data\n",
732 pmf, PM_DEVICE(dip)))
733 scanp = kmem_zalloc(sizeof (pm_scan_t), KM_SLEEP);
734 DEVI(dip)->devi_pm_scan = scanp;
735 } else if (scanp->ps_scan_flags & PM_SCAN_STOP) {
736 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): "
737 "clear PM_SCAN_STOP flag\n", pmf, PM_DEVICE(dip)))
738 scanp->ps_scan_flags &= ~PM_SCAN_STOP;
740 PM_UNLOCK_DIP(dip);
744 * pm_scan_fini - remove pm scan data structure when stopping pm on the device
746 void
747 pm_scan_fini(dev_info_t *dip)
749 PMD_FUNC(pmf, "scan_fini")
750 pm_scan_t *scanp;
752 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
753 ASSERT(!PM_ISBC(dip));
754 PM_LOCK_DIP(dip);
755 scanp = PM_GET_PM_SCAN(dip);
756 if (!scanp) {
757 PM_UNLOCK_DIP(dip);
758 return;
761 ASSERT(!scanp->ps_scan_id && !(scanp->ps_scan_flags &
762 (PM_SCANNING | PM_SCAN_DISPATCHED | PM_SCAN_AGAIN)));
764 kmem_free(scanp, sizeof (pm_scan_t));
765 DEVI(dip)->devi_pm_scan = NULL;
766 PM_UNLOCK_DIP(dip);
770 * Given a pointer to a component struct, return the current power level
771 * (struct contains index unless it is a continuous level).
772 * Located here in hopes of getting both this and dev_is_needed into the
773 * cache together
775 static int
776 cur_power(pm_component_t *cp)
778 if (cp->pmc_cur_pwr == PM_LEVEL_UNKNOWN)
779 return (cp->pmc_cur_pwr);
781 return (cp->pmc_comp.pmc_lvals[cp->pmc_cur_pwr]);
784 static char *
785 pm_decode_direction(int direction)
787 switch (direction) {
788 case PM_LEVEL_UPONLY:
789 return ("up");
791 case PM_LEVEL_EXACT:
792 return ("exact");
794 case PM_LEVEL_DOWNONLY:
795 return ("down");
797 default:
798 return ("INVALID DIRECTION");
802 char *
803 pm_decode_op(pm_bus_power_op_t op)
805 switch (op) {
806 case BUS_POWER_CHILD_PWRCHG:
807 return ("CHILD_PWRCHG");
808 case BUS_POWER_NEXUS_PWRUP:
809 return ("NEXUS_PWRUP");
810 case BUS_POWER_PRE_NOTIFICATION:
811 return ("PRE_NOTIFICATION");
812 case BUS_POWER_POST_NOTIFICATION:
813 return ("POST_NOTIFICATION");
814 case BUS_POWER_HAS_CHANGED:
815 return ("HAS_CHANGED");
816 case BUS_POWER_NOINVOL:
817 return ("NOINVOL");
818 default:
819 return ("UNKNOWN OP");
824 * Returns true if level is a possible (valid) power level for component
827 e_pm_valid_power(dev_info_t *dip, int cmpt, int level)
829 PMD_FUNC(pmf, "e_pm_valid_power")
830 pm_component_t *cp = PM_CP(dip, cmpt);
831 int i;
832 int *ip = cp->pmc_comp.pmc_lvals;
833 int limit = cp->pmc_comp.pmc_numlevels;
835 if (level < 0)
836 return (0);
837 for (i = 0; i < limit; i++) {
838 if (level == *ip++)
839 return (1);
841 #ifdef DEBUG
842 if (pm_debug & PMD_FAIL) {
843 ip = cp->pmc_comp.pmc_lvals;
845 for (i = 0; i < limit; i++)
846 PMD(PMD_FAIL, ("%s: index=%d, level=%d\n",
847 pmf, i, *ip++))
849 #endif
850 return (0);
853 static int pm_start(dev_info_t *dip);
855 * Returns true if device is pm'd (after calling pm_start if need be)
858 e_pm_valid_info(dev_info_t *dip, pm_info_t **infop)
860 pm_info_t *info;
863 * Check if the device is power managed if not.
864 * To make the common case (device is power managed already)
865 * fast, we check without the lock. If device is not already
866 * power managed, then we take the lock and the long route through
867 * go get it managed. Devices never go unmanaged until they
868 * detach.
870 info = PM_GET_PM_INFO(dip);
871 if (!info) {
872 if (!DEVI_IS_ATTACHING(dip)) {
873 return (0);
875 if (pm_start(dip) != DDI_SUCCESS) {
876 return (0);
878 info = PM_GET_PM_INFO(dip);
880 ASSERT(info);
881 if (infop != NULL)
882 *infop = info;
883 return (1);
887 e_pm_valid_comp(dev_info_t *dip, int cmpt, pm_component_t **cpp)
889 if (cmpt >= 0 && cmpt < PM_NUMCMPTS(dip)) {
890 if (cpp != NULL)
891 *cpp = PM_CP(dip, cmpt);
892 return (1);
893 } else {
894 return (0);
899 * Internal guts of ddi_dev_is_needed and pm_raise/lower_power
901 static int
902 dev_is_needed(dev_info_t *dip, int cmpt, int level, int direction)
904 PMD_FUNC(pmf, "din")
905 pm_component_t *cp;
906 char *pathbuf;
907 int result;
909 ASSERT(direction == PM_LEVEL_UPONLY || direction == PM_LEVEL_DOWNONLY);
910 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, cmpt, &cp) ||
911 !e_pm_valid_power(dip, cmpt, level))
912 return (DDI_FAILURE);
914 PMD(PMD_DIN, ("%s: %s@%s(%s#%d) cmpt=%d, dir=%s, new=%d, cur=%d\n",
915 pmf, PM_DEVICE(dip), cmpt, pm_decode_direction(direction),
916 level, cur_power(cp)))
918 if (pm_set_power(dip, cmpt, level, direction,
919 PM_CANBLOCK_BLOCK, 0, &result) != DDI_SUCCESS) {
920 if (direction == PM_LEVEL_UPONLY) {
921 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
922 (void) ddi_pathname(dip, pathbuf);
923 cmn_err(CE_WARN, "Device %s failed to power up.",
924 pathbuf);
925 kmem_free(pathbuf, MAXPATHLEN);
927 PMD(PMD_DIN | PMD_FAIL, ("%s: %s@%s(%s#%d) [%d] %s->%d failed, "
928 "errno %d\n", pmf, PM_DEVICE(dip), cmpt,
929 pm_decode_direction(direction), level, result))
930 return (DDI_FAILURE);
933 PMD(PMD_RESCAN | PMD_DIN, ("%s: pm_rescan %s@%s(%s#%d)\n", pmf,
934 PM_DEVICE(dip)))
935 pm_rescan(dip);
936 return (DDI_SUCCESS);
940 * We can get multiple pm_rescan() threads, if one of them discovers
941 * that no scan is running at the moment, it kicks it into action.
942 * Otherwise, it tells the current scanning thread to scan again when
943 * it is done by asserting the PM_SCAN_AGAIN flag. The PM_SCANNING and
944 * PM_SCAN_AGAIN flags are used to regulate scan, to make sure only one
945 * thread at a time runs the pm_scan_dev() code.
947 void
948 pm_rescan(void *arg)
950 PMD_FUNC(pmf, "rescan")
951 dev_info_t *dip = (dev_info_t *)arg;
952 pm_info_t *info;
953 pm_scan_t *scanp;
954 timeout_id_t scanid;
956 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
957 PM_LOCK_DIP(dip);
958 info = PM_GET_PM_INFO(dip);
959 scanp = PM_GET_PM_SCAN(dip);
960 if (pm_scans_disabled || !PM_SCANABLE(dip) || !info || !scanp ||
961 (scanp->ps_scan_flags & PM_SCAN_STOP)) {
962 PM_UNLOCK_DIP(dip);
963 return;
965 if (scanp->ps_scan_flags & PM_SCANNING) {
966 scanp->ps_scan_flags |= PM_SCAN_AGAIN;
967 PM_UNLOCK_DIP(dip);
968 return;
969 } else if (scanp->ps_scan_id) {
970 scanid = scanp->ps_scan_id;
971 scanp->ps_scan_id = 0;
972 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): cancel timeout scanid %lx\n",
973 pmf, PM_DEVICE(dip), (ulong_t)scanid))
974 PM_UNLOCK_DIP(dip);
975 (void) untimeout(scanid);
976 PM_LOCK_DIP(dip);
980 * Dispatching pm_scan during attach time is risky due to the fact that
981 * attach might soon fail and dip dissolved, and panic may happen while
982 * attempting to stop scan. So schedule a pm_rescan instead.
983 * (Note that if either of the first two terms are true, taskq_dispatch
984 * will not be invoked).
986 * Multiple pm_scan dispatching is unecessary and costly to keep track
987 * of. The PM_SCAN_DISPATCHED flag is used between pm_rescan and pm_scan
988 * to regulate the dispatching.
990 * Scan is stopped before the device is detached (in pm_detaching())
991 * but it may get re-started during the post_detach processing if the
992 * driver fails to detach.
994 if (DEVI_IS_ATTACHING(dip) ||
995 (scanp->ps_scan_flags & PM_SCAN_DISPATCHED) ||
996 !taskq_dispatch(system_taskq, pm_scan, (void *)dip, TQ_NOSLEEP)) {
997 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): attaching, pm_scan already "
998 "dispatched or dispatching failed\n", pmf, PM_DEVICE(dip)))
999 if (scanp->ps_scan_id) {
1000 scanid = scanp->ps_scan_id;
1001 scanp->ps_scan_id = 0;
1002 PM_UNLOCK_DIP(dip);
1003 (void) untimeout(scanid);
1004 PM_LOCK_DIP(dip);
1005 if (scanp->ps_scan_id) {
1006 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): a competing "
1007 "thread scheduled pm_rescan, scanid %lx\n",
1008 pmf, PM_DEVICE(dip),
1009 (ulong_t)scanp->ps_scan_id))
1010 PM_UNLOCK_DIP(dip);
1011 return;
1014 scanp->ps_scan_id = timeout(pm_rescan, (void *)dip,
1015 (scanp->ps_idle_down ? pm_id_ticks :
1016 (PM_MIN_SCAN(dip) * hz)));
1017 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): scheduled next pm_rescan, "
1018 "scanid %lx\n", pmf, PM_DEVICE(dip),
1019 (ulong_t)scanp->ps_scan_id))
1020 } else {
1021 PMD(PMD_SCAN, ("%s: dispatched pm_scan for %s@%s(%s#%d)\n",
1022 pmf, PM_DEVICE(dip)))
1023 scanp->ps_scan_flags |= PM_SCAN_DISPATCHED;
1025 PM_UNLOCK_DIP(dip);
1028 void
1029 pm_scan(void *arg)
1031 PMD_FUNC(pmf, "scan")
1032 dev_info_t *dip = (dev_info_t *)arg;
1033 pm_scan_t *scanp;
1034 time_t nextscan;
1036 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
1038 PM_LOCK_DIP(dip);
1039 scanp = PM_GET_PM_SCAN(dip);
1040 ASSERT(scanp && PM_GET_PM_INFO(dip));
1042 if (pm_scans_disabled || !PM_SCANABLE(dip) ||
1043 (scanp->ps_scan_flags & PM_SCAN_STOP)) {
1044 scanp->ps_scan_flags &= ~(PM_SCAN_AGAIN | PM_SCAN_DISPATCHED);
1045 PM_UNLOCK_DIP(dip);
1046 return;
1049 if (scanp->ps_idle_down) {
1051 * make sure we remember idledown was in affect until
1052 * we've completed the scan
1054 PMID_SET_SCANS(scanp->ps_idle_down)
1055 PMD(PMD_IDLEDOWN, ("%s: %s@%s(%s#%d): idledown starts "
1056 "(pmid %x)\n", pmf, PM_DEVICE(dip), scanp->ps_idle_down))
1059 /* possible having two threads running pm_scan() */
1060 if (scanp->ps_scan_flags & PM_SCANNING) {
1061 scanp->ps_scan_flags |= PM_SCAN_AGAIN;
1062 PMD(PMD_SCAN, ("%s: scanning, will scan %s@%s(%s#%d) again\n",
1063 pmf, PM_DEVICE(dip)))
1064 scanp->ps_scan_flags &= ~PM_SCAN_DISPATCHED;
1065 PM_UNLOCK_DIP(dip);
1066 return;
1069 scanp->ps_scan_flags |= PM_SCANNING;
1070 scanp->ps_scan_flags &= ~PM_SCAN_DISPATCHED;
1071 do {
1072 scanp->ps_scan_flags &= ~PM_SCAN_AGAIN;
1073 PM_UNLOCK_DIP(dip);
1074 nextscan = pm_scan_dev(dip);
1075 PM_LOCK_DIP(dip);
1076 } while (scanp->ps_scan_flags & PM_SCAN_AGAIN);
1078 ASSERT(scanp->ps_scan_flags & PM_SCANNING);
1079 scanp->ps_scan_flags &= ~PM_SCANNING;
1081 if (scanp->ps_idle_down) {
1082 scanp->ps_idle_down &= ~PMID_SCANS;
1083 PMD(PMD_IDLEDOWN, ("%s: %s@%s(%s#%d): idledown ends "
1084 "(pmid %x)\n", pmf, PM_DEVICE(dip), scanp->ps_idle_down))
1087 /* schedule for next idle check */
1088 if (nextscan != LONG_MAX) {
1089 if (nextscan > (LONG_MAX / hz))
1090 nextscan = (LONG_MAX - 1) / hz;
1091 if (scanp->ps_scan_id) {
1092 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): while scanning "
1093 "another rescan scheduled scanid(%lx)\n", pmf,
1094 PM_DEVICE(dip), (ulong_t)scanp->ps_scan_id))
1095 PM_UNLOCK_DIP(dip);
1096 return;
1097 } else if (!(scanp->ps_scan_flags & PM_SCAN_STOP)) {
1098 scanp->ps_scan_id = timeout(pm_rescan, (void *)dip,
1099 (clock_t)(nextscan * hz));
1100 PMD(PMD_SCAN, ("%s: nextscan for %s@%s(%s#%d) in "
1101 "%lx sec, scanid(%lx) \n", pmf, PM_DEVICE(dip),
1102 (ulong_t)nextscan, (ulong_t)scanp->ps_scan_id))
1105 PM_UNLOCK_DIP(dip);
1108 void
1109 pm_get_timestamps(dev_info_t *dip, time_t *valuep)
1111 int components = PM_NUMCMPTS(dip);
1112 int i;
1114 ASSERT(components > 0);
1115 PM_LOCK_BUSY(dip); /* so we get a consistent view */
1116 for (i = 0; i < components; i++) {
1117 valuep[i] = PM_CP(dip, i)->pmc_timestamp;
1119 PM_UNLOCK_BUSY(dip);
1123 * Returns true if device needs to be kept up because it exported the
1124 * "no-involuntary-power-cycles" property or we're pretending it did (console
1125 * fb case) or it is an ancestor of such a device and has used up the "one
1126 * free cycle" allowed when all such leaf nodes have voluntarily powered down
1127 * upon detach
1130 pm_noinvol(dev_info_t *dip)
1132 PMD_FUNC(pmf, "noinvol")
1135 * This doesn't change over the life of a driver, so no locking needed
1137 if (PM_IS_CFB(dip)) {
1138 PMD(PMD_NOINVOL | PMD_CFB, ("%s: inhibits CFB %s@%s(%s#%d)\n",
1139 pmf, PM_DEVICE(dip)))
1140 return (1);
1143 * Not an issue if no such kids
1145 if (DEVI(dip)->devi_pm_noinvolpm == 0) {
1146 #ifdef DEBUG
1147 if (DEVI(dip)->devi_pm_volpmd != 0) {
1148 dev_info_t *pdip = dip;
1149 do {
1150 PMD(PMD_NOINVOL, ("%s: %s@%s(%s#%d) noinvol %d "
1151 "volpmd %d\n", pmf, PM_DEVICE(pdip),
1152 DEVI(pdip)->devi_pm_noinvolpm,
1153 DEVI(pdip)->devi_pm_volpmd))
1154 pdip = ddi_get_parent(pdip);
1155 } while (pdip);
1157 #endif
1158 ASSERT(DEVI(dip)->devi_pm_volpmd == 0);
1159 return (0);
1163 * Since we now maintain the counts correct at every node, we no longer
1164 * need to look up the tree. An ancestor cannot use up the free cycle
1165 * without the children getting their counts adjusted.
1168 #ifdef DEBUG
1169 if (DEVI(dip)->devi_pm_noinvolpm != DEVI(dip)->devi_pm_volpmd)
1170 PMD(PMD_NOINVOL, ("%s: (%d != %d) inhibits %s@%s(%s#%d)\n", pmf,
1171 DEVI(dip)->devi_pm_noinvolpm, DEVI(dip)->devi_pm_volpmd,
1172 PM_DEVICE(dip)))
1173 #endif
1174 return (DEVI(dip)->devi_pm_noinvolpm != DEVI(dip)->devi_pm_volpmd);
1177 static int cur_threshold(dev_info_t *, int);
1178 static int pm_next_lower_power(pm_component_t *, int);
1181 * This function performs the actual scanning of the device.
1182 * It attempts to power off the indicated device's components if they have
1183 * been idle and other restrictions are met.
1184 * pm_scan_dev calculates and returns when the next scan should happen for
1185 * this device.
1187 time_t
1188 pm_scan_dev(dev_info_t *dip)
1190 PMD_FUNC(pmf, "scan_dev")
1191 pm_scan_t *scanp;
1192 time_t *timestamp, idletime, now, thresh;
1193 time_t timeleft = 0;
1194 #ifdef PMDDEBUG
1195 int curpwr;
1196 #endif
1197 int i, nxtpwr, pwrndx, unused;
1198 size_t size;
1199 pm_component_t *cp;
1200 dev_info_t *pdip = ddi_get_parent(dip);
1201 int circ;
1202 clock_t min_scan = pm_default_min_scan;
1205 * skip attaching device
1207 if (DEVI_IS_ATTACHING(dip)) {
1208 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) is attaching, timeleft(%lx)\n",
1209 pmf, PM_DEVICE(dip), min_scan))
1210 return (min_scan);
1213 PM_LOCK_DIP(dip);
1214 scanp = PM_GET_PM_SCAN(dip);
1215 min_scan = PM_MIN_SCAN(dip);
1216 ASSERT(scanp && PM_GET_PM_INFO(dip));
1218 PMD(PMD_SCAN, ("%s: [BEGIN %s@%s(%s#%d)]\n", pmf, PM_DEVICE(dip)))
1219 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): kuc is %d\n", pmf, PM_DEVICE(dip),
1220 PM_KUC(dip)))
1222 /* no scan under the following conditions */
1223 if (pm_scans_disabled || !PM_SCANABLE(dip) ||
1224 (scanp->ps_scan_flags & PM_SCAN_STOP) ||
1225 (PM_KUC(dip) != 0) ||
1226 PM_ISDIRECT(dip) || pm_noinvol(dip)) {
1227 PM_UNLOCK_DIP(dip);
1228 PMD(PMD_SCAN, ("%s: [END, %s@%s(%s#%d)] no scan, "
1229 "scan_disabled(%d), apm_enabled(%d), cpupm(%d), "
1230 "kuc(%d), %s directpm, %s pm_noinvol\n",
1231 pmf, PM_DEVICE(dip), pm_scans_disabled, autopm_enabled,
1232 cpupm, PM_KUC(dip),
1233 PM_ISDIRECT(dip) ? "is" : "is not",
1234 pm_noinvol(dip) ? "is" : "is not"))
1235 return (LONG_MAX);
1237 PM_UNLOCK_DIP(dip);
1239 if (!ndi_devi_tryenter(pdip, &circ)) {
1240 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) can't hold pdip",
1241 pmf, PM_DEVICE(pdip)))
1242 return ((time_t)1);
1244 now = gethrestime_sec();
1245 size = PM_NUMCMPTS(dip) * sizeof (time_t);
1246 timestamp = kmem_alloc(size, KM_SLEEP);
1247 pm_get_timestamps(dip, timestamp);
1250 * Since we removed support for backwards compatible devices,
1251 * (see big comment at top of file)
1252 * it is no longer required to deal with component 0 last.
1254 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
1256 * If already off (an optimization, perhaps)
1258 cp = PM_CP(dip, i);
1259 pwrndx = cp->pmc_cur_pwr;
1260 #ifdef PMDDEBUG
1261 curpwr = (pwrndx == PM_LEVEL_UNKNOWN) ?
1262 PM_LEVEL_UNKNOWN :
1263 cp->pmc_comp.pmc_lvals[pwrndx];
1264 #endif
1266 if (pwrndx == 0) {
1267 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d off or "
1268 "lowest\n", pmf, PM_DEVICE(dip), i))
1269 /* skip device if off or at its lowest */
1270 continue;
1273 thresh = cur_threshold(dip, i); /* comp i threshold */
1274 if ((timestamp[i] == 0) || (cp->pmc_busycount > 0)) {
1275 /* were busy or newly became busy by another thread */
1276 if (timeleft == 0)
1277 timeleft = max(thresh, min_scan);
1278 else
1279 timeleft = min(
1280 timeleft, max(thresh, min_scan));
1281 continue;
1284 idletime = now - timestamp[i]; /* idle time */
1285 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d idle time %lx\n",
1286 pmf, PM_DEVICE(dip), i, idletime))
1287 if (idletime >= thresh || PM_IS_PID(dip)) {
1288 nxtpwr = pm_next_lower_power(cp, pwrndx);
1289 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d, %d->%d\n",
1290 pmf, PM_DEVICE(dip), i, curpwr, nxtpwr))
1291 if (pm_set_power(dip, i, nxtpwr, PM_LEVEL_DOWNONLY,
1292 PM_CANBLOCK_FAIL, 1, &unused) != DDI_SUCCESS &&
1293 PM_CURPOWER(dip, i) != nxtpwr) {
1294 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d, "
1295 "%d->%d Failed\n", pmf, PM_DEVICE(dip),
1296 i, curpwr, nxtpwr))
1297 timeleft = min_scan;
1298 continue;
1299 } else {
1300 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d, "
1301 "%d->%d, GOOD curpwr %d\n", pmf,
1302 PM_DEVICE(dip), i, curpwr, nxtpwr,
1303 cur_power(cp)))
1305 if (nxtpwr == 0) /* component went off */
1306 continue;
1309 * scan to next lower level
1311 if (timeleft == 0)
1312 timeleft = max(
1313 1, cur_threshold(dip, i));
1314 else
1315 timeleft = min(timeleft,
1316 max(1, cur_threshold(dip, i)));
1317 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d, "
1318 "timeleft(%lx)\n", pmf, PM_DEVICE(dip),
1319 i, timeleft))
1321 } else { /* comp not idle long enough */
1322 if (timeleft == 0)
1323 timeleft = thresh - idletime;
1324 else
1325 timeleft = min(timeleft, (thresh - idletime));
1326 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d, timeleft="
1327 "%lx\n", pmf, PM_DEVICE(dip), i, timeleft))
1330 ndi_devi_exit(pdip, circ);
1331 kmem_free(timestamp, size);
1332 PMD(PMD_SCAN, ("%s: [END %s@%s(%s#%d)] timeleft(%lx)\n", pmf,
1333 PM_DEVICE(dip), timeleft))
1336 * if components are already at lowest level, timeleft is left 0
1338 return ((timeleft == 0) ? LONG_MAX : timeleft);
1342 * pm_scan_stop - cancel scheduled pm_rescan,
1343 * wait for termination of dispatched pm_scan thread
1344 * and active pm_scan_dev thread.
1346 void
1347 pm_scan_stop(dev_info_t *dip)
1349 PMD_FUNC(pmf, "scan_stop")
1350 pm_scan_t *scanp;
1351 timeout_id_t scanid;
1353 PMD(PMD_SCAN, ("%s: [BEGIN %s@%s(%s#%d)]\n", pmf, PM_DEVICE(dip)))
1354 PM_LOCK_DIP(dip);
1355 scanp = PM_GET_PM_SCAN(dip);
1356 if (!scanp) {
1357 PMD(PMD_SCAN, ("%s: [END %s@%s(%s#%d)] scan not initialized\n",
1358 pmf, PM_DEVICE(dip)))
1359 PM_UNLOCK_DIP(dip);
1360 return;
1362 scanp->ps_scan_flags |= PM_SCAN_STOP;
1364 /* cancel scheduled scan taskq */
1365 while (scanp->ps_scan_id) {
1366 scanid = scanp->ps_scan_id;
1367 scanp->ps_scan_id = 0;
1368 PM_UNLOCK_DIP(dip);
1369 (void) untimeout(scanid);
1370 PM_LOCK_DIP(dip);
1373 while (scanp->ps_scan_flags & (PM_SCANNING | PM_SCAN_DISPATCHED)) {
1374 PM_UNLOCK_DIP(dip);
1375 delay(1);
1376 PM_LOCK_DIP(dip);
1378 PM_UNLOCK_DIP(dip);
1379 PMD(PMD_SCAN, ("%s: [END %s@%s(%s#%d)]\n", pmf, PM_DEVICE(dip)))
1383 pm_scan_stop_walk(dev_info_t *dip, void *arg)
1385 _NOTE(ARGUNUSED(arg))
1387 if (!PM_GET_PM_SCAN(dip))
1388 return (DDI_WALK_CONTINUE);
1389 ASSERT(!PM_ISBC(dip));
1390 pm_scan_stop(dip);
1391 return (DDI_WALK_CONTINUE);
1395 * Converts a power level value to its index
1397 static int
1398 power_val_to_index(pm_component_t *cp, int val)
1400 int limit, i, *ip;
1402 ASSERT(val != PM_LEVEL_UPONLY && val != PM_LEVEL_DOWNONLY &&
1403 val != PM_LEVEL_EXACT);
1404 /* convert power value into index (i) */
1405 limit = cp->pmc_comp.pmc_numlevels;
1406 ip = cp->pmc_comp.pmc_lvals;
1407 for (i = 0; i < limit; i++)
1408 if (val == *ip++)
1409 return (i);
1410 return (-1);
1414 * Converts a numeric power level to a printable string
1416 static char *
1417 power_val_to_string(pm_component_t *cp, int val)
1419 int index;
1421 if (val == PM_LEVEL_UPONLY)
1422 return ("<UPONLY>");
1424 if (val == PM_LEVEL_UNKNOWN ||
1425 (index = power_val_to_index(cp, val)) == -1)
1426 return ("<LEVEL_UNKNOWN>");
1428 return (cp->pmc_comp.pmc_lnames[index]);
1432 * Return true if this node has been claimed by a ppm.
1434 static int
1435 pm_ppm_claimed(dev_info_t *dip)
1437 return (PPM(dip) != NULL);
1441 * A node which was voluntarily power managed has just used up its "free cycle"
1442 * and need is volpmd field cleared, and the same done to all its descendents
1444 static void
1445 pm_clear_volpm_dip(dev_info_t *dip)
1447 PMD_FUNC(pmf, "clear_volpm_dip")
1449 if (dip == NULL)
1450 return;
1451 PMD(PMD_NOINVOL, ("%s: clear volpm from %s@%s(%s#%d)\n", pmf,
1452 PM_DEVICE(dip)))
1453 DEVI(dip)->devi_pm_volpmd = 0;
1454 for (dip = ddi_get_child(dip); dip; dip = ddi_get_next_sibling(dip)) {
1455 pm_clear_volpm_dip(dip);
1460 * A node which was voluntarily power managed has used up the "free cycles"
1461 * for the subtree that it is the root of. Scan through the list of detached
1462 * nodes and adjust the counts of any that are descendents of the node.
1464 static void
1465 pm_clear_volpm_list(dev_info_t *dip)
1467 PMD_FUNC(pmf, "clear_volpm_list")
1468 char *pathbuf;
1469 size_t len;
1470 pm_noinvol_t *ip;
1472 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1473 (void) ddi_pathname(dip, pathbuf);
1474 len = strlen(pathbuf);
1475 PMD(PMD_NOINVOL, ("%s: clear volpm list %s\n", pmf, pathbuf))
1476 rw_enter(&pm_noinvol_rwlock, RW_WRITER);
1477 for (ip = pm_noinvol_head; ip; ip = ip->ni_next) {
1478 PMD(PMD_NOINVOL, ("%s: clear volpm: ni_path %s\n", pmf,
1479 ip->ni_path))
1480 if (strncmp(pathbuf, ip->ni_path, len) == 0 &&
1481 ip->ni_path[len] == '/') {
1482 PMD(PMD_NOINVOL, ("%s: clear volpm: %s\n", pmf,
1483 ip->ni_path))
1484 ip->ni_volpmd = 0;
1485 ip->ni_wasvolpmd = 0;
1488 kmem_free(pathbuf, MAXPATHLEN);
1489 rw_exit(&pm_noinvol_rwlock);
1493 * Powers a device, suspending or resuming the driver if it is a backward
1494 * compatible device, calling into ppm to change power level.
1495 * Called with the component's power lock held.
1497 static int
1498 power_dev(dev_info_t *dip, int comp, int level, int old_level,
1499 pm_canblock_t canblock, pm_ppm_devlist_t **devlist)
1501 PMD_FUNC(pmf, "power_dev")
1502 power_req_t power_req;
1503 int power_op_ret; /* DDI_SUCCESS or DDI_FAILURE */
1504 int resume_needed = 0;
1505 int suspended = 0;
1506 int result;
1507 #ifdef PMDDEBUG
1508 struct pm_component *cp = PM_CP(dip, comp);
1509 #endif
1510 int bc = PM_ISBC(dip);
1511 int pm_all_components_off(dev_info_t *);
1512 int clearvolpmd = 0;
1513 char pathbuf[MAXNAMELEN];
1514 #ifdef PMDDEBUG
1515 char *ppmname, *ppmaddr;
1516 #endif
1518 * If this is comp 0 of a backwards compat device and we are
1519 * going to take the power away, we need to detach it with
1520 * DDI_PM_SUSPEND command.
1522 if (bc && comp == 0 && POWERING_OFF(old_level, level)) {
1523 if (devi_detach(dip, DDI_PM_SUSPEND) != DDI_SUCCESS) {
1524 /* We could not suspend before turning cmpt zero off */
1525 PMD(PMD_ERROR, ("%s: could not suspend %s@%s(%s#%d)\n",
1526 pmf, PM_DEVICE(dip)))
1527 return (DDI_FAILURE);
1528 } else {
1529 DEVI(dip)->devi_pm_flags |= PMC_SUSPENDED;
1530 suspended++;
1533 power_req.request_type = PMR_PPM_SET_POWER;
1534 power_req.req.ppm_set_power_req.who = dip;
1535 power_req.req.ppm_set_power_req.cmpt = comp;
1536 power_req.req.ppm_set_power_req.old_level = old_level;
1537 power_req.req.ppm_set_power_req.new_level = level;
1538 power_req.req.ppm_set_power_req.canblock = canblock;
1539 power_req.req.ppm_set_power_req.cookie = NULL;
1540 #ifdef PMDDEBUG
1541 if (pm_ppm_claimed(dip)) {
1542 ppmname = PM_NAME(PPM(dip));
1543 ppmaddr = PM_ADDR(PPM(dip));
1545 } else {
1546 ppmname = "noppm";
1547 ppmaddr = "0";
1549 PMD(PMD_PPM, ("%s: %s@%s(%s#%d):%s[%d] %s (%d) -> %s (%d) via %s@%s\n",
1550 pmf, PM_DEVICE(dip), cp->pmc_comp.pmc_name, comp,
1551 power_val_to_string(cp, old_level), old_level,
1552 power_val_to_string(cp, level), level, ppmname, ppmaddr))
1553 #endif
1555 * If non-bc noinvolpm device is turning first comp on, or noinvolpm
1556 * bc device comp 0 is powering on, then we count it as a power cycle
1557 * against its voluntary count.
1559 if (DEVI(dip)->devi_pm_volpmd &&
1560 (!bc && pm_all_components_off(dip) && level != 0) ||
1561 (bc && comp == 0 && POWERING_ON(old_level, level)))
1562 clearvolpmd = 1;
1563 if ((power_op_ret = pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER,
1564 &power_req, &result)) == DDI_SUCCESS) {
1566 * Now do involuntary pm accounting; If we've just cycled power
1567 * on a voluntarily pm'd node, and by inference on its entire
1568 * subtree, we need to set the subtree (including those nodes
1569 * already detached) volpmd counts to 0, and subtract out the
1570 * value of the current node's volpmd count from the ancestors
1572 if (clearvolpmd) {
1573 int volpmd = DEVI(dip)->devi_pm_volpmd;
1574 pm_clear_volpm_dip(dip);
1575 pm_clear_volpm_list(dip);
1576 if (volpmd) {
1577 (void) ddi_pathname(dip, pathbuf);
1578 (void) pm_noinvol_update(PM_BP_NOINVOL_POWER,
1579 volpmd, 0, pathbuf, dip);
1582 } else {
1583 PMD(PMD_FAIL, ("%s: can't set comp %d (%s) of %s@%s(%s#%d) "
1584 "to level %d (%s)\n", pmf, comp, cp->pmc_comp.pmc_name,
1585 PM_DEVICE(dip), level, power_val_to_string(cp, level)))
1588 * If some other devices were also powered up (e.g. other cpus in
1589 * the same domain) return a pointer to that list
1591 if (devlist) {
1592 *devlist = (pm_ppm_devlist_t *)
1593 power_req.req.ppm_set_power_req.cookie;
1596 * We will have to resume the device if the device is backwards compat
1597 * device and either of the following is true:
1598 * -This is comp 0 and we have successfully powered it up
1599 * -This is comp 0 and we have failed to power it down. Resume is
1600 * needed because we have suspended it above
1603 if (bc && comp == 0) {
1604 ASSERT(PM_ISDIRECT(dip) || DEVI_IS_DETACHING(dip));
1605 if (power_op_ret == DDI_SUCCESS) {
1606 if (POWERING_ON(old_level, level)) {
1608 * It must be either suspended or resumed
1609 * via pm_power_has_changed path
1611 ASSERT((DEVI(dip)->devi_pm_flags &
1612 PMC_SUSPENDED) ||
1613 (PM_CP(dip, comp)->pmc_flags &
1614 PM_PHC_WHILE_SET_POWER));
1616 resume_needed = suspended;
1618 } else {
1619 if (POWERING_OFF(old_level, level)) {
1621 * It must be either suspended or resumed
1622 * via pm_power_has_changed path
1624 ASSERT((DEVI(dip)->devi_pm_flags &
1625 PMC_SUSPENDED) ||
1626 (PM_CP(dip, comp)->pmc_flags &
1627 PM_PHC_WHILE_SET_POWER));
1629 resume_needed = suspended;
1633 if (resume_needed) {
1634 ASSERT(DEVI(dip)->devi_pm_flags & PMC_SUSPENDED);
1635 /* ppm is not interested in DDI_PM_RESUME */
1636 if ((power_op_ret = devi_attach(dip, DDI_PM_RESUME)) ==
1637 DDI_SUCCESS) {
1638 DEVI(dip)->devi_pm_flags &= ~PMC_SUSPENDED;
1639 } else
1640 cmn_err(CE_WARN, "!pm: Can't resume %s@%s(%s#%d)",
1641 PM_DEVICE(dip));
1643 return (power_op_ret);
1647 * Return true if we are the owner or a borrower of the devi lock. See
1648 * pm_lock_power_single() about borrowing the lock.
1650 static int
1651 pm_devi_lock_held(dev_info_t *dip)
1653 lock_loan_t *cur;
1655 if (DEVI_BUSY_OWNED(dip))
1656 return (1);
1658 /* return false if no locks borrowed */
1659 if (lock_loan_head.pmlk_next == NULL)
1660 return (0);
1662 mutex_enter(&pm_loan_lock);
1663 /* see if our thread is registered as a lock borrower. */
1664 for (cur = lock_loan_head.pmlk_next; cur; cur = cur->pmlk_next)
1665 if (cur->pmlk_borrower == curthread)
1666 break;
1667 mutex_exit(&pm_loan_lock);
1669 return (cur != NULL && cur->pmlk_lender == DEVI(dip)->devi_busy_thread);
1673 * pm_set_power: adjusts power level of device. Assumes device is power
1674 * manageable & component exists.
1676 * Cases which require us to bring up devices we keep up ("wekeepups") for
1677 * backwards compatible devices:
1678 * component 0 is off and we're bringing it up from 0
1679 * bring up wekeepup first
1680 * and recursively when component 0 is off and we bring some other
1681 * component up from 0
1682 * For devices which are not backward compatible, our dependency notion is much
1683 * simpler. Unless all components are off, then wekeeps must be on.
1684 * We don't treat component 0 differently.
1685 * Canblock tells how to deal with a direct pm'd device.
1686 * Scan arg tells us if we were called from scan, in which case we don't need
1687 * to go back to the root node and walk down to change power.
1690 pm_set_power(dev_info_t *dip, int comp, int level, int direction,
1691 pm_canblock_t canblock, int scan, int *retp)
1693 PMD_FUNC(pmf, "set_power")
1694 char *pathbuf;
1695 pm_bp_child_pwrchg_t bpc;
1696 pm_sp_misc_t pspm;
1697 int ret = DDI_SUCCESS;
1698 int unused = DDI_SUCCESS;
1699 dev_info_t *pdip = ddi_get_parent(dip);
1701 #ifdef DEBUG
1702 int diverted = 0;
1705 * This prevents operations on the console from calling prom_printf and
1706 * either deadlocking or bringing up the console because of debug
1707 * output
1709 if (dip == cfb_dip) {
1710 diverted++;
1711 mutex_enter(&pm_debug_lock);
1712 pm_divertdebug++;
1713 mutex_exit(&pm_debug_lock);
1715 #endif
1716 ASSERT(direction == PM_LEVEL_UPONLY || direction == PM_LEVEL_DOWNONLY ||
1717 direction == PM_LEVEL_EXACT);
1718 PMD(PMD_SET, ("%s: %s@%s(%s#%d), comp=%d, dir=%s, new=%d\n",
1719 pmf, PM_DEVICE(dip), comp, pm_decode_direction(direction), level))
1720 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1721 (void) ddi_pathname(dip, pathbuf);
1722 bpc.bpc_dip = dip;
1723 bpc.bpc_path = pathbuf;
1724 bpc.bpc_comp = comp;
1725 bpc.bpc_olevel = PM_CURPOWER(dip, comp);
1726 bpc.bpc_nlevel = level;
1727 pspm.pspm_direction = direction;
1728 pspm.pspm_errnop = retp;
1729 pspm.pspm_canblock = canblock;
1730 pspm.pspm_scan = scan;
1731 bpc.bpc_private = &pspm;
1734 * If a config operation is being done (we've locked the parent) or
1735 * we already hold the power lock (we've locked the node)
1736 * then we can operate directly on the node because we have already
1737 * brought up all the ancestors, otherwise, we have to go back to the
1738 * top of the tree.
1740 if (pm_devi_lock_held(pdip) || pm_devi_lock_held(dip))
1741 ret = pm_busop_set_power(dip, NULL, BUS_POWER_CHILD_PWRCHG,
1742 (void *)&bpc, (void *)&unused);
1743 else
1744 ret = pm_busop_bus_power(ddi_root_node(), NULL,
1745 BUS_POWER_CHILD_PWRCHG, (void *)&bpc, (void *)&unused);
1746 #ifdef DEBUG
1747 if (ret != DDI_SUCCESS || *retp != DDI_SUCCESS) {
1748 PMD(PMD_ERROR, ("%s: %s@%s(%s#%d) can't change power, ret=%d, "
1749 "errno=%d\n", pmf, PM_DEVICE(dip), ret, *retp))
1751 if (diverted) {
1752 mutex_enter(&pm_debug_lock);
1753 pm_divertdebug--;
1754 mutex_exit(&pm_debug_lock);
1756 #endif
1757 kmem_free(pathbuf, MAXPATHLEN);
1758 return (ret);
1762 * If holddip is set, then if a dip is found we return with the node held.
1764 * This code uses the same locking scheme as e_ddi_hold_devi_by_path
1765 * (resolve_pathname), but it does not drive attach.
1767 dev_info_t *
1768 pm_name_to_dip(char *pathname, int holddip)
1770 struct pathname pn;
1771 char *component;
1772 dev_info_t *parent, *child;
1773 int circ;
1775 if ((pathname == NULL) || (*pathname != '/'))
1776 return (NULL);
1778 /* setup pathname and allocate component */
1779 if (pn_get(pathname, UIO_SYSSPACE, &pn))
1780 return (NULL);
1781 component = kmem_alloc(MAXNAMELEN, KM_SLEEP);
1783 /* start at top, process '/' component */
1784 parent = child = ddi_root_node();
1785 ndi_hold_devi(parent);
1786 pn_skipslash(&pn);
1787 ASSERT(i_ddi_devi_attached(parent));
1789 /* process components of pathname */
1790 while (pn_pathleft(&pn)) {
1791 (void) pn_getcomponent(&pn, component);
1793 /* enter parent and search for component child */
1794 ndi_devi_enter(parent, &circ);
1795 child = ndi_devi_findchild(parent, component);
1796 if ((child == NULL) || !i_ddi_devi_attached(child)) {
1797 child = NULL;
1798 ndi_devi_exit(parent, circ);
1799 ndi_rele_devi(parent);
1800 goto out;
1803 /* attached child found, hold child and release parent */
1804 ndi_hold_devi(child);
1805 ndi_devi_exit(parent, circ);
1806 ndi_rele_devi(parent);
1808 /* child becomes parent, and process next component */
1809 parent = child;
1810 pn_skipslash(&pn);
1812 /* loop with active ndi_devi_hold of child->parent */
1815 out:
1816 pn_free(&pn);
1817 kmem_free(component, MAXNAMELEN);
1819 /* if we are not asked to return with hold, drop current hold */
1820 if (child && !holddip)
1821 ndi_rele_devi(child);
1822 return (child);
1826 * Search for a dependency and mark it unsatisfied
1828 static void
1829 pm_unsatisfy(char *keeper, char *kept)
1831 PMD_FUNC(pmf, "unsatisfy")
1832 pm_pdr_t *dp;
1834 PMD(PMD_KEEPS, ("%s: keeper=%s, kept=%s\n", pmf, keeper, kept))
1835 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
1836 if (!dp->pdr_isprop) {
1837 if (strcmp(dp->pdr_keeper, keeper) == 0 &&
1838 (dp->pdr_kept_count > 0) &&
1839 strcmp(dp->pdr_kept_paths[0], kept) == 0) {
1840 if (dp->pdr_satisfied) {
1841 dp->pdr_satisfied = 0;
1842 pm_unresolved_deps++;
1843 PMD(PMD_KEEPS, ("%s: clear satisfied, "
1844 "pm_unresolved_deps now %d\n", pmf,
1845 pm_unresolved_deps))
1853 * Device dip is being un power managed, it keeps up count other devices.
1854 * We need to release any hold we have on the kept devices, and also
1855 * mark the dependency no longer satisfied.
1857 static void
1858 pm_unkeeps(int count, char *keeper, char **keptpaths, int pwr)
1860 PMD_FUNC(pmf, "unkeeps")
1861 int i, j;
1862 dev_info_t *kept;
1863 dev_info_t *dip;
1864 struct pm_component *cp;
1865 int keeper_on = 0, circ;
1867 PMD(PMD_KEEPS, ("%s: count=%d, keeper=%s, keptpaths=%p\n", pmf, count,
1868 keeper, (void *)keptpaths))
1870 * Try to grab keeper. Keeper may have gone away by now,
1871 * in this case, used the passed in value pwr
1873 dip = pm_name_to_dip(keeper, 1);
1874 for (i = 0; i < count; i++) {
1875 /* Release power hold */
1876 kept = pm_name_to_dip(keptpaths[i], 1);
1877 if (kept) {
1878 PMD(PMD_KEEPS, ("%s: %s@%s(%s#%d)[%d]\n", pmf,
1879 PM_DEVICE(kept), i))
1881 * We need to check if we skipped a bringup here
1882 * because we could have failed the bringup
1883 * (ie DIRECT PM device) and have
1884 * not increment the count.
1886 if ((dip != NULL) && (PM_GET_PM_INFO(dip) != NULL)) {
1887 keeper_on = 0;
1888 PM_LOCK_POWER(dip, &circ);
1889 for (j = 0; j < PM_NUMCMPTS(dip); j++) {
1890 cp = &DEVI(dip)->devi_pm_components[j];
1891 if (cur_power(cp)) {
1892 keeper_on++;
1893 break;
1896 if (keeper_on && (PM_SKBU(kept) == 0)) {
1897 pm_rele_power(kept);
1898 DEVI(kept)->devi_pm_flags
1899 &= ~PMC_SKIP_BRINGUP;
1901 PM_UNLOCK_POWER(dip, circ);
1902 } else if (pwr) {
1903 if (PM_SKBU(kept) == 0) {
1904 pm_rele_power(kept);
1905 DEVI(kept)->devi_pm_flags
1906 &= ~PMC_SKIP_BRINGUP;
1909 ddi_release_devi(kept);
1912 * mark this dependency not satisfied
1914 pm_unsatisfy(keeper, keptpaths[i]);
1916 if (dip)
1917 ddi_release_devi(dip);
1921 * Device kept is being un power managed, it is kept up by keeper.
1922 * We need to mark the dependency no longer satisfied.
1924 static void
1925 pm_unkepts(char *kept, char *keeper)
1927 PMD_FUNC(pmf, "unkepts")
1928 PMD(PMD_KEEPS, ("%s: kept=%s, keeper=%s\n", pmf, kept, keeper))
1929 ASSERT(keeper != NULL);
1931 * mark this dependency not satisfied
1933 pm_unsatisfy(keeper, kept);
1937 * Removes dependency information and hold on the kepts, if the path is a
1938 * path of a keeper.
1940 static void
1941 pm_free_keeper(char *path, int pwr)
1943 pm_pdr_t *dp;
1944 int i;
1945 size_t length;
1947 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
1948 if (strcmp(dp->pdr_keeper, path) != 0)
1949 continue;
1951 * Remove all our kept holds and the dependency records,
1952 * then free up the kept lists.
1954 pm_unkeeps(dp->pdr_kept_count, path, dp->pdr_kept_paths, pwr);
1955 if (dp->pdr_kept_count) {
1956 for (i = 0; i < dp->pdr_kept_count; i++) {
1957 length = strlen(dp->pdr_kept_paths[i]);
1958 kmem_free(dp->pdr_kept_paths[i], length + 1);
1960 kmem_free(dp->pdr_kept_paths,
1961 dp->pdr_kept_count * sizeof (char **));
1962 dp->pdr_kept_paths = NULL;
1963 dp->pdr_kept_count = 0;
1969 * Removes the device represented by path from the list of kepts, if the
1970 * path is a path of a kept
1972 static void
1973 pm_free_kept(char *path)
1975 pm_pdr_t *dp;
1976 int i;
1977 int j, count;
1978 size_t length;
1979 char **paths;
1981 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
1982 if (dp->pdr_kept_count == 0)
1983 continue;
1984 count = dp->pdr_kept_count;
1985 /* Remove this device from the kept path lists */
1986 for (i = 0; i < count; i++) {
1987 if (strcmp(dp->pdr_kept_paths[i], path) == 0) {
1988 pm_unkepts(path, dp->pdr_keeper);
1989 length = strlen(dp->pdr_kept_paths[i]) + 1;
1990 kmem_free(dp->pdr_kept_paths[i], length);
1991 dp->pdr_kept_paths[i] = NULL;
1992 dp->pdr_kept_count--;
1995 /* Compact the kept paths array */
1996 if (dp->pdr_kept_count) {
1997 length = dp->pdr_kept_count * sizeof (char **);
1998 paths = kmem_zalloc(length, KM_SLEEP);
1999 j = 0;
2000 for (i = 0; i < count; i++) {
2001 if (dp->pdr_kept_paths[i] != NULL) {
2002 paths[j] = dp->pdr_kept_paths[i];
2003 j++;
2006 ASSERT(j == dp->pdr_kept_count);
2008 /* Now free the old array and point to the new one */
2009 kmem_free(dp->pdr_kept_paths, count * sizeof (char **));
2010 if (dp->pdr_kept_count)
2011 dp->pdr_kept_paths = paths;
2012 else
2013 dp->pdr_kept_paths = NULL;
2018 * Free the dependency information for a device.
2020 void
2021 pm_free_keeps(char *path, int pwr)
2023 PMD_FUNC(pmf, "free_keeps")
2025 #ifdef DEBUG
2026 int doprdeps = 0;
2027 void prdeps(char *);
2029 PMD(PMD_KEEPS, ("%s: %s\n", pmf, path))
2030 if (pm_debug & PMD_KEEPS) {
2031 doprdeps = 1;
2032 prdeps("pm_free_keeps before");
2034 #endif
2036 * First assume we are a keeper and remove all our kepts.
2038 pm_free_keeper(path, pwr);
2040 * Now assume we a kept device, and remove all our records.
2042 pm_free_kept(path);
2043 #ifdef DEBUG
2044 if (doprdeps) {
2045 prdeps("pm_free_keeps after");
2047 #endif
2050 static int
2051 pm_is_kept(char *path)
2053 pm_pdr_t *dp;
2054 int i;
2056 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
2057 if (dp->pdr_kept_count == 0)
2058 continue;
2059 for (i = 0; i < dp->pdr_kept_count; i++) {
2060 if (strcmp(dp->pdr_kept_paths[i], path) == 0)
2061 return (1);
2064 return (0);
2067 static void
2068 e_pm_hold_rele_power(dev_info_t *dip, int cnt)
2070 PMD_FUNC(pmf, "hold_rele_power")
2071 int circ;
2073 if ((dip == NULL) ||
2074 (PM_GET_PM_INFO(dip) == NULL) || PM_ISBC(dip))
2075 return;
2077 PM_LOCK_POWER(dip, &circ);
2078 ASSERT(cnt >= 0 && PM_KUC(dip) >= 0 || cnt < 0 && PM_KUC(dip) > 0);
2079 PMD(PMD_KIDSUP, ("%s: kidsupcnt for %s@%s(%s#%d) %d->%d\n", pmf,
2080 PM_DEVICE(dip), PM_KUC(dip), (PM_KUC(dip) + cnt)))
2082 PM_KUC(dip) += cnt;
2084 ASSERT(PM_KUC(dip) >= 0);
2085 PM_UNLOCK_POWER(dip, circ);
2087 if (cnt < 0 && PM_KUC(dip) == 0)
2088 pm_rescan(dip);
2091 #define MAX_PPM_HANDLERS 4
2093 kmutex_t ppm_lock; /* in case we ever do multi-threaded startup */
2095 struct ppm_callbacks {
2096 int (*ppmc_func)(dev_info_t *);
2097 dev_info_t *ppmc_dip;
2098 } ppm_callbacks[MAX_PPM_HANDLERS + 1];
2102 * This routine calls into all the registered ppms to notify them
2103 * that either all components of power-managed devices are at their
2104 * lowest levels or no longer all are at their lowest levels.
2106 static void
2107 pm_ppm_notify_all_lowest(dev_info_t *dip, int mode)
2109 struct ppm_callbacks *ppmcp;
2110 power_req_t power_req;
2111 int result = 0;
2113 power_req.request_type = PMR_PPM_ALL_LOWEST;
2114 power_req.req.ppm_all_lowest_req.mode = mode;
2115 mutex_enter(&ppm_lock);
2116 for (ppmcp = ppm_callbacks; ppmcp->ppmc_func; ppmcp++)
2117 (void) pm_ctlops((dev_info_t *)ppmcp->ppmc_dip, dip,
2118 DDI_CTLOPS_POWER, &power_req, &result);
2119 mutex_exit(&ppm_lock);
2120 if (mode == PM_ALL_LOWEST) {
2121 if (autoS3_enabled) {
2122 PMD(PMD_SX, ("pm_ppm_notify_all_lowest triggering "
2123 "autos3\n"))
2124 mutex_enter(&srn_clone_lock);
2125 if (srn_signal) {
2126 srn_inuse++;
2127 PMD(PMD_SX, ("(*srn_signal)(AUTOSX, 3)\n"))
2128 (*srn_signal)(SRN_TYPE_AUTOSX, 3);
2129 srn_inuse--;
2130 } else {
2131 PMD(PMD_SX, ("srn_signal NULL\n"))
2133 mutex_exit(&srn_clone_lock);
2134 } else {
2135 PMD(PMD_SX, ("pm_ppm_notify_all_lowest autos3 "
2136 "disabled\n"));
2141 static void
2142 pm_set_pm_info(dev_info_t *dip, void *value)
2144 DEVI(dip)->devi_pm_info = value;
2147 pm_rsvp_t *pm_blocked_list;
2150 * Look up an entry in the blocked list by dip and component
2152 static pm_rsvp_t *
2153 pm_rsvp_lookup(dev_info_t *dip, int comp)
2155 pm_rsvp_t *p;
2156 ASSERT(MUTEX_HELD(&pm_rsvp_lock));
2157 for (p = pm_blocked_list; p; p = p->pr_next)
2158 if (p->pr_dip == dip && p->pr_comp == comp) {
2159 return (p);
2161 return (NULL);
2165 * Called when a device which is direct power managed (or the parent or
2166 * dependent of such a device) changes power, or when a pm clone is closed
2167 * that was direct power managing a device. This call results in pm_blocked()
2168 * (below) returning.
2170 void
2171 pm_proceed(dev_info_t *dip, int cmd, int comp, int newlevel)
2173 PMD_FUNC(pmf, "proceed")
2174 pm_rsvp_t *found = NULL;
2175 pm_rsvp_t *p;
2177 mutex_enter(&pm_rsvp_lock);
2178 switch (cmd) {
2180 * we're giving up control, let any pending op continue
2182 case PMP_RELEASE:
2183 for (p = pm_blocked_list; p; p = p->pr_next) {
2184 if (dip == p->pr_dip) {
2185 p->pr_retval = PMP_RELEASE;
2186 PMD(PMD_DPM, ("%s: RELEASE %s@%s(%s#%d)\n",
2187 pmf, PM_DEVICE(dip)))
2188 cv_signal(&p->pr_cv);
2191 break;
2194 * process has done PM_SET_CURRENT_POWER; let a matching request
2195 * succeed and a non-matching request for the same device fail
2197 case PMP_SETPOWER:
2198 found = pm_rsvp_lookup(dip, comp);
2199 if (!found) /* if driver not waiting */
2200 break;
2202 * This cannot be pm_lower_power, since that can only happen
2203 * during detach or probe
2205 if (found->pr_newlevel <= newlevel) {
2206 found->pr_retval = PMP_SUCCEED;
2207 PMD(PMD_DPM, ("%s: SUCCEED %s@%s(%s#%d)\n", pmf,
2208 PM_DEVICE(dip)))
2209 } else {
2210 found->pr_retval = PMP_FAIL;
2211 PMD(PMD_DPM, ("%s: FAIL %s@%s(%s#%d)\n", pmf,
2212 PM_DEVICE(dip)))
2214 cv_signal(&found->pr_cv);
2215 break;
2217 default:
2218 panic("pm_proceed unknown cmd %d", cmd);
2220 mutex_exit(&pm_rsvp_lock);
2224 * This routine dispatches new work to the dependency thread. Caller must
2225 * be prepared to block for memory if necessary.
2227 void
2228 pm_dispatch_to_dep_thread(int cmd, char *keeper, char *kept, int wait,
2229 int *res, int cached_pwr)
2231 pm_dep_wk_t *new_work;
2233 new_work = kmem_zalloc(sizeof (pm_dep_wk_t), KM_SLEEP);
2234 new_work->pdw_type = cmd;
2235 new_work->pdw_wait = wait;
2236 new_work->pdw_done = 0;
2237 new_work->pdw_ret = 0;
2238 new_work->pdw_pwr = cached_pwr;
2239 cv_init(&new_work->pdw_cv, NULL, CV_DEFAULT, NULL);
2240 if (keeper != NULL) {
2241 new_work->pdw_keeper = kmem_zalloc(strlen(keeper) + 1,
2242 KM_SLEEP);
2243 (void) strcpy(new_work->pdw_keeper, keeper);
2245 if (kept != NULL) {
2246 new_work->pdw_kept = kmem_zalloc(strlen(kept) + 1, KM_SLEEP);
2247 (void) strcpy(new_work->pdw_kept, kept);
2249 mutex_enter(&pm_dep_thread_lock);
2250 if (pm_dep_thread_workq == NULL) {
2251 pm_dep_thread_workq = new_work;
2252 pm_dep_thread_tail = new_work;
2253 new_work->pdw_next = NULL;
2254 } else {
2255 pm_dep_thread_tail->pdw_next = new_work;
2256 pm_dep_thread_tail = new_work;
2257 new_work->pdw_next = NULL;
2259 cv_signal(&pm_dep_thread_cv);
2260 /* If caller asked for it, wait till it is done. */
2261 if (wait) {
2262 while (!new_work->pdw_done)
2263 cv_wait(&new_work->pdw_cv, &pm_dep_thread_lock);
2265 * Pass return status, if any, back.
2267 if (res != NULL)
2268 *res = new_work->pdw_ret;
2270 * If we asked to wait, it is our job to free the request
2271 * structure.
2273 if (new_work->pdw_keeper)
2274 kmem_free(new_work->pdw_keeper,
2275 strlen(new_work->pdw_keeper) + 1);
2276 if (new_work->pdw_kept)
2277 kmem_free(new_work->pdw_kept,
2278 strlen(new_work->pdw_kept) + 1);
2279 kmem_free(new_work, sizeof (pm_dep_wk_t));
2281 mutex_exit(&pm_dep_thread_lock);
2285 * Release the pm resource for this device.
2287 void
2288 pm_rem_info(dev_info_t *dip)
2290 PMD_FUNC(pmf, "rem_info")
2291 int i, count = 0;
2292 pm_info_t *info = PM_GET_PM_INFO(dip);
2293 dev_info_t *pdip = ddi_get_parent(dip);
2294 char *pathbuf;
2295 int work_type = PM_DEP_WK_DETACH;
2297 ASSERT(info);
2299 ASSERT(!PM_IAM_LOCKING_DIP(dip));
2300 if (PM_ISDIRECT(dip)) {
2301 info->pmi_dev_pm_state &= ~PM_DIRECT;
2302 ASSERT(info->pmi_clone);
2303 info->pmi_clone = 0;
2304 pm_proceed(dip, PMP_RELEASE, -1, -1);
2306 ASSERT(!PM_GET_PM_SCAN(dip));
2309 * Now adjust parent's kidsupcnt. BC nodes we check only comp 0,
2310 * Others we check all components. BC node that has already
2311 * called pm_destroy_components() has zero component count.
2312 * Parents that get notification are not adjusted because their
2313 * kidsupcnt is always 0 (or 1 during configuration).
2315 PMD(PMD_KEEPS, ("%s: %s@%s(%s#%d) has %d components\n", pmf,
2316 PM_DEVICE(dip), PM_NUMCMPTS(dip)))
2318 /* node is detached, so we can examine power without locking */
2319 if (PM_ISBC(dip)) {
2320 count = (PM_CURPOWER(dip, 0) != 0);
2321 } else {
2322 for (i = 0; i < PM_NUMCMPTS(dip); i++)
2323 count += (PM_CURPOWER(dip, i) != 0);
2326 if (PM_NUMCMPTS(dip) && pdip && !PM_WANTS_NOTIFICATION(pdip))
2327 e_pm_hold_rele_power(pdip, -count);
2329 /* Schedule a request to clean up dependency records */
2330 pathbuf = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
2331 (void) ddi_pathname(dip, pathbuf);
2332 pm_dispatch_to_dep_thread(work_type, pathbuf, pathbuf,
2333 PM_DEP_NOWAIT, NULL, (count > 0));
2334 kmem_free(pathbuf, MAXPATHLEN);
2337 * Adjust the pm_comps_notlowest count since this device is
2338 * not being power-managed anymore.
2340 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
2341 pm_component_t *cp = PM_CP(dip, i);
2342 if (cp->pmc_cur_pwr != 0)
2343 PM_DECR_NOTLOWEST(dip)
2346 * Once we clear the info pointer, it looks like it is not power
2347 * managed to everybody else.
2349 pm_set_pm_info(dip, NULL);
2350 kmem_free(info, sizeof (pm_info_t));
2354 pm_get_norm_pwrs(dev_info_t *dip, int **valuep, size_t *length)
2356 int components = PM_NUMCMPTS(dip);
2357 int *bufp;
2358 size_t size;
2359 int i;
2361 if (components <= 0) {
2362 cmn_err(CE_NOTE, "!pm: %s@%s(%s#%d) has no components, "
2363 "can't get normal power values\n", PM_DEVICE(dip));
2364 return (DDI_FAILURE);
2365 } else {
2366 size = components * sizeof (int);
2367 bufp = kmem_alloc(size, KM_SLEEP);
2368 for (i = 0; i < components; i++) {
2369 bufp[i] = pm_get_normal_power(dip, i);
2372 *length = size;
2373 *valuep = bufp;
2374 return (DDI_SUCCESS);
2377 static int
2378 pm_reset_timestamps(dev_info_t *dip, void *arg)
2380 _NOTE(ARGUNUSED(arg))
2382 int components;
2383 int i;
2385 if (!PM_GET_PM_INFO(dip))
2386 return (DDI_WALK_CONTINUE);
2387 components = PM_NUMCMPTS(dip);
2388 ASSERT(components > 0);
2389 PM_LOCK_BUSY(dip);
2390 for (i = 0; i < components; i++) {
2391 struct pm_component *cp;
2393 * If the component was not marked as busy,
2394 * reset its timestamp to now.
2396 cp = PM_CP(dip, i);
2397 if (cp->pmc_timestamp)
2398 cp->pmc_timestamp = gethrestime_sec();
2400 PM_UNLOCK_BUSY(dip);
2401 return (DDI_WALK_CONTINUE);
2405 * Convert a power level to an index into the levels array (or
2406 * just PM_LEVEL_UNKNOWN in that special case).
2408 static int
2409 pm_level_to_index(dev_info_t *dip, pm_component_t *cp, int level)
2411 PMD_FUNC(pmf, "level_to_index")
2412 int i;
2413 int limit = cp->pmc_comp.pmc_numlevels;
2414 int *ip = cp->pmc_comp.pmc_lvals;
2416 if (level == PM_LEVEL_UNKNOWN)
2417 return (level);
2419 for (i = 0; i < limit; i++) {
2420 if (level == *ip++) {
2421 PMD(PMD_LEVEL, ("%s: %s@%s(%s#%d)[%d] to %x\n",
2422 pmf, PM_DEVICE(dip),
2423 (int)(cp - DEVI(dip)->devi_pm_components), level))
2424 return (i);
2427 panic("pm_level_to_index: level %d not found for device "
2428 "%s@%s(%s#%d)", level, PM_DEVICE(dip));
2429 /*NOTREACHED*/
2433 * Internal function to set current power level
2435 static void
2436 e_pm_set_cur_pwr(dev_info_t *dip, pm_component_t *cp, int level)
2438 PMD_FUNC(pmf, "set_cur_pwr")
2439 int curpwr = (cp->pmc_flags & PM_PHC_WHILE_SET_POWER ?
2440 cp->pmc_phc_pwr : cp->pmc_cur_pwr);
2443 * Nothing to adjust if current & new levels are the same.
2445 if (curpwr != PM_LEVEL_UNKNOWN &&
2446 level == cp->pmc_comp.pmc_lvals[curpwr])
2447 return;
2450 * Keep the count for comps doing transition to/from lowest
2451 * level.
2453 if (curpwr == 0) {
2454 PM_INCR_NOTLOWEST(dip);
2455 } else if (level == cp->pmc_comp.pmc_lvals[0]) {
2456 PM_DECR_NOTLOWEST(dip);
2458 cp->pmc_phc_pwr = PM_LEVEL_UNKNOWN;
2459 cp->pmc_cur_pwr = pm_level_to_index(dip, cp, level);
2462 static int pm_phc_impl(dev_info_t *, int, int, int);
2465 * This is the default method of setting the power of a device if no ppm
2466 * driver has claimed it.
2469 pm_power(dev_info_t *dip, int comp, int level)
2471 PMD_FUNC(pmf, "power")
2472 struct dev_ops *ops;
2473 int (*fn)(dev_info_t *, int, int);
2474 struct pm_component *cp = PM_CP(dip, comp);
2475 int retval;
2476 pm_info_t *info = PM_GET_PM_INFO(dip);
2478 PMD(PMD_KIDSUP, ("%s: %s@%s(%s#%d), comp=%d, level=%d\n", pmf,
2479 PM_DEVICE(dip), comp, level))
2480 if (!(ops = ddi_get_driver(dip))) {
2481 PMD(PMD_FAIL, ("%s: %s@%s(%s#%d) has no ops\n", pmf,
2482 PM_DEVICE(dip)))
2483 return (DDI_FAILURE);
2485 if ((ops->devo_rev < 2) || !(fn = ops->devo_power)) {
2486 PMD(PMD_FAIL, ("%s: %s%s\n", pmf,
2487 (ops->devo_rev < 2 ? " wrong devo_rev" : ""),
2488 (!fn ? " devo_power NULL" : "")))
2489 return (DDI_FAILURE);
2491 cp->pmc_flags |= PM_POWER_OP;
2492 retval = (*fn)(dip, comp, level);
2493 cp->pmc_flags &= ~PM_POWER_OP;
2494 if (retval == DDI_SUCCESS) {
2495 e_pm_set_cur_pwr(dip, PM_CP(dip, comp), level);
2496 return (DDI_SUCCESS);
2500 * If pm_power_has_changed() detected a deadlock with pm_power() it
2501 * updated only the power level of the component. If our attempt to
2502 * set the device new to a power level above has failed we sync the
2503 * total power state via phc code now.
2505 if (cp->pmc_flags & PM_PHC_WHILE_SET_POWER) {
2506 int phc_lvl =
2507 cp->pmc_comp.pmc_lvals[cp->pmc_cur_pwr];
2509 ASSERT(info);
2510 (void) pm_phc_impl(dip, comp, phc_lvl, 0);
2511 PMD(PMD_PHC, ("%s: phc %s@%s(%s#%d) comp=%d level=%d\n",
2512 pmf, PM_DEVICE(dip), comp, phc_lvl))
2515 PMD(PMD_FAIL, ("%s: can't set comp=%d (%s) of %s@%s(%s#%d) to "
2516 "level=%d (%s)\n", pmf, comp, cp->pmc_comp.pmc_name, PM_DEVICE(dip),
2517 level, power_val_to_string(cp, level)));
2518 return (DDI_FAILURE);
2522 pm_unmanage(dev_info_t *dip)
2524 PMD_FUNC(pmf, "unmanage")
2525 power_req_t power_req;
2526 int result, retval = 0;
2528 ASSERT(!PM_IAM_LOCKING_DIP(dip));
2529 PMD(PMD_REMDEV | PMD_KIDSUP, ("%s: %s@%s(%s#%d)\n", pmf,
2530 PM_DEVICE(dip)))
2531 power_req.request_type = PMR_PPM_UNMANAGE;
2532 power_req.req.ppm_config_req.who = dip;
2533 if (pm_ppm_claimed(dip))
2534 retval = pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER,
2535 &power_req, &result);
2536 #ifdef DEBUG
2537 else
2538 retval = pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER,
2539 &power_req, &result);
2540 #endif
2541 ASSERT(retval == DDI_SUCCESS);
2542 pm_rem_info(dip);
2543 return (retval);
2547 pm_raise_power(dev_info_t *dip, int comp, int level)
2549 if (level < 0)
2550 return (DDI_FAILURE);
2551 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, comp, NULL) ||
2552 !e_pm_valid_power(dip, comp, level))
2553 return (DDI_FAILURE);
2555 return (dev_is_needed(dip, comp, level, PM_LEVEL_UPONLY));
2559 pm_lower_power(dev_info_t *dip, int comp, int level)
2561 PMD_FUNC(pmf, "pm_lower_power")
2563 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, comp, NULL) ||
2564 !e_pm_valid_power(dip, comp, level)) {
2565 PMD(PMD_FAIL, ("%s: validation checks failed for %s@%s(%s#%d) "
2566 "comp=%d level=%d\n", pmf, PM_DEVICE(dip), comp, level))
2567 return (DDI_FAILURE);
2570 if (!DEVI_IS_DETACHING(dip)) {
2571 PMD(PMD_FAIL, ("%s: %s@%s(%s#%d) not detaching\n",
2572 pmf, PM_DEVICE(dip)))
2573 return (DDI_FAILURE);
2577 * If we don't care about saving power, or we're treating this node
2578 * specially, then this is a no-op
2580 if (!PM_SCANABLE(dip) || pm_noinvol(dip)) {
2581 PMD(PMD_FAIL, ("%s: %s@%s(%s#%d) %s%s%s%s\n",
2582 pmf, PM_DEVICE(dip),
2583 !autopm_enabled ? "!autopm_enabled " : "",
2584 !PM_POLLING_CPUPM ? "!cpupm_polling " : "",
2585 PM_CPUPM_DISABLED ? "cpupm_disabled " : "",
2586 pm_noinvol(dip) ? "pm_noinvol()" : ""))
2587 return (DDI_SUCCESS);
2590 if (dev_is_needed(dip, comp, level, PM_LEVEL_DOWNONLY) != DDI_SUCCESS) {
2591 PMD(PMD_FAIL, ("%s: %s@%s(%s#%d) dev_is_needed failed\n", pmf,
2592 PM_DEVICE(dip)))
2593 return (DDI_FAILURE);
2595 return (DDI_SUCCESS);
2599 * Find the entries struct for a given dip in the blocked list, return it locked
2601 static psce_t *
2602 pm_psc_dip_to_direct(dev_info_t *dip, pscc_t **psccp)
2604 pscc_t *p;
2605 psce_t *psce;
2607 rw_enter(&pm_pscc_direct_rwlock, RW_READER);
2608 for (p = pm_pscc_direct; p; p = p->pscc_next) {
2609 if (p->pscc_dip == dip) {
2610 *psccp = p;
2611 psce = p->pscc_entries;
2612 mutex_enter(&psce->psce_lock);
2613 ASSERT(psce);
2614 rw_exit(&pm_pscc_direct_rwlock);
2615 return (psce);
2618 rw_exit(&pm_pscc_direct_rwlock);
2619 panic("sunpm: no entry for dip %p in direct list", (void *)dip);
2620 /*NOTREACHED*/
2624 * Write an entry indicating a power level change (to be passed to a process
2625 * later) in the given psce.
2626 * If we were called in the path that brings up the console fb in the
2627 * case of entering the prom, we don't want to sleep. If the alloc fails, then
2628 * we create a record that has a size of -1, a physaddr of NULL, and that
2629 * has the overflow flag set.
2631 static int
2632 psc_entry(ushort_t event, psce_t *psce, dev_info_t *dip, int comp, int new,
2633 int old, int which, pm_canblock_t canblock)
2635 char buf[MAXNAMELEN];
2636 pm_state_change_t *p;
2637 size_t size;
2638 caddr_t physpath = NULL;
2639 int overrun = 0;
2641 ASSERT(MUTEX_HELD(&psce->psce_lock));
2642 (void) ddi_pathname(dip, buf);
2643 size = strlen(buf) + 1;
2644 p = psce->psce_in;
2645 if (canblock == PM_CANBLOCK_BYPASS) {
2646 physpath = kmem_alloc(size, KM_NOSLEEP);
2647 if (physpath == NULL) {
2649 * mark current entry as overrun
2651 p->flags |= PSC_EVENT_LOST;
2652 size = (size_t)-1;
2654 } else
2655 physpath = kmem_alloc(size, KM_SLEEP);
2656 if (p->size) { /* overflow; mark the next entry */
2657 if (p->size != (size_t)-1)
2658 kmem_free(p->physpath, p->size);
2659 ASSERT(psce->psce_out == p);
2660 if (p == psce->psce_last) {
2661 psce->psce_first->flags |= PSC_EVENT_LOST;
2662 psce->psce_out = psce->psce_first;
2663 } else {
2664 (p + 1)->flags |= PSC_EVENT_LOST;
2665 psce->psce_out = (p + 1);
2667 overrun++;
2668 } else if (physpath == NULL) { /* alloc failed, mark this entry */
2669 p->flags |= PSC_EVENT_LOST;
2670 p->size = 0;
2671 p->physpath = NULL;
2673 if (which == PSC_INTEREST) {
2674 mutex_enter(&pm_compcnt_lock);
2675 if (pm_comps_notlowest == 0)
2676 p->flags |= PSC_ALL_LOWEST;
2677 else
2678 p->flags &= ~PSC_ALL_LOWEST;
2679 mutex_exit(&pm_compcnt_lock);
2681 p->event = event;
2682 p->timestamp = gethrestime_sec();
2683 p->component = comp;
2684 p->old_level = old;
2685 p->new_level = new;
2686 p->physpath = physpath;
2687 p->size = size;
2688 if (physpath != NULL)
2689 (void) strcpy(p->physpath, buf);
2690 if (p == psce->psce_last)
2691 psce->psce_in = psce->psce_first;
2692 else
2693 psce->psce_in = ++p;
2694 mutex_exit(&psce->psce_lock);
2695 return (overrun);
2699 * Find the next entry on the interest list. We keep a pointer to the item we
2700 * last returned in the user's cooke. Returns a locked entries struct.
2702 static psce_t *
2703 psc_interest(void **cookie, pscc_t **psccp)
2705 pscc_t *pscc;
2706 pscc_t **cookiep = (pscc_t **)cookie;
2708 if (*cookiep == NULL)
2709 pscc = pm_pscc_interest;
2710 else
2711 pscc = (*cookiep)->pscc_next;
2712 if (pscc) {
2713 *cookiep = pscc;
2714 *psccp = pscc;
2715 mutex_enter(&pscc->pscc_entries->psce_lock);
2716 return (pscc->pscc_entries);
2717 } else {
2718 return (NULL);
2723 * Create an entry for a process to pick up indicating a power level change.
2725 static void
2726 pm_enqueue_notify(ushort_t cmd, dev_info_t *dip, int comp,
2727 int newlevel, int oldlevel, pm_canblock_t canblock)
2729 PMD_FUNC(pmf, "enqueue_notify")
2730 pscc_t *pscc;
2731 psce_t *psce;
2732 void *cookie = NULL;
2733 int overrun;
2735 ASSERT(MUTEX_HELD(&pm_rsvp_lock));
2736 switch (cmd) {
2737 case PSC_PENDING_CHANGE: /* only for controlling process */
2738 PMD(PMD_DPM, ("%s: PENDING %s@%s(%s#%d), comp %d, %d -> %d\n",
2739 pmf, PM_DEVICE(dip), comp, oldlevel, newlevel))
2740 psce = pm_psc_dip_to_direct(dip, &pscc);
2741 ASSERT(psce);
2742 PMD(PMD_IOCTL, ("%s: PENDING: %s@%s(%s#%d) pm_poll_cnt[%d] "
2743 "%d\n", pmf, PM_DEVICE(dip), pscc->pscc_clone,
2744 pm_poll_cnt[pscc->pscc_clone]))
2745 overrun = psc_entry(cmd, psce, dip, comp, newlevel, oldlevel,
2746 PSC_DIRECT, canblock);
2747 PMD(PMD_DPM, ("%s: sig %d\n", pmf, pscc->pscc_clone))
2748 mutex_enter(&pm_clone_lock);
2749 if (!overrun)
2750 pm_poll_cnt[pscc->pscc_clone]++;
2751 cv_signal(&pm_clones_cv[pscc->pscc_clone]);
2752 pollwakeup(&pm_pollhead, (POLLRDNORM | POLLIN));
2753 mutex_exit(&pm_clone_lock);
2754 break;
2755 case PSC_HAS_CHANGED:
2756 PMD(PMD_DPM, ("%s: HAS %s@%s(%s#%d), comp %d, %d -> %d\n",
2757 pmf, PM_DEVICE(dip), comp, oldlevel, newlevel))
2758 if (PM_ISDIRECT(dip) && canblock != PM_CANBLOCK_BYPASS) {
2759 psce = pm_psc_dip_to_direct(dip, &pscc);
2760 PMD(PMD_IOCTL, ("%s: HAS: %s@%s(%s#%d) pm_poll_cnt[%d] "
2761 "%d\n", pmf, PM_DEVICE(dip), pscc->pscc_clone,
2762 pm_poll_cnt[pscc->pscc_clone]))
2763 overrun = psc_entry(cmd, psce, dip, comp, newlevel,
2764 oldlevel, PSC_DIRECT, canblock);
2765 PMD(PMD_DPM, ("%s: sig %d\n", pmf, pscc->pscc_clone))
2766 mutex_enter(&pm_clone_lock);
2767 if (!overrun)
2768 pm_poll_cnt[pscc->pscc_clone]++;
2769 cv_signal(&pm_clones_cv[pscc->pscc_clone]);
2770 pollwakeup(&pm_pollhead, (POLLRDNORM | POLLIN));
2771 mutex_exit(&pm_clone_lock);
2773 mutex_enter(&pm_clone_lock);
2774 rw_enter(&pm_pscc_interest_rwlock, RW_READER);
2775 while ((psce = psc_interest(&cookie, &pscc)) != NULL) {
2776 (void) psc_entry(cmd, psce, dip, comp, newlevel,
2777 oldlevel, PSC_INTEREST, canblock);
2778 cv_signal(&pm_clones_cv[pscc->pscc_clone]);
2780 rw_exit(&pm_pscc_interest_rwlock);
2781 mutex_exit(&pm_clone_lock);
2782 break;
2783 #ifdef DEBUG
2784 default:
2785 ASSERT(0);
2786 #endif
2790 static void
2791 pm_enqueue_notify_others(pm_ppm_devlist_t **listp, pm_canblock_t canblock)
2793 if (listp) {
2794 pm_ppm_devlist_t *p, *next = NULL;
2796 for (p = *listp; p; p = next) {
2797 next = p->ppd_next;
2798 pm_enqueue_notify(PSC_HAS_CHANGED, p->ppd_who,
2799 p->ppd_cmpt, p->ppd_new_level, p->ppd_old_level,
2800 canblock);
2801 kmem_free(p, sizeof (pm_ppm_devlist_t));
2803 *listp = NULL;
2808 * Try to get the power locks of the parent node and target (child)
2809 * node. Return true if successful (with both locks held) or false
2810 * (with no locks held).
2812 static int
2813 pm_try_parent_child_locks(dev_info_t *pdip,
2814 dev_info_t *dip, int *pcircp, int *circp)
2816 if (ndi_devi_tryenter(pdip, pcircp))
2817 if (PM_TRY_LOCK_POWER(dip, circp)) {
2818 return (1);
2819 } else {
2820 ndi_devi_exit(pdip, *pcircp);
2822 return (0);
2826 * Determine if the power lock owner is blocked by current thread.
2827 * returns :
2828 * 1 - If the thread owning the effective power lock (the first lock on
2829 * which a thread blocks when it does PM_LOCK_POWER) is blocked by
2830 * a mutex held by the current thread.
2832 * 0 - otherwise
2834 * Note : This function is called by pm_power_has_changed to determine whether
2835 * it is executing in parallel with pm_set_power.
2837 static int
2838 pm_blocked_by_us(dev_info_t *dip)
2840 power_req_t power_req;
2841 kthread_t *owner;
2842 int result;
2843 kmutex_t *mp;
2844 dev_info_t *ppm = (dev_info_t *)DEVI(dip)->devi_pm_ppm;
2846 power_req.request_type = PMR_PPM_POWER_LOCK_OWNER;
2847 power_req.req.ppm_power_lock_owner_req.who = dip;
2848 if (pm_ctlops(ppm, dip, DDI_CTLOPS_POWER, &power_req, &result) !=
2849 DDI_SUCCESS) {
2851 * It is assumed that if the device is claimed by ppm, ppm
2852 * will always implement this request type and it'll always
2853 * return success. We panic here, if it fails.
2855 panic("pm: Can't determine power lock owner of %s@%s(%s#%d)\n",
2856 PM_DEVICE(dip));
2857 /*NOTREACHED*/
2860 if ((owner = power_req.req.ppm_power_lock_owner_req.owner) != NULL &&
2861 owner->t_state == TS_SLEEP &&
2862 owner->t_sobj_ops &&
2863 SOBJ_TYPE(owner->t_sobj_ops) == SOBJ_MUTEX &&
2864 (mp = (kmutex_t *)owner->t_wchan) &&
2865 mutex_owner(mp) == curthread)
2866 return (1);
2868 return (0);
2872 * Notify parent which wants to hear about a child's power changes.
2874 static void
2875 pm_notify_parent(dev_info_t *dip,
2876 dev_info_t *pdip, int comp, int old_level, int level)
2878 pm_bp_has_changed_t bphc;
2879 pm_sp_misc_t pspm;
2880 char *pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
2881 int result = DDI_SUCCESS;
2883 bphc.bphc_dip = dip;
2884 bphc.bphc_path = ddi_pathname(dip, pathbuf);
2885 bphc.bphc_comp = comp;
2886 bphc.bphc_olevel = old_level;
2887 bphc.bphc_nlevel = level;
2888 pspm.pspm_canblock = PM_CANBLOCK_BLOCK;
2889 pspm.pspm_scan = 0;
2890 bphc.bphc_private = &pspm;
2891 (void) (*PM_BUS_POWER_FUNC(pdip))(pdip, NULL,
2892 BUS_POWER_HAS_CHANGED, (void *)&bphc, (void *)&result);
2893 kmem_free(pathbuf, MAXPATHLEN);
2897 * Check if we need to resume a BC device, and make the attach call as required.
2899 static int
2900 pm_check_and_resume(dev_info_t *dip, int comp, int old_level, int level)
2902 int ret = DDI_SUCCESS;
2904 if (PM_ISBC(dip) && comp == 0 && old_level == 0 && level != 0) {
2905 ASSERT(DEVI(dip)->devi_pm_flags & PMC_SUSPENDED);
2906 /* ppm is not interested in DDI_PM_RESUME */
2907 if ((ret = devi_attach(dip, DDI_PM_RESUME)) != DDI_SUCCESS)
2908 /* XXX Should we mark it resumed, */
2909 /* even though it failed? */
2910 cmn_err(CE_WARN, "!pm: Can't resume %s@%s",
2911 PM_NAME(dip), PM_ADDR(dip));
2912 DEVI(dip)->devi_pm_flags &= ~PMC_SUSPENDED;
2915 return (ret);
2919 * Tests outside the lock to see if we should bother to enqueue an entry
2920 * for any watching process. If yes, then caller will take the lock and
2921 * do the full protocol
2923 static int
2924 pm_watchers()
2926 if (pm_processes_stopped)
2927 return (0);
2928 return (pm_pscc_direct || pm_pscc_interest);
2931 static int pm_phc_impl(dev_info_t *, int, int, int);
2934 * A driver is reporting that the power of one of its device's components
2935 * has changed. Update the power state accordingly.
2938 pm_power_has_changed(dev_info_t *dip, int comp, int level)
2940 PMD_FUNC(pmf, "pm_power_has_changed")
2941 int ret;
2942 dev_info_t *pdip = ddi_get_parent(dip);
2943 struct pm_component *cp;
2944 int blocked, circ, pcirc, old_level;
2946 if (level < 0) {
2947 PMD(PMD_FAIL, ("%s: %s@%s(%s#%d): bad level=%d\n", pmf,
2948 PM_DEVICE(dip), level))
2949 return (DDI_FAILURE);
2952 PMD(PMD_KIDSUP | PMD_DEP, ("%s: %s@%s(%s#%d), comp=%d, level=%d\n", pmf,
2953 PM_DEVICE(dip), comp, level))
2955 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, comp, &cp) ||
2956 !e_pm_valid_power(dip, comp, level))
2957 return (DDI_FAILURE);
2960 * A driver thread calling pm_power_has_changed and another thread
2961 * calling pm_set_power can deadlock. The problem is not resolvable
2962 * by changing lock order, so we use pm_blocked_by_us() to detect
2963 * this specific deadlock. If we can't get the lock immediately
2964 * and we are deadlocked, just update the component's level, do
2965 * notifications, and return. We intend to update the total power
2966 * state later (if the other thread fails to set power to the
2967 * desired level). If we were called because of a power change on a
2968 * component that isn't involved in a set_power op, update all state
2969 * immediately.
2971 cp = PM_CP(dip, comp);
2972 while (!pm_try_parent_child_locks(pdip, dip, &pcirc, &circ)) {
2973 if (((blocked = pm_blocked_by_us(dip)) != 0) &&
2974 (cp->pmc_flags & PM_POWER_OP)) {
2975 if (pm_watchers()) {
2976 mutex_enter(&pm_rsvp_lock);
2977 pm_enqueue_notify(PSC_HAS_CHANGED, dip, comp,
2978 level, cur_power(cp), PM_CANBLOCK_BLOCK);
2979 mutex_exit(&pm_rsvp_lock);
2981 if (pdip && PM_WANTS_NOTIFICATION(pdip))
2982 pm_notify_parent(dip,
2983 pdip, comp, cur_power(cp), level);
2984 (void) pm_check_and_resume(dip,
2985 comp, cur_power(cp), level);
2988 * Stash the old power index, update curpwr, and flag
2989 * that the total power state needs to be synched.
2991 cp->pmc_flags |= PM_PHC_WHILE_SET_POWER;
2993 * Several pm_power_has_changed calls could arrive
2994 * while the set power path remains blocked. Keep the
2995 * oldest old power and the newest new power of any
2996 * sequence of phc calls which arrive during deadlock.
2998 if (cp->pmc_phc_pwr == PM_LEVEL_UNKNOWN)
2999 cp->pmc_phc_pwr = cp->pmc_cur_pwr;
3000 cp->pmc_cur_pwr =
3001 pm_level_to_index(dip, cp, level);
3002 PMD(PMD_PHC, ("%s: deadlock for %s@%s(%s#%d), comp=%d, "
3003 "level=%d\n", pmf, PM_DEVICE(dip), comp, level))
3004 return (DDI_SUCCESS);
3005 } else
3006 if (blocked) { /* blocked, but different cmpt? */
3007 if (!ndi_devi_tryenter(pdip, &pcirc)) {
3008 cmn_err(CE_NOTE,
3009 "!pm: parent kuc not updated due "
3010 "to possible deadlock.\n");
3011 return (pm_phc_impl(dip,
3012 comp, level, 1));
3014 old_level = cur_power(cp);
3015 if (pdip && !PM_WANTS_NOTIFICATION(pdip) &&
3016 (!PM_ISBC(dip) || comp == 0) &&
3017 POWERING_ON(old_level, level))
3018 pm_hold_power(pdip);
3019 ret = pm_phc_impl(dip, comp, level, 1);
3020 if (pdip && !PM_WANTS_NOTIFICATION(pdip)) {
3021 if ((!PM_ISBC(dip) ||
3022 comp == 0) && level == 0 &&
3023 old_level != PM_LEVEL_UNKNOWN)
3024 pm_rele_power(pdip);
3026 ndi_devi_exit(pdip, pcirc);
3027 /* child lock not held: deadlock */
3028 return (ret);
3030 delay(1);
3031 PMD(PMD_PHC, ("%s: try lock again\n", pmf))
3034 /* non-deadlock case */
3035 old_level = cur_power(cp);
3036 if (pdip && !PM_WANTS_NOTIFICATION(pdip) &&
3037 (!PM_ISBC(dip) || comp == 0) && POWERING_ON(old_level, level))
3038 pm_hold_power(pdip);
3039 ret = pm_phc_impl(dip, comp, level, 1);
3040 if (pdip && !PM_WANTS_NOTIFICATION(pdip)) {
3041 if ((!PM_ISBC(dip) || comp == 0) && level == 0 &&
3042 old_level != PM_LEVEL_UNKNOWN)
3043 pm_rele_power(pdip);
3045 PM_UNLOCK_POWER(dip, circ);
3046 ndi_devi_exit(pdip, pcirc);
3047 return (ret);
3051 * Account for power changes to a component of the the console frame buffer.
3052 * If lowering power from full (or "unkown", which is treatd as full)
3053 * we will increment the "components off" count of the fb device.
3054 * Subsequent lowering of the same component doesn't affect the count. If
3055 * raising a component back to full power, we will decrement the count.
3057 * Return: the increment value for pm_cfb_comps_off (-1, 0, or 1)
3059 static int
3060 calc_cfb_comps_incr(dev_info_t *dip, int cmpt, int old, int new)
3062 struct pm_component *cp = PM_CP(dip, cmpt);
3063 int on = (old == PM_LEVEL_UNKNOWN || old == cp->pmc_norm_pwr);
3064 int want_normal = (new == cp->pmc_norm_pwr);
3065 int incr = 0;
3067 if (on && !want_normal)
3068 incr = 1;
3069 else if (!on && want_normal)
3070 incr = -1;
3071 return (incr);
3075 * Adjust the count of console frame buffer components < full power.
3077 static void
3078 update_comps_off(int incr, dev_info_t *dip)
3080 mutex_enter(&pm_cfb_lock);
3081 pm_cfb_comps_off += incr;
3082 ASSERT(pm_cfb_comps_off <= PM_NUMCMPTS(dip));
3083 mutex_exit(&pm_cfb_lock);
3087 * Update the power state in the framework (via the ppm). The 'notify'
3088 * argument tells whether to notify watchers. Power lock is already held.
3090 static int
3091 pm_phc_impl(dev_info_t *dip, int comp, int level, int notify)
3093 PMD_FUNC(pmf, "phc_impl")
3094 power_req_t power_req;
3095 int i, dodeps = 0;
3096 dev_info_t *pdip = ddi_get_parent(dip);
3097 int result;
3098 int old_level;
3099 struct pm_component *cp;
3100 int incr = 0;
3101 dev_info_t *ppm = (dev_info_t *)DEVI(dip)->devi_pm_ppm;
3102 int work_type = 0;
3103 char *pathbuf;
3105 /* Must use "official" power level for this test. */
3106 cp = PM_CP(dip, comp);
3107 old_level = (cp->pmc_flags & PM_PHC_WHILE_SET_POWER ?
3108 cp->pmc_phc_pwr : cp->pmc_cur_pwr);
3109 if (old_level != PM_LEVEL_UNKNOWN)
3110 old_level = cp->pmc_comp.pmc_lvals[old_level];
3112 if (level == old_level) {
3113 PMD(PMD_SET, ("%s: %s@%s(%s#%d), comp=%d is already at "
3114 "level=%d\n", pmf, PM_DEVICE(dip), comp, level))
3115 return (DDI_SUCCESS);
3119 * Tell ppm about this.
3121 power_req.request_type = PMR_PPM_POWER_CHANGE_NOTIFY;
3122 power_req.req.ppm_notify_level_req.who = dip;
3123 power_req.req.ppm_notify_level_req.cmpt = comp;
3124 power_req.req.ppm_notify_level_req.new_level = level;
3125 power_req.req.ppm_notify_level_req.old_level = old_level;
3126 if (pm_ctlops(ppm, dip, DDI_CTLOPS_POWER, &power_req,
3127 &result) == DDI_FAILURE) {
3128 PMD(PMD_FAIL, ("%s: pm_ctlops %s@%s(%s#%d) to %d failed\n",
3129 pmf, PM_DEVICE(dip), level))
3130 return (DDI_FAILURE);
3133 if (PM_IS_CFB(dip)) {
3134 incr = calc_cfb_comps_incr(dip, comp, old_level, level);
3136 if (incr) {
3137 update_comps_off(incr, dip);
3138 PMD(PMD_CFB, ("%s: %s@%s(%s#%d) comp=%d %d->%d "
3139 "cfb_comps_off->%d\n", pmf, PM_DEVICE(dip),
3140 comp, old_level, level, pm_cfb_comps_off))
3143 e_pm_set_cur_pwr(dip, PM_CP(dip, comp), level);
3144 result = DDI_SUCCESS;
3146 if (notify) {
3147 if (pdip && PM_WANTS_NOTIFICATION(pdip))
3148 pm_notify_parent(dip, pdip, comp, old_level, level);
3149 (void) pm_check_and_resume(dip, comp, old_level, level);
3153 * Decrement the dependency kidsup count if we turn a device
3154 * off.
3156 if (POWERING_OFF(old_level, level)) {
3157 dodeps = 1;
3158 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
3159 cp = PM_CP(dip, i);
3160 if (cur_power(cp)) {
3161 dodeps = 0;
3162 break;
3165 if (dodeps)
3166 work_type = PM_DEP_WK_POWER_OFF;
3170 * Increment if we turn it on. Check to see
3171 * if other comps are already on, if so,
3172 * dont increment.
3174 if (POWERING_ON(old_level, level)) {
3175 dodeps = 1;
3176 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
3177 cp = PM_CP(dip, i);
3178 if (comp == i)
3179 continue;
3180 /* -1 also treated as 0 in this case */
3181 if (cur_power(cp) > 0) {
3182 dodeps = 0;
3183 break;
3186 if (dodeps)
3187 work_type = PM_DEP_WK_POWER_ON;
3190 if (dodeps) {
3191 pathbuf = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
3192 (void) ddi_pathname(dip, pathbuf);
3193 pm_dispatch_to_dep_thread(work_type, pathbuf, NULL,
3194 PM_DEP_NOWAIT, NULL, 0);
3195 kmem_free(pathbuf, MAXPATHLEN);
3198 if (notify && (level != old_level) && pm_watchers()) {
3199 mutex_enter(&pm_rsvp_lock);
3200 pm_enqueue_notify(PSC_HAS_CHANGED, dip, comp, level, old_level,
3201 PM_CANBLOCK_BLOCK);
3202 mutex_exit(&pm_rsvp_lock);
3205 PMD(PMD_RESCAN, ("%s: %s@%s(%s#%d): pm_rescan\n", pmf, PM_DEVICE(dip)))
3206 pm_rescan(dip);
3207 return (DDI_SUCCESS);
3211 * This function is called at startup time to notify pm of the existence
3212 * of any platform power managers for this platform. As a result of
3213 * this registration, each function provided will be called each time
3214 * a device node is attached, until one returns true, and it must claim the
3215 * device node (by returning non-zero) if it wants to be involved in the
3216 * node's power management. If it does claim the node, then it will
3217 * subsequently be notified of attach and detach events.
3222 pm_register_ppm(int (*func)(dev_info_t *), dev_info_t *dip)
3224 PMD_FUNC(pmf, "register_ppm")
3225 struct ppm_callbacks *ppmcp;
3226 pm_component_t *cp;
3227 int i, pwr, result, circ;
3228 power_req_t power_req;
3229 struct ppm_notify_level_req *p = &power_req.req.ppm_notify_level_req;
3230 void pm_ppm_claim(dev_info_t *);
3232 mutex_enter(&ppm_lock);
3233 ppmcp = ppm_callbacks;
3234 for (i = 0; i < MAX_PPM_HANDLERS; i++, ppmcp++) {
3235 if (ppmcp->ppmc_func == NULL) {
3236 ppmcp->ppmc_func = func;
3237 ppmcp->ppmc_dip = dip;
3238 break;
3241 mutex_exit(&ppm_lock);
3243 if (i >= MAX_PPM_HANDLERS)
3244 return (DDI_FAILURE);
3245 while ((dip = ddi_get_parent(dip)) != NULL) {
3246 if (dip != ddi_root_node() && PM_GET_PM_INFO(dip) == NULL)
3247 continue;
3248 pm_ppm_claim(dip);
3249 /* don't bother with the not power-manageable nodes */
3250 if (pm_ppm_claimed(dip) && PM_GET_PM_INFO(dip)) {
3252 * Tell ppm about this.
3254 power_req.request_type = PMR_PPM_POWER_CHANGE_NOTIFY;
3255 p->old_level = PM_LEVEL_UNKNOWN;
3256 p->who = dip;
3257 PM_LOCK_POWER(dip, &circ);
3258 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
3259 cp = PM_CP(dip, i);
3260 pwr = cp->pmc_cur_pwr;
3261 if (pwr != PM_LEVEL_UNKNOWN) {
3262 p->cmpt = i;
3263 p->new_level = cur_power(cp);
3264 p->old_level = PM_LEVEL_UNKNOWN;
3265 if (pm_ctlops(PPM(dip), dip,
3266 DDI_CTLOPS_POWER, &power_req,
3267 &result) == DDI_FAILURE) {
3268 PMD(PMD_FAIL, ("%s: pc "
3269 "%s@%s(%s#%d) to %d "
3270 "fails\n", pmf,
3271 PM_DEVICE(dip), pwr))
3275 PM_UNLOCK_POWER(dip, circ);
3278 return (DDI_SUCCESS);
3282 * Call the ppm's that have registered and adjust the devinfo struct as
3283 * appropriate. First one to claim it gets it. The sets of devices claimed
3284 * by each ppm are assumed to be disjoint.
3286 void
3287 pm_ppm_claim(dev_info_t *dip)
3289 struct ppm_callbacks *ppmcp;
3291 if (PPM(dip)) {
3292 return;
3294 mutex_enter(&ppm_lock);
3295 for (ppmcp = ppm_callbacks; ppmcp->ppmc_func; ppmcp++) {
3296 if ((*ppmcp->ppmc_func)(dip)) {
3297 DEVI(dip)->devi_pm_ppm =
3298 (struct dev_info *)ppmcp->ppmc_dip;
3299 mutex_exit(&ppm_lock);
3300 return;
3303 mutex_exit(&ppm_lock);
3307 * Node is being detached so stop autopm until we see if it succeeds, in which
3308 * case pm_stop will be called. For backwards compatible devices we bring the
3309 * device up to full power on the assumption the detach will succeed.
3311 void
3312 pm_detaching(dev_info_t *dip)
3314 PMD_FUNC(pmf, "detaching")
3315 pm_info_t *info = PM_GET_PM_INFO(dip);
3316 int iscons;
3318 PMD(PMD_REMDEV, ("%s: %s@%s(%s#%d), %d comps\n", pmf, PM_DEVICE(dip),
3319 PM_NUMCMPTS(dip)))
3320 if (info == NULL)
3321 return;
3322 ASSERT(DEVI_IS_DETACHING(dip));
3323 PM_LOCK_DIP(dip);
3324 info->pmi_dev_pm_state |= PM_DETACHING;
3325 PM_UNLOCK_DIP(dip);
3326 if (!PM_ISBC(dip))
3327 pm_scan_stop(dip);
3330 * console and old-style devices get brought up when detaching.
3332 iscons = PM_IS_CFB(dip);
3333 if (iscons || PM_ISBC(dip)) {
3334 (void) pm_all_to_normal(dip, PM_CANBLOCK_BYPASS);
3335 if (iscons) {
3336 mutex_enter(&pm_cfb_lock);
3337 while (cfb_inuse) {
3338 mutex_exit(&pm_cfb_lock);
3339 PMD(PMD_CFB, ("%s: delay; cfb_inuse\n", pmf))
3340 delay(1);
3341 mutex_enter(&pm_cfb_lock);
3343 ASSERT(cfb_dip_detaching == NULL);
3344 ASSERT(cfb_dip);
3345 cfb_dip_detaching = cfb_dip; /* case detach fails */
3346 cfb_dip = NULL;
3347 mutex_exit(&pm_cfb_lock);
3353 * Node failed to detach. If it used to be autopm'd, make it so again.
3355 void
3356 pm_detach_failed(dev_info_t *dip)
3358 PMD_FUNC(pmf, "detach_failed")
3359 pm_info_t *info = PM_GET_PM_INFO(dip);
3360 int pm_all_at_normal(dev_info_t *);
3362 if (info == NULL)
3363 return;
3364 ASSERT(DEVI_IS_DETACHING(dip));
3365 if (info->pmi_dev_pm_state & PM_DETACHING) {
3366 info->pmi_dev_pm_state &= ~PM_DETACHING;
3367 if (info->pmi_dev_pm_state & PM_ALLNORM_DEFERRED) {
3368 /* Make sure the operation is still needed */
3369 if (!pm_all_at_normal(dip)) {
3370 if (pm_all_to_normal(dip,
3371 PM_CANBLOCK_FAIL) != DDI_SUCCESS) {
3372 PMD(PMD_ERROR, ("%s: could not bring "
3373 "%s@%s(%s#%d) to normal\n", pmf,
3374 PM_DEVICE(dip)))
3377 info->pmi_dev_pm_state &= ~PM_ALLNORM_DEFERRED;
3380 if (!PM_ISBC(dip)) {
3381 mutex_enter(&pm_scan_lock);
3382 if (PM_SCANABLE(dip))
3383 pm_scan_init(dip);
3384 mutex_exit(&pm_scan_lock);
3385 pm_rescan(dip);
3389 /* generic Backwards Compatible component */
3390 static char *bc_names[] = {"off", "on"};
3392 static pm_comp_t bc_comp = {"unknown", 2, NULL, NULL, &bc_names[0]};
3394 static void
3395 e_pm_default_levels(dev_info_t *dip, pm_component_t *cp, int norm)
3397 pm_comp_t *pmc;
3398 pmc = &cp->pmc_comp;
3399 pmc->pmc_numlevels = 2;
3400 pmc->pmc_lvals[0] = 0;
3401 pmc->pmc_lvals[1] = norm;
3402 e_pm_set_cur_pwr(dip, cp, norm);
3405 static void
3406 e_pm_default_components(dev_info_t *dip, int cmpts)
3408 int i;
3409 pm_component_t *p = DEVI(dip)->devi_pm_components;
3411 p = DEVI(dip)->devi_pm_components;
3412 for (i = 0; i < cmpts; i++, p++) {
3413 p->pmc_comp = bc_comp; /* struct assignment */
3414 p->pmc_comp.pmc_lvals = kmem_zalloc(2 * sizeof (int),
3415 KM_SLEEP);
3416 p->pmc_comp.pmc_thresh = kmem_alloc(2 * sizeof (int),
3417 KM_SLEEP);
3418 p->pmc_comp.pmc_numlevels = 2;
3419 p->pmc_comp.pmc_thresh[0] = INT_MAX;
3420 p->pmc_comp.pmc_thresh[1] = INT_MAX;
3425 * Called from functions that require components to exist already to allow
3426 * for their creation by parsing the pm-components property.
3427 * Device will not be power managed as a result of this call
3428 * No locking needed because we're single threaded by the ndi_devi_enter
3429 * done while attaching, and the device isn't visible until after it has
3430 * attached
3433 pm_premanage(dev_info_t *dip, int style)
3435 PMD_FUNC(pmf, "premanage")
3436 pm_comp_t *pcp, *compp;
3437 int cmpts, i, norm, error;
3438 pm_component_t *p = DEVI(dip)->devi_pm_components;
3439 pm_comp_t *pm_autoconfig(dev_info_t *, int *);
3441 ASSERT(!PM_IAM_LOCKING_DIP(dip));
3443 * If this dip has already been processed, don't mess with it
3445 if (DEVI(dip)->devi_pm_flags & PMC_COMPONENTS_DONE)
3446 return (DDI_SUCCESS);
3447 if (DEVI(dip)->devi_pm_flags & PMC_COMPONENTS_FAILED) {
3448 return (DDI_FAILURE);
3451 * Look up pm-components property and create components accordingly
3452 * If that fails, fall back to backwards compatibility
3454 if ((compp = pm_autoconfig(dip, &error)) == NULL) {
3456 * If error is set, the property existed but was not well formed
3458 if (error || (style == PM_STYLE_NEW)) {
3459 DEVI(dip)->devi_pm_flags |= PMC_COMPONENTS_FAILED;
3460 return (DDI_FAILURE);
3463 * If they don't have the pm-components property, then we
3464 * want the old "no pm until PM_SET_DEVICE_THRESHOLDS ioctl"
3465 * behavior driver must have called pm_create_components, and
3466 * we need to flesh out dummy components
3468 if ((cmpts = PM_NUMCMPTS(dip)) == 0) {
3470 * Not really failure, but we don't want the
3471 * caller to treat it as success
3473 return (DDI_FAILURE);
3475 DEVI(dip)->devi_pm_flags |= PMC_BC;
3476 e_pm_default_components(dip, cmpts);
3477 for (i = 0; i < cmpts; i++) {
3479 * if normal power not set yet, we don't really know
3480 * what *ANY* of the power values are. If normal
3481 * power is set, then we assume for this backwards
3482 * compatible case that the values are 0, normal power.
3484 norm = pm_get_normal_power(dip, i);
3485 if (norm == (uint_t)-1) {
3486 PMD(PMD_ERROR, ("%s: %s@%s(%s#%d)[%d]\n", pmf,
3487 PM_DEVICE(dip), i))
3488 return (DDI_FAILURE);
3491 * Components of BC devices start at their normal power,
3492 * so count them to be not at their lowest power.
3494 PM_INCR_NOTLOWEST(dip);
3495 e_pm_default_levels(dip, PM_CP(dip, i), norm);
3497 } else {
3499 * e_pm_create_components was called from pm_autoconfig(), it
3500 * creates components with no descriptions (or known levels)
3502 cmpts = PM_NUMCMPTS(dip);
3503 ASSERT(cmpts != 0);
3504 pcp = compp;
3505 p = DEVI(dip)->devi_pm_components;
3506 for (i = 0; i < cmpts; i++, p++) {
3507 p->pmc_comp = *pcp++; /* struct assignment */
3508 ASSERT(PM_CP(dip, i)->pmc_cur_pwr == 0);
3509 e_pm_set_cur_pwr(dip, PM_CP(dip, i), PM_LEVEL_UNKNOWN);
3511 if (DEVI(dip)->devi_pm_flags & PMC_CPU_THRESH)
3512 pm_set_device_threshold(dip, pm_cpu_idle_threshold,
3513 PMC_CPU_THRESH);
3514 else
3515 pm_set_device_threshold(dip, pm_system_idle_threshold,
3516 PMC_DEF_THRESH);
3517 kmem_free(compp, cmpts * sizeof (pm_comp_t));
3519 return (DDI_SUCCESS);
3523 * Called from during or after the device's attach to let us know it is ready
3524 * to play autopm. Look up the pm model and manage the device accordingly.
3525 * Returns system call errno value.
3526 * If DDI_ATTACH and DDI_DETACH were in same namespace, this would be
3527 * a little cleaner
3529 * Called with dip lock held, return with dip lock unheld.
3533 e_pm_manage(dev_info_t *dip, int style)
3535 PMD_FUNC(pmf, "e_manage")
3536 pm_info_t *info;
3537 dev_info_t *pdip = ddi_get_parent(dip);
3538 int pm_thresh_specd(dev_info_t *);
3539 int count;
3540 char *pathbuf;
3542 if (pm_premanage(dip, style) != DDI_SUCCESS) {
3543 return (DDI_FAILURE);
3545 PMD(PMD_KIDSUP, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
3546 ASSERT(PM_GET_PM_INFO(dip) == NULL);
3547 info = kmem_zalloc(sizeof (pm_info_t), KM_SLEEP);
3550 * Now set up parent's kidsupcnt. BC nodes are assumed to start
3551 * out at their normal power, so they are "up", others start out
3552 * unknown, which is effectively "up". Parent which want notification
3553 * get kidsupcnt of 0 always.
3555 count = (PM_ISBC(dip)) ? 1 : PM_NUMCMPTS(dip);
3556 if (count && pdip && !PM_WANTS_NOTIFICATION(pdip))
3557 e_pm_hold_rele_power(pdip, count);
3559 pm_set_pm_info(dip, info);
3561 * Apply any recorded thresholds
3563 (void) pm_thresh_specd(dip);
3566 * Do dependency processing.
3568 pathbuf = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
3569 (void) ddi_pathname(dip, pathbuf);
3570 pm_dispatch_to_dep_thread(PM_DEP_WK_ATTACH, pathbuf, pathbuf,
3571 PM_DEP_NOWAIT, NULL, 0);
3572 kmem_free(pathbuf, MAXPATHLEN);
3574 if (!PM_ISBC(dip)) {
3575 mutex_enter(&pm_scan_lock);
3576 if (PM_SCANABLE(dip)) {
3577 pm_scan_init(dip);
3578 mutex_exit(&pm_scan_lock);
3579 pm_rescan(dip);
3580 } else {
3581 mutex_exit(&pm_scan_lock);
3584 return (0);
3588 * This is the obsolete exported interface for a driver to find out its
3589 * "normal" (max) power.
3590 * We only get components destroyed while no power management is
3591 * going on (and the device is detached), so we don't need a mutex here
3594 pm_get_normal_power(dev_info_t *dip, int comp)
3597 if (comp >= 0 && comp < PM_NUMCMPTS(dip)) {
3598 return (PM_CP(dip, comp)->pmc_norm_pwr);
3600 return (DDI_FAILURE);
3604 * Fetches the current power level. Return DDI_SUCCESS or DDI_FAILURE.
3607 pm_get_current_power(dev_info_t *dip, int comp, int *levelp)
3609 if (comp >= 0 && comp < PM_NUMCMPTS(dip)) {
3610 *levelp = PM_CURPOWER(dip, comp);
3611 return (DDI_SUCCESS);
3613 return (DDI_FAILURE);
3617 * Returns current threshold of indicated component
3619 static int
3620 cur_threshold(dev_info_t *dip, int comp)
3622 pm_component_t *cp = PM_CP(dip, comp);
3623 int pwr;
3625 if (PM_ISBC(dip)) {
3627 * backwards compatible nodes only have one threshold
3629 return (cp->pmc_comp.pmc_thresh[1]);
3631 pwr = cp->pmc_cur_pwr;
3632 if (pwr == PM_LEVEL_UNKNOWN) {
3633 int thresh;
3634 if (DEVI(dip)->devi_pm_flags & PMC_NEXDEF_THRESH)
3635 thresh = pm_default_nexus_threshold;
3636 else if (DEVI(dip)->devi_pm_flags & PMC_CPU_THRESH)
3637 thresh = pm_cpu_idle_threshold;
3638 else
3639 thresh = pm_system_idle_threshold;
3640 return (thresh);
3642 ASSERT(cp->pmc_comp.pmc_thresh);
3643 return (cp->pmc_comp.pmc_thresh[pwr]);
3647 * Compute next lower component power level given power index.
3649 static int
3650 pm_next_lower_power(pm_component_t *cp, int pwrndx)
3652 int nxt_pwr;
3654 if (pwrndx == PM_LEVEL_UNKNOWN) {
3655 nxt_pwr = cp->pmc_comp.pmc_lvals[0];
3656 } else {
3657 pwrndx--;
3658 ASSERT(pwrndx >= 0);
3659 nxt_pwr = cp->pmc_comp.pmc_lvals[pwrndx];
3661 return (nxt_pwr);
3665 * Update the maxpower (normal) power of a component. Note that the
3666 * component's power level is only changed if it's current power level
3667 * is higher than the new max power.
3670 pm_update_maxpower(dev_info_t *dip, int comp, int level)
3672 PMD_FUNC(pmf, "update_maxpower")
3673 int old;
3674 int result;
3676 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, comp, NULL) ||
3677 !e_pm_valid_power(dip, comp, level)) {
3678 PMD(PMD_FAIL, ("%s: validation checks failed for %s@%s(%s#%d) "
3679 "comp=%d level=%d\n", pmf, PM_DEVICE(dip), comp, level))
3680 return (DDI_FAILURE);
3682 old = e_pm_get_max_power(dip, comp);
3683 e_pm_set_max_power(dip, comp, level);
3685 if (pm_set_power(dip, comp, level, PM_LEVEL_DOWNONLY,
3686 PM_CANBLOCK_BLOCK, 0, &result) != DDI_SUCCESS) {
3687 e_pm_set_max_power(dip, comp, old);
3688 PMD(PMD_FAIL, ("%s: %s@%s(%s#%d) pm_set_power failed\n", pmf,
3689 PM_DEVICE(dip)))
3690 return (DDI_FAILURE);
3692 return (DDI_SUCCESS);
3696 * Bring all components of device to normal power
3699 pm_all_to_normal(dev_info_t *dip, pm_canblock_t canblock)
3701 PMD_FUNC(pmf, "all_to_normal")
3702 int *normal;
3703 int i, ncomps, result;
3704 size_t size;
3705 int changefailed = 0;
3707 PMD(PMD_ALLNORM, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
3708 ASSERT(PM_GET_PM_INFO(dip));
3709 if (pm_get_norm_pwrs(dip, &normal, &size) != DDI_SUCCESS) {
3710 PMD(PMD_ALLNORM, ("%s: can't get norm pwrs for "
3711 "%s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
3712 return (DDI_FAILURE);
3714 ncomps = PM_NUMCMPTS(dip);
3715 for (i = 0; i < ncomps; i++) {
3716 if (pm_set_power(dip, i, normal[i],
3717 PM_LEVEL_UPONLY, canblock, 0, &result) != DDI_SUCCESS) {
3718 changefailed++;
3719 PMD(PMD_ALLNORM | PMD_FAIL, ("%s: failed to set "
3720 "%s@%s(%s#%d)[%d] to %d, errno %d\n", pmf,
3721 PM_DEVICE(dip), i, normal[i], result))
3724 kmem_free(normal, size);
3725 if (changefailed) {
3726 PMD(PMD_FAIL, ("%s: failed to set %d comps %s@%s(%s#%d) "
3727 "to full power\n", pmf, changefailed, PM_DEVICE(dip)))
3728 return (DDI_FAILURE);
3730 return (DDI_SUCCESS);
3734 * Returns true if all components of device are at normal power
3737 pm_all_at_normal(dev_info_t *dip)
3739 PMD_FUNC(pmf, "all_at_normal")
3740 int *normal;
3741 int i;
3742 size_t size;
3744 PMD(PMD_ALLNORM, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
3745 if (pm_get_norm_pwrs(dip, &normal, &size) != DDI_SUCCESS) {
3746 PMD(PMD_ALLNORM, ("%s: can't get normal power\n", pmf))
3747 return (DDI_FAILURE);
3749 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
3750 int current = PM_CURPOWER(dip, i);
3751 if (normal[i] > current) {
3752 PMD(PMD_ALLNORM, ("%s: %s@%s(%s#%d) comp=%d, "
3753 "norm=%d, cur=%d\n", pmf, PM_DEVICE(dip), i,
3754 normal[i], current))
3755 break;
3758 kmem_free(normal, size);
3759 if (i != PM_NUMCMPTS(dip)) {
3760 return (0);
3762 return (1);
3765 static void bring_pmdep_up(dev_info_t *, int);
3767 static void
3768 bring_wekeeps_up(char *keeper)
3770 PMD_FUNC(pmf, "bring_wekeeps_up")
3771 int i;
3772 pm_pdr_t *dp;
3773 pm_info_t *wku_info;
3774 char *kept_path;
3775 dev_info_t *kept;
3777 if (panicstr) {
3778 return;
3781 * We process the request even if the keeper detaches because
3782 * detach processing expects this to increment kidsupcnt of kept.
3784 PMD(PMD_BRING, ("%s: keeper= %s\n", pmf, keeper))
3785 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
3786 if (strcmp(dp->pdr_keeper, keeper) != 0)
3787 continue;
3788 for (i = 0; i < dp->pdr_kept_count; i++) {
3789 kept_path = dp->pdr_kept_paths[i];
3790 if (kept_path == NULL)
3791 continue;
3792 ASSERT(kept_path[0] != '\0');
3793 if ((kept = pm_name_to_dip(kept_path, 1)) == NULL)
3794 continue;
3795 wku_info = PM_GET_PM_INFO(kept);
3796 if (wku_info == NULL) {
3797 if (kept)
3798 ddi_release_devi(kept);
3799 continue;
3802 * Don't mess with it if it is being detached, it isn't
3803 * safe to call its power entry point
3805 if (wku_info->pmi_dev_pm_state & PM_DETACHING) {
3806 if (kept)
3807 ddi_release_devi(kept);
3808 continue;
3810 bring_pmdep_up(kept, 1);
3811 ddi_release_devi(kept);
3817 * Bring up the 'kept' device passed as argument
3819 static void
3820 bring_pmdep_up(dev_info_t *kept_dip, int hold)
3822 PMD_FUNC(pmf, "bring_pmdep_up")
3823 int is_all_at_normal = 0;
3826 * If the kept device has been unmanaged, do nothing.
3828 if (!PM_GET_PM_INFO(kept_dip))
3829 return;
3831 /* Just ignore DIRECT PM device till they are released. */
3832 if (!pm_processes_stopped && PM_ISDIRECT(kept_dip) &&
3833 !(is_all_at_normal = pm_all_at_normal(kept_dip))) {
3834 PMD(PMD_BRING, ("%s: can't bring up PM_DIRECT %s@%s(%s#%d) "
3835 "controlling process did something else\n", pmf,
3836 PM_DEVICE(kept_dip)))
3837 DEVI(kept_dip)->devi_pm_flags |= PMC_SKIP_BRINGUP;
3838 return;
3840 /* if we got here the keeper had a transition from OFF->ON */
3841 if (hold)
3842 pm_hold_power(kept_dip);
3844 if (!is_all_at_normal)
3845 (void) pm_all_to_normal(kept_dip, PM_CANBLOCK_FAIL);
3849 * A bunch of stuff that belongs only to the next routine (or two)
3852 static const char namestr[] = "NAME=";
3853 static const int nameln = sizeof (namestr) - 1;
3854 static const char pmcompstr[] = "pm-components";
3856 struct pm_comp_pkg {
3857 pm_comp_t *comp;
3858 struct pm_comp_pkg *next;
3861 #define isdigit(ch) ((ch) >= '0' && (ch) <= '9')
3863 #define isxdigit(ch) (isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \
3864 ((ch) >= 'A' && (ch) <= 'F'))
3867 * Rather than duplicate this code ...
3868 * (this code excerpted from the function that follows it)
3870 #define FINISH_COMP { \
3871 ASSERT(compp); \
3872 compp->pmc_lnames_sz = size; \
3873 tp = compp->pmc_lname_buf = kmem_alloc(size, KM_SLEEP); \
3874 compp->pmc_numlevels = level; \
3875 compp->pmc_lnames = kmem_alloc(level * sizeof (char *), KM_SLEEP); \
3876 compp->pmc_lvals = kmem_alloc(level * sizeof (int), KM_SLEEP); \
3877 compp->pmc_thresh = kmem_alloc(level * sizeof (int), KM_SLEEP); \
3878 /* copy string out of prop array into buffer */ \
3879 for (j = 0; j < level; j++) { \
3880 compp->pmc_thresh[j] = INT_MAX; /* only [0] sticks */ \
3881 compp->pmc_lvals[j] = lvals[j]; \
3882 (void) strcpy(tp, lnames[j]); \
3883 compp->pmc_lnames[j] = tp; \
3884 tp += lszs[j]; \
3886 ASSERT(tp > compp->pmc_lname_buf && tp <= \
3887 compp->pmc_lname_buf + compp->pmc_lnames_sz); \
3891 * Create (empty) component data structures.
3893 static void
3894 e_pm_create_components(dev_info_t *dip, int num_components)
3896 struct pm_component *compp, *ocompp;
3897 int i, size = 0;
3899 ASSERT(!PM_IAM_LOCKING_DIP(dip));
3900 ASSERT(!DEVI(dip)->devi_pm_components);
3901 ASSERT(!(DEVI(dip)->devi_pm_flags & PMC_COMPONENTS_DONE));
3902 size = sizeof (struct pm_component) * num_components;
3904 compp = kmem_zalloc(size, KM_SLEEP);
3905 ocompp = compp;
3906 DEVI(dip)->devi_pm_comp_size = size;
3907 DEVI(dip)->devi_pm_num_components = num_components;
3908 PM_LOCK_BUSY(dip);
3909 for (i = 0; i < num_components; i++) {
3910 compp->pmc_timestamp = gethrestime_sec();
3911 compp->pmc_norm_pwr = (uint_t)-1;
3912 compp++;
3914 PM_UNLOCK_BUSY(dip);
3915 DEVI(dip)->devi_pm_components = ocompp;
3916 DEVI(dip)->devi_pm_flags |= PMC_COMPONENTS_DONE;
3920 * Parse hex or decimal value from char string
3922 static char *
3923 pm_parsenum(char *cp, int *valp)
3925 int ch, offset;
3926 char numbuf[256];
3927 char *np = numbuf;
3928 int value = 0;
3930 ch = *cp++;
3931 if (isdigit(ch)) {
3932 if (ch == '0') {
3933 if ((ch = *cp++) == 'x' || ch == 'X') {
3934 ch = *cp++;
3935 while (isxdigit(ch)) {
3936 *np++ = (char)ch;
3937 ch = *cp++;
3939 *np = 0;
3940 cp--;
3941 goto hexval;
3942 } else {
3943 goto digit;
3945 } else {
3946 digit:
3947 while (isdigit(ch)) {
3948 *np++ = (char)ch;
3949 ch = *cp++;
3951 *np = 0;
3952 cp--;
3953 goto decval;
3955 } else
3956 return (NULL);
3958 hexval:
3959 for (np = numbuf; *np; np++) {
3960 if (*np >= 'a' && *np <= 'f')
3961 offset = 'a' - 10;
3962 else if (*np >= 'A' && *np <= 'F')
3963 offset = 'A' - 10;
3964 else if (*np >= '0' && *np <= '9')
3965 offset = '0';
3966 value *= 16;
3967 value += *np - offset;
3969 *valp = value;
3970 return (cp);
3972 decval:
3973 offset = '0';
3974 for (np = numbuf; *np; np++) {
3975 value *= 10;
3976 value += *np - offset;
3978 *valp = value;
3979 return (cp);
3983 * Set max (previously documented as "normal") power.
3985 static void
3986 e_pm_set_max_power(dev_info_t *dip, int component_number, int level)
3988 PM_CP(dip, component_number)->pmc_norm_pwr = level;
3992 * Get max (previously documented as "normal") power.
3994 static int
3995 e_pm_get_max_power(dev_info_t *dip, int component_number)
3997 return (PM_CP(dip, component_number)->pmc_norm_pwr);
4001 * Internal routine for destroying components
4002 * It is called even when there might not be any, so it must be forgiving.
4004 static void
4005 e_pm_destroy_components(dev_info_t *dip)
4007 int i;
4008 struct pm_component *cp;
4010 ASSERT(!PM_IAM_LOCKING_DIP(dip));
4011 if (PM_NUMCMPTS(dip) == 0)
4012 return;
4013 cp = DEVI(dip)->devi_pm_components;
4014 ASSERT(cp);
4015 for (i = 0; i < PM_NUMCMPTS(dip); i++, cp++) {
4016 int nlevels = cp->pmc_comp.pmc_numlevels;
4017 kmem_free(cp->pmc_comp.pmc_lvals, nlevels * sizeof (int));
4018 kmem_free(cp->pmc_comp.pmc_thresh, nlevels * sizeof (int));
4020 * For BC nodes, the rest is static in bc_comp, so skip it
4022 if (PM_ISBC(dip))
4023 continue;
4024 kmem_free(cp->pmc_comp.pmc_name, cp->pmc_comp.pmc_name_sz);
4025 kmem_free(cp->pmc_comp.pmc_lnames, nlevels * sizeof (char *));
4026 kmem_free(cp->pmc_comp.pmc_lname_buf,
4027 cp->pmc_comp.pmc_lnames_sz);
4029 kmem_free(DEVI(dip)->devi_pm_components, DEVI(dip)->devi_pm_comp_size);
4030 DEVI(dip)->devi_pm_components = NULL;
4031 DEVI(dip)->devi_pm_num_components = 0;
4032 DEVI(dip)->devi_pm_flags &=
4033 ~(PMC_COMPONENTS_DONE | PMC_COMPONENTS_FAILED);
4037 * Read the pm-components property (if there is one) and use it to set up
4038 * components. Returns a pointer to an array of component structures if
4039 * pm-components found and successfully parsed, else returns NULL.
4040 * Sets error return *errp to true to indicate a failure (as opposed to no
4041 * property being present).
4043 pm_comp_t *
4044 pm_autoconfig(dev_info_t *dip, int *errp)
4046 PMD_FUNC(pmf, "autoconfig")
4047 uint_t nelems;
4048 char **pp;
4049 pm_comp_t *compp = NULL;
4050 int i, j, level, components = 0;
4051 size_t size = 0;
4052 struct pm_comp_pkg *p, *ptail;
4053 struct pm_comp_pkg *phead = NULL;
4054 int *lvals = NULL;
4055 int *lszs = NULL;
4056 int *np = NULL;
4057 int npi = 0;
4058 char **lnames = NULL;
4059 char *cp, *tp;
4060 pm_comp_t *ret = NULL;
4062 ASSERT(!PM_IAM_LOCKING_DIP(dip));
4063 *errp = 0; /* assume success */
4064 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
4065 (char *)pmcompstr, &pp, &nelems) != DDI_PROP_SUCCESS) {
4066 return (NULL);
4069 if (nelems < 3) { /* need at least one name and two levels */
4070 goto errout;
4074 * pm_create_components is no longer allowed
4076 if (PM_NUMCMPTS(dip) != 0) {
4077 PMD(PMD_ERROR, ("%s: %s@%s(%s#%d) has %d comps\n",
4078 pmf, PM_DEVICE(dip), PM_NUMCMPTS(dip)))
4079 goto errout;
4082 lvals = kmem_alloc(nelems * sizeof (int), KM_SLEEP);
4083 lszs = kmem_alloc(nelems * sizeof (int), KM_SLEEP);
4084 lnames = kmem_alloc(nelems * sizeof (char *), KM_SLEEP);
4085 np = kmem_alloc(nelems * sizeof (int), KM_SLEEP);
4087 level = 0;
4088 phead = NULL;
4089 for (i = 0; i < nelems; i++) {
4090 cp = pp[i];
4091 if (!isdigit(*cp)) { /* must be name */
4092 if (strncmp(cp, namestr, nameln) != 0) {
4093 goto errout;
4095 if (i != 0) {
4096 if (level == 0) { /* no level spec'd */
4097 PMD(PMD_ERROR, ("%s: no level spec'd\n",
4098 pmf))
4099 goto errout;
4101 np[npi++] = lvals[level - 1];
4102 /* finish up previous component levels */
4103 FINISH_COMP;
4105 cp += nameln;
4106 if (!*cp) {
4107 PMD(PMD_ERROR, ("%s: nsa\n", pmf))
4108 goto errout;
4110 p = kmem_zalloc(sizeof (*phead), KM_SLEEP);
4111 if (phead == NULL) {
4112 phead = ptail = p;
4113 } else {
4114 ptail->next = p;
4115 ptail = p;
4117 compp = p->comp = kmem_zalloc(sizeof (pm_comp_t),
4118 KM_SLEEP);
4119 compp->pmc_name_sz = strlen(cp) + 1;
4120 compp->pmc_name = kmem_zalloc(compp->pmc_name_sz,
4121 KM_SLEEP);
4122 (void) strncpy(compp->pmc_name, cp, compp->pmc_name_sz);
4123 components++;
4124 level = 0;
4125 } else { /* better be power level <num>=<name> */
4126 #ifdef DEBUG
4127 tp = cp;
4128 #endif
4129 if (i == 0 ||
4130 (cp = pm_parsenum(cp, &lvals[level])) == NULL) {
4131 PMD(PMD_ERROR, ("%s: parsenum(%s)\n", pmf, tp))
4132 goto errout;
4134 #ifdef DEBUG
4135 tp = cp;
4136 #endif
4137 if (*cp++ != '=' || !*cp) {
4138 PMD(PMD_ERROR, ("%s: ex =, got %s\n", pmf, tp))
4139 goto errout;
4142 lszs[level] = strlen(cp) + 1;
4143 size += lszs[level];
4144 lnames[level] = cp; /* points into prop string */
4145 level++;
4148 np[npi++] = lvals[level - 1];
4149 if (level == 0) { /* ended with a name */
4150 PMD(PMD_ERROR, ("%s: ewn\n", pmf))
4151 goto errout;
4153 FINISH_COMP;
4157 * Now we have a list of components--we have to return instead an
4158 * array of them, but we can just copy the top level and leave
4159 * the rest as is
4161 (void) e_pm_create_components(dip, components);
4162 for (i = 0; i < components; i++)
4163 e_pm_set_max_power(dip, i, np[i]);
4165 ret = kmem_zalloc(components * sizeof (pm_comp_t), KM_SLEEP);
4166 for (i = 0, p = phead; i < components; i++) {
4167 ASSERT(p);
4169 * Now sanity-check values: levels must be monotonically
4170 * increasing
4172 if (p->comp->pmc_numlevels < 2) {
4173 PMD(PMD_ERROR, ("%s: comp %s of %s@%s(%s#%d) only %d "
4174 "levels\n", pmf,
4175 p->comp->pmc_name, PM_DEVICE(dip),
4176 p->comp->pmc_numlevels))
4177 goto errout;
4179 for (j = 0; j < p->comp->pmc_numlevels; j++) {
4180 if ((p->comp->pmc_lvals[j] < 0) || ((j > 0) &&
4181 (p->comp->pmc_lvals[j] <=
4182 p->comp->pmc_lvals[j - 1]))) {
4183 PMD(PMD_ERROR, ("%s: comp %s of %s@%s(%s#%d) "
4184 "not mono. incr, %d follows %d\n", pmf,
4185 p->comp->pmc_name, PM_DEVICE(dip),
4186 p->comp->pmc_lvals[j],
4187 p->comp->pmc_lvals[j - 1]))
4188 goto errout;
4191 ret[i] = *p->comp; /* struct assignment */
4192 for (j = 0; j < i; j++) {
4194 * Test for unique component names
4196 if (strcmp(ret[j].pmc_name, ret[i].pmc_name) == 0) {
4197 PMD(PMD_ERROR, ("%s: %s of %s@%s(%s#%d) not "
4198 "unique\n", pmf, ret[j].pmc_name,
4199 PM_DEVICE(dip)))
4200 goto errout;
4203 ptail = p;
4204 p = p->next;
4205 phead = p; /* errout depends on phead making sense */
4206 kmem_free(ptail->comp, sizeof (*ptail->comp));
4207 kmem_free(ptail, sizeof (*ptail));
4209 out:
4210 ddi_prop_free(pp);
4211 if (lvals)
4212 kmem_free(lvals, nelems * sizeof (int));
4213 if (lszs)
4214 kmem_free(lszs, nelems * sizeof (int));
4215 if (lnames)
4216 kmem_free(lnames, nelems * sizeof (char *));
4217 if (np)
4218 kmem_free(np, nelems * sizeof (int));
4219 return (ret);
4221 errout:
4222 e_pm_destroy_components(dip);
4223 *errp = 1; /* signal failure */
4224 cmn_err(CE_CONT, "!pm: %s property ", pmcompstr);
4225 for (i = 0; i < nelems - 1; i++)
4226 cmn_err(CE_CONT, "!'%s', ", pp[i]);
4227 if (nelems != 0)
4228 cmn_err(CE_CONT, "!'%s'", pp[nelems - 1]);
4229 cmn_err(CE_CONT, "! for %s@%s(%s#%d) is ill-formed.\n", PM_DEVICE(dip));
4230 for (p = phead; p; ) {
4231 pm_comp_t *pp;
4232 int n;
4234 ptail = p;
4236 * Free component data structures
4238 pp = p->comp;
4239 n = pp->pmc_numlevels;
4240 if (pp->pmc_name_sz) {
4241 kmem_free(pp->pmc_name, pp->pmc_name_sz);
4243 if (pp->pmc_lnames_sz) {
4244 kmem_free(pp->pmc_lname_buf, pp->pmc_lnames_sz);
4246 if (pp->pmc_lnames) {
4247 kmem_free(pp->pmc_lnames, n * (sizeof (char *)));
4249 if (pp->pmc_thresh) {
4250 kmem_free(pp->pmc_thresh, n * (sizeof (int)));
4252 if (pp->pmc_lvals) {
4253 kmem_free(pp->pmc_lvals, n * (sizeof (int)));
4255 p = ptail->next;
4256 kmem_free(ptail, sizeof (*ptail));
4258 if (ret != NULL)
4259 kmem_free(ret, components * sizeof (pm_comp_t));
4260 ret = NULL;
4261 goto out;
4265 * Set threshold values for a devices components by dividing the target
4266 * threshold (base) by the number of transitions and assign each transition
4267 * that threshold. This will get the entire device down in the target time if
4268 * all components are idle and even if there are dependencies among components.
4270 * Devices may well get powered all the way down before the target time, but
4271 * at least the EPA will be happy.
4273 void
4274 pm_set_device_threshold(dev_info_t *dip, int base, int flag)
4276 PMD_FUNC(pmf, "set_device_threshold")
4277 int target_threshold = (base * 95) / 100;
4278 int level, comp; /* loop counters */
4279 int transitions = 0;
4280 int ncomp = PM_NUMCMPTS(dip);
4281 int thresh;
4282 int remainder;
4283 pm_comp_t *pmc;
4284 int i, circ;
4286 ASSERT(!PM_IAM_LOCKING_DIP(dip));
4287 PM_LOCK_DIP(dip);
4289 * First we handle the easy one. If we're setting the default
4290 * threshold for a node with children, then we set it to the
4291 * default nexus threshold (currently 0) and mark it as default
4292 * nexus threshold instead
4294 if (PM_IS_NEXUS(dip)) {
4295 if (flag == PMC_DEF_THRESH) {
4296 PMD(PMD_THRESH, ("%s: [%s@%s(%s#%d) NEXDEF]\n", pmf,
4297 PM_DEVICE(dip)))
4298 thresh = pm_default_nexus_threshold;
4299 for (comp = 0; comp < ncomp; comp++) {
4300 pmc = &PM_CP(dip, comp)->pmc_comp;
4301 for (level = 1; level < pmc->pmc_numlevels;
4302 level++) {
4303 pmc->pmc_thresh[level] = thresh;
4306 DEVI(dip)->devi_pm_dev_thresh =
4307 pm_default_nexus_threshold;
4309 * If the nexus node is being reconfigured back to
4310 * the default threshold, adjust the notlowest count.
4312 if (DEVI(dip)->devi_pm_flags &
4313 (PMC_DEV_THRESH|PMC_COMP_THRESH)) {
4314 PM_LOCK_POWER(dip, &circ);
4315 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
4316 if (PM_CURPOWER(dip, i) == 0)
4317 continue;
4318 mutex_enter(&pm_compcnt_lock);
4319 ASSERT(pm_comps_notlowest);
4320 pm_comps_notlowest--;
4321 PMD(PMD_LEVEL, ("%s: %s@%s(%s#%d) decr "
4322 "notlowest to %d\n", pmf,
4323 PM_DEVICE(dip), pm_comps_notlowest))
4324 if (pm_comps_notlowest == 0)
4325 pm_ppm_notify_all_lowest(dip,
4326 PM_ALL_LOWEST);
4327 mutex_exit(&pm_compcnt_lock);
4329 PM_UNLOCK_POWER(dip, circ);
4331 DEVI(dip)->devi_pm_flags &= PMC_THRESH_NONE;
4332 DEVI(dip)->devi_pm_flags |= PMC_NEXDEF_THRESH;
4333 PM_UNLOCK_DIP(dip);
4334 return;
4335 } else if (DEVI(dip)->devi_pm_flags & PMC_NEXDEF_THRESH) {
4337 * If the nexus node is being configured for a
4338 * non-default threshold, include that node in
4339 * the notlowest accounting.
4341 PM_LOCK_POWER(dip, &circ);
4342 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
4343 if (PM_CURPOWER(dip, i) == 0)
4344 continue;
4345 mutex_enter(&pm_compcnt_lock);
4346 if (pm_comps_notlowest == 0)
4347 pm_ppm_notify_all_lowest(dip,
4348 PM_NOT_ALL_LOWEST);
4349 pm_comps_notlowest++;
4350 PMD(PMD_LEVEL, ("%s: %s@%s(%s#%d) incr "
4351 "notlowest to %d\n", pmf,
4352 PM_DEVICE(dip), pm_comps_notlowest))
4353 mutex_exit(&pm_compcnt_lock);
4355 PM_UNLOCK_POWER(dip, circ);
4359 * Compute the total number of transitions for all components
4360 * of the device. Distribute the threshold evenly over them
4362 for (comp = 0; comp < ncomp; comp++) {
4363 pmc = &PM_CP(dip, comp)->pmc_comp;
4364 ASSERT(pmc->pmc_numlevels > 1);
4365 transitions += pmc->pmc_numlevels - 1;
4367 ASSERT(transitions);
4368 thresh = target_threshold / transitions;
4370 for (comp = 0; comp < ncomp; comp++) {
4371 pmc = &PM_CP(dip, comp)->pmc_comp;
4372 for (level = 1; level < pmc->pmc_numlevels; level++) {
4373 pmc->pmc_thresh[level] = thresh;
4377 #ifdef DEBUG
4378 for (comp = 0; comp < ncomp; comp++) {
4379 pmc = &PM_CP(dip, comp)->pmc_comp;
4380 for (level = 1; level < pmc->pmc_numlevels; level++) {
4381 PMD(PMD_THRESH, ("%s: thresh before %s@%s(%s#%d) "
4382 "comp=%d, level=%d, %d\n", pmf, PM_DEVICE(dip),
4383 comp, level, pmc->pmc_thresh[level]))
4386 #endif
4388 * Distribute any remainder till they are all gone
4390 remainder = target_threshold - thresh * transitions;
4391 level = 1;
4392 #ifdef DEBUG
4393 PMD(PMD_THRESH, ("%s: remainder=%d target_threshold=%d thresh=%d "
4394 "trans=%d\n", pmf, remainder, target_threshold, thresh,
4395 transitions))
4396 #endif
4397 while (remainder > 0) {
4398 comp = 0;
4399 while (remainder && (comp < ncomp)) {
4400 pmc = &PM_CP(dip, comp)->pmc_comp;
4401 if (level < pmc->pmc_numlevels) {
4402 pmc->pmc_thresh[level] += 1;
4403 remainder--;
4405 comp++;
4407 level++;
4409 #ifdef DEBUG
4410 for (comp = 0; comp < ncomp; comp++) {
4411 pmc = &PM_CP(dip, comp)->pmc_comp;
4412 for (level = 1; level < pmc->pmc_numlevels; level++) {
4413 PMD(PMD_THRESH, ("%s: thresh after %s@%s(%s#%d) "
4414 "comp=%d level=%d, %d\n", pmf, PM_DEVICE(dip),
4415 comp, level, pmc->pmc_thresh[level]))
4418 #endif
4419 ASSERT(PM_IAM_LOCKING_DIP(dip));
4420 DEVI(dip)->devi_pm_dev_thresh = base;
4421 DEVI(dip)->devi_pm_flags &= PMC_THRESH_NONE;
4422 DEVI(dip)->devi_pm_flags |= flag;
4423 PM_UNLOCK_DIP(dip);
4427 * Called when there is no old-style platform power management driver
4429 static int
4430 ddi_no_platform_power(power_req_t *req)
4432 _NOTE(ARGUNUSED(req))
4433 return (DDI_FAILURE);
4437 * This function calls the entry point supplied by the platform-specific
4438 * pm driver to bring the device component 'pm_cmpt' to power level 'pm_level'.
4439 * The use of global for getting the function name from platform-specific
4440 * pm driver is not ideal, but it is simple and efficient.
4441 * The previous property lookup was being done in the idle loop on swift
4442 * systems without pmc chips and hurt deskbench performance as well as
4443 * violating scheduler locking rules
4445 int (*pm_platform_power)(power_req_t *) = ddi_no_platform_power;
4448 * Old obsolete interface for a device to request a power change (but only
4449 * an increase in power)
4452 ddi_dev_is_needed(dev_info_t *dip, int cmpt, int level)
4454 return (pm_raise_power(dip, cmpt, level));
4458 * The old obsolete interface to platform power management. Only used by
4459 * Gypsy platform and APM on X86.
4462 ddi_power(dev_info_t *dip, int pm_cmpt, int pm_level)
4464 power_req_t request;
4466 request.request_type = PMR_SET_POWER;
4467 request.req.set_power_req.who = dip;
4468 request.req.set_power_req.cmpt = pm_cmpt;
4469 request.req.set_power_req.level = pm_level;
4470 return (ddi_ctlops(dip, dip, DDI_CTLOPS_POWER, &request, NULL));
4474 * A driver can invoke this from its detach routine when DDI_SUSPEND is
4475 * passed. Returns true if subsequent processing could result in power being
4476 * removed from the device. The arg is not currently used because it is
4477 * implicit in the operation of cpr/DR.
4480 ddi_removing_power(dev_info_t *dip)
4482 _NOTE(ARGUNUSED(dip))
4483 return (pm_powering_down);
4487 * Returns true if a device indicates that its parent handles suspend/resume
4488 * processing for it.
4491 e_ddi_parental_suspend_resume(dev_info_t *dip)
4493 return (DEVI(dip)->devi_pm_flags & PMC_PARENTAL_SR);
4497 * Called for devices which indicate that their parent does suspend/resume
4498 * handling for them
4501 e_ddi_suspend(dev_info_t *dip, ddi_detach_cmd_t cmd)
4503 power_req_t request;
4504 request.request_type = PMR_SUSPEND;
4505 request.req.suspend_req.who = dip;
4506 request.req.suspend_req.cmd = cmd;
4507 return (ddi_ctlops(dip, dip, DDI_CTLOPS_POWER, &request, NULL));
4511 * Called for devices which indicate that their parent does suspend/resume
4512 * handling for them
4515 e_ddi_resume(dev_info_t *dip, ddi_attach_cmd_t cmd)
4517 power_req_t request;
4518 request.request_type = PMR_RESUME;
4519 request.req.resume_req.who = dip;
4520 request.req.resume_req.cmd = cmd;
4521 return (ddi_ctlops(dip, dip, DDI_CTLOPS_POWER, &request, NULL));
4525 * Old obsolete exported interface for drivers to create components.
4526 * This is now handled by exporting the pm-components property.
4529 pm_create_components(dev_info_t *dip, int num_components)
4531 PMD_FUNC(pmf, "pm_create_components")
4533 if (num_components < 1)
4534 return (DDI_FAILURE);
4536 if (!DEVI_IS_ATTACHING(dip)) {
4537 return (DDI_FAILURE);
4540 /* don't need to lock dip because attach is single threaded */
4541 if (DEVI(dip)->devi_pm_components) {
4542 PMD(PMD_ERROR, ("%s: %s@%s(%s#%d) already has %d\n", pmf,
4543 PM_DEVICE(dip), PM_NUMCMPTS(dip)))
4544 return (DDI_FAILURE);
4546 e_pm_create_components(dip, num_components);
4547 DEVI(dip)->devi_pm_flags |= PMC_BC;
4548 e_pm_default_components(dip, num_components);
4549 return (DDI_SUCCESS);
4553 * Obsolete interface previously called by drivers to destroy their components
4554 * at detach time. This is now done automatically. However, we need to keep
4555 * this for the old drivers.
4557 void
4558 pm_destroy_components(dev_info_t *dip)
4560 PMD_FUNC(pmf, "pm_destroy_components")
4561 dev_info_t *pdip = ddi_get_parent(dip);
4563 PMD(PMD_REMDEV | PMD_KIDSUP, ("%s: %s@%s(%s#%d)\n", pmf,
4564 PM_DEVICE(dip)))
4565 ASSERT(DEVI_IS_DETACHING(dip));
4566 #ifdef DEBUG
4567 if (!PM_ISBC(dip))
4568 cmn_err(CE_WARN, "!driver exporting pm-components property "
4569 "(%s@%s) calls pm_destroy_components", PM_NAME(dip),
4570 PM_ADDR(dip));
4571 #endif
4573 * We ignore this unless this is an old-style driver, except for
4574 * printing the message above
4576 if (PM_NUMCMPTS(dip) == 0 || !PM_ISBC(dip)) {
4577 PMD(PMD_REMDEV, ("%s: ignore %s@%s(%s#%d)\n", pmf,
4578 PM_DEVICE(dip)))
4579 return;
4581 ASSERT(PM_GET_PM_INFO(dip));
4584 * pm_unmanage will clear info pointer later, after dealing with
4585 * dependencies
4587 ASSERT(!PM_GET_PM_SCAN(dip)); /* better be gone already */
4589 * Now adjust parent's kidsupcnt. We check only comp 0.
4590 * Parents that get notification are not adjusted because their
4591 * kidsupcnt is always 0 (or 1 during probe and attach).
4593 if ((PM_CURPOWER(dip, 0) != 0) && pdip && !PM_WANTS_NOTIFICATION(pdip))
4594 pm_rele_power(pdip);
4595 #ifdef DEBUG
4596 else {
4597 PMD(PMD_KIDSUP, ("%s: kuc stays %s@%s(%s#%d) comps gone\n",
4598 pmf, PM_DEVICE(dip)))
4600 #endif
4601 e_pm_destroy_components(dip);
4603 * Forget we ever knew anything about the components of this device
4605 DEVI(dip)->devi_pm_flags &=
4606 ~(PMC_BC | PMC_COMPONENTS_DONE | PMC_COMPONENTS_FAILED);
4610 * Exported interface for a driver to set a component busy.
4613 pm_busy_component(dev_info_t *dip, int cmpt)
4615 struct pm_component *cp;
4617 ASSERT(dip != NULL);
4618 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, cmpt, &cp))
4619 return (DDI_FAILURE);
4620 PM_LOCK_BUSY(dip);
4621 cp->pmc_busycount++;
4622 cp->pmc_timestamp = 0;
4623 PM_UNLOCK_BUSY(dip);
4624 return (DDI_SUCCESS);
4628 * Exported interface for a driver to set a component idle.
4631 pm_idle_component(dev_info_t *dip, int cmpt)
4633 PMD_FUNC(pmf, "pm_idle_component")
4634 struct pm_component *cp;
4635 pm_scan_t *scanp = PM_GET_PM_SCAN(dip);
4637 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, cmpt, &cp))
4638 return (DDI_FAILURE);
4640 PM_LOCK_BUSY(dip);
4641 if (cp->pmc_busycount) {
4642 if (--(cp->pmc_busycount) == 0)
4643 cp->pmc_timestamp = gethrestime_sec();
4644 } else {
4645 cp->pmc_timestamp = gethrestime_sec();
4648 PM_UNLOCK_BUSY(dip);
4651 * if device becomes idle during idle down period, try scan it down
4653 if (scanp && PM_IS_PID(dip)) {
4654 PMD(PMD_IDLEDOWN, ("%s: %s@%s(%s#%d) idle.\n", pmf,
4655 PM_DEVICE(dip)))
4656 pm_rescan(dip);
4657 return (DDI_SUCCESS);
4661 * handle scan not running with nexus threshold == 0
4664 if (PM_IS_NEXUS(dip) && (cp->pmc_busycount == 0)) {
4665 pm_rescan(dip);
4668 return (DDI_SUCCESS);
4672 * This is the old obsolete interface called by drivers to set their normal
4673 * power. Thus we can't fix its behavior or return a value.
4674 * This functionality is replaced by the pm-component property.
4675 * We'll only get components destroyed while no power management is
4676 * going on (and the device is detached), so we don't need a mutex here
4678 void
4679 pm_set_normal_power(dev_info_t *dip, int comp, int level)
4681 PMD_FUNC(pmf, "set_normal_power")
4682 #ifdef DEBUG
4683 if (!PM_ISBC(dip))
4684 cmn_err(CE_WARN, "!call to pm_set_normal_power() by %s@%s "
4685 "(driver exporting pm-components property) ignored",
4686 PM_NAME(dip), PM_ADDR(dip));
4687 #endif
4688 if (PM_ISBC(dip)) {
4689 PMD(PMD_NORM, ("%s: %s@%s(%s#%d) set normal power comp=%d, "
4690 "level=%d\n", pmf, PM_DEVICE(dip), comp, level))
4691 e_pm_set_max_power(dip, comp, level);
4692 e_pm_default_levels(dip, PM_CP(dip, comp), level);
4697 * Called on a successfully detached driver to free pm resources
4699 static void
4700 pm_stop(dev_info_t *dip)
4702 PMD_FUNC(pmf, "stop")
4703 dev_info_t *pdip = ddi_get_parent(dip);
4705 ASSERT(!PM_IAM_LOCKING_DIP(dip));
4706 /* stopping scan, destroy scan data structure */
4707 if (!PM_ISBC(dip)) {
4708 pm_scan_stop(dip);
4709 pm_scan_fini(dip);
4712 if (PM_GET_PM_INFO(dip) != NULL) {
4713 if (pm_unmanage(dip) == DDI_SUCCESS) {
4715 * Old style driver may have called
4716 * pm_destroy_components already, but just in case ...
4718 e_pm_destroy_components(dip);
4719 } else {
4720 PMD(PMD_FAIL, ("%s: can't pm_unmanage %s@%s(%s#%d)\n",
4721 pmf, PM_DEVICE(dip)))
4723 } else {
4724 if (PM_NUMCMPTS(dip))
4725 e_pm_destroy_components(dip);
4726 else {
4727 if (DEVI(dip)->devi_pm_flags & PMC_NOPMKID) {
4728 DEVI(dip)->devi_pm_flags &= ~PMC_NOPMKID;
4729 if (pdip && !PM_WANTS_NOTIFICATION(pdip)) {
4730 pm_rele_power(pdip);
4731 } else if (pdip &&
4732 MDI_VHCI(pdip) && MDI_CLIENT(dip)) {
4733 (void) mdi_power(pdip,
4734 MDI_PM_RELE_POWER,
4735 (void *)dip, NULL, 0);
4743 * The node is the subject of a reparse pm props ioctl. Throw away the old
4744 * info and start over.
4747 e_new_pm_props(dev_info_t *dip)
4749 if (PM_GET_PM_INFO(dip) != NULL) {
4750 pm_stop(dip);
4752 if (e_pm_manage(dip, PM_STYLE_NEW) != DDI_SUCCESS) {
4753 return (DDI_FAILURE);
4756 e_pm_props(dip);
4757 return (DDI_SUCCESS);
4761 * Device has been attached, so process its pm properties
4763 void
4764 e_pm_props(dev_info_t *dip)
4766 char *pp;
4767 int len;
4768 int flags = 0;
4769 int propflag = DDI_PROP_DONTPASS|DDI_PROP_CANSLEEP;
4772 * It doesn't matter if we do this more than once, we should always
4773 * get the same answers, and if not, then the last one in is the
4774 * best one.
4776 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, propflag, "pm-hardware-state",
4777 (caddr_t)&pp, &len) == DDI_PROP_SUCCESS) {
4778 if (strcmp(pp, "needs-suspend-resume") == 0) {
4779 flags = PMC_NEEDS_SR;
4780 } else if (strcmp(pp, "no-suspend-resume") == 0) {
4781 flags = PMC_NO_SR;
4782 } else if (strcmp(pp, "parental-suspend-resume") == 0) {
4783 flags = PMC_PARENTAL_SR;
4784 } else {
4785 cmn_err(CE_NOTE, "!device %s@%s has unrecognized "
4786 "%s property value '%s'", PM_NAME(dip),
4787 PM_ADDR(dip), "pm-hardware-state", pp);
4789 kmem_free(pp, len);
4792 * This next segment (PMC_WANTS_NOTIFY) is in
4793 * support of nexus drivers which will want to be involved in
4794 * (or at least notified of) their child node's power level transitions.
4795 * "pm-want-child-notification?" is defined by the parent.
4797 if (ddi_prop_exists(DDI_DEV_T_ANY, dip, propflag,
4798 "pm-want-child-notification?") && PM_HAS_BUS_POWER(dip))
4799 flags |= PMC_WANTS_NOTIFY;
4800 ASSERT(PM_HAS_BUS_POWER(dip) || !ddi_prop_exists(DDI_DEV_T_ANY,
4801 dip, propflag, "pm-want-child-notification?"));
4802 if (ddi_prop_exists(DDI_DEV_T_ANY, dip, propflag,
4803 "no-involuntary-power-cycles"))
4804 flags |= PMC_NO_INVOL;
4806 * Is the device a CPU device?
4808 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, propflag, "pm-class",
4809 (caddr_t)&pp, &len) == DDI_PROP_SUCCESS) {
4810 if (strcmp(pp, "CPU") == 0) {
4811 flags |= PMC_CPU_DEVICE;
4812 } else {
4813 cmn_err(CE_NOTE, "!device %s@%s has unrecognized "
4814 "%s property value '%s'", PM_NAME(dip),
4815 PM_ADDR(dip), "pm-class", pp);
4817 kmem_free(pp, len);
4819 /* devfs single threads us */
4820 DEVI(dip)->devi_pm_flags |= flags;
4824 * This is the DDI_CTLOPS_POWER handler that is used when there is no ppm
4825 * driver which has claimed a node.
4826 * Sets old_power in arg struct.
4828 static int
4829 pm_default_ctlops(dev_info_t *dip, dev_info_t *rdip,
4830 ddi_ctl_enum_t ctlop, void *arg, void *result)
4832 _NOTE(ARGUNUSED(dip))
4833 PMD_FUNC(pmf, "ctlops")
4834 power_req_t *reqp = (power_req_t *)arg;
4835 int retval;
4836 dev_info_t *target_dip;
4837 int new_level, old_level, cmpt;
4838 #ifdef PMDDEBUG
4839 char *format;
4840 #endif
4843 * The interface for doing the actual power level changes is now
4844 * through the DDI_CTLOPS_POWER bus_ctl, so that we can plug in
4845 * different platform-specific power control drivers.
4847 * This driver implements the "default" version of this interface.
4848 * If no ppm driver has been installed then this interface is called
4849 * instead.
4851 ASSERT(dip == NULL);
4852 switch (ctlop) {
4853 case DDI_CTLOPS_POWER:
4854 switch (reqp->request_type) {
4855 case PMR_PPM_SET_POWER:
4857 target_dip = reqp->req.ppm_set_power_req.who;
4858 ASSERT(target_dip == rdip);
4859 new_level = reqp->req.ppm_set_power_req.new_level;
4860 cmpt = reqp->req.ppm_set_power_req.cmpt;
4861 /* pass back old power for the PM_LEVEL_UNKNOWN case */
4862 old_level = PM_CURPOWER(target_dip, cmpt);
4863 reqp->req.ppm_set_power_req.old_level = old_level;
4864 retval = pm_power(target_dip, cmpt, new_level);
4865 PMD(PMD_PPM, ("%s: PPM_SET_POWER %s@%s(%s#%d)[%d] %d->"
4866 "%d %s\n", pmf, PM_DEVICE(target_dip), cmpt,
4867 old_level, new_level, (retval == DDI_SUCCESS ?
4868 "chd" : "no chg")))
4869 return (retval);
4872 case PMR_PPM_PRE_DETACH:
4873 case PMR_PPM_POST_DETACH:
4874 case PMR_PPM_PRE_ATTACH:
4875 case PMR_PPM_POST_ATTACH:
4876 case PMR_PPM_PRE_PROBE:
4877 case PMR_PPM_POST_PROBE:
4878 case PMR_PPM_PRE_RESUME:
4879 case PMR_PPM_INIT_CHILD:
4880 case PMR_PPM_UNINIT_CHILD:
4881 #ifdef PMDDEBUG
4882 switch (reqp->request_type) {
4883 case PMR_PPM_PRE_DETACH:
4884 format = "%s: PMR_PPM_PRE_DETACH "
4885 "%s@%s(%s#%d)\n";
4886 break;
4887 case PMR_PPM_POST_DETACH:
4888 format = "%s: PMR_PPM_POST_DETACH "
4889 "%s@%s(%s#%d) rets %d\n";
4890 break;
4891 case PMR_PPM_PRE_ATTACH:
4892 format = "%s: PMR_PPM_PRE_ATTACH "
4893 "%s@%s(%s#%d)\n";
4894 break;
4895 case PMR_PPM_POST_ATTACH:
4896 format = "%s: PMR_PPM_POST_ATTACH "
4897 "%s@%s(%s#%d) rets %d\n";
4898 break;
4899 case PMR_PPM_PRE_PROBE:
4900 format = "%s: PMR_PPM_PRE_PROBE "
4901 "%s@%s(%s#%d)\n";
4902 break;
4903 case PMR_PPM_POST_PROBE:
4904 format = "%s: PMR_PPM_POST_PROBE "
4905 "%s@%s(%s#%d) rets %d\n";
4906 break;
4907 case PMR_PPM_PRE_RESUME:
4908 format = "%s: PMR_PPM_PRE_RESUME "
4909 "%s@%s(%s#%d) rets %d\n";
4910 break;
4911 case PMR_PPM_INIT_CHILD:
4912 format = "%s: PMR_PPM_INIT_CHILD "
4913 "%s@%s(%s#%d)\n";
4914 break;
4915 case PMR_PPM_UNINIT_CHILD:
4916 format = "%s: PMR_PPM_UNINIT_CHILD "
4917 "%s@%s(%s#%d)\n";
4918 break;
4919 default:
4920 break;
4922 PMD(PMD_PPM, (format, pmf, PM_DEVICE(rdip),
4923 reqp->req.ppm_config_req.result))
4924 #endif
4925 return (DDI_SUCCESS);
4927 case PMR_PPM_POWER_CHANGE_NOTIFY:
4929 * Nothing for us to do
4931 ASSERT(reqp->req.ppm_notify_level_req.who == rdip);
4932 PMD(PMD_PPM, ("%s: PMR_PPM_POWER_CHANGE_NOTIFY "
4933 "%s@%s(%s#%d)[%d] %d->%d\n", pmf,
4934 PM_DEVICE(reqp->req.ppm_notify_level_req.who),
4935 reqp->req.ppm_notify_level_req.cmpt,
4936 PM_CURPOWER(reqp->req.ppm_notify_level_req.who,
4937 reqp->req.ppm_notify_level_req.cmpt),
4938 reqp->req.ppm_notify_level_req.new_level))
4939 return (DDI_SUCCESS);
4941 case PMR_PPM_UNMANAGE:
4942 PMD(PMD_PPM, ("%s: PMR_PPM_UNMANAGE %s@%s(%s#%d)\n",
4943 pmf, PM_DEVICE(rdip)))
4944 return (DDI_SUCCESS);
4946 case PMR_PPM_LOCK_POWER:
4947 pm_lock_power_single(reqp->req.ppm_lock_power_req.who,
4948 reqp->req.ppm_lock_power_req.circp);
4949 return (DDI_SUCCESS);
4951 case PMR_PPM_UNLOCK_POWER:
4952 pm_unlock_power_single(
4953 reqp->req.ppm_unlock_power_req.who,
4954 reqp->req.ppm_unlock_power_req.circ);
4955 return (DDI_SUCCESS);
4957 case PMR_PPM_TRY_LOCK_POWER:
4958 *(int *)result = pm_try_locking_power_single(
4959 reqp->req.ppm_lock_power_req.who,
4960 reqp->req.ppm_lock_power_req.circp);
4961 return (DDI_SUCCESS);
4963 case PMR_PPM_POWER_LOCK_OWNER:
4964 target_dip = reqp->req.ppm_power_lock_owner_req.who;
4965 ASSERT(target_dip == rdip);
4966 reqp->req.ppm_power_lock_owner_req.owner =
4967 DEVI(rdip)->devi_busy_thread;
4968 return (DDI_SUCCESS);
4969 default:
4970 PMD(PMD_ERROR, ("%s: default!\n", pmf))
4971 return (DDI_FAILURE);
4974 default:
4975 PMD(PMD_ERROR, ("%s: unknown\n", pmf))
4976 return (DDI_FAILURE);
4981 * We overload the bus_ctl ops here--perhaps we ought to have a distinct
4982 * power_ops struct for this functionality instead?
4983 * However, we only ever do this on a ppm driver.
4986 pm_ctlops(dev_info_t *d, dev_info_t *r, ddi_ctl_enum_t op, void *a, void *v)
4988 int (*fp)();
4990 /* if no ppm handler, call the default routine */
4991 if (d == NULL) {
4992 return (pm_default_ctlops(d, r, op, a, v));
4994 if (!d || !r)
4995 return (DDI_FAILURE);
4996 ASSERT(DEVI(d)->devi_ops && DEVI(d)->devi_ops->devo_bus_ops &&
4997 DEVI(d)->devi_ops->devo_bus_ops->bus_ctl);
4999 fp = DEVI(d)->devi_ops->devo_bus_ops->bus_ctl;
5000 return ((*fp)(d, r, op, a, v));
5004 * Called on a node when attach completes or the driver makes its first pm
5005 * call (whichever comes first).
5006 * In the attach case, device may not be power manageable at all.
5007 * Don't need to lock the dip because we're single threaded by the devfs code
5009 static int
5010 pm_start(dev_info_t *dip)
5012 PMD_FUNC(pmf, "start")
5013 int ret;
5014 dev_info_t *pdip = ddi_get_parent(dip);
5015 int e_pm_manage(dev_info_t *, int);
5016 void pm_noinvol_specd(dev_info_t *dip);
5018 e_pm_props(dip);
5019 pm_noinvol_specd(dip);
5021 * If this dip has already been processed, don't mess with it
5022 * (but decrement the speculative count we did above, as whatever
5023 * code put it under pm already will have dealt with it)
5025 if (PM_GET_PM_INFO(dip)) {
5026 PMD(PMD_KIDSUP, ("%s: pm already done for %s@%s(%s#%d)\n",
5027 pmf, PM_DEVICE(dip)))
5028 return (0);
5030 ret = e_pm_manage(dip, PM_STYLE_UNKNOWN);
5032 if (PM_GET_PM_INFO(dip) == NULL) {
5034 * keep the kidsupcount increment as is
5036 DEVI(dip)->devi_pm_flags |= PMC_NOPMKID;
5037 if (pdip && !PM_WANTS_NOTIFICATION(pdip)) {
5038 pm_hold_power(pdip);
5039 } else if (pdip && MDI_VHCI(pdip) && MDI_CLIENT(dip)) {
5040 (void) mdi_power(pdip, MDI_PM_HOLD_POWER,
5041 (void *)dip, NULL, 0);
5044 PMD(PMD_KIDSUP, ("%s: pm of %s@%s(%s#%d) failed, parent "
5045 "left up\n", pmf, PM_DEVICE(dip)))
5048 return (ret);
5052 * Keep a list of recorded thresholds. For now we just keep a list and
5053 * search it linearly. We don't expect too many entries. Can always hash it
5054 * later if we need to.
5056 void
5057 pm_record_thresh(pm_thresh_rec_t *rp)
5059 pm_thresh_rec_t *pptr, *ptr;
5061 ASSERT(*rp->ptr_physpath);
5062 rw_enter(&pm_thresh_rwlock, RW_WRITER);
5063 for (pptr = NULL, ptr = pm_thresh_head;
5064 ptr; pptr = ptr, ptr = ptr->ptr_next) {
5065 if (strcmp(rp->ptr_physpath, ptr->ptr_physpath) == 0) {
5066 /* replace this one */
5067 rp->ptr_next = ptr->ptr_next;
5068 if (pptr) {
5069 pptr->ptr_next = rp;
5070 } else {
5071 pm_thresh_head = rp;
5073 rw_exit(&pm_thresh_rwlock);
5074 kmem_free(ptr, ptr->ptr_size);
5075 return;
5077 continue;
5080 * There was not a match in the list, insert this one in front
5082 if (pm_thresh_head) {
5083 rp->ptr_next = pm_thresh_head;
5084 pm_thresh_head = rp;
5085 } else {
5086 rp->ptr_next = NULL;
5087 pm_thresh_head = rp;
5089 rw_exit(&pm_thresh_rwlock);
5093 * Create a new dependency record and hang a new dependency entry off of it
5095 pm_pdr_t *
5096 newpdr(char *kept, char *keeps, int isprop)
5098 size_t size = strlen(kept) + strlen(keeps) + 2 + sizeof (pm_pdr_t);
5099 pm_pdr_t *p = kmem_zalloc(size, KM_SLEEP);
5100 p->pdr_size = size;
5101 p->pdr_isprop = isprop;
5102 p->pdr_kept_paths = NULL;
5103 p->pdr_kept_count = 0;
5104 p->pdr_kept = (char *)((intptr_t)p + sizeof (pm_pdr_t));
5105 (void) strcpy(p->pdr_kept, kept);
5106 p->pdr_keeper = (char *)((intptr_t)p->pdr_kept + strlen(kept) + 1);
5107 (void) strcpy(p->pdr_keeper, keeps);
5108 ASSERT((intptr_t)p->pdr_keeper + strlen(p->pdr_keeper) + 1 <=
5109 (intptr_t)p + size);
5110 ASSERT((intptr_t)p->pdr_kept + strlen(p->pdr_kept) + 1 <=
5111 (intptr_t)p + size);
5112 return (p);
5116 * Keep a list of recorded dependencies. We only keep the
5117 * keeper -> kept list for simplification. At this point We do not
5118 * care about whether the devices are attached or not yet,
5119 * this would be done in pm_keeper() and pm_kept().
5120 * If a PM_RESET_PM happens, then we tear down and forget the dependencies,
5121 * and it is up to the user to issue the ioctl again if they want it
5122 * (e.g. pmconfig)
5123 * Returns true if dependency already exists in the list.
5126 pm_record_keeper(char *kept, char *keeper, int isprop)
5128 PMD_FUNC(pmf, "record_keeper")
5129 pm_pdr_t *npdr, *ppdr, *pdr;
5131 PMD(PMD_KEEPS, ("%s: %s, %s\n", pmf, kept, keeper))
5132 ASSERT(kept && keeper);
5133 #ifdef DEBUG
5134 if (pm_debug & PMD_KEEPS)
5135 prdeps("pm_record_keeper entry");
5136 #endif
5137 for (ppdr = NULL, pdr = pm_dep_head; pdr;
5138 ppdr = pdr, pdr = pdr->pdr_next) {
5139 PMD(PMD_KEEPS, ("%s: check %s, %s\n", pmf, pdr->pdr_kept,
5140 pdr->pdr_keeper))
5141 if (strcmp(kept, pdr->pdr_kept) == 0 &&
5142 strcmp(keeper, pdr->pdr_keeper) == 0) {
5143 PMD(PMD_KEEPS, ("%s: match\n", pmf))
5144 return (1);
5148 * We did not find any match, so we have to make an entry
5150 npdr = newpdr(kept, keeper, isprop);
5151 if (ppdr) {
5152 ASSERT(ppdr->pdr_next == NULL);
5153 ppdr->pdr_next = npdr;
5154 } else {
5155 ASSERT(pm_dep_head == NULL);
5156 pm_dep_head = npdr;
5158 #ifdef DEBUG
5159 if (pm_debug & PMD_KEEPS)
5160 prdeps("pm_record_keeper after new record");
5161 #endif
5162 if (!isprop)
5163 pm_unresolved_deps++;
5164 else
5165 pm_prop_deps++;
5166 return (0);
5170 * Look up this device in the set of devices we've seen ioctls for
5171 * to see if we are holding a threshold spec for it. If so, make it so.
5172 * At ioctl time, we were given the physical path of the device.
5175 pm_thresh_specd(dev_info_t *dip)
5177 void pm_apply_recorded_thresh(dev_info_t *, pm_thresh_rec_t *);
5178 char *path = 0;
5179 char pathbuf[MAXNAMELEN];
5180 pm_thresh_rec_t *rp;
5182 path = ddi_pathname(dip, pathbuf);
5184 rw_enter(&pm_thresh_rwlock, RW_READER);
5185 for (rp = pm_thresh_head; rp; rp = rp->ptr_next) {
5186 if (strcmp(rp->ptr_physpath, path) != 0)
5187 continue;
5188 pm_apply_recorded_thresh(dip, rp);
5189 rw_exit(&pm_thresh_rwlock);
5190 return (1);
5192 rw_exit(&pm_thresh_rwlock);
5193 return (0);
5196 static int
5197 pm_set_keeping(dev_info_t *keeper, dev_info_t *kept)
5199 PMD_FUNC(pmf, "set_keeping")
5200 int j, up = 0, circ;
5201 void prdeps(char *);
5203 PMD(PMD_KEEPS, ("%s: keeper=%s@%s(%s#%d), kept=%s@%s(%s#%d)\n", pmf,
5204 PM_DEVICE(keeper), PM_DEVICE(kept)))
5205 #ifdef DEBUG
5206 if (pm_debug & PMD_KEEPS)
5207 prdeps("Before PAD\n");
5208 #endif
5209 ASSERT(keeper != kept);
5210 if (PM_GET_PM_INFO(keeper) == NULL) {
5211 cmn_err(CE_CONT, "!device %s@%s(%s#%d) keeps up device "
5212 "%s@%s(%s#%d), but the former is not power managed",
5213 PM_DEVICE(keeper), PM_DEVICE(kept));
5214 PMD((PMD_FAIL | PMD_KEEPS), ("%s: keeper %s@%s(%s#%d) is not"
5215 "power managed\n", pmf, PM_DEVICE(keeper)))
5216 return (0);
5218 if (PM_GET_PM_INFO(kept) == NULL) {
5219 cmn_err(CE_CONT, "!device %s@%s(%s#%d) keeps up device "
5220 "%s@%s(%s#%d), but the latter is not power managed",
5221 PM_DEVICE(keeper), PM_DEVICE(kept));
5222 PMD((PMD_FAIL | PMD_KEEPS), ("%s: kept %s@%s(%s#%d) is not"
5223 "power managed\n", pmf, PM_DEVICE(kept)))
5224 return (0);
5227 PM_LOCK_POWER(keeper, &circ);
5228 for (j = 0; j < PM_NUMCMPTS(keeper); j++) {
5229 if (PM_CURPOWER(keeper, j)) {
5230 up++;
5231 break;
5234 if (up) {
5235 /* Bringup and maintain a hold on the kept */
5236 PMD(PMD_KEEPS, ("%s: place a hold on kept %s@%s(%s#%d)\n", pmf,
5237 PM_DEVICE(kept)))
5238 bring_pmdep_up(kept, 1);
5240 PM_UNLOCK_POWER(keeper, circ);
5241 #ifdef DEBUG
5242 if (pm_debug & PMD_KEEPS)
5243 prdeps("After PAD\n");
5244 #endif
5245 return (1);
5249 * Should this device keep up another device?
5250 * Look up this device in the set of devices we've seen ioctls for
5251 * to see if we are holding a dependency spec for it. If so, make it so.
5252 * Because we require the kept device to be attached already in order to
5253 * make the list entry (and hold it), we only need to look for keepers.
5254 * At ioctl time, we were given the physical path of the device.
5257 pm_keeper(char *keeper)
5259 PMD_FUNC(pmf, "keeper")
5260 int pm_apply_recorded_dep(dev_info_t *, pm_pdr_t *);
5261 dev_info_t *dip;
5262 pm_pdr_t *dp;
5263 dev_info_t *kept = NULL;
5264 int ret = 0;
5265 int i;
5267 if (!pm_unresolved_deps && !pm_prop_deps)
5268 return (0);
5269 ASSERT(keeper != NULL);
5270 dip = pm_name_to_dip(keeper, 1);
5271 if (dip == NULL)
5272 return (0);
5273 PMD(PMD_KEEPS, ("%s: keeper=%s\n", pmf, keeper))
5274 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
5275 if (!dp->pdr_isprop) {
5276 if (!pm_unresolved_deps)
5277 continue;
5278 PMD(PMD_KEEPS, ("%s: keeper %s\n", pmf, dp->pdr_keeper))
5279 if (dp->pdr_satisfied) {
5280 PMD(PMD_KEEPS, ("%s: satisfied\n", pmf))
5281 continue;
5283 if (strcmp(dp->pdr_keeper, keeper) == 0) {
5284 ret += pm_apply_recorded_dep(dip, dp);
5286 } else {
5287 if (strcmp(dp->pdr_keeper, keeper) != 0)
5288 continue;
5289 for (i = 0; i < dp->pdr_kept_count; i++) {
5290 if (dp->pdr_kept_paths[i] == NULL)
5291 continue;
5292 kept = pm_name_to_dip(dp->pdr_kept_paths[i], 1);
5293 if (kept == NULL)
5294 continue;
5295 ASSERT(ddi_prop_exists(DDI_DEV_T_ANY, kept,
5296 DDI_PROP_DONTPASS, dp->pdr_kept));
5297 PMD(PMD_KEEPS, ("%s: keeper=%s@%s(%s#%d), "
5298 "kept=%s@%s(%s#%d) keptcnt=%d\n",
5299 pmf, PM_DEVICE(dip), PM_DEVICE(kept),
5300 dp->pdr_kept_count))
5301 if (kept != dip) {
5302 ret += pm_set_keeping(dip, kept);
5304 ddi_release_devi(kept);
5309 ddi_release_devi(dip);
5310 return (ret);
5314 * Should this device be kept up by another device?
5315 * Look up all dependency recorded from PM_ADD_DEPENDENT and
5316 * PM_ADD_DEPENDENT_PROPERTY ioctls. Record down on the keeper's
5317 * kept device lists.
5319 static int
5320 pm_kept(char *keptp)
5322 PMD_FUNC(pmf, "kept")
5323 pm_pdr_t *dp;
5324 int found = 0;
5325 int ret = 0;
5326 dev_info_t *keeper;
5327 dev_info_t *kept;
5328 size_t length;
5329 int i;
5330 char **paths;
5331 char *path;
5333 ASSERT(keptp != NULL);
5334 kept = pm_name_to_dip(keptp, 1);
5335 if (kept == NULL)
5336 return (0);
5337 PMD(PMD_KEEPS, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(kept)))
5338 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
5339 if (dp->pdr_isprop) {
5340 PMD(PMD_KEEPS, ("%s: property %s\n", pmf, dp->pdr_kept))
5341 if (ddi_prop_exists(DDI_DEV_T_ANY, kept,
5342 DDI_PROP_DONTPASS, dp->pdr_kept)) {
5344 * Dont allow self dependency.
5346 if (strcmp(dp->pdr_keeper, keptp) == 0)
5347 continue;
5348 keeper = pm_name_to_dip(dp->pdr_keeper, 1);
5349 if (keeper == NULL)
5350 continue;
5351 PMD(PMD_KEEPS, ("%s: adding to kepts path list "
5352 "%p\n", pmf, (void *)kept))
5353 #ifdef DEBUG
5354 if (pm_debug & PMD_DEP)
5355 prdeps("Before Adding from pm_kept\n");
5356 #endif
5358 * Add ourselves to the dip list.
5360 if (dp->pdr_kept_count == 0) {
5361 length = strlen(keptp) + 1;
5362 path =
5363 kmem_alloc(length, KM_SLEEP);
5364 paths = kmem_alloc(sizeof (char **),
5365 KM_SLEEP);
5366 (void) strcpy(path, keptp);
5367 paths[0] = path;
5368 dp->pdr_kept_paths = paths;
5369 dp->pdr_kept_count++;
5370 } else {
5371 /* Check to see if already on list */
5372 for (i = 0; i < dp->pdr_kept_count;
5373 i++) {
5374 if (strcmp(keptp,
5375 dp->pdr_kept_paths[i])
5376 == 0) {
5377 found++;
5378 break;
5381 if (found) {
5382 ddi_release_devi(keeper);
5383 continue;
5385 length = dp->pdr_kept_count *
5386 sizeof (char **);
5387 paths = kmem_alloc(
5388 length + sizeof (char **),
5389 KM_SLEEP);
5390 if (dp->pdr_kept_count) {
5391 bcopy(dp->pdr_kept_paths,
5392 paths, length);
5393 kmem_free(dp->pdr_kept_paths,
5394 length);
5396 dp->pdr_kept_paths = paths;
5397 length = strlen(keptp) + 1;
5398 path =
5399 kmem_alloc(length, KM_SLEEP);
5400 (void) strcpy(path, keptp);
5401 dp->pdr_kept_paths[i] = path;
5402 dp->pdr_kept_count++;
5404 #ifdef DEBUG
5405 if (pm_debug & PMD_DEP)
5406 prdeps("After from pm_kept\n");
5407 #endif
5408 if (keeper) {
5409 ret += pm_set_keeping(keeper, kept);
5410 ddi_release_devi(keeper);
5413 } else {
5415 * pm_keeper would be called later to do
5416 * the actual pm_set_keeping.
5418 PMD(PMD_KEEPS, ("%s: adding to kepts path list %p\n",
5419 pmf, (void *)kept))
5420 #ifdef DEBUG
5421 if (pm_debug & PMD_DEP)
5422 prdeps("Before Adding from pm_kept\n");
5423 #endif
5424 if (strcmp(keptp, dp->pdr_kept) == 0) {
5425 if (dp->pdr_kept_paths == NULL) {
5426 length = strlen(keptp) + 1;
5427 path =
5428 kmem_alloc(length, KM_SLEEP);
5429 paths = kmem_alloc(sizeof (char **),
5430 KM_SLEEP);
5431 (void) strcpy(path, keptp);
5432 paths[0] = path;
5433 dp->pdr_kept_paths = paths;
5434 dp->pdr_kept_count++;
5437 #ifdef DEBUG
5438 if (pm_debug & PMD_DEP)
5439 prdeps("After from pm_kept\n");
5440 #endif
5443 ddi_release_devi(kept);
5444 return (ret);
5448 * Apply a recorded dependency. dp specifies the dependency, and
5449 * keeper is already known to be the device that keeps up the other (kept) one.
5450 * We have to the whole tree for the "kept" device, then apply
5451 * the dependency (which may already be applied).
5454 pm_apply_recorded_dep(dev_info_t *keeper, pm_pdr_t *dp)
5456 PMD_FUNC(pmf, "apply_recorded_dep")
5457 dev_info_t *kept = NULL;
5458 int ret = 0;
5459 char *keptp = NULL;
5462 * Device to Device dependency can only be 1 to 1.
5464 if (dp->pdr_kept_paths == NULL)
5465 return (0);
5466 keptp = dp->pdr_kept_paths[0];
5467 if (keptp == NULL)
5468 return (0);
5469 ASSERT(*keptp != '\0');
5470 kept = pm_name_to_dip(keptp, 1);
5471 if (kept == NULL)
5472 return (0);
5473 if (kept) {
5474 PMD(PMD_KEEPS, ("%s: keeper=%s, kept=%s\n", pmf,
5475 dp->pdr_keeper, keptp))
5476 if (pm_set_keeping(keeper, kept)) {
5477 ASSERT(dp->pdr_satisfied == 0);
5478 dp->pdr_satisfied = 1;
5479 ASSERT(pm_unresolved_deps);
5480 pm_unresolved_deps--;
5481 ret++;
5484 ddi_release_devi(kept);
5486 return (ret);
5490 * Called from common/io/pm.c
5493 pm_cur_power(pm_component_t *cp)
5495 return (cur_power(cp));
5499 * External interface to sanity-check a power level.
5502 pm_valid_power(dev_info_t *dip, int comp, int level)
5504 PMD_FUNC(pmf, "valid_power")
5506 if (comp >= 0 && comp < PM_NUMCMPTS(dip) && level >= 0)
5507 return (e_pm_valid_power(dip, comp, level));
5508 else {
5509 PMD(PMD_FAIL, ("%s: comp=%d, ncomp=%d, level=%d\n",
5510 pmf, comp, PM_NUMCMPTS(dip), level))
5511 return (0);
5516 * Called when a device that is direct power managed needs to change state.
5517 * This routine arranges to block the request until the process managing
5518 * the device makes the change (or some other incompatible change) or
5519 * the process closes /dev/pm.
5521 static int
5522 pm_block(dev_info_t *dip, int comp, int newpower, int oldpower)
5524 pm_rsvp_t *new = kmem_zalloc(sizeof (*new), KM_SLEEP);
5525 int ret = 0;
5526 void pm_dequeue_blocked(pm_rsvp_t *);
5527 void pm_enqueue_blocked(pm_rsvp_t *);
5529 ASSERT(!pm_processes_stopped);
5530 ASSERT(PM_IAM_LOCKING_DIP(dip));
5531 new->pr_dip = dip;
5532 new->pr_comp = comp;
5533 new->pr_newlevel = newpower;
5534 new->pr_oldlevel = oldpower;
5535 cv_init(&new->pr_cv, NULL, CV_DEFAULT, NULL);
5536 mutex_enter(&pm_rsvp_lock);
5537 pm_enqueue_blocked(new);
5538 pm_enqueue_notify(PSC_PENDING_CHANGE, dip, comp, newpower, oldpower,
5539 PM_CANBLOCK_BLOCK);
5540 PM_UNLOCK_DIP(dip);
5542 * truss may make the cv_wait_sig return prematurely
5544 while (ret == 0) {
5546 * Normally there will be no user context involved, but if
5547 * there is (e.g. we are here via an ioctl call to a driver)
5548 * then we should allow the process to abort the request,
5549 * or we get an unkillable process if the same thread does
5550 * PM_DIRECT_PM and pm_raise_power
5552 if (cv_wait_sig(&new->pr_cv, &pm_rsvp_lock) == 0) {
5553 ret = PMP_FAIL;
5554 } else {
5555 ret = new->pr_retval;
5558 pm_dequeue_blocked(new);
5559 mutex_exit(&pm_rsvp_lock);
5560 cv_destroy(&new->pr_cv);
5561 kmem_free(new, sizeof (*new));
5562 return (ret);
5566 * Returns true if the process is interested in power level changes (has issued
5567 * PM_GET_STATE_CHANGE ioctl).
5570 pm_interest_registered(int clone)
5572 ASSERT(clone >= 0 && clone < PM_MAX_CLONE - 1);
5573 return (pm_interest[clone]);
5576 static void pm_enqueue_pscc(pscc_t *, pscc_t **);
5579 * Process with clone has just done PM_DIRECT_PM on dip, or has asked to
5580 * watch all state transitions (dip == NULL). Set up data
5581 * structs to communicate with process about state changes.
5583 void
5584 pm_register_watcher(int clone, dev_info_t *dip)
5586 pscc_t *p;
5587 psce_t *psce;
5590 * We definitely need a control struct, then we have to search to see
5591 * there is already an entries struct (in the dip != NULL case).
5593 pscc_t *pscc = kmem_zalloc(sizeof (*pscc), KM_SLEEP);
5594 pscc->pscc_clone = clone;
5595 pscc->pscc_dip = dip;
5597 if (dip) {
5598 int found = 0;
5599 rw_enter(&pm_pscc_direct_rwlock, RW_WRITER);
5600 for (p = pm_pscc_direct; p; p = p->pscc_next) {
5602 * Already an entry for this clone, so just use it
5603 * for the new one (for the case where a single
5604 * process is watching multiple devices)
5606 if (p->pscc_clone == clone) {
5607 pscc->pscc_entries = p->pscc_entries;
5608 pscc->pscc_entries->psce_references++;
5609 found++;
5610 break;
5613 if (!found) { /* create a new one */
5614 psce = kmem_zalloc(sizeof (psce_t), KM_SLEEP);
5615 mutex_init(&psce->psce_lock, NULL, MUTEX_DEFAULT, NULL);
5616 psce->psce_first =
5617 kmem_zalloc(sizeof (pm_state_change_t) * PSCCOUNT,
5618 KM_SLEEP);
5619 psce->psce_in = psce->psce_out = psce->psce_first;
5620 psce->psce_last = &psce->psce_first[PSCCOUNT - 1];
5621 psce->psce_references = 1;
5622 pscc->pscc_entries = psce;
5624 pm_enqueue_pscc(pscc, &pm_pscc_direct);
5625 rw_exit(&pm_pscc_direct_rwlock);
5626 } else {
5627 ASSERT(!pm_interest_registered(clone));
5628 rw_enter(&pm_pscc_interest_rwlock, RW_WRITER);
5629 #ifdef DEBUG
5630 for (p = pm_pscc_interest; p; p = p->pscc_next) {
5632 * Should not be an entry for this clone!
5634 ASSERT(p->pscc_clone != clone);
5636 #endif
5637 psce = kmem_zalloc(sizeof (psce_t), KM_SLEEP);
5638 psce->psce_first = kmem_zalloc(sizeof (pm_state_change_t) *
5639 PSCCOUNT, KM_SLEEP);
5640 psce->psce_in = psce->psce_out = psce->psce_first;
5641 psce->psce_last = &psce->psce_first[PSCCOUNT - 1];
5642 psce->psce_references = 1;
5643 pscc->pscc_entries = psce;
5644 pm_enqueue_pscc(pscc, &pm_pscc_interest);
5645 pm_interest[clone] = 1;
5646 rw_exit(&pm_pscc_interest_rwlock);
5651 * Remove the given entry from the blocked list
5653 void
5654 pm_dequeue_blocked(pm_rsvp_t *p)
5656 ASSERT(MUTEX_HELD(&pm_rsvp_lock));
5657 if (pm_blocked_list == p) {
5658 ASSERT(p->pr_prev == NULL);
5659 if (p->pr_next != NULL)
5660 p->pr_next->pr_prev = NULL;
5661 pm_blocked_list = p->pr_next;
5662 } else {
5663 ASSERT(p->pr_prev != NULL);
5664 p->pr_prev->pr_next = p->pr_next;
5665 if (p->pr_next != NULL)
5666 p->pr_next->pr_prev = p->pr_prev;
5671 * Remove the given control struct from the given list
5673 static void
5674 pm_dequeue_pscc(pscc_t *p, pscc_t **list)
5676 if (*list == p) {
5677 ASSERT(p->pscc_prev == NULL);
5678 if (p->pscc_next != NULL)
5679 p->pscc_next->pscc_prev = NULL;
5680 *list = p->pscc_next;
5681 } else {
5682 ASSERT(p->pscc_prev != NULL);
5683 p->pscc_prev->pscc_next = p->pscc_next;
5684 if (p->pscc_next != NULL)
5685 p->pscc_next->pscc_prev = p->pscc_prev;
5690 * Stick the control struct specified on the front of the list
5692 static void
5693 pm_enqueue_pscc(pscc_t *p, pscc_t **list)
5695 pscc_t *h; /* entry at head of list */
5696 if ((h = *list) == NULL) {
5697 *list = p;
5698 ASSERT(p->pscc_next == NULL);
5699 ASSERT(p->pscc_prev == NULL);
5700 } else {
5701 p->pscc_next = h;
5702 ASSERT(h->pscc_prev == NULL);
5703 h->pscc_prev = p;
5704 ASSERT(p->pscc_prev == NULL);
5705 *list = p;
5710 * If dip is NULL, process is closing "clone" clean up all its registrations.
5711 * Otherwise only clean up those for dip because process is just giving up
5712 * control of a direct device.
5714 void
5715 pm_deregister_watcher(int clone, dev_info_t *dip)
5717 pscc_t *p, *pn;
5718 psce_t *psce;
5719 int found = 0;
5721 if (dip == NULL) {
5722 rw_enter(&pm_pscc_interest_rwlock, RW_WRITER);
5723 for (p = pm_pscc_interest; p; p = pn) {
5724 pn = p->pscc_next;
5725 if (p->pscc_clone == clone) {
5726 pm_dequeue_pscc(p, &pm_pscc_interest);
5727 psce = p->pscc_entries;
5728 ASSERT(psce->psce_references == 1);
5729 mutex_destroy(&psce->psce_lock);
5730 kmem_free(psce->psce_first,
5731 sizeof (pm_state_change_t) * PSCCOUNT);
5732 kmem_free(psce, sizeof (*psce));
5733 kmem_free(p, sizeof (*p));
5736 pm_interest[clone] = 0;
5737 rw_exit(&pm_pscc_interest_rwlock);
5739 found = 0;
5740 rw_enter(&pm_pscc_direct_rwlock, RW_WRITER);
5741 for (p = pm_pscc_direct; p; p = pn) {
5742 pn = p->pscc_next;
5743 if ((dip && p->pscc_dip == dip) ||
5744 (dip == NULL && clone == p->pscc_clone)) {
5745 ASSERT(clone == p->pscc_clone);
5746 found++;
5748 * Remove from control list
5750 pm_dequeue_pscc(p, &pm_pscc_direct);
5752 * If we're the last reference, free the
5753 * entries struct.
5755 psce = p->pscc_entries;
5756 ASSERT(psce);
5757 if (psce->psce_references == 1) {
5758 kmem_free(psce->psce_first,
5759 PSCCOUNT * sizeof (pm_state_change_t));
5760 kmem_free(psce, sizeof (*psce));
5761 } else {
5762 psce->psce_references--;
5764 kmem_free(p, sizeof (*p));
5767 ASSERT(dip == NULL || found);
5768 rw_exit(&pm_pscc_direct_rwlock);
5772 * Search the indicated list for an entry that matches clone, and return a
5773 * pointer to it. To be interesting, the entry must have something ready to
5774 * be passed up to the controlling process.
5775 * The returned entry will be locked upon return from this call.
5777 static psce_t *
5778 pm_psc_find_clone(int clone, pscc_t **list, krwlock_t *lock)
5780 pscc_t *p;
5781 psce_t *psce;
5782 rw_enter(lock, RW_READER);
5783 for (p = *list; p; p = p->pscc_next) {
5784 if (clone == p->pscc_clone) {
5785 psce = p->pscc_entries;
5786 mutex_enter(&psce->psce_lock);
5787 if (psce->psce_out->size) {
5788 rw_exit(lock);
5789 return (psce);
5790 } else {
5791 mutex_exit(&psce->psce_lock);
5795 rw_exit(lock);
5796 return (NULL);
5799 static psce_t *pm_psc_find_clone(int, pscc_t **, krwlock_t *);
5801 * Find an entry for a particular clone in the direct list.
5803 psce_t *
5804 pm_psc_clone_to_direct(int clone)
5806 return (pm_psc_find_clone(clone, &pm_pscc_direct,
5807 &pm_pscc_direct_rwlock));
5811 * Find an entry for a particular clone in the interest list.
5813 psce_t *
5814 pm_psc_clone_to_interest(int clone)
5816 return (pm_psc_find_clone(clone, &pm_pscc_interest,
5817 &pm_pscc_interest_rwlock));
5821 * Put the given entry at the head of the blocked list
5823 void
5824 pm_enqueue_blocked(pm_rsvp_t *p)
5826 ASSERT(MUTEX_HELD(&pm_rsvp_lock));
5827 ASSERT(p->pr_next == NULL);
5828 ASSERT(p->pr_prev == NULL);
5829 if (pm_blocked_list != NULL) {
5830 p->pr_next = pm_blocked_list;
5831 ASSERT(pm_blocked_list->pr_prev == NULL);
5832 pm_blocked_list->pr_prev = p;
5833 pm_blocked_list = p;
5834 } else {
5835 pm_blocked_list = p;
5840 * Sets every power managed device back to its default threshold
5842 void
5843 pm_all_to_default_thresholds(void)
5845 ddi_walk_devs(ddi_root_node(), pm_set_dev_thr_walk,
5846 (void *) &pm_system_idle_threshold);
5849 static int
5850 pm_set_dev_thr_walk(dev_info_t *dip, void *arg)
5852 int thr = (int)(*(int *)arg);
5854 if (!PM_GET_PM_INFO(dip))
5855 return (DDI_WALK_CONTINUE);
5856 pm_set_device_threshold(dip, thr, PMC_DEF_THRESH);
5857 return (DDI_WALK_CONTINUE);
5861 * Returns the current threshold value (in seconds) for the indicated component
5864 pm_current_threshold(dev_info_t *dip, int comp, int *threshp)
5866 if (comp < 0 || comp >= PM_NUMCMPTS(dip)) {
5867 return (DDI_FAILURE);
5868 } else {
5869 *threshp = cur_threshold(dip, comp);
5870 return (DDI_SUCCESS);
5875 * To be called when changing the power level of a component of a device.
5876 * On some platforms, changing power on one device may require that power
5877 * be changed on other, related devices in the same transaction. Thus, we
5878 * always pass this request to the platform power manager so that all the
5879 * affected devices will be locked.
5881 void
5882 pm_lock_power(dev_info_t *dip, int *circp)
5884 power_req_t power_req;
5885 int result;
5887 power_req.request_type = PMR_PPM_LOCK_POWER;
5888 power_req.req.ppm_lock_power_req.who = dip;
5889 power_req.req.ppm_lock_power_req.circp = circp;
5890 (void) pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER, &power_req, &result);
5894 * Release the lock (or locks) acquired to change the power of a device.
5895 * See comments for pm_lock_power.
5897 void
5898 pm_unlock_power(dev_info_t *dip, int circ)
5900 power_req_t power_req;
5901 int result;
5903 power_req.request_type = PMR_PPM_UNLOCK_POWER;
5904 power_req.req.ppm_unlock_power_req.who = dip;
5905 power_req.req.ppm_unlock_power_req.circ = circ;
5906 (void) pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER, &power_req, &result);
5911 * Attempt (without blocking) to acquire the lock(s) needed to change the
5912 * power of a component of a device. See comments for pm_lock_power.
5914 * Return: 1 if lock(s) acquired, 0 if not.
5917 pm_try_locking_power(dev_info_t *dip, int *circp)
5919 power_req_t power_req;
5920 int result;
5922 power_req.request_type = PMR_PPM_TRY_LOCK_POWER;
5923 power_req.req.ppm_lock_power_req.who = dip;
5924 power_req.req.ppm_lock_power_req.circp = circp;
5925 (void) pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER, &power_req, &result);
5926 return (result);
5931 * Lock power state of a device.
5933 * The implementation handles a special case where another thread may have
5934 * acquired the lock and created/launched this thread to do the work. If
5935 * the lock cannot be acquired immediately, we check to see if this thread
5936 * is registered as a borrower of the lock. If so, we may proceed without
5937 * the lock. This assumes that the lending thread blocks on the completion
5938 * of this thread.
5940 * Note 1: for use by ppm only.
5942 * Note 2: On failing to get the lock immediately, we search lock_loan list
5943 * for curthread (as borrower of the lock). On a hit, we check that the
5944 * lending thread already owns the lock we want. It is safe to compare
5945 * devi_busy_thread and thread id of the lender because in the == case (the
5946 * only one we care about) we know that the owner is blocked. Similarly,
5947 * If we find that curthread isn't registered as a lock borrower, it is safe
5948 * to use the blocking call (ndi_devi_enter) because we know that if we
5949 * weren't already listed as a borrower (upstream on the call stack) we won't
5950 * become one.
5952 void
5953 pm_lock_power_single(dev_info_t *dip, int *circp)
5955 lock_loan_t *cur;
5957 /* if the lock is available, we are done. */
5958 if (ndi_devi_tryenter(dip, circp))
5959 return;
5961 mutex_enter(&pm_loan_lock);
5962 /* see if our thread is registered as a lock borrower. */
5963 for (cur = lock_loan_head.pmlk_next; cur; cur = cur->pmlk_next)
5964 if (cur->pmlk_borrower == curthread)
5965 break;
5966 mutex_exit(&pm_loan_lock);
5968 /* if this thread not already registered, it is safe to block */
5969 if (cur == NULL)
5970 ndi_devi_enter(dip, circp);
5971 else {
5972 /* registered: does lender own the lock we want? */
5973 if (cur->pmlk_lender == DEVI(dip)->devi_busy_thread) {
5974 ASSERT(cur->pmlk_dip == NULL || cur->pmlk_dip == dip);
5975 cur->pmlk_dip = dip;
5976 } else /* no: just block for it */
5977 ndi_devi_enter(dip, circp);
5983 * Drop the lock on the device's power state. See comment for
5984 * pm_lock_power_single() for special implementation considerations.
5986 * Note: for use by ppm only.
5988 void
5989 pm_unlock_power_single(dev_info_t *dip, int circ)
5991 lock_loan_t *cur;
5993 /* optimization: mutex not needed to check empty list */
5994 if (lock_loan_head.pmlk_next == NULL) {
5995 ndi_devi_exit(dip, circ);
5996 return;
5999 mutex_enter(&pm_loan_lock);
6000 /* see if our thread is registered as a lock borrower. */
6001 for (cur = lock_loan_head.pmlk_next; cur; cur = cur->pmlk_next)
6002 if (cur->pmlk_borrower == curthread)
6003 break;
6004 mutex_exit(&pm_loan_lock);
6006 if (cur == NULL || cur->pmlk_dip != dip)
6007 /* we acquired the lock directly, so return it */
6008 ndi_devi_exit(dip, circ);
6012 * Try to take the lock for changing the power level of a component.
6014 * Note: for use by ppm only.
6017 pm_try_locking_power_single(dev_info_t *dip, int *circp)
6019 return (ndi_devi_tryenter(dip, circp));
6022 #ifdef DEBUG
6024 * The following are used only to print out data structures for debugging
6026 void
6027 prdeps(char *msg)
6030 pm_pdr_t *rp;
6031 int i;
6033 pm_log("pm_dep_head %s %p\n", msg, (void *)pm_dep_head);
6034 for (rp = pm_dep_head; rp; rp = rp->pdr_next) {
6035 pm_log("%p: %s keeper %s, kept %s, kept count %d, next %p\n",
6036 (void *)rp, (rp->pdr_isprop ? "property" : "device"),
6037 rp->pdr_keeper, rp->pdr_kept, rp->pdr_kept_count,
6038 (void *)rp->pdr_next);
6039 if (rp->pdr_kept_count != 0) {
6040 pm_log("kept list = ");
6041 i = 0;
6042 while (i < rp->pdr_kept_count) {
6043 pm_log("%s ", rp->pdr_kept_paths[i]);
6044 i++;
6046 pm_log("\n");
6051 void
6052 pr_noinvol(char *hdr)
6054 pm_noinvol_t *ip;
6056 pm_log("%s\n", hdr);
6057 rw_enter(&pm_noinvol_rwlock, RW_READER);
6058 for (ip = pm_noinvol_head; ip; ip = ip->ni_next)
6059 pm_log("\tmaj %d, flags %x, noinvolpm %d %s\n",
6060 ip->ni_major, ip->ni_flags, ip->ni_noinvolpm, ip->ni_path);
6061 rw_exit(&pm_noinvol_rwlock);
6063 #endif
6066 * Attempt to apply the thresholds indicated by rp to the node specified by
6067 * dip.
6069 void
6070 pm_apply_recorded_thresh(dev_info_t *dip, pm_thresh_rec_t *rp)
6072 PMD_FUNC(pmf, "apply_recorded_thresh")
6073 int i, j;
6074 int comps = PM_NUMCMPTS(dip);
6075 struct pm_component *cp;
6076 pm_pte_t *ep;
6077 int pm_valid_thresh(dev_info_t *, pm_thresh_rec_t *);
6079 PMD(PMD_THRESH, ("%s: part: %s@%s(%s#%d), rp %p, %s\n", pmf,
6080 PM_DEVICE(dip), (void *)rp, rp->ptr_physpath))
6081 PM_LOCK_DIP(dip);
6082 if (!PM_GET_PM_INFO(dip) || PM_ISBC(dip) || !pm_valid_thresh(dip, rp)) {
6083 PMD(PMD_FAIL, ("%s: part: %s@%s(%s#%d) PM_GET_PM_INFO %p\n",
6084 pmf, PM_DEVICE(dip), (void*)PM_GET_PM_INFO(dip)))
6085 PMD(PMD_FAIL, ("%s: part: %s@%s(%s#%d) PM_ISBC %d\n",
6086 pmf, PM_DEVICE(dip), PM_ISBC(dip)))
6087 PMD(PMD_FAIL, ("%s: part: %s@%s(%s#%d) pm_valid_thresh %d\n",
6088 pmf, PM_DEVICE(dip), pm_valid_thresh(dip, rp)))
6089 PM_UNLOCK_DIP(dip);
6090 return;
6093 ep = rp->ptr_entries;
6095 * Here we do the special case of a device threshold
6097 if (rp->ptr_numcomps == 0) { /* PM_SET_DEVICE_THRESHOLD product */
6098 ASSERT(ep && ep->pte_numthresh == 1);
6099 PMD(PMD_THRESH, ("%s: set dev thr %s@%s(%s#%d) to 0x%x\n",
6100 pmf, PM_DEVICE(dip), ep->pte_thresh[0]))
6101 PM_UNLOCK_DIP(dip);
6102 pm_set_device_threshold(dip, ep->pte_thresh[0], PMC_DEV_THRESH);
6103 if (PM_SCANABLE(dip))
6104 pm_rescan(dip);
6105 return;
6107 for (i = 0; i < comps; i++) {
6108 cp = PM_CP(dip, i);
6109 for (j = 0; j < ep->pte_numthresh; j++) {
6110 PMD(PMD_THRESH, ("%s: set thr %d for %s@%s(%s#%d)[%d] "
6111 "to %x\n", pmf, j, PM_DEVICE(dip),
6112 i, ep->pte_thresh[j]))
6113 cp->pmc_comp.pmc_thresh[j + 1] = ep->pte_thresh[j];
6115 ep++;
6117 DEVI(dip)->devi_pm_flags &= PMC_THRESH_NONE;
6118 DEVI(dip)->devi_pm_flags |= PMC_COMP_THRESH;
6119 PM_UNLOCK_DIP(dip);
6121 if (PM_SCANABLE(dip))
6122 pm_rescan(dip);
6126 * Returns true if the threshold specified by rp could be applied to dip
6127 * (that is, the number of components and transitions are the same)
6130 pm_valid_thresh(dev_info_t *dip, pm_thresh_rec_t *rp)
6132 PMD_FUNC(pmf, "valid_thresh")
6133 int comps, i;
6134 pm_component_t *cp;
6135 pm_pte_t *ep;
6137 if (!PM_GET_PM_INFO(dip) || PM_ISBC(dip)) {
6138 PMD(PMD_ERROR, ("%s: %s: no pm_info or BC\n", pmf,
6139 rp->ptr_physpath))
6140 return (0);
6143 * Special case: we represent the PM_SET_DEVICE_THRESHOLD case by
6144 * an entry with numcomps == 0, (since we don't know how many
6145 * components there are in advance). This is always a valid
6146 * spec.
6148 if (rp->ptr_numcomps == 0) {
6149 ASSERT(rp->ptr_entries && rp->ptr_entries->pte_numthresh == 1);
6150 return (1);
6152 if (rp->ptr_numcomps != (comps = PM_NUMCMPTS(dip))) {
6153 PMD(PMD_ERROR, ("%s: comp # mm (dip %d cmd %d) for %s\n",
6154 pmf, PM_NUMCMPTS(dip), rp->ptr_numcomps, rp->ptr_physpath))
6155 return (0);
6157 ep = rp->ptr_entries;
6158 for (i = 0; i < comps; i++) {
6159 cp = PM_CP(dip, i);
6160 if ((ep + i)->pte_numthresh !=
6161 cp->pmc_comp.pmc_numlevels - 1) {
6162 PMD(PMD_ERROR, ("%s: %s[%d]: thresh=%d, record=%d\n",
6163 pmf, rp->ptr_physpath, i,
6164 cp->pmc_comp.pmc_numlevels - 1,
6165 (ep + i)->pte_numthresh))
6166 return (0);
6169 return (1);
6173 * Remove any recorded threshold for device physpath
6174 * We know there will be at most one.
6176 void
6177 pm_unrecord_threshold(char *physpath)
6179 pm_thresh_rec_t *pptr, *ptr;
6181 rw_enter(&pm_thresh_rwlock, RW_WRITER);
6182 for (pptr = NULL, ptr = pm_thresh_head; ptr; ptr = ptr->ptr_next) {
6183 if (strcmp(physpath, ptr->ptr_physpath) == 0) {
6184 if (pptr) {
6185 pptr->ptr_next = ptr->ptr_next;
6186 } else {
6187 ASSERT(pm_thresh_head == ptr);
6188 pm_thresh_head = ptr->ptr_next;
6190 kmem_free(ptr, ptr->ptr_size);
6191 break;
6193 pptr = ptr;
6195 rw_exit(&pm_thresh_rwlock);
6199 * Discard all recorded thresholds. We are returning to the default pm state.
6201 void
6202 pm_discard_thresholds(void)
6204 pm_thresh_rec_t *rp;
6205 rw_enter(&pm_thresh_rwlock, RW_WRITER);
6206 while (pm_thresh_head) {
6207 rp = pm_thresh_head;
6208 pm_thresh_head = rp->ptr_next;
6209 kmem_free(rp, rp->ptr_size);
6211 rw_exit(&pm_thresh_rwlock);
6215 * Discard all recorded dependencies. We are returning to the default pm state.
6217 void
6218 pm_discard_dependencies(void)
6220 pm_pdr_t *rp;
6221 int i;
6222 size_t length;
6224 #ifdef DEBUG
6225 if (pm_debug & PMD_DEP)
6226 prdeps("Before discard\n");
6227 #endif
6228 ddi_walk_devs(ddi_root_node(), pm_discard_dep_walk, NULL);
6230 #ifdef DEBUG
6231 if (pm_debug & PMD_DEP)
6232 prdeps("After discard\n");
6233 #endif
6234 while (pm_dep_head) {
6235 rp = pm_dep_head;
6236 if (!rp->pdr_isprop) {
6237 ASSERT(rp->pdr_satisfied == 0);
6238 ASSERT(pm_unresolved_deps);
6239 pm_unresolved_deps--;
6240 } else {
6241 ASSERT(pm_prop_deps);
6242 pm_prop_deps--;
6244 pm_dep_head = rp->pdr_next;
6245 if (rp->pdr_kept_count) {
6246 for (i = 0; i < rp->pdr_kept_count; i++) {
6247 length = strlen(rp->pdr_kept_paths[i]) + 1;
6248 kmem_free(rp->pdr_kept_paths[i], length);
6250 kmem_free(rp->pdr_kept_paths,
6251 rp->pdr_kept_count * sizeof (char **));
6253 kmem_free(rp, rp->pdr_size);
6258 static int
6259 pm_discard_dep_walk(dev_info_t *dip, void *arg)
6261 _NOTE(ARGUNUSED(arg))
6262 char *pathbuf;
6264 if (PM_GET_PM_INFO(dip) == NULL)
6265 return (DDI_WALK_CONTINUE);
6266 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
6267 (void) ddi_pathname(dip, pathbuf);
6268 pm_free_keeper(pathbuf, 0);
6269 kmem_free(pathbuf, MAXPATHLEN);
6270 return (DDI_WALK_CONTINUE);
6273 static int
6274 pm_kept_walk(dev_info_t *dip, void *arg)
6276 _NOTE(ARGUNUSED(arg))
6277 char *pathbuf;
6279 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
6280 (void) ddi_pathname(dip, pathbuf);
6281 (void) pm_kept(pathbuf);
6282 kmem_free(pathbuf, MAXPATHLEN);
6284 return (DDI_WALK_CONTINUE);
6287 static int
6288 pm_keeper_walk(dev_info_t *dip, void *arg)
6290 _NOTE(ARGUNUSED(arg))
6291 char *pathbuf;
6293 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
6294 (void) ddi_pathname(dip, pathbuf);
6295 (void) pm_keeper(pathbuf);
6296 kmem_free(pathbuf, MAXPATHLEN);
6298 return (DDI_WALK_CONTINUE);
6301 static char *
6302 pdw_type_decode(int type)
6304 switch (type) {
6305 case PM_DEP_WK_POWER_ON:
6306 return ("power on");
6307 case PM_DEP_WK_POWER_OFF:
6308 return ("power off");
6309 case PM_DEP_WK_DETACH:
6310 return ("detach");
6311 case PM_DEP_WK_REMOVE_DEP:
6312 return ("remove dep");
6313 case PM_DEP_WK_BRINGUP_SELF:
6314 return ("bringup self");
6315 case PM_DEP_WK_RECORD_KEEPER:
6316 return ("add dependent");
6317 case PM_DEP_WK_RECORD_KEEPER_PROP:
6318 return ("add dependent property");
6319 case PM_DEP_WK_KEPT:
6320 return ("kept");
6321 case PM_DEP_WK_KEEPER:
6322 return ("keeper");
6323 case PM_DEP_WK_ATTACH:
6324 return ("attach");
6325 case PM_DEP_WK_CHECK_KEPT:
6326 return ("check kept");
6327 case PM_DEP_WK_CPR_SUSPEND:
6328 return ("suspend");
6329 case PM_DEP_WK_CPR_RESUME:
6330 return ("resume");
6331 default:
6332 return ("unknown");
6337 static void
6338 pm_rele_dep(char *keeper)
6340 PMD_FUNC(pmf, "rele_dep")
6341 pm_pdr_t *dp;
6342 char *kept_path = NULL;
6343 dev_info_t *kept = NULL;
6344 int count = 0;
6346 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
6347 if (strcmp(dp->pdr_keeper, keeper) != 0)
6348 continue;
6349 for (count = 0; count < dp->pdr_kept_count; count++) {
6350 kept_path = dp->pdr_kept_paths[count];
6351 if (kept_path == NULL)
6352 continue;
6353 kept = pm_name_to_dip(kept_path, 1);
6354 if (kept) {
6355 PMD(PMD_KEEPS, ("%s: release kept=%s@%s(%s#%d) "
6356 "of keeper=%s\n", pmf, PM_DEVICE(kept),
6357 keeper))
6358 ASSERT(DEVI(kept)->devi_pm_kidsupcnt > 0);
6359 pm_rele_power(kept);
6360 ddi_release_devi(kept);
6367 * Called when we are just released from direct PM. Bring ourself up
6368 * if our keeper is up since dependency is not honored while a kept
6369 * device is under direct PM.
6371 static void
6372 pm_bring_self_up(char *keptpath)
6374 PMD_FUNC(pmf, "bring_self_up")
6375 dev_info_t *kept;
6376 dev_info_t *keeper;
6377 pm_pdr_t *dp;
6378 int i, j;
6379 int up = 0, circ;
6381 kept = pm_name_to_dip(keptpath, 1);
6382 if (kept == NULL)
6383 return;
6384 PMD(PMD_KEEPS, ("%s: kept=%s@%s(%s#%d)\n", pmf, PM_DEVICE(kept)))
6385 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
6386 if (dp->pdr_kept_count == 0)
6387 continue;
6388 for (i = 0; i < dp->pdr_kept_count; i++) {
6389 if (strcmp(dp->pdr_kept_paths[i], keptpath) != 0)
6390 continue;
6391 keeper = pm_name_to_dip(dp->pdr_keeper, 1);
6392 if (keeper) {
6393 PMD(PMD_KEEPS, ("%s: keeper=%s@%s(%s#%d)\n",
6394 pmf, PM_DEVICE(keeper)))
6395 PM_LOCK_POWER(keeper, &circ);
6396 for (j = 0; j < PM_NUMCMPTS(keeper);
6397 j++) {
6398 if (PM_CURPOWER(keeper, j)) {
6399 PMD(PMD_KEEPS, ("%s: comp="
6400 "%d is up\n", pmf, j))
6401 up++;
6404 if (up) {
6405 if (PM_SKBU(kept))
6406 DEVI(kept)->devi_pm_flags &=
6407 ~PMC_SKIP_BRINGUP;
6408 bring_pmdep_up(kept, 1);
6410 PM_UNLOCK_POWER(keeper, circ);
6411 ddi_release_devi(keeper);
6415 ddi_release_devi(kept);
6418 static void
6419 pm_process_dep_request(pm_dep_wk_t *work)
6421 PMD_FUNC(pmf, "dep_req")
6422 int ret;
6424 PMD(PMD_DEP, ("%s: work=%s\n", pmf,
6425 pdw_type_decode(work->pdw_type)))
6426 PMD(PMD_DEP, ("%s: keeper=%s, kept=%s\n", pmf,
6427 (work->pdw_keeper ? work->pdw_keeper : "NULL"),
6428 (work->pdw_kept ? work->pdw_kept : "NULL")))
6430 switch (work->pdw_type) {
6431 case PM_DEP_WK_POWER_ON:
6432 /* Bring up the kept devices and put a hold on them */
6433 bring_wekeeps_up(work->pdw_keeper);
6434 break;
6435 case PM_DEP_WK_POWER_OFF:
6436 /* Release the kept devices */
6437 pm_rele_dep(work->pdw_keeper);
6438 break;
6439 case PM_DEP_WK_DETACH:
6440 pm_free_keeps(work->pdw_keeper, work->pdw_pwr);
6441 break;
6442 case PM_DEP_WK_REMOVE_DEP:
6443 pm_discard_dependencies();
6444 break;
6445 case PM_DEP_WK_BRINGUP_SELF:
6447 * We deferred satisfying our dependency till now, so satisfy
6448 * it again and bring ourselves up.
6450 pm_bring_self_up(work->pdw_kept);
6451 break;
6452 case PM_DEP_WK_RECORD_KEEPER:
6453 (void) pm_record_keeper(work->pdw_kept, work->pdw_keeper, 0);
6454 ddi_walk_devs(ddi_root_node(), pm_kept_walk, NULL);
6455 ddi_walk_devs(ddi_root_node(), pm_keeper_walk, NULL);
6456 break;
6457 case PM_DEP_WK_RECORD_KEEPER_PROP:
6458 (void) pm_record_keeper(work->pdw_kept, work->pdw_keeper, 1);
6459 ddi_walk_devs(ddi_root_node(), pm_keeper_walk, NULL);
6460 ddi_walk_devs(ddi_root_node(), pm_kept_walk, NULL);
6461 break;
6462 case PM_DEP_WK_KEPT:
6463 ret = pm_kept(work->pdw_kept);
6464 PMD(PMD_DEP, ("%s: PM_DEP_WK_KEPT: pm_kept returns %d\n", pmf,
6465 ret))
6466 break;
6467 case PM_DEP_WK_KEEPER:
6468 ret = pm_keeper(work->pdw_keeper);
6469 PMD(PMD_DEP, ("%s: PM_DEP_WK_KEEPER: pm_keeper returns %d\n",
6470 pmf, ret))
6471 break;
6472 case PM_DEP_WK_ATTACH:
6473 ret = pm_keeper(work->pdw_keeper);
6474 PMD(PMD_DEP, ("%s: PM_DEP_WK_ATTACH: pm_keeper returns %d\n",
6475 pmf, ret))
6476 ret = pm_kept(work->pdw_kept);
6477 PMD(PMD_DEP, ("%s: PM_DEP_WK_ATTACH: pm_kept returns %d\n",
6478 pmf, ret))
6479 break;
6480 case PM_DEP_WK_CHECK_KEPT:
6481 ret = pm_is_kept(work->pdw_kept);
6482 PMD(PMD_DEP, ("%s: PM_DEP_WK_CHECK_KEPT: kept=%s, ret=%d\n",
6483 pmf, work->pdw_kept, ret))
6484 break;
6485 case PM_DEP_WK_CPR_SUSPEND:
6486 pm_discard_dependencies();
6487 break;
6488 case PM_DEP_WK_CPR_RESUME:
6489 ddi_walk_devs(ddi_root_node(), pm_kept_walk, NULL);
6490 ddi_walk_devs(ddi_root_node(), pm_keeper_walk, NULL);
6491 break;
6492 default:
6493 ASSERT(0);
6494 break;
6497 * Free the work structure if the requester is not waiting
6498 * Otherwise it is the requester's responsiblity to free it.
6500 if (!work->pdw_wait) {
6501 if (work->pdw_keeper)
6502 kmem_free(work->pdw_keeper,
6503 strlen(work->pdw_keeper) + 1);
6504 if (work->pdw_kept)
6505 kmem_free(work->pdw_kept, strlen(work->pdw_kept) + 1);
6506 kmem_free(work, sizeof (pm_dep_wk_t));
6507 } else {
6509 * Notify requester if it is waiting for it.
6511 work->pdw_ret = ret;
6512 work->pdw_done = 1;
6513 cv_signal(&work->pdw_cv);
6518 * Process PM dependency requests.
6520 static void
6521 pm_dep_thread(void)
6523 pm_dep_wk_t *work;
6524 callb_cpr_t cprinfo;
6526 CALLB_CPR_INIT(&cprinfo, &pm_dep_thread_lock, callb_generic_cpr,
6527 "pm_dep_thread");
6528 for (;;) {
6529 mutex_enter(&pm_dep_thread_lock);
6530 if (pm_dep_thread_workq == NULL) {
6531 CALLB_CPR_SAFE_BEGIN(&cprinfo);
6532 cv_wait(&pm_dep_thread_cv, &pm_dep_thread_lock);
6533 CALLB_CPR_SAFE_END(&cprinfo, &pm_dep_thread_lock);
6535 work = pm_dep_thread_workq;
6536 pm_dep_thread_workq = work->pdw_next;
6537 if (pm_dep_thread_tail == work)
6538 pm_dep_thread_tail = work->pdw_next;
6539 mutex_exit(&pm_dep_thread_lock);
6540 pm_process_dep_request(work);
6543 /*NOTREACHED*/
6547 * Set the power level of the indicated device to unknown (if it is not a
6548 * backwards compatible device), as it has just been resumed, and it won't
6549 * know if the power was removed or not. Adjust parent's kidsupcnt if necessary.
6551 void
6552 pm_forget_power_level(dev_info_t *dip)
6554 dev_info_t *pdip = ddi_get_parent(dip);
6555 int i, count = 0;
6557 if (!PM_ISBC(dip)) {
6558 for (i = 0; i < PM_NUMCMPTS(dip); i++)
6559 count += (PM_CURPOWER(dip, i) == 0);
6561 if (count && pdip && !PM_WANTS_NOTIFICATION(pdip))
6562 e_pm_hold_rele_power(pdip, count);
6565 * Count this as a power cycle if we care
6567 if (DEVI(dip)->devi_pm_volpmd &&
6568 PM_CP(dip, 0)->pmc_cur_pwr == 0)
6569 DEVI(dip)->devi_pm_volpmd = 0;
6570 for (i = 0; i < PM_NUMCMPTS(dip); i++)
6571 e_pm_set_cur_pwr(dip, PM_CP(dip, i), PM_LEVEL_UNKNOWN);
6576 * This function advises the caller whether it should make a power-off
6577 * transition at this time or not. If the transition is not advised
6578 * at this time, the time that the next power-off transition can
6579 * be made from now is returned through "intervalp" pointer.
6580 * This function returns:
6582 * 1 power-off advised
6583 * 0 power-off not advised, intervalp will point to seconds from
6584 * now that a power-off is advised. If it is passed the number
6585 * of years that policy specifies the device should last,
6586 * a large number is returned as the time interval.
6587 * -1 error
6590 pm_trans_check(struct pm_trans_data *datap, time_t *intervalp)
6592 PMD_FUNC(pmf, "pm_trans_check")
6593 char dbuf[DC_SCSI_MFR_LEN];
6594 struct pm_scsi_cycles *scp;
6595 int service_years, service_weeks, full_years;
6596 time_t now, service_seconds, tdiff;
6597 time_t within_year, when_allowed;
6598 char *ptr;
6599 int lower_bound_cycles, upper_bound_cycles, cycles_allowed;
6600 int cycles_diff, cycles_over;
6601 struct pm_smart_count *smart_p;
6603 if (datap == NULL) {
6604 PMD(PMD_TCHECK, ("%s: NULL data pointer!\n", pmf))
6605 return (-1);
6608 if (datap->format == DC_SCSI_FORMAT) {
6610 * Power cycles of the scsi drives are distributed
6611 * over 5 years with the following percentage ratio:
6613 * 30%, 25%, 20%, 15%, and 10%
6615 * The power cycle quota for each year is distributed
6616 * linearly through out the year. The equation for
6617 * determining the expected cycles is:
6619 * e = a * (n / y)
6621 * e = expected cycles
6622 * a = allocated cycles for this year
6623 * n = number of seconds since beginning of this year
6624 * y = number of seconds in a year
6626 * Note that beginning of the year starts the day that
6627 * the drive has been put on service.
6629 * If the drive has passed its expected cycles, we
6630 * can determine when it can start to power cycle
6631 * again to keep it on track to meet the 5-year
6632 * life expectancy. The equation for determining
6633 * when to power cycle is:
6635 * w = y * (c / a)
6637 * w = when it can power cycle again
6638 * y = number of seconds in a year
6639 * c = current number of cycles
6640 * a = allocated cycles for the year
6643 char pcnt[DC_SCSI_NPY] = { 30, 55, 75, 90, 100 };
6645 scp = &datap->un.scsi_cycles;
6646 PMD(PMD_TCHECK, ("%s: format=%d, lifemax=%d, ncycles=%d, "
6647 "svc_date=%s, svc_flag=%d\n", pmf, datap->format,
6648 scp->lifemax, scp->ncycles, scp->svc_date, scp->flag))
6649 if (scp->ncycles < 0 || scp->flag != 0) {
6650 PMD(PMD_TCHECK, ("%s: ncycles < 0 || flag != 0\n", pmf))
6651 return (-1);
6654 if (scp->ncycles > scp->lifemax) {
6655 *intervalp = (LONG_MAX / hz);
6656 return (0);
6660 * convert service date to time_t
6662 bcopy(scp->svc_date, dbuf, DC_SCSI_YEAR_LEN);
6663 dbuf[DC_SCSI_YEAR_LEN] = '\0';
6664 ptr = dbuf;
6665 service_years = stoi(&ptr) - EPOCH_YEAR;
6666 bcopy(&scp->svc_date[DC_SCSI_YEAR_LEN], dbuf,
6667 DC_SCSI_WEEK_LEN);
6668 dbuf[DC_SCSI_WEEK_LEN] = '\0';
6671 * scsi standard does not specify WW data,
6672 * could be (00-51) or (01-52)
6674 ptr = dbuf;
6675 service_weeks = stoi(&ptr);
6676 if (service_years < 0 ||
6677 service_weeks < 0 || service_weeks > 52) {
6678 PMD(PMD_TCHECK, ("%s: service year %d and week %d\n",
6679 pmf, service_years, service_weeks))
6680 return (-1);
6684 * calculate service date in seconds-since-epoch,
6685 * adding one day for each leap-year.
6687 * (years-since-epoch + 2) fixes integer truncation,
6688 * example: (8) leap-years during [1972, 2000]
6689 * (2000 - 1970) = 30; and (30 + 2) / 4 = 8;
6691 service_seconds = (service_years * DC_SPY) +
6692 (service_weeks * DC_SPW) +
6693 (((service_years + 2) / 4) * DC_SPD);
6695 now = gethrestime_sec();
6697 * since the granularity of 'svc_date' is day not second,
6698 * 'now' should be rounded up to full day.
6700 now = ((now + DC_SPD -1) / DC_SPD) * DC_SPD;
6701 if (service_seconds > now) {
6702 PMD(PMD_TCHECK, ("%s: service date (%ld) later "
6703 "than now (%ld)!\n", pmf, service_seconds, now))
6704 return (-1);
6707 tdiff = now - service_seconds;
6708 PMD(PMD_TCHECK, ("%s: age is %ld sec\n", pmf, tdiff))
6711 * NOTE - Leap years are not considered in the calculations
6712 * below.
6714 full_years = (tdiff / DC_SPY);
6715 if ((full_years >= DC_SCSI_NPY) &&
6716 (scp->ncycles <= scp->lifemax))
6717 return (1);
6720 * Determine what is the normal cycle usage for the
6721 * device at the beginning and the end of this year.
6723 lower_bound_cycles = (!full_years) ? 0 :
6724 ((scp->lifemax * pcnt[full_years - 1]) / 100);
6725 upper_bound_cycles = (scp->lifemax * pcnt[full_years]) / 100;
6727 if (scp->ncycles <= lower_bound_cycles)
6728 return (1);
6731 * The linear slope that determines how many cycles
6732 * are allowed this year is number of seconds
6733 * passed this year over total number of seconds in a year.
6735 cycles_diff = (upper_bound_cycles - lower_bound_cycles);
6736 within_year = (tdiff % DC_SPY);
6737 cycles_allowed = lower_bound_cycles +
6738 (((uint64_t)cycles_diff * (uint64_t)within_year) / DC_SPY);
6739 PMD(PMD_TCHECK, ("%s: lived %d yrs and %ld secs\n", pmf,
6740 full_years, within_year))
6741 PMD(PMD_TCHECK, ("%s: # of cycles allowed %d\n", pmf,
6742 cycles_allowed))
6744 if (scp->ncycles <= cycles_allowed)
6745 return (1);
6748 * The transition is not advised now but we can
6749 * determine when the next transition can be made.
6751 * Depending on how many cycles the device has been
6752 * over-used, we may need to skip years with
6753 * different percentage quota in order to determine
6754 * when the next transition can be made.
6756 cycles_over = (scp->ncycles - lower_bound_cycles);
6757 while (cycles_over > cycles_diff) {
6758 full_years++;
6759 if (full_years >= DC_SCSI_NPY) {
6760 *intervalp = (LONG_MAX / hz);
6761 return (0);
6763 cycles_over -= cycles_diff;
6764 lower_bound_cycles = upper_bound_cycles;
6765 upper_bound_cycles =
6766 (scp->lifemax * pcnt[full_years]) / 100;
6767 cycles_diff = (upper_bound_cycles - lower_bound_cycles);
6771 * The linear slope that determines when the next transition
6772 * can be made is the relative position of used cycles within a
6773 * year over total number of cycles within that year.
6775 when_allowed = service_seconds + (full_years * DC_SPY) +
6776 (((uint64_t)DC_SPY * (uint64_t)cycles_over) / cycles_diff);
6777 *intervalp = (when_allowed - now);
6778 if (*intervalp > (LONG_MAX / hz))
6779 *intervalp = (LONG_MAX / hz);
6780 PMD(PMD_TCHECK, ("%s: no cycle is allowed in %ld secs\n", pmf,
6781 *intervalp))
6782 return (0);
6783 } else if (datap->format == DC_SMART_FORMAT) {
6785 * power cycles of SATA disks are reported from SMART
6786 * attributes.
6788 smart_p = &datap->un.smart_count;
6789 if (smart_p->consumed >= smart_p->allowed) {
6790 *intervalp = (LONG_MAX / hz);
6791 PMD(PMD_TCHECK, ("%s: exceeded lifemax cycles.\n", pmf))
6792 return (0);
6793 } else
6794 return (1);
6797 PMD(PMD_TCHECK, ("%s: unknown format!\n", pmf))
6798 return (-1);
6802 * Nexus drivers call into pm framework to indicate which child driver is about
6803 * to be installed. In some platforms, ppm may need to configure the hardware
6804 * for successful installation of a driver.
6807 pm_init_child(dev_info_t *dip)
6809 power_req_t power_req;
6811 ASSERT(ddi_binding_name(dip));
6812 ASSERT(ddi_get_name_addr(dip));
6813 pm_ppm_claim(dip);
6814 if (pm_ppm_claimed(dip)) { /* if ppm driver claims the node */
6815 power_req.request_type = PMR_PPM_INIT_CHILD;
6816 power_req.req.ppm_config_req.who = dip;
6817 ASSERT(PPM(dip) != NULL);
6818 return (pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER, &power_req,
6819 NULL));
6820 } else {
6821 #ifdef DEBUG
6822 /* pass it to the default handler so we can debug things */
6823 power_req.request_type = PMR_PPM_INIT_CHILD;
6824 power_req.req.ppm_config_req.who = dip;
6825 (void) pm_ctlops(NULL, dip,
6826 DDI_CTLOPS_POWER, &power_req, NULL);
6827 #endif
6829 return (DDI_SUCCESS);
6833 * Bring parent of a node that is about to be probed up to full power, and
6834 * arrange for it to stay up until pm_post_probe() or pm_post_attach() decide
6835 * it is time to let it go down again
6837 void
6838 pm_pre_probe(dev_info_t *dip, pm_ppm_cookie_t *cp)
6840 int result;
6841 power_req_t power_req;
6843 bzero(cp, sizeof (*cp));
6844 cp->ppc_dip = dip;
6846 pm_ppm_claim(dip);
6847 if (pm_ppm_claimed(dip)) { /* if ppm driver claims the node */
6848 power_req.request_type = PMR_PPM_PRE_PROBE;
6849 power_req.req.ppm_config_req.who = dip;
6850 ASSERT(PPM(dip) != NULL);
6851 (void) pm_ctlops(PPM(dip), dip,
6852 DDI_CTLOPS_POWER, &power_req, &result);
6853 cp->ppc_ppm = PPM(dip);
6854 } else {
6855 #ifdef DEBUG
6856 /* pass it to the default handler so we can debug things */
6857 power_req.request_type = PMR_PPM_PRE_PROBE;
6858 power_req.req.ppm_config_req.who = dip;
6859 (void) pm_ctlops(NULL, dip,
6860 DDI_CTLOPS_POWER, &power_req, &result);
6861 #endif
6862 cp->ppc_ppm = NULL;
6867 pm_pre_config(dev_info_t *dip, char *devnm)
6869 PMD_FUNC(pmf, "pre_config")
6870 int ret;
6872 if (MDI_VHCI(dip)) {
6873 PMD(PMD_SET, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
6874 ret = mdi_power(dip, MDI_PM_PRE_CONFIG, NULL, devnm, 0);
6875 return (ret == MDI_SUCCESS ? DDI_SUCCESS : DDI_FAILURE);
6876 } else if (!PM_GET_PM_INFO(dip))
6877 return (DDI_SUCCESS);
6879 PMD(PMD_SET, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
6880 pm_hold_power(dip);
6881 ret = pm_all_to_normal(dip, PM_CANBLOCK_BLOCK);
6882 if (ret != DDI_SUCCESS)
6883 pm_rele_power(dip);
6884 return (ret);
6888 * This routine is called by devfs during its walk to unconfigue a node.
6889 * If the call is due to auto mod_unloads and the dip is not at its
6890 * full power, we return DDI_FAILURE to terminate the walk, otherwise
6891 * return DDI_SUCCESS.
6894 pm_pre_unconfig(dev_info_t *dip, int flags, int *held, char *devnm)
6896 PMD_FUNC(pmf, "pre_unconfig")
6897 int ret;
6899 if (MDI_VHCI(dip)) {
6900 PMD(PMD_SET, ("%s: %s@%s(%s#%d), flags=%x\n", pmf,
6901 PM_DEVICE(dip), flags))
6902 ret = mdi_power(dip, MDI_PM_PRE_UNCONFIG, held, devnm, flags);
6903 return (ret == MDI_SUCCESS ? DDI_SUCCESS : DDI_FAILURE);
6904 } else if (!PM_GET_PM_INFO(dip))
6905 return (DDI_SUCCESS);
6907 PMD(PMD_SET, ("%s: %s@%s(%s#%d), flags=%x\n", pmf, PM_DEVICE(dip),
6908 flags))
6909 *held = 0;
6912 * If the dip is a leaf node, don't power it up.
6914 if (!ddi_get_child(dip))
6915 return (DDI_SUCCESS);
6918 * Do not power up the node if it is called due to auto-modunload.
6920 if ((flags & NDI_AUTODETACH) && !pm_all_at_normal(dip))
6921 return (DDI_FAILURE);
6923 pm_hold_power(dip);
6924 *held = 1;
6925 ret = pm_all_to_normal(dip, PM_CANBLOCK_BLOCK);
6926 if (ret != DDI_SUCCESS) {
6927 pm_rele_power(dip);
6928 *held = 0;
6930 return (ret);
6934 * Notify ppm of attach action. Parent is already held at full power by
6935 * probe action.
6937 void
6938 pm_pre_attach(dev_info_t *dip, pm_ppm_cookie_t *cp, ddi_attach_cmd_t cmd)
6940 static char *me = "pm_pre_attach";
6941 power_req_t power_req;
6942 int result;
6945 * Initialize and fill in the PPM cookie
6947 bzero(cp, sizeof (*cp));
6948 cp->ppc_cmd = (int)cmd;
6949 cp->ppc_ppm = PPM(dip);
6950 cp->ppc_dip = dip;
6953 * DDI_ATTACH and DDI_RESUME cmds need to call platform specific
6954 * Power Management stuff. DDI_RESUME also has to purge it's
6955 * powerlevel information.
6957 switch (cmd) {
6958 case DDI_ATTACH:
6959 if (cp->ppc_ppm) { /* if ppm driver claims the node */
6960 power_req.request_type = PMR_PPM_PRE_ATTACH;
6961 power_req.req.ppm_config_req.who = dip;
6962 ASSERT(PPM(dip));
6963 (void) pm_ctlops(cp->ppc_ppm, dip, DDI_CTLOPS_POWER,
6964 &power_req, &result);
6966 #ifdef DEBUG
6967 else {
6968 power_req.request_type = PMR_PPM_PRE_ATTACH;
6969 power_req.req.ppm_config_req.who = dip;
6970 (void) pm_ctlops(NULL, dip,
6971 DDI_CTLOPS_POWER, &power_req, &result);
6973 #endif
6974 break;
6975 case DDI_RESUME:
6976 pm_forget_power_level(dip);
6978 if (cp->ppc_ppm) { /* if ppm driver claims the node */
6979 power_req.request_type = PMR_PPM_PRE_RESUME;
6980 power_req.req.resume_req.who = cp->ppc_dip;
6981 power_req.req.resume_req.cmd =
6982 (ddi_attach_cmd_t)cp->ppc_cmd;
6983 ASSERT(PPM(cp->ppc_dip) == cp->ppc_ppm);
6984 (void) pm_ctlops(cp->ppc_ppm, cp->ppc_dip,
6985 DDI_CTLOPS_POWER, &power_req, &result);
6987 #ifdef DEBUG
6988 else {
6989 power_req.request_type = PMR_PPM_PRE_RESUME;
6990 power_req.req.resume_req.who = cp->ppc_dip;
6991 power_req.req.resume_req.cmd =
6992 (ddi_attach_cmd_t)cp->ppc_cmd;
6993 (void) pm_ctlops(NULL, cp->ppc_dip,
6994 DDI_CTLOPS_POWER, &power_req, &result);
6996 #endif
6997 break;
6999 case DDI_PM_RESUME:
7000 break;
7002 default:
7003 panic(me);
7008 * Nexus drivers call into pm framework to indicate which child driver is
7009 * being uninstalled. In some platforms, ppm may need to reconfigure the
7010 * hardware since the device driver is no longer installed.
7013 pm_uninit_child(dev_info_t *dip)
7015 power_req_t power_req;
7017 ASSERT(ddi_binding_name(dip));
7018 ASSERT(ddi_get_name_addr(dip));
7019 pm_ppm_claim(dip);
7020 if (pm_ppm_claimed(dip)) { /* if ppm driver claims the node */
7021 power_req.request_type = PMR_PPM_UNINIT_CHILD;
7022 power_req.req.ppm_config_req.who = dip;
7023 ASSERT(PPM(dip));
7024 return (pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER, &power_req,
7025 NULL));
7026 } else {
7027 #ifdef DEBUG
7028 /* pass it to the default handler so we can debug things */
7029 power_req.request_type = PMR_PPM_UNINIT_CHILD;
7030 power_req.req.ppm_config_req.who = dip;
7031 (void) pm_ctlops(NULL, dip, DDI_CTLOPS_POWER, &power_req, NULL);
7032 #endif
7034 return (DDI_SUCCESS);
7037 * Decrement kidsupcnt so scan can turn the parent back off if it is idle
7038 * Also notify ppm of result of probe if there is a ppm that cares
7040 void
7041 pm_post_probe(pm_ppm_cookie_t *cp, int ret, int probe_failed)
7043 _NOTE(ARGUNUSED(probe_failed))
7044 int result;
7045 power_req_t power_req;
7047 if (cp->ppc_ppm) { /* if ppm driver claims the node */
7048 power_req.request_type = PMR_PPM_POST_PROBE;
7049 power_req.req.ppm_config_req.who = cp->ppc_dip;
7050 power_req.req.ppm_config_req.result = ret;
7051 ASSERT(PPM(cp->ppc_dip) == cp->ppc_ppm);
7052 (void) pm_ctlops(cp->ppc_ppm, cp->ppc_dip, DDI_CTLOPS_POWER,
7053 &power_req, &result);
7055 #ifdef DEBUG
7056 else {
7057 power_req.request_type = PMR_PPM_POST_PROBE;
7058 power_req.req.ppm_config_req.who = cp->ppc_dip;
7059 power_req.req.ppm_config_req.result = ret;
7060 (void) pm_ctlops(NULL, cp->ppc_dip, DDI_CTLOPS_POWER,
7061 &power_req, &result);
7063 #endif
7066 void
7067 pm_post_config(dev_info_t *dip, char *devnm)
7069 PMD_FUNC(pmf, "post_config")
7071 if (MDI_VHCI(dip)) {
7072 PMD(PMD_SET, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
7073 (void) mdi_power(dip, MDI_PM_POST_CONFIG, NULL, devnm, 0);
7074 return;
7075 } else if (!PM_GET_PM_INFO(dip))
7076 return;
7078 PMD(PMD_SET, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
7079 pm_rele_power(dip);
7082 void
7083 pm_post_unconfig(dev_info_t *dip, int held, char *devnm)
7085 PMD_FUNC(pmf, "post_unconfig")
7087 if (MDI_VHCI(dip)) {
7088 PMD(PMD_SET, ("%s: %s@%s(%s#%d), held = %d\n", pmf,
7089 PM_DEVICE(dip), held))
7090 (void) mdi_power(dip, MDI_PM_POST_UNCONFIG, &held, devnm, 0);
7091 return;
7092 } else if (!PM_GET_PM_INFO(dip))
7093 return;
7095 PMD(PMD_SET, ("%s: %s@%s(%s#%d), held = %d\n", pmf, PM_DEVICE(dip),
7096 held))
7097 if (!held)
7098 return;
7100 * We have held power in pre_unconfig, release it here.
7102 pm_rele_power(dip);
7106 * Notify ppm of result of attach if there is a ppm that cares
7108 void
7109 pm_post_attach(pm_ppm_cookie_t *cp, int ret)
7111 int result;
7112 power_req_t power_req;
7113 dev_info_t *dip;
7115 if (cp->ppc_cmd != DDI_ATTACH)
7116 return;
7118 dip = cp->ppc_dip;
7120 if (ret == DDI_SUCCESS) {
7122 * Attach succeeded, so proceed to doing post-attach pm tasks
7124 if (PM_GET_PM_INFO(dip) == NULL)
7125 (void) pm_start(dip);
7126 } else {
7128 * Attach may have got pm started before failing
7130 pm_stop(dip);
7133 if (cp->ppc_ppm) { /* if ppm driver claims the node */
7134 power_req.request_type = PMR_PPM_POST_ATTACH;
7135 power_req.req.ppm_config_req.who = cp->ppc_dip;
7136 power_req.req.ppm_config_req.result = ret;
7137 ASSERT(PPM(cp->ppc_dip) == cp->ppc_ppm);
7138 (void) pm_ctlops(cp->ppc_ppm, cp->ppc_dip,
7139 DDI_CTLOPS_POWER, &power_req, &result);
7141 #ifdef DEBUG
7142 else {
7143 power_req.request_type = PMR_PPM_POST_ATTACH;
7144 power_req.req.ppm_config_req.who = cp->ppc_dip;
7145 power_req.req.ppm_config_req.result = ret;
7146 (void) pm_ctlops(NULL, cp->ppc_dip,
7147 DDI_CTLOPS_POWER, &power_req, &result);
7149 #endif
7153 * Notify ppm of attach action. Parent is already held at full power by
7154 * probe action.
7156 void
7157 pm_pre_detach(dev_info_t *dip, ddi_detach_cmd_t cmd, pm_ppm_cookie_t *cp)
7159 int result;
7160 power_req_t power_req;
7162 bzero(cp, sizeof (*cp));
7163 cp->ppc_dip = dip;
7164 cp->ppc_cmd = (int)cmd;
7166 switch (cmd) {
7167 case DDI_DETACH:
7168 pm_detaching(dip); /* suspend pm while detaching */
7169 if (pm_ppm_claimed(dip)) { /* if ppm driver claims node */
7170 power_req.request_type = PMR_PPM_PRE_DETACH;
7171 power_req.req.ppm_config_req.who = dip;
7172 ASSERT(PPM(dip));
7173 (void) pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER,
7174 &power_req, &result);
7175 cp->ppc_ppm = PPM(dip);
7176 } else {
7177 #ifdef DEBUG
7178 /* pass to the default handler so we can debug things */
7179 power_req.request_type = PMR_PPM_PRE_DETACH;
7180 power_req.req.ppm_config_req.who = dip;
7181 (void) pm_ctlops(NULL, dip,
7182 DDI_CTLOPS_POWER, &power_req, &result);
7183 #endif
7184 cp->ppc_ppm = NULL;
7186 break;
7188 default:
7189 break;
7194 * Dip is either a leaf node that exported "no-involuntary-power-cycles" prop.,
7195 * (if devi_pm_noinvol count is 0) or an ancestor of such a node. We need to
7196 * make an entry to record the details, which includes certain flag settings.
7198 static void
7199 pm_record_invol_path(char *path, int flags, int noinvolpm, int volpmd,
7200 int wasvolpmd, major_t major)
7202 PMD_FUNC(pmf, "record_invol_path")
7203 major_t pm_path_to_major(char *);
7204 size_t plen;
7205 pm_noinvol_t *ip, *np, *pp;
7206 pp = NULL;
7208 plen = strlen(path) + 1;
7209 np = kmem_zalloc(sizeof (*np), KM_SLEEP);
7210 np->ni_size = plen;
7211 np->ni_path = kmem_alloc(plen, KM_SLEEP);
7212 np->ni_noinvolpm = noinvolpm;
7213 np->ni_volpmd = volpmd;
7214 np->ni_wasvolpmd = wasvolpmd;
7215 np->ni_flags = flags;
7216 (void) strcpy(np->ni_path, path);
7218 * If we haven't actually seen the node attached, it is hard to figure
7219 * out its major. If we could hold the node by path, we would be much
7220 * happier here.
7222 if (major == DDI_MAJOR_T_NONE) {
7223 np->ni_major = pm_path_to_major(path);
7224 } else {
7225 np->ni_major = major;
7227 rw_enter(&pm_noinvol_rwlock, RW_WRITER);
7228 for (ip = pm_noinvol_head; ip; pp = ip, ip = ip->ni_next) {
7229 int comp = strcmp(path, ip->ni_path);
7230 if (comp < 0) {
7231 PMD(PMD_NOINVOL, ("%s: %s insert before %s\n",
7232 pmf, path, ip->ni_path))
7233 /* insert before current entry */
7234 np->ni_next = ip;
7235 if (pp) {
7236 pp->ni_next = np;
7237 } else {
7238 pm_noinvol_head = np;
7240 rw_exit(&pm_noinvol_rwlock);
7241 #ifdef DEBUG
7242 if (pm_debug & PMD_NOINVOL)
7243 pr_noinvol("record_invol_path exit0");
7244 #endif
7245 return;
7246 } else if (comp == 0) {
7247 panic("%s already in pm_noinvol list", path);
7251 * If we did not find an entry in the list that this should go before,
7252 * then it must go at the end
7254 if (pp) {
7255 PMD(PMD_NOINVOL, ("%s: %s append after %s\n", pmf, path,
7256 pp->ni_path))
7257 ASSERT(pp->ni_next == 0);
7258 pp->ni_next = np;
7259 } else {
7260 PMD(PMD_NOINVOL, ("%s: %s added to end-of-list\n", pmf, path))
7261 ASSERT(!pm_noinvol_head);
7262 pm_noinvol_head = np;
7264 rw_exit(&pm_noinvol_rwlock);
7265 #ifdef DEBUG
7266 if (pm_debug & PMD_NOINVOL)
7267 pr_noinvol("record_invol_path exit");
7268 #endif
7271 void
7272 pm_record_invol(dev_info_t *dip)
7274 char *pathbuf;
7275 int pm_all_components_off(dev_info_t *);
7276 int volpmd = (PM_NUMCMPTS(dip) > 0) && pm_all_components_off(dip);
7278 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
7279 (void) ddi_pathname(dip, pathbuf);
7281 pm_record_invol_path(pathbuf, (DEVI(dip)->devi_pm_flags &
7282 (PMC_NO_INVOL | PMC_CONSOLE_FB)), DEVI(dip)->devi_pm_noinvolpm,
7283 DEVI(dip)->devi_pm_volpmd, volpmd, PM_MAJOR(dip));
7286 * If this child's detach will be holding up its ancestors, then we
7287 * allow for an exception to that if all children of this type have
7288 * gone down voluntarily.
7289 * Now walk down the tree incrementing devi_pm_noinvolpm
7291 (void) pm_noinvol_update(PM_BP_NOINVOL_DETACH, 0, volpmd, pathbuf,
7292 dip);
7293 kmem_free(pathbuf, MAXPATHLEN);
7296 void
7297 pm_post_detach(pm_ppm_cookie_t *cp, int ret)
7299 dev_info_t *dip = cp->ppc_dip;
7300 int result;
7301 power_req_t power_req;
7303 switch (cp->ppc_cmd) {
7304 case DDI_DETACH:
7305 if (cp->ppc_ppm) { /* if ppm driver claims the node */
7306 power_req.request_type = PMR_PPM_POST_DETACH;
7307 power_req.req.ppm_config_req.who = cp->ppc_dip;
7308 power_req.req.ppm_config_req.result = ret;
7309 ASSERT(PPM(cp->ppc_dip) == cp->ppc_ppm);
7310 (void) pm_ctlops(cp->ppc_ppm, cp->ppc_dip,
7311 DDI_CTLOPS_POWER, &power_req, &result);
7313 #ifdef DEBUG
7314 else {
7315 power_req.request_type = PMR_PPM_POST_DETACH;
7316 power_req.req.ppm_config_req.who = cp->ppc_dip;
7317 power_req.req.ppm_config_req.result = ret;
7318 (void) pm_ctlops(NULL, cp->ppc_dip,
7319 DDI_CTLOPS_POWER, &power_req, &result);
7321 #endif
7322 if (ret == DDI_SUCCESS) {
7324 * For hotplug detach we assume it is *really* gone
7326 if (cp->ppc_cmd == DDI_DETACH &&
7327 ((DEVI(dip)->devi_pm_flags &
7328 (PMC_NO_INVOL | PMC_CONSOLE_FB)) ||
7329 DEVI(dip)->devi_pm_noinvolpm))
7330 pm_record_invol(dip);
7331 DEVI(dip)->devi_pm_flags &=
7332 ~(PMC_NO_INVOL | PMC_NOINVOL_DONE);
7335 * If console fb is detaching, then we don't need to
7336 * worry any more about it going off (pm_detaching has
7337 * brought up all components)
7339 if (PM_IS_CFB(dip)) {
7340 mutex_enter(&pm_cfb_lock);
7341 ASSERT(cfb_dip_detaching);
7342 ASSERT(cfb_dip == NULL);
7343 ASSERT(pm_cfb_comps_off == 0);
7344 cfb_dip_detaching = NULL;
7345 mutex_exit(&pm_cfb_lock);
7347 pm_stop(dip); /* make it permanent */
7348 } else {
7349 if (PM_IS_CFB(dip)) {
7350 mutex_enter(&pm_cfb_lock);
7351 ASSERT(cfb_dip_detaching);
7352 ASSERT(cfb_dip == NULL);
7353 ASSERT(pm_cfb_comps_off == 0);
7354 cfb_dip = cfb_dip_detaching;
7355 cfb_dip_detaching = NULL;
7356 mutex_exit(&pm_cfb_lock);
7358 pm_detach_failed(dip); /* resume power management */
7360 break;
7361 case DDI_PM_SUSPEND:
7362 break;
7363 case DDI_SUSPEND:
7364 break; /* legal, but nothing to do */
7365 default:
7366 #ifdef DEBUG
7367 panic("pm_post_detach: unrecognized cmd %d for detach",
7368 cp->ppc_cmd);
7369 /*NOTREACHED*/
7370 #else
7371 break;
7372 #endif
7377 * Called after vfs_mountroot has got the clock started to fix up timestamps
7378 * that were set when root bush drivers attached. hresttime was 0 then, so the
7379 * devices look busy but have a 0 busycnt
7382 pm_adjust_timestamps(dev_info_t *dip, void *arg)
7384 _NOTE(ARGUNUSED(arg))
7386 pm_info_t *info = PM_GET_PM_INFO(dip);
7387 struct pm_component *cp;
7388 int i;
7390 if (!info)
7391 return (DDI_WALK_CONTINUE);
7392 PM_LOCK_BUSY(dip);
7393 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
7394 cp = PM_CP(dip, i);
7395 if (cp->pmc_timestamp == 0 && cp->pmc_busycount == 0)
7396 cp->pmc_timestamp = gethrestime_sec();
7398 PM_UNLOCK_BUSY(dip);
7399 return (DDI_WALK_CONTINUE);
7403 * Called at attach time to see if the device being attached has a record in
7404 * the no involuntary power cycles list. If so, we do some bookkeeping on the
7405 * parents and set a flag in the dip
7407 void
7408 pm_noinvol_specd(dev_info_t *dip)
7410 PMD_FUNC(pmf, "noinvol_specd")
7411 char *pathbuf;
7412 pm_noinvol_t *ip, *pp = NULL;
7413 int wasvolpmd;
7414 int found = 0;
7416 if (DEVI(dip)->devi_pm_flags & PMC_NOINVOL_DONE)
7417 return;
7418 DEVI(dip)->devi_pm_flags |= PMC_NOINVOL_DONE;
7419 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
7420 (void) ddi_pathname(dip, pathbuf);
7422 PM_LOCK_DIP(dip);
7423 DEVI(dip)->devi_pm_volpmd = 0;
7424 DEVI(dip)->devi_pm_noinvolpm = 0;
7425 rw_enter(&pm_noinvol_rwlock, RW_READER);
7426 for (ip = pm_noinvol_head; ip; pp = ip, ip = ip->ni_next) {
7427 PMD(PMD_NOINVOL, ("%s: comparing '%s' to '%s'\n",
7428 pmf, pathbuf, ip->ni_path))
7429 if (strcmp(pathbuf, ip->ni_path) == 0) {
7430 found++;
7431 break;
7434 rw_exit(&pm_noinvol_rwlock);
7435 if (!found) {
7436 PM_UNLOCK_DIP(dip);
7437 kmem_free(pathbuf, MAXPATHLEN);
7438 return;
7440 rw_enter(&pm_noinvol_rwlock, RW_WRITER);
7441 pp = NULL;
7442 for (ip = pm_noinvol_head; ip; pp = ip, ip = ip->ni_next) {
7443 PMD(PMD_NOINVOL, ("%s: comparing '%s' to '%s'\n",
7444 pmf, pathbuf, ip->ni_path))
7445 if (strcmp(pathbuf, ip->ni_path) == 0) {
7446 ip->ni_flags &= ~PMC_DRIVER_REMOVED;
7447 DEVI(dip)->devi_pm_flags |= ip->ni_flags;
7449 * Handle special case of console fb
7451 if (PM_IS_CFB(dip)) {
7452 mutex_enter(&pm_cfb_lock);
7453 cfb_dip = dip;
7454 PMD(PMD_CFB, ("%s: %s@%s(%s#%d) setting "
7455 "cfb_dip\n", pmf, PM_DEVICE(dip)))
7456 mutex_exit(&pm_cfb_lock);
7458 DEVI(dip)->devi_pm_noinvolpm = ip->ni_noinvolpm;
7459 ASSERT((DEVI(dip)->devi_pm_flags &
7460 (PMC_NO_INVOL | PMC_CONSOLE_FB)) ||
7461 DEVI(dip)->devi_pm_noinvolpm);
7462 DEVI(dip)->devi_pm_volpmd = ip->ni_volpmd;
7463 PMD(PMD_NOINVOL, ("%s: noinvol=%d, volpmd=%d, "
7464 "wasvolpmd=%d, flags=%x, path=%s\n", pmf,
7465 ip->ni_noinvolpm, ip->ni_volpmd,
7466 ip->ni_wasvolpmd, ip->ni_flags, ip->ni_path))
7468 * free the entry in hopes the list will now be empty
7469 * and we won't have to search it any more until the
7470 * device detaches
7472 if (pp) {
7473 PMD(PMD_NOINVOL, ("%s: free %s, prev %s\n",
7474 pmf, ip->ni_path, pp->ni_path))
7475 pp->ni_next = ip->ni_next;
7476 } else {
7477 PMD(PMD_NOINVOL, ("%s: free %s head\n",
7478 pmf, ip->ni_path))
7479 ASSERT(pm_noinvol_head == ip);
7480 pm_noinvol_head = ip->ni_next;
7482 PM_UNLOCK_DIP(dip);
7483 wasvolpmd = ip->ni_wasvolpmd;
7484 rw_exit(&pm_noinvol_rwlock);
7485 kmem_free(ip->ni_path, ip->ni_size);
7486 kmem_free(ip, sizeof (*ip));
7488 * Now walk up the tree decrementing devi_pm_noinvolpm
7489 * (and volpmd if appropriate)
7491 (void) pm_noinvol_update(PM_BP_NOINVOL_ATTACH, 0,
7492 wasvolpmd, pathbuf, dip);
7493 #ifdef DEBUG
7494 if (pm_debug & PMD_NOINVOL)
7495 pr_noinvol("noinvol_specd exit");
7496 #endif
7497 kmem_free(pathbuf, MAXPATHLEN);
7498 return;
7501 kmem_free(pathbuf, MAXPATHLEN);
7502 rw_exit(&pm_noinvol_rwlock);
7503 PM_UNLOCK_DIP(dip);
7507 pm_all_components_off(dev_info_t *dip)
7509 int i;
7510 pm_component_t *cp;
7512 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
7513 cp = PM_CP(dip, i);
7514 if (cp->pmc_cur_pwr == PM_LEVEL_UNKNOWN ||
7515 cp->pmc_comp.pmc_lvals[cp->pmc_cur_pwr])
7516 return (0);
7518 return (1); /* all off */
7522 * Make sure that all "no involuntary power cycles" devices are attached.
7523 * Called before doing a cpr suspend to make sure the driver has a say about
7524 * the power cycle
7527 pm_reattach_noinvol(void)
7529 PMD_FUNC(pmf, "reattach_noinvol")
7530 pm_noinvol_t *ip;
7531 char *path;
7532 dev_info_t *dip;
7535 * Prevent the modunload thread from unloading any modules until we
7536 * have completely stopped all kernel threads.
7538 modunload_disable();
7539 for (ip = pm_noinvol_head; ip; ip = ip->ni_next) {
7541 * Forget we'v ever seen any entry
7543 ip->ni_persistent = 0;
7545 restart:
7546 rw_enter(&pm_noinvol_rwlock, RW_READER);
7547 for (ip = pm_noinvol_head; ip; ip = ip->ni_next) {
7548 #ifdef PMDDEBUG
7549 major_t maj;
7550 maj = ip->ni_major;
7551 #endif
7552 path = ip->ni_path;
7553 if (path != NULL && !(ip->ni_flags & PMC_DRIVER_REMOVED)) {
7554 if (ip->ni_persistent) {
7556 * If we weren't able to make this entry
7557 * go away, then we give up, as
7558 * holding/attaching the driver ought to have
7559 * resulted in this entry being deleted
7561 PMD(PMD_NOINVOL, ("%s: can't reattach %s "
7562 "(%s|%d)\n", pmf, ip->ni_path,
7563 ddi_major_to_name(maj), (int)maj))
7564 cmn_err(CE_WARN, "cpr: unable to reattach %s ",
7565 ip->ni_path);
7566 modunload_enable();
7567 rw_exit(&pm_noinvol_rwlock);
7568 return (0);
7570 ip->ni_persistent++;
7571 rw_exit(&pm_noinvol_rwlock);
7572 PMD(PMD_NOINVOL, ("%s: holding %s\n", pmf, path))
7573 dip = e_ddi_hold_devi_by_path(path, 0);
7574 if (dip == NULL) {
7575 PMD(PMD_NOINVOL, ("%s: can't hold (%s|%d)\n",
7576 pmf, path, (int)maj))
7577 cmn_err(CE_WARN, "cpr: unable to hold %s "
7578 "driver", path);
7579 modunload_enable();
7580 return (0);
7581 } else {
7582 PMD(PMD_DHR, ("%s: release %s\n", pmf, path))
7584 * Since the modunload thread is stopped, we
7585 * don't have to keep the driver held, which
7586 * saves a ton of bookkeeping
7588 ddi_release_devi(dip);
7589 goto restart;
7591 } else {
7592 PMD(PMD_NOINVOL, ("%s: skip %s; unknown major\n",
7593 pmf, ip->ni_path))
7594 continue;
7597 rw_exit(&pm_noinvol_rwlock);
7598 return (1);
7601 void
7602 pm_reattach_noinvol_fini(void)
7604 modunload_enable();
7608 * Display pm support code
7613 * console frame-buffer power-mgmt gets enabled when debugging
7614 * services are not present or console fbpm override is set
7616 void
7617 pm_cfb_setup(const char *stdout_path)
7619 PMD_FUNC(pmf, "cfb_setup")
7620 extern int obpdebug;
7621 char *devname;
7622 dev_info_t *dip;
7623 int devname_len;
7624 extern dev_info_t *fbdip;
7627 * By virtue of this function being called (from consconfig),
7628 * we know stdout is a framebuffer.
7630 stdout_is_framebuffer = 1;
7632 if (obpdebug || (boothowto & RB_DEBUG)) {
7633 if (pm_cfb_override == 0) {
7635 * Console is frame buffer, but we want to suppress
7636 * pm on it because of debugging setup
7638 pm_cfb_enabled = 0;
7639 cmn_err(CE_NOTE, "Kernel debugger present: disabling "
7640 "console power management.");
7642 * however, we still need to know which is the console
7643 * fb in order to suppress pm on it
7645 } else {
7646 cmn_err(CE_WARN, "Kernel debugger present: see "
7647 "kmdb(1M) for interaction with power management.");
7650 #ifdef DEBUG
7652 * IF console is fb and is power managed, don't do prom_printfs from
7653 * pm debug macro
7655 if (pm_cfb_enabled && !pm_debug_to_console) {
7656 if (pm_debug)
7657 prom_printf("pm debug output will be to log only\n");
7658 pm_divertdebug++;
7660 #endif
7661 devname = i_ddi_strdup((char *)stdout_path, KM_SLEEP);
7662 devname_len = strlen(devname) + 1;
7663 PMD(PMD_CFB, ("%s: stripped %s\n", pmf, devname))
7664 /* if the driver is attached */
7665 if ((dip = fbdip) != NULL) {
7666 PMD(PMD_CFB, ("%s: attached: %s@%s(%s#%d)\n", pmf,
7667 PM_DEVICE(dip)))
7669 * We set up here as if the driver were power manageable in case
7670 * we get a later attach of a pm'able driver (which would result
7671 * in a panic later)
7673 cfb_dip = dip;
7674 DEVI(dip)->devi_pm_flags |= (PMC_CONSOLE_FB | PMC_NO_INVOL);
7675 PMD(PMD_CFB, ("%s: cfb_dip -> %s@%s(%s#%d)\n", pmf,
7676 PM_DEVICE(dip)))
7677 #ifdef DEBUG
7678 if (!(PM_GET_PM_INFO(dip) != NULL && PM_NUMCMPTS(dip))) {
7679 PMD(PMD_CFB, ("%s: %s@%s(%s#%d) not power-managed\n",
7680 pmf, PM_DEVICE(dip)))
7682 #endif
7683 } else {
7684 char *ep;
7685 PMD(PMD_CFB, ("%s: pntd %s failed\n", pmf, devname))
7686 pm_record_invol_path(devname,
7687 (PMC_CONSOLE_FB | PMC_NO_INVOL), 1, 0, 0,
7688 DDI_MAJOR_T_NONE);
7689 for (ep = strrchr(devname, '/'); ep != devname;
7690 ep = strrchr(devname, '/')) {
7691 PMD(PMD_CFB, ("%s: devname %s\n", pmf, devname))
7692 *ep = '\0';
7693 dip = pm_name_to_dip(devname, 0);
7694 if (dip != NULL) {
7696 * Walk up the tree incrementing
7697 * devi_pm_noinvolpm
7699 (void) pm_noinvol_update(PM_BP_NOINVOL_CFB,
7700 0, 0, devname, dip);
7701 break;
7702 } else {
7703 pm_record_invol_path(devname,
7704 PMC_NO_INVOL, 1, 0, 0, DDI_MAJOR_T_NONE);
7708 kmem_free(devname, devname_len);
7711 void
7712 pm_cfb_rele(void)
7714 mutex_enter(&pm_cfb_lock);
7716 * this call isn't using the console any more, it is ok to take it
7717 * down if the count goes to 0
7719 cfb_inuse--;
7720 mutex_exit(&pm_cfb_lock);
7724 * software interrupt handler for fbpm; this function exists because we can't
7725 * bring up the frame buffer power from above lock level. So if we need to,
7726 * we instead schedule a softint that runs this routine and takes us into
7727 * debug_enter (a bit delayed from the original request, but avoiding a panic).
7729 static uint_t
7730 pm_cfb_softint(caddr_t int_handler_arg)
7732 _NOTE(ARGUNUSED(int_handler_arg))
7733 int rval = DDI_INTR_UNCLAIMED;
7735 mutex_enter(&pm_cfb_lock);
7736 if (pm_soft_pending) {
7737 mutex_exit(&pm_cfb_lock);
7738 debug_enter(NULL);
7739 /* acquired in debug_enter before calling pm_cfb_trigger */
7740 pm_cfb_rele();
7741 mutex_enter(&pm_cfb_lock);
7742 pm_soft_pending = B_FALSE;
7743 mutex_exit(&pm_cfb_lock);
7744 rval = DDI_INTR_CLAIMED;
7745 } else
7746 mutex_exit(&pm_cfb_lock);
7748 return (rval);
7751 void
7752 pm_cfb_setup_intr(void)
7754 PMD_FUNC(pmf, "cfb_setup_intr")
7755 extern void prom_set_outfuncs(void (*)(void), void (*)(void));
7756 void pm_cfb_check_and_powerup(void);
7758 mutex_init(&pm_cfb_lock, NULL, MUTEX_SPIN, (void *)ipltospl(SPL8));
7759 #ifdef PMDDEBUG
7760 mutex_init(&pm_debug_lock, NULL, MUTEX_SPIN, (void *)ipltospl(SPL8));
7761 #endif
7763 if (!stdout_is_framebuffer) {
7764 PMD(PMD_CFB, ("%s: console not fb\n", pmf))
7765 return;
7769 * setup software interrupt handler
7771 if (ddi_add_softintr(ddi_root_node(), DDI_SOFTINT_HIGH, &pm_soft_id,
7772 NULL, NULL, pm_cfb_softint, NULL) != DDI_SUCCESS)
7773 panic("pm: unable to register soft intr.");
7775 prom_set_outfuncs(pm_cfb_check_and_powerup, pm_cfb_rele);
7779 * Checks to see if it is safe to write to the console wrt power management
7780 * (i.e. if the console is a framebuffer, then it must be at full power)
7781 * returns 1 when power is off (power-up is needed)
7782 * returns 0 when power is on (power-up not needed)
7785 pm_cfb_check_and_hold(void)
7788 * cfb_dip is set iff console is a power manageable frame buffer
7789 * device
7791 extern int modrootloaded;
7793 mutex_enter(&pm_cfb_lock);
7794 cfb_inuse++;
7795 ASSERT(cfb_inuse); /* wrap? */
7796 if (modrootloaded && cfb_dip) {
7798 * don't power down the frame buffer, the prom is using it
7800 if (pm_cfb_comps_off) {
7801 mutex_exit(&pm_cfb_lock);
7802 return (1);
7805 mutex_exit(&pm_cfb_lock);
7806 return (0);
7810 * turn on cfb power (which is known to be off).
7811 * Must be called below lock level!
7813 void
7814 pm_cfb_powerup(void)
7816 pm_info_t *info;
7817 int norm;
7818 int ccount, ci;
7819 int unused;
7820 #ifdef DEBUG
7822 * Can't reenter prom_prekern, so suppress pm debug messages
7823 * (still go to circular buffer).
7825 mutex_enter(&pm_debug_lock);
7826 pm_divertdebug++;
7827 mutex_exit(&pm_debug_lock);
7828 #endif
7829 info = PM_GET_PM_INFO(cfb_dip);
7830 ASSERT(info);
7832 ccount = PM_NUMCMPTS(cfb_dip);
7833 for (ci = 0; ci < ccount; ci++) {
7834 norm = pm_get_normal_power(cfb_dip, ci);
7835 (void) pm_set_power(cfb_dip, ci, norm, PM_LEVEL_UPONLY,
7836 PM_CANBLOCK_BYPASS, 0, &unused);
7838 #ifdef DEBUG
7839 mutex_enter(&pm_debug_lock);
7840 pm_divertdebug--;
7841 mutex_exit(&pm_debug_lock);
7842 #endif
7846 * Check if the console framebuffer is powered up. If not power it up.
7847 * Note: Calling pm_cfb_check_and_hold has put a hold on the power state which
7848 * must be released by calling pm_cfb_rele when the console fb operation
7849 * is completed.
7851 void
7852 pm_cfb_check_and_powerup(void)
7854 if (pm_cfb_check_and_hold())
7855 pm_cfb_powerup();
7859 * Trigger a low level interrupt to power up console frame buffer.
7861 void
7862 pm_cfb_trigger(void)
7864 if (cfb_dip == NULL)
7865 return;
7867 mutex_enter(&pm_cfb_lock);
7869 * If the machine appears to be hung, pulling the keyboard connector of
7870 * the console will cause a high level interrupt and go to debug_enter.
7871 * But, if the fb is powered down, this routine will be called to bring
7872 * it up (by generating a softint to do the work). If a second attempt
7873 * at triggering this softint happens before the first one completes,
7874 * we panic as softints are most likely not being handled.
7876 if (pm_soft_pending) {
7877 panicstr = "pm_cfb_trigger: failed to enter the debugger";
7878 panic(panicstr); /* does a power up at any intr level */
7879 /* NOTREACHED */
7881 pm_soft_pending = B_TRUE;
7882 mutex_exit(&pm_cfb_lock);
7883 ddi_trigger_softintr(pm_soft_id);
7886 static major_t i_path_to_major(char *, char *);
7888 major_t
7889 pm_path_to_major(char *path)
7891 PMD_FUNC(pmf, "path_to_major")
7892 char *np, *ap, *bp;
7893 major_t ret;
7894 size_t len;
7896 PMD(PMD_NOINVOL, ("%s: %s\n", pmf, path))
7898 np = strrchr(path, '/');
7899 if (np != NULL)
7900 np++;
7901 else
7902 np = path;
7903 len = strlen(np) + 1;
7904 bp = kmem_alloc(len, KM_SLEEP);
7905 (void) strcpy(bp, np);
7906 if ((ap = strchr(bp, '@')) != NULL) {
7907 *ap = '\0';
7909 PMD(PMD_NOINVOL, ("%s: %d\n", pmf, ddi_name_to_major(np)))
7910 ret = i_path_to_major(path, np);
7911 kmem_free(bp, len);
7912 return (ret);
7915 #ifdef DEBUG
7916 #ifndef sparc
7917 clock_t pt_sleep = 1;
7918 #endif
7920 char *pm_msgp;
7921 char *pm_bufend;
7922 char *pm_msgbuf = NULL;
7923 int pm_logpages = 0x100;
7924 #include <sys/sunldi.h>
7925 #include <sys/uio.h>
7926 clock_t pm_log_sleep = 1000;
7927 int pm_extra_cr = 1;
7928 volatile int pm_tty = 1;
7930 #define PMLOGPGS pm_logpages
7932 #if defined(__x86)
7933 void pm_printf(char *s);
7934 #endif
7936 /*PRINTFLIKE1*/
7937 void
7938 pm_log(const char *fmt, ...)
7940 va_list adx;
7941 size_t size;
7943 mutex_enter(&pm_debug_lock);
7944 if (pm_msgbuf == NULL) {
7945 pm_msgbuf = kmem_zalloc(mmu_ptob(PMLOGPGS), KM_SLEEP);
7946 pm_bufend = pm_msgbuf + mmu_ptob(PMLOGPGS) - 1;
7947 pm_msgp = pm_msgbuf;
7949 va_start(adx, fmt);
7950 size = vsnprintf(NULL, 0, fmt, adx) + 1;
7951 va_end(adx);
7952 va_start(adx, fmt);
7953 if (size > (pm_bufend - pm_msgp)) { /* wraps */
7954 bzero(pm_msgp, pm_bufend - pm_msgp);
7955 (void) vsnprintf(pm_msgbuf, size, fmt, adx);
7956 if (!pm_divertdebug)
7957 prom_printf("%s", pm_msgp);
7958 #if defined(__x86)
7959 if (pm_tty) {
7960 pm_printf(pm_msgp);
7961 if (pm_extra_cr)
7962 pm_printf("\r");
7964 #endif
7965 pm_msgp = pm_msgbuf + size;
7966 } else {
7967 (void) vsnprintf(pm_msgp, size, fmt, adx);
7968 #if defined(__x86)
7969 if (pm_tty) {
7970 pm_printf(pm_msgp);
7971 if (pm_extra_cr)
7972 pm_printf("\r");
7974 #endif
7975 if (!pm_divertdebug)
7976 prom_printf("%s", pm_msgp);
7977 pm_msgp += size;
7979 va_end(adx);
7980 mutex_exit(&pm_debug_lock);
7981 drv_usecwait((clock_t)pm_log_sleep);
7983 #endif /* DEBUG */
7986 * We want to save the state of any directly pm'd devices over the suspend/
7987 * resume process so that we can put them back the way the controlling
7988 * process left them.
7990 void
7991 pm_save_direct_levels(void)
7993 pm_processes_stopped = 1;
7994 ddi_walk_devs(ddi_root_node(), pm_save_direct_lvl_walk, 0);
7997 static int
7998 pm_save_direct_lvl_walk(dev_info_t *dip, void *arg)
8000 _NOTE(ARGUNUSED(arg))
8001 int i;
8002 int *ip;
8003 pm_info_t *info = PM_GET_PM_INFO(dip);
8005 if (!info)
8006 return (DDI_WALK_CONTINUE);
8008 if (PM_ISDIRECT(dip) && !PM_ISBC(dip)) {
8009 if (PM_NUMCMPTS(dip) > 2) {
8010 info->pmi_lp = kmem_alloc(PM_NUMCMPTS(dip) *
8011 sizeof (int), KM_SLEEP);
8012 ip = info->pmi_lp;
8013 } else {
8014 ip = info->pmi_levels;
8016 /* autopm and processes are stopped, ok not to lock power */
8017 for (i = 0; i < PM_NUMCMPTS(dip); i++)
8018 *ip++ = PM_CURPOWER(dip, i);
8020 * There is a small window between stopping the
8021 * processes and setting pm_processes_stopped where
8022 * a driver could get hung up in a pm_raise_power()
8023 * call. Free any such driver now.
8025 pm_proceed(dip, PMP_RELEASE, -1, -1);
8028 return (DDI_WALK_CONTINUE);
8031 void
8032 pm_restore_direct_levels(void)
8035 * If cpr didn't call pm_save_direct_levels, (because stopping user
8036 * threads failed) then we don't want to try to restore them
8038 if (!pm_processes_stopped)
8039 return;
8041 ddi_walk_devs(ddi_root_node(), pm_restore_direct_lvl_walk, 0);
8042 pm_processes_stopped = 0;
8045 static int
8046 pm_restore_direct_lvl_walk(dev_info_t *dip, void *arg)
8048 _NOTE(ARGUNUSED(arg))
8049 PMD_FUNC(pmf, "restore_direct_lvl_walk")
8050 int i, nc, result;
8051 int *ip;
8053 pm_info_t *info = PM_GET_PM_INFO(dip);
8054 if (!info)
8055 return (DDI_WALK_CONTINUE);
8057 if (PM_ISDIRECT(dip) && !PM_ISBC(dip)) {
8058 if ((nc = PM_NUMCMPTS(dip)) > 2) {
8059 ip = &info->pmi_lp[nc - 1];
8060 } else {
8061 ip = &info->pmi_levels[nc - 1];
8064 * Because fb drivers fail attempts to turn off the
8065 * fb when the monitor is on, but treat a request to
8066 * turn on the monitor as a request to turn on the
8067 * fb too, we process components in descending order
8068 * Because autopm is disabled and processes aren't
8069 * running, it is ok to examine current power outside
8070 * of the power lock
8072 for (i = nc - 1; i >= 0; i--, ip--) {
8073 if (PM_CURPOWER(dip, i) == *ip)
8074 continue;
8075 if (pm_set_power(dip, i, *ip, PM_LEVEL_EXACT,
8076 PM_CANBLOCK_BYPASS, 0, &result) != DDI_SUCCESS) {
8077 cmn_err(CE_WARN, "cpr: unable "
8078 "to restore power level of "
8079 "component %d of directly "
8080 "power manged device %s@%s"
8081 " to %d",
8082 i, PM_NAME(dip),
8083 PM_ADDR(dip), *ip);
8084 PMD(PMD_FAIL, ("%s: failed to restore "
8085 "%s@%s(%s#%d)[%d] exact(%d)->%d, "
8086 "errno %d\n", pmf, PM_DEVICE(dip), i,
8087 PM_CURPOWER(dip, i), *ip, result))
8090 if (nc > 2) {
8091 kmem_free(info->pmi_lp, nc * sizeof (int));
8092 info->pmi_lp = NULL;
8095 return (DDI_WALK_CONTINUE);
8099 * Stolen from the bootdev module
8100 * attempt to convert a path to a major number
8102 static major_t
8103 i_path_to_major(char *path, char *leaf_name)
8105 extern major_t path_to_major(char *pathname);
8106 major_t maj;
8108 if ((maj = path_to_major(path)) == DDI_MAJOR_T_NONE) {
8109 maj = ddi_name_to_major(leaf_name);
8112 return (maj);
8115 static void i_pm_driver_removed(major_t major);
8118 * When user calls rem_drv, we need to forget no-involuntary-power-cycles state
8119 * An entry in the list means that the device is detached, so we need to
8120 * adjust its ancestors as if they had just seen this attach, and any detached
8121 * ancestors need to have their list entries adjusted.
8123 void
8124 pm_driver_removed(major_t major)
8128 * Serialize removal of drivers. This is to keep ancestors of
8129 * a node that is being deleted from getting deleted and added back
8130 * with different counters.
8132 mutex_enter(&pm_remdrv_lock);
8133 i_pm_driver_removed(major);
8134 mutex_exit(&pm_remdrv_lock);
8137 static void adjust_ancestors(char *, int);
8138 static int pm_is_noinvol_ancestor(pm_noinvol_t *);
8139 static void pm_noinvol_process_ancestors(char *);
8142 * This routine is called recursively by pm_noinvol_process_ancestors()
8144 static void
8145 i_pm_driver_removed(major_t major)
8147 PMD_FUNC(pmf, "driver_removed")
8148 pm_noinvol_t *ip, *pp = NULL;
8149 int wasvolpmd;
8150 ASSERT(major != DDI_MAJOR_T_NONE);
8151 PMD(PMD_NOINVOL, ("%s: %s\n", pmf, ddi_major_to_name(major)))
8152 again:
8153 rw_enter(&pm_noinvol_rwlock, RW_WRITER);
8154 for (ip = pm_noinvol_head; ip; pp = ip, ip = ip->ni_next) {
8155 if (major != ip->ni_major)
8156 continue;
8158 * If it is an ancestor of no-invol node, which is
8159 * not removed, skip it. This is to cover the case of
8160 * ancestor removed without removing its descendants.
8162 if (pm_is_noinvol_ancestor(ip)) {
8163 ip->ni_flags |= PMC_DRIVER_REMOVED;
8164 continue;
8166 wasvolpmd = ip->ni_wasvolpmd;
8168 * remove the entry from the list
8170 if (pp) {
8171 PMD(PMD_NOINVOL, ("%s: freeing %s, prev is %s\n",
8172 pmf, ip->ni_path, pp->ni_path))
8173 pp->ni_next = ip->ni_next;
8174 } else {
8175 PMD(PMD_NOINVOL, ("%s: free %s head\n", pmf,
8176 ip->ni_path))
8177 ASSERT(pm_noinvol_head == ip);
8178 pm_noinvol_head = ip->ni_next;
8180 rw_exit(&pm_noinvol_rwlock);
8181 adjust_ancestors(ip->ni_path, wasvolpmd);
8183 * Had an ancestor been removed before this node, it would have
8184 * been skipped. Adjust the no-invol counters for such skipped
8185 * ancestors.
8187 pm_noinvol_process_ancestors(ip->ni_path);
8188 kmem_free(ip->ni_path, ip->ni_size);
8189 kmem_free(ip, sizeof (*ip));
8190 goto again;
8192 rw_exit(&pm_noinvol_rwlock);
8196 * returns 1, if *aip is a ancestor of a no-invol node
8197 * 0, otherwise
8199 static int
8200 pm_is_noinvol_ancestor(pm_noinvol_t *aip)
8202 pm_noinvol_t *ip;
8204 ASSERT(strlen(aip->ni_path) != 0);
8205 for (ip = pm_noinvol_head; ip; ip = ip->ni_next) {
8206 if (ip == aip)
8207 continue;
8209 * To be an ancestor, the path must be an initial substring of
8210 * the descendent, and end just before a '/' in the
8211 * descendent's path.
8213 if ((strstr(ip->ni_path, aip->ni_path) == ip->ni_path) &&
8214 (ip->ni_path[strlen(aip->ni_path)] == '/'))
8215 return (1);
8217 return (0);
8221 * scan through the pm_noinvolpm list adjusting ancestors of the current
8222 * node; Modifies string *path.
8224 static void
8225 adjust_ancestors(char *path, int wasvolpmd)
8227 PMD_FUNC(pmf, "adjust_ancestors")
8228 char *cp;
8229 pm_noinvol_t *lp;
8230 pm_noinvol_t *pp = NULL;
8231 major_t locked = DDI_MAJOR_T_NONE;
8232 dev_info_t *dip;
8233 char *pathbuf;
8234 size_t pathbuflen = strlen(path) + 1;
8237 * First we look up the ancestor's dip. If we find it, then we
8238 * adjust counts up the tree
8240 PMD(PMD_NOINVOL, ("%s: %s wasvolpmd %d\n", pmf, path, wasvolpmd))
8241 pathbuf = kmem_alloc(pathbuflen, KM_SLEEP);
8242 (void) strcpy(pathbuf, path);
8243 cp = strrchr(pathbuf, '/');
8244 if (cp == NULL) {
8245 /* if no ancestors, then nothing to do */
8246 kmem_free(pathbuf, pathbuflen);
8247 return;
8249 *cp = '\0';
8250 dip = pm_name_to_dip(pathbuf, 1);
8251 if (dip != NULL) {
8252 locked = PM_MAJOR(dip);
8254 (void) pm_noinvol_update(PM_BP_NOINVOL_REMDRV, 0, wasvolpmd,
8255 path, dip);
8257 if (locked != DDI_MAJOR_T_NONE)
8258 ddi_release_devi(dip);
8259 } else {
8260 char *apath;
8261 size_t len = strlen(pathbuf) + 1;
8262 int lock_held = 1;
8265 * Now check for ancestors that exist only in the list
8267 apath = kmem_alloc(len, KM_SLEEP);
8268 (void) strcpy(apath, pathbuf);
8269 rw_enter(&pm_noinvol_rwlock, RW_WRITER);
8270 for (lp = pm_noinvol_head; lp; pp = lp, lp = lp->ni_next) {
8272 * This can only happen once. Since we have to drop
8273 * the lock, we need to extract the relevant info.
8275 if (strcmp(pathbuf, lp->ni_path) == 0) {
8276 PMD(PMD_NOINVOL, ("%s: %s no %d -> %d\n", pmf,
8277 lp->ni_path, lp->ni_noinvolpm,
8278 lp->ni_noinvolpm - 1))
8279 lp->ni_noinvolpm--;
8280 if (wasvolpmd && lp->ni_volpmd) {
8281 PMD(PMD_NOINVOL, ("%s: %s vol %d -> "
8282 "%d\n", pmf, lp->ni_path,
8283 lp->ni_volpmd, lp->ni_volpmd - 1))
8284 lp->ni_volpmd--;
8287 * remove the entry from the list, if there
8288 * are no more no-invol descendants and node
8289 * itself is not a no-invol node.
8291 if (!(lp->ni_noinvolpm ||
8292 (lp->ni_flags & PMC_NO_INVOL))) {
8293 ASSERT(lp->ni_volpmd == 0);
8294 if (pp) {
8295 PMD(PMD_NOINVOL, ("%s: freeing "
8296 "%s, prev is %s\n", pmf,
8297 lp->ni_path, pp->ni_path))
8298 pp->ni_next = lp->ni_next;
8299 } else {
8300 PMD(PMD_NOINVOL, ("%s: free %s "
8301 "head\n", pmf, lp->ni_path))
8302 ASSERT(pm_noinvol_head == lp);
8303 pm_noinvol_head = lp->ni_next;
8305 lock_held = 0;
8306 rw_exit(&pm_noinvol_rwlock);
8307 adjust_ancestors(apath, wasvolpmd);
8308 /* restore apath */
8309 (void) strcpy(apath, pathbuf);
8310 kmem_free(lp->ni_path, lp->ni_size);
8311 kmem_free(lp, sizeof (*lp));
8313 break;
8316 if (lock_held)
8317 rw_exit(&pm_noinvol_rwlock);
8318 adjust_ancestors(apath, wasvolpmd);
8319 kmem_free(apath, len);
8321 kmem_free(pathbuf, pathbuflen);
8325 * Do no-invol processing for any ancestors i.e. adjust counters of ancestors,
8326 * which were skipped even though their drivers were removed.
8328 static void
8329 pm_noinvol_process_ancestors(char *path)
8331 pm_noinvol_t *lp;
8333 rw_enter(&pm_noinvol_rwlock, RW_READER);
8334 for (lp = pm_noinvol_head; lp; lp = lp->ni_next) {
8335 if (strstr(path, lp->ni_path) &&
8336 (lp->ni_flags & PMC_DRIVER_REMOVED)) {
8337 rw_exit(&pm_noinvol_rwlock);
8338 i_pm_driver_removed(lp->ni_major);
8339 return;
8342 rw_exit(&pm_noinvol_rwlock);
8346 * Returns true if (detached) device needs to be kept up because it exported the
8347 * "no-involuntary-power-cycles" property or we're pretending it did (console
8348 * fb case) or it is an ancestor of such a device and has used up the "one
8349 * free cycle" allowed when all such leaf nodes have voluntarily powered down
8350 * upon detach. In any event, we need an exact hit on the path or we return
8351 * false.
8354 pm_noinvol_detached(char *path)
8356 PMD_FUNC(pmf, "noinvol_detached")
8357 pm_noinvol_t *ip;
8358 int ret = 0;
8360 rw_enter(&pm_noinvol_rwlock, RW_READER);
8361 for (ip = pm_noinvol_head; ip; ip = ip->ni_next) {
8362 if (strcmp(path, ip->ni_path) == 0) {
8363 if (ip->ni_flags & PMC_CONSOLE_FB) {
8364 PMD(PMD_NOINVOL | PMD_CFB, ("%s: inhibits CFB "
8365 "%s\n", pmf, path))
8366 ret = 1;
8367 break;
8369 #ifdef DEBUG
8370 if (ip->ni_noinvolpm != ip->ni_volpmd)
8371 PMD(PMD_NOINVOL, ("%s: (%d != %d) inhibits %s"
8372 "\n", pmf, ip->ni_noinvolpm, ip->ni_volpmd,
8373 path))
8374 #endif
8375 ret = (ip->ni_noinvolpm != ip->ni_volpmd);
8376 break;
8379 rw_exit(&pm_noinvol_rwlock);
8380 return (ret);
8384 pm_is_cfb(dev_info_t *dip)
8386 return (dip == cfb_dip);
8389 #ifdef DEBUG
8391 * Return true if all components of the console frame buffer are at
8392 * "normal" power, i.e., fully on. For the case where the console is not
8393 * a framebuffer, we also return true
8396 pm_cfb_is_up(void)
8398 return (pm_cfb_comps_off == 0);
8400 #endif
8403 * Preventing scan from powering down the node by incrementing the
8404 * kidsupcnt.
8406 void
8407 pm_hold_power(dev_info_t *dip)
8409 e_pm_hold_rele_power(dip, 1);
8413 * Releasing the hold by decrementing the kidsupcnt allowing scan
8414 * to power down the node if all conditions are met.
8416 void
8417 pm_rele_power(dev_info_t *dip)
8419 e_pm_hold_rele_power(dip, -1);
8423 * A wrapper of pm_all_to_normal() to power up a dip
8424 * to its normal level
8427 pm_powerup(dev_info_t *dip)
8429 PMD_FUNC(pmf, "pm_powerup")
8431 PMD(PMD_ALLNORM, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
8432 ASSERT(!(servicing_interrupt()));
8435 * in case this node is not already participating pm
8437 if (!PM_GET_PM_INFO(dip)) {
8438 if (!DEVI_IS_ATTACHING(dip))
8439 return (DDI_SUCCESS);
8440 if (pm_start(dip) != DDI_SUCCESS)
8441 return (DDI_FAILURE);
8442 if (!PM_GET_PM_INFO(dip))
8443 return (DDI_SUCCESS);
8446 return (pm_all_to_normal(dip, PM_CANBLOCK_BLOCK));
8450 pm_rescan_walk(dev_info_t *dip, void *arg)
8452 _NOTE(ARGUNUSED(arg))
8454 if (!PM_GET_PM_INFO(dip) || PM_ISBC(dip))
8455 return (DDI_WALK_CONTINUE);
8458 * Currently pm_cpr_callb/resume code is the only caller
8459 * and it needs to make sure that stopped scan get
8460 * reactivated. Otherwise, rescan walk needn't reactive
8461 * stopped scan.
8463 pm_scan_init(dip);
8465 (void) pm_rescan(dip);
8466 return (DDI_WALK_CONTINUE);
8469 static dev_info_t *
8470 pm_get_next_descendent(dev_info_t *dip, dev_info_t *tdip)
8472 dev_info_t *wdip, *pdip;
8474 for (wdip = tdip; wdip != dip; wdip = pdip) {
8475 pdip = ddi_get_parent(wdip);
8476 if (pdip == dip)
8477 return (wdip);
8479 return (NULL);
8483 pm_busop_bus_power(dev_info_t *dip, void *impl_arg, pm_bus_power_op_t op,
8484 void *arg, void *result)
8486 PMD_FUNC(pmf, "bp_bus_power")
8487 dev_info_t *cdip;
8488 pm_info_t *cinfo;
8489 pm_bp_child_pwrchg_t *bpc;
8490 pm_sp_misc_t *pspm;
8491 pm_bp_nexus_pwrup_t *bpn;
8492 pm_bp_child_pwrchg_t new_bpc;
8493 pm_bp_noinvol_t *bpi;
8494 dev_info_t *tdip;
8495 char *pathbuf;
8496 int ret = DDI_SUCCESS;
8497 int errno = 0;
8498 pm_component_t *cp;
8500 PMD(PMD_SET, ("%s: %s@%s(%s#%d) %s\n", pmf, PM_DEVICE(dip),
8501 pm_decode_op(op)))
8502 switch (op) {
8503 case BUS_POWER_CHILD_PWRCHG:
8504 bpc = (pm_bp_child_pwrchg_t *)arg;
8505 pspm = (pm_sp_misc_t *)bpc->bpc_private;
8506 tdip = bpc->bpc_dip;
8507 cdip = pm_get_next_descendent(dip, tdip);
8508 cinfo = PM_GET_PM_INFO(cdip);
8509 if (cdip != tdip) {
8511 * If the node is an involved parent, it needs to
8512 * power up the node as it is needed. There is nothing
8513 * else the framework can do here.
8515 if (PM_WANTS_NOTIFICATION(cdip)) {
8516 PMD(PMD_SET, ("%s: call bus_power for "
8517 "%s@%s(%s#%d)\n", pmf, PM_DEVICE(cdip)))
8518 return ((*PM_BUS_POWER_FUNC(cdip))(cdip,
8519 impl_arg, op, arg, result));
8521 ASSERT(pspm->pspm_direction == PM_LEVEL_UPONLY ||
8522 pspm->pspm_direction == PM_LEVEL_DOWNONLY ||
8523 pspm->pspm_direction == PM_LEVEL_EXACT);
8525 * we presume that the parent needs to be up in
8526 * order for the child to change state (either
8527 * because it must already be on if the child is on
8528 * (and the pm_all_to_normal_nexus() will be a nop)
8529 * or because it will need to be on for the child
8530 * to come on; so we make the call regardless
8532 pm_hold_power(cdip);
8533 if (cinfo) {
8534 pm_canblock_t canblock = pspm->pspm_canblock;
8535 ret = pm_all_to_normal_nexus(cdip, canblock);
8536 if (ret != DDI_SUCCESS) {
8537 pm_rele_power(cdip);
8538 return (ret);
8541 PMD(PMD_SET, ("%s: walk down to %s@%s(%s#%d)\n", pmf,
8542 PM_DEVICE(cdip)))
8543 ret = pm_busop_bus_power(cdip, impl_arg, op, arg,
8544 result);
8545 pm_rele_power(cdip);
8546 } else {
8547 ret = pm_busop_set_power(cdip, impl_arg, op, arg,
8548 result);
8550 return (ret);
8552 case BUS_POWER_NEXUS_PWRUP:
8553 bpn = (pm_bp_nexus_pwrup_t *)arg;
8554 pspm = (pm_sp_misc_t *)bpn->bpn_private;
8556 if (!e_pm_valid_info(dip, NULL) ||
8557 !e_pm_valid_comp(dip, bpn->bpn_comp, &cp) ||
8558 !e_pm_valid_power(dip, bpn->bpn_comp, bpn->bpn_level)) {
8559 PMD(PMD_SET, ("%s: %s@%s(%s#%d) has no pm info; EIO\n",
8560 pmf, PM_DEVICE(dip)))
8561 *pspm->pspm_errnop = EIO;
8562 *(int *)result = DDI_FAILURE;
8563 return (DDI_FAILURE);
8566 ASSERT(bpn->bpn_dip == dip);
8567 PMD(PMD_SET, ("%s: nexus powerup for %s@%s(%s#%d)\n", pmf,
8568 PM_DEVICE(dip)))
8569 new_bpc.bpc_dip = dip;
8570 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
8571 new_bpc.bpc_path = ddi_pathname(dip, pathbuf);
8572 new_bpc.bpc_comp = bpn->bpn_comp;
8573 new_bpc.bpc_olevel = PM_CURPOWER(dip, bpn->bpn_comp);
8574 new_bpc.bpc_nlevel = bpn->bpn_level;
8575 new_bpc.bpc_private = bpn->bpn_private;
8576 ((pm_sp_misc_t *)(new_bpc.bpc_private))->pspm_direction =
8577 PM_LEVEL_UPONLY;
8578 ((pm_sp_misc_t *)(new_bpc.bpc_private))->pspm_errnop =
8579 &errno;
8580 ret = pm_busop_set_power(dip, impl_arg, BUS_POWER_CHILD_PWRCHG,
8581 (void *)&new_bpc, result);
8582 kmem_free(pathbuf, MAXPATHLEN);
8583 return (ret);
8585 case BUS_POWER_NOINVOL:
8586 bpi = (pm_bp_noinvol_t *)arg;
8587 tdip = bpi->bpni_dip;
8588 cdip = pm_get_next_descendent(dip, tdip);
8590 /* In case of rem_drv, the leaf node has been removed */
8591 if (cdip == NULL)
8592 return (DDI_SUCCESS);
8594 cinfo = PM_GET_PM_INFO(cdip);
8595 if (cdip != tdip) {
8596 if (PM_WANTS_NOTIFICATION(cdip)) {
8597 PMD(PMD_NOINVOL,
8598 ("%s: call bus_power for %s@%s(%s#%d)\n",
8599 pmf, PM_DEVICE(cdip)))
8600 ret = (*PM_BUS_POWER_FUNC(cdip))
8601 (cdip, NULL, op, arg, result);
8602 if ((cinfo) && (ret == DDI_SUCCESS))
8603 (void) pm_noinvol_update_node(cdip,
8604 bpi);
8605 return (ret);
8606 } else {
8607 PMD(PMD_NOINVOL,
8608 ("%s: walk down to %s@%s(%s#%d)\n", pmf,
8609 PM_DEVICE(cdip)))
8610 ret = pm_busop_bus_power(cdip, NULL, op,
8611 arg, result);
8613 * Update the current node.
8615 if ((cinfo) && (ret == DDI_SUCCESS))
8616 (void) pm_noinvol_update_node(cdip,
8617 bpi);
8618 return (ret);
8620 } else {
8622 * For attach, detach, power up:
8623 * Do nothing for leaf node since its
8624 * counts are already updated.
8625 * For CFB and driver removal, since the
8626 * path and the target dip passed in is up to and incl.
8627 * the immediate ancestor, need to do the update.
8629 PMD(PMD_NOINVOL, ("%s: target %s@%s(%s#%d) is "
8630 "reached\n", pmf, PM_DEVICE(cdip)))
8631 if (cinfo && ((bpi->bpni_cmd == PM_BP_NOINVOL_REMDRV) ||
8632 (bpi->bpni_cmd == PM_BP_NOINVOL_CFB)))
8633 (void) pm_noinvol_update_node(cdip, bpi);
8634 return (DDI_SUCCESS);
8637 default:
8638 PMD(PMD_SET, ("%s: operation %d is not supported!\n", pmf, op))
8639 return (DDI_FAILURE);
8643 static int
8644 pm_busop_set_power(dev_info_t *dip, void *impl_arg, pm_bus_power_op_t op,
8645 void *arg, void *resultp)
8647 _NOTE(ARGUNUSED(impl_arg))
8648 PMD_FUNC(pmf, "bp_set_power")
8649 pm_ppm_devlist_t *devl = NULL;
8650 int clevel, circ;
8651 #ifdef DEBUG
8652 int circ_db, ccirc_db;
8653 #endif
8654 int ret = DDI_SUCCESS;
8655 dev_info_t *cdip;
8656 pm_bp_child_pwrchg_t *bpc = (pm_bp_child_pwrchg_t *)arg;
8657 pm_sp_misc_t *pspm = (pm_sp_misc_t *)bpc->bpc_private;
8658 pm_canblock_t canblock = pspm->pspm_canblock;
8659 int scan = pspm->pspm_scan;
8660 int comp = bpc->bpc_comp;
8661 int olevel = bpc->bpc_olevel;
8662 int nlevel = bpc->bpc_nlevel;
8663 int comps_off_incr = 0;
8664 dev_info_t *pdip = ddi_get_parent(dip);
8665 int dodeps;
8666 int direction = pspm->pspm_direction;
8667 int *errnop = pspm->pspm_errnop;
8668 #ifdef PMDDEBUG
8669 char *dir = pm_decode_direction(direction);
8670 #endif
8671 int *iresp = (int *)resultp;
8672 time_t idletime, thresh;
8673 pm_component_t *cp = PM_CP(dip, comp);
8674 int work_type;
8676 *iresp = DDI_SUCCESS;
8677 *errnop = 0;
8678 ASSERT(op == BUS_POWER_CHILD_PWRCHG);
8679 PMD(PMD_SET, ("%s: %s@%s(%s#%d) %s\n", pmf, PM_DEVICE(dip),
8680 pm_decode_op(op)))
8683 * The following set of conditions indicate we are here to handle a
8684 * driver's pm_[raise|lower]_power request, but the device is being
8685 * power managed (PM_DIRECT_PM) by a user process. For that case
8686 * we want to pm_block and pass a status back to the caller based
8687 * on whether the controlling process's next activity on the device
8688 * matches the current request or not. This distinction tells
8689 * downstream functions to avoid calling into a driver or changing
8690 * the framework's power state. To actually block, we need:
8692 * PM_ISDIRECT(dip)
8693 * no reason to block unless a process is directly controlling dev
8694 * direction != PM_LEVEL_EXACT
8695 * EXACT is used by controlling proc's PM_SET_CURRENT_POWER ioctl
8696 * !pm_processes_stopped
8697 * don't block if controlling proc already be stopped for cpr
8698 * canblock != PM_CANBLOCK_BYPASS
8699 * our caller must not have explicitly prevented blocking
8701 if (direction != PM_LEVEL_EXACT && canblock != PM_CANBLOCK_BYPASS) {
8702 PM_LOCK_DIP(dip);
8703 while (PM_ISDIRECT(dip) && !pm_processes_stopped) {
8704 /* releases dip lock */
8705 ret = pm_busop_match_request(dip, bpc);
8706 if (ret == EAGAIN) {
8707 PM_LOCK_DIP(dip);
8708 continue;
8710 return (*iresp = ret);
8712 PM_UNLOCK_DIP(dip);
8714 /* BC device is never scanned, so power will stick until we are done */
8715 if (PM_ISBC(dip) && comp != 0 && nlevel != 0 &&
8716 direction != PM_LEVEL_DOWNONLY) {
8717 int nrmpwr0 = pm_get_normal_power(dip, 0);
8718 if (pm_set_power(dip, 0, nrmpwr0, direction,
8719 canblock, 0, resultp) != DDI_SUCCESS) {
8720 /* *resultp set by pm_set_power */
8721 return (DDI_FAILURE);
8724 if (PM_WANTS_NOTIFICATION(pdip)) {
8725 PMD(PMD_SET, ("%s: pre_notify %s@%s(%s#%d) for child "
8726 "%s@%s(%s#%d)\n", pmf, PM_DEVICE(pdip), PM_DEVICE(dip)))
8727 ret = (*PM_BUS_POWER_FUNC(pdip))(pdip, NULL,
8728 BUS_POWER_PRE_NOTIFICATION, bpc, resultp);
8729 if (ret != DDI_SUCCESS) {
8730 PMD(PMD_SET, ("%s: failed to pre_notify %s@%s(%s#%d)\n",
8731 pmf, PM_DEVICE(pdip)))
8732 return (DDI_FAILURE);
8734 } else {
8736 * Since we don't know what the actual power level is,
8737 * we place a power hold on the parent no matter what
8738 * component and level is changing.
8740 pm_hold_power(pdip);
8742 PM_LOCK_POWER(dip, &circ);
8743 clevel = PM_CURPOWER(dip, comp);
8745 * It's possible that a call was made to pm_update_maxpower()
8746 * on another thread before we took the lock above. So, we need to
8747 * make sure that this request isn't processed after the
8748 * change of power executed on behalf of pm_update_maxpower().
8750 if (nlevel > pm_get_normal_power(dip, comp)) {
8751 PMD(PMD_SET, ("%s: requested level is higher than normal.\n",
8752 pmf))
8753 ret = DDI_FAILURE;
8754 *iresp = DDI_FAILURE;
8755 goto post_notify;
8757 PMD(PMD_SET, ("%s: %s@%s(%s#%d), cmp=%d, olvl=%d, nlvl=%d, clvl=%d, "
8758 "dir=%s\n", pmf, PM_DEVICE(dip), comp, bpc->bpc_olevel, nlevel,
8759 clevel, dir))
8760 switch (direction) {
8761 case PM_LEVEL_UPONLY:
8762 /* Powering up */
8763 if (clevel >= nlevel) {
8764 PMD(PMD_SET, ("%s: current level is already "
8765 "at or above the requested level.\n", pmf))
8766 *iresp = DDI_SUCCESS;
8767 ret = DDI_SUCCESS;
8768 goto post_notify;
8770 break;
8771 case PM_LEVEL_EXACT:
8772 /* specific level request */
8773 if (clevel == nlevel && !PM_ISBC(dip)) {
8774 PMD(PMD_SET, ("%s: current level is already "
8775 "at the requested level.\n", pmf))
8776 *iresp = DDI_SUCCESS;
8777 ret = DDI_SUCCESS;
8778 goto post_notify;
8779 } else if (PM_IS_CFB(dip) && (nlevel < clevel)) {
8780 PMD(PMD_CFB, ("%s: powerdown of console\n", pmf))
8781 if (!pm_cfb_enabled) {
8782 PMD(PMD_ERROR | PMD_CFB,
8783 ("%s: !pm_cfb_enabled, fails\n", pmf))
8784 *errnop = EINVAL;
8785 *iresp = DDI_FAILURE;
8786 ret = DDI_FAILURE;
8787 goto post_notify;
8789 mutex_enter(&pm_cfb_lock);
8790 while (cfb_inuse) {
8791 mutex_exit(&pm_cfb_lock);
8792 if (delay_sig(1) == EINTR) {
8793 ret = DDI_FAILURE;
8794 *iresp = DDI_FAILURE;
8795 *errnop = EINTR;
8796 goto post_notify;
8798 mutex_enter(&pm_cfb_lock);
8800 mutex_exit(&pm_cfb_lock);
8802 break;
8803 case PM_LEVEL_DOWNONLY:
8804 /* Powering down */
8805 thresh = cur_threshold(dip, comp);
8806 idletime = gethrestime_sec() - cp->pmc_timestamp;
8807 if (scan && ((PM_KUC(dip) != 0) ||
8808 (cp->pmc_busycount > 0) ||
8809 ((idletime < thresh) && !PM_IS_PID(dip)))) {
8810 #ifdef DEBUG
8811 if (DEVI(dip)->devi_pm_kidsupcnt != 0)
8812 PMD(PMD_SET, ("%s: scan failed: "
8813 "kidsupcnt != 0\n", pmf))
8814 if (cp->pmc_busycount > 0)
8815 PMD(PMD_SET, ("%s: scan failed: "
8816 "device become busy\n", pmf))
8817 if (idletime < thresh)
8818 PMD(PMD_SET, ("%s: scan failed: device "
8819 "hasn't been idle long enough\n", pmf))
8820 #endif
8821 *iresp = DDI_FAILURE;
8822 *errnop = EBUSY;
8823 ret = DDI_FAILURE;
8824 goto post_notify;
8825 } else if (clevel != PM_LEVEL_UNKNOWN && clevel <= nlevel) {
8826 PMD(PMD_SET, ("%s: current level is already at "
8827 "or below the requested level.\n", pmf))
8828 *iresp = DDI_SUCCESS;
8829 ret = DDI_SUCCESS;
8830 goto post_notify;
8832 break;
8835 if (PM_IS_CFB(dip) && (comps_off_incr =
8836 calc_cfb_comps_incr(dip, comp, clevel, nlevel)) > 0) {
8838 * Pre-adjust pm_cfb_comps_off if lowering a console fb
8839 * component from full power. Remember that we tried to
8840 * lower power in case it fails and we need to back out
8841 * the adjustment.
8843 update_comps_off(comps_off_incr, dip);
8844 PMD(PMD_CFB, ("%s: %s@%s(%s#%d)[%d] %d->%d cfb_comps_off->%d\n",
8845 pmf, PM_DEVICE(dip), comp, clevel, nlevel,
8846 pm_cfb_comps_off))
8849 if ((*iresp = power_dev(dip,
8850 comp, nlevel, clevel, canblock, &devl)) == DDI_SUCCESS) {
8851 #ifdef DEBUG
8853 * All descendents of this node should already be powered off.
8855 if (PM_CURPOWER(dip, comp) == 0) {
8856 pm_desc_pwrchk_t pdpchk;
8857 pdpchk.pdpc_dip = dip;
8858 pdpchk.pdpc_par_involved = PM_WANTS_NOTIFICATION(dip);
8859 ndi_devi_enter(dip, &circ_db);
8860 for (cdip = ddi_get_child(dip); cdip != NULL;
8861 cdip = ddi_get_next_sibling(cdip)) {
8862 ndi_devi_enter(cdip, &ccirc_db);
8863 ddi_walk_devs(cdip, pm_desc_pwrchk_walk,
8864 (void *)&pdpchk);
8865 ndi_devi_exit(cdip, ccirc_db);
8867 ndi_devi_exit(dip, circ_db);
8869 #endif
8871 * Post-adjust pm_cfb_comps_off if we brought an fb component
8872 * back up to full power.
8874 if (PM_IS_CFB(dip) && comps_off_incr < 0) {
8875 update_comps_off(comps_off_incr, dip);
8876 PMD(PMD_CFB, ("%s: %s@%s(%s#%d)[%d] %d->%d "
8877 "cfb_comps_off->%d\n", pmf, PM_DEVICE(dip),
8878 comp, clevel, nlevel, pm_cfb_comps_off))
8880 dodeps = 0;
8881 if (POWERING_OFF(clevel, nlevel)) {
8882 if (PM_ISBC(dip)) {
8883 dodeps = (comp == 0);
8884 } else {
8885 int i;
8886 dodeps = 1;
8887 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
8888 /* if some component still on */
8889 if (PM_CURPOWER(dip, i)) {
8890 dodeps = 0;
8891 break;
8895 if (dodeps)
8896 work_type = PM_DEP_WK_POWER_OFF;
8897 } else if (POWERING_ON(clevel, nlevel)) {
8898 if (PM_ISBC(dip)) {
8899 dodeps = (comp == 0);
8900 } else {
8901 int i;
8902 dodeps = 1;
8903 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
8904 if (i == comp)
8905 continue;
8906 if (PM_CURPOWER(dip, i) > 0) {
8907 dodeps = 0;
8908 break;
8912 if (dodeps)
8913 work_type = PM_DEP_WK_POWER_ON;
8916 if (dodeps) {
8917 char *pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
8919 (void) ddi_pathname(dip, pathbuf);
8920 pm_dispatch_to_dep_thread(work_type, pathbuf, NULL,
8921 PM_DEP_NOWAIT, NULL, 0);
8922 kmem_free(pathbuf, MAXPATHLEN);
8924 if ((PM_CURPOWER(dip, comp) == nlevel) && pm_watchers()) {
8925 int old;
8927 /* If old power cached during deadlock, use it. */
8928 old = (cp->pmc_flags & PM_PHC_WHILE_SET_POWER ?
8929 cp->pmc_phc_pwr : olevel);
8930 mutex_enter(&pm_rsvp_lock);
8931 pm_enqueue_notify(PSC_HAS_CHANGED, dip, comp, nlevel,
8932 old, canblock);
8933 pm_enqueue_notify_others(&devl, canblock);
8934 mutex_exit(&pm_rsvp_lock);
8935 } else {
8936 pm_ppm_devlist_t *p;
8937 pm_ppm_devlist_t *next;
8938 for (p = devl; p != NULL; p = next) {
8939 next = p->ppd_next;
8940 kmem_free(p, sizeof (pm_ppm_devlist_t));
8942 devl = NULL;
8946 * If we are coming from a scan, don't do it again,
8947 * else we can have infinite loops.
8949 if (!scan)
8950 pm_rescan(dip);
8951 } else {
8952 /* if we incremented pm_comps_off_count, but failed */
8953 if (comps_off_incr > 0) {
8954 update_comps_off(-comps_off_incr, dip);
8955 PMD(PMD_CFB, ("%s: %s@%s(%s#%d)[%d] %d->%d "
8956 "cfb_comps_off->%d\n", pmf, PM_DEVICE(dip),
8957 comp, clevel, nlevel, pm_cfb_comps_off))
8959 *errnop = EIO;
8962 post_notify:
8964 * This thread may have been in deadlock with pm_power_has_changed.
8965 * Before releasing power lock, clear the flag which marks this
8966 * condition.
8968 cp->pmc_flags &= ~PM_PHC_WHILE_SET_POWER;
8971 * Update the old power level in the bus power structure with the
8972 * actual power level before the transition was made to the new level.
8973 * Some involved parents depend on this information to keep track of
8974 * their children's power transition.
8976 if (*iresp != DDI_FAILURE)
8977 bpc->bpc_olevel = clevel;
8979 if (PM_WANTS_NOTIFICATION(pdip)) {
8980 ret = (*PM_BUS_POWER_FUNC(pdip))(pdip, NULL,
8981 BUS_POWER_POST_NOTIFICATION, bpc, resultp);
8982 PM_UNLOCK_POWER(dip, circ);
8983 PMD(PMD_SET, ("%s: post_notify %s@%s(%s#%d) for "
8984 "child %s@%s(%s#%d), ret=%d\n", pmf, PM_DEVICE(pdip),
8985 PM_DEVICE(dip), ret))
8986 } else {
8987 nlevel = cur_power(cp); /* in case phc deadlock updated pwr */
8988 PM_UNLOCK_POWER(dip, circ);
8990 * Now that we know what power transition has occurred
8991 * (if any), release the power hold. Leave the hold
8992 * in effect in the case of OFF->ON transition.
8994 if (!(clevel == 0 && nlevel > 0 &&
8995 (!PM_ISBC(dip) || comp == 0)))
8996 pm_rele_power(pdip);
8998 * If the power transition was an ON->OFF transition,
8999 * remove the power hold from the parent.
9001 if ((clevel > 0 || clevel == PM_LEVEL_UNKNOWN) &&
9002 nlevel == 0 && (!PM_ISBC(dip) || comp == 0))
9003 pm_rele_power(pdip);
9005 if (*iresp != DDI_SUCCESS || ret != DDI_SUCCESS)
9006 return (DDI_FAILURE);
9007 else
9008 return (DDI_SUCCESS);
9012 * If an app (SunVTS or Xsun) has taken control, then block until it
9013 * gives it up or makes the requested power level change, unless
9014 * we have other instructions about blocking. Returns DDI_SUCCESS,
9015 * DDI_FAILURE or EAGAIN (owner released device from directpm).
9017 static int
9018 pm_busop_match_request(dev_info_t *dip, void *arg)
9020 PMD_FUNC(pmf, "bp_match_request")
9021 pm_bp_child_pwrchg_t *bpc = (pm_bp_child_pwrchg_t *)arg;
9022 pm_sp_misc_t *pspm = (pm_sp_misc_t *)bpc->bpc_private;
9023 int comp = bpc->bpc_comp;
9024 int nlevel = bpc->bpc_nlevel;
9025 pm_canblock_t canblock = pspm->pspm_canblock;
9026 int direction = pspm->pspm_direction;
9027 int clevel, circ;
9029 ASSERT(PM_IAM_LOCKING_DIP(dip));
9030 PM_LOCK_POWER(dip, &circ);
9031 clevel = PM_CURPOWER(dip, comp);
9032 PMD(PMD_SET, ("%s: %s@%s(%s#%d), cmp=%d, nlvl=%d, clvl=%d\n",
9033 pmf, PM_DEVICE(dip), comp, nlevel, clevel))
9034 if (direction == PM_LEVEL_UPONLY) {
9035 if (clevel >= nlevel) {
9036 PM_UNLOCK_POWER(dip, circ);
9037 PM_UNLOCK_DIP(dip);
9038 return (DDI_SUCCESS);
9040 } else if (clevel == nlevel) {
9041 PM_UNLOCK_POWER(dip, circ);
9042 PM_UNLOCK_DIP(dip);
9043 return (DDI_SUCCESS);
9045 if (canblock == PM_CANBLOCK_FAIL) {
9046 PM_UNLOCK_POWER(dip, circ);
9047 PM_UNLOCK_DIP(dip);
9048 return (DDI_FAILURE);
9050 if (canblock == PM_CANBLOCK_BLOCK) {
9052 * To avoid a deadlock, we must not hold the
9053 * power lock when we pm_block.
9055 PM_UNLOCK_POWER(dip, circ);
9056 PMD(PMD_SET, ("%s: blocking\n", pmf))
9057 /* pm_block releases dip lock */
9058 switch (pm_block(dip, comp, nlevel, clevel)) {
9059 case PMP_RELEASE:
9060 return (EAGAIN);
9061 case PMP_SUCCEED:
9062 return (DDI_SUCCESS);
9063 case PMP_FAIL:
9064 return (DDI_FAILURE);
9066 } else {
9067 ASSERT(0);
9069 _NOTE(NOTREACHED);
9070 return (DDI_FAILURE); /* keep gcc happy */
9073 static int
9074 pm_all_to_normal_nexus(dev_info_t *dip, pm_canblock_t canblock)
9076 PMD_FUNC(pmf, "all_to_normal_nexus")
9077 int *normal;
9078 int i, ncomps;
9079 size_t size;
9080 int changefailed = 0;
9081 int ret, result = DDI_SUCCESS;
9082 pm_bp_nexus_pwrup_t bpn;
9083 pm_sp_misc_t pspm;
9085 ASSERT(PM_GET_PM_INFO(dip));
9086 PMD(PMD_ALLNORM, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
9087 if (pm_get_norm_pwrs(dip, &normal, &size) != DDI_SUCCESS) {
9088 PMD(PMD_ALLNORM, ("%s: can't get norm pwrs\n", pmf))
9089 return (DDI_FAILURE);
9091 ncomps = PM_NUMCMPTS(dip);
9092 for (i = 0; i < ncomps; i++) {
9093 bpn.bpn_dip = dip;
9094 bpn.bpn_comp = i;
9095 bpn.bpn_level = normal[i];
9096 pspm.pspm_canblock = canblock;
9097 pspm.pspm_scan = 0;
9098 bpn.bpn_private = &pspm;
9099 ret = pm_busop_bus_power(dip, NULL, BUS_POWER_NEXUS_PWRUP,
9100 (void *)&bpn, (void *)&result);
9101 if (ret != DDI_SUCCESS || result != DDI_SUCCESS) {
9102 PMD(PMD_FAIL | PMD_ALLNORM, ("%s: %s@%s(%s#%d)[%d] "
9103 "->%d failure result %d\n", pmf, PM_DEVICE(dip),
9104 i, normal[i], result))
9105 changefailed++;
9108 kmem_free(normal, size);
9109 if (changefailed) {
9110 PMD(PMD_FAIL, ("%s: failed to set %d comps %s@%s(%s#%d) "
9111 "full power\n", pmf, changefailed, PM_DEVICE(dip)))
9112 return (DDI_FAILURE);
9114 return (DDI_SUCCESS);
9118 pm_noinvol_update(int subcmd, int volpmd, int wasvolpmd, char *path,
9119 dev_info_t *tdip)
9121 PMD_FUNC(pmf, "noinvol_update")
9122 pm_bp_noinvol_t args;
9123 int ret;
9124 int result = DDI_SUCCESS;
9126 args.bpni_path = path;
9127 args.bpni_dip = tdip;
9128 args.bpni_cmd = subcmd;
9129 args.bpni_wasvolpmd = wasvolpmd;
9130 args.bpni_volpmd = volpmd;
9131 PMD(PMD_NOINVOL, ("%s: update for path %s tdip %p subcmd %d "
9132 "volpmd %d wasvolpmd %d\n", pmf,
9133 path, (void *)tdip, subcmd, wasvolpmd, volpmd))
9134 ret = pm_busop_bus_power(ddi_root_node(), NULL, BUS_POWER_NOINVOL,
9135 &args, &result);
9136 return (ret);
9139 void
9140 pm_noinvol_update_node(dev_info_t *dip, pm_bp_noinvol_t *req)
9142 PMD_FUNC(pmf, "noinvol_update_node")
9144 PMD(PMD_NOINVOL, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
9145 switch (req->bpni_cmd) {
9146 case PM_BP_NOINVOL_ATTACH:
9147 PMD(PMD_NOINVOL, ("%s: PM_PB_NOINVOL_ATTACH %s@%s(%s#%d) "
9148 "noinvol %d->%d\n", pmf, PM_DEVICE(dip),
9149 DEVI(dip)->devi_pm_noinvolpm,
9150 DEVI(dip)->devi_pm_noinvolpm - 1))
9151 ASSERT(DEVI(dip)->devi_pm_noinvolpm);
9152 PM_LOCK_DIP(dip);
9153 DEVI(dip)->devi_pm_noinvolpm--;
9154 if (req->bpni_wasvolpmd) {
9155 PMD(PMD_NOINVOL, ("%s: PM_BP_NOINVOL_ATTACH "
9156 "%s@%s(%s#%d) volpmd %d->%d\n", pmf,
9157 PM_DEVICE(dip), DEVI(dip)->devi_pm_volpmd,
9158 DEVI(dip)->devi_pm_volpmd - 1))
9159 if (DEVI(dip)->devi_pm_volpmd)
9160 DEVI(dip)->devi_pm_volpmd--;
9162 PM_UNLOCK_DIP(dip);
9163 break;
9165 case PM_BP_NOINVOL_DETACH:
9166 PMD(PMD_NOINVOL, ("%s: PM_BP_NOINVOL_DETACH %s@%s(%s#%d) "
9167 "noinvolpm %d->%d\n", pmf, PM_DEVICE(dip),
9168 DEVI(dip)->devi_pm_noinvolpm,
9169 DEVI(dip)->devi_pm_noinvolpm + 1))
9170 PM_LOCK_DIP(dip);
9171 DEVI(dip)->devi_pm_noinvolpm++;
9172 if (req->bpni_wasvolpmd) {
9173 PMD(PMD_NOINVOL, ("%s: PM_BP_NOINVOL_DETACH "
9174 "%s@%s(%s#%d) volpmd %d->%d\n", pmf,
9175 PM_DEVICE(dip), DEVI(dip)->devi_pm_volpmd,
9176 DEVI(dip)->devi_pm_volpmd + 1))
9177 DEVI(dip)->devi_pm_volpmd++;
9179 PM_UNLOCK_DIP(dip);
9180 break;
9182 case PM_BP_NOINVOL_REMDRV:
9183 PMD(PMD_NOINVOL, ("%s: PM_BP_NOINVOL_REMDRV %s@%s(%s#%d) "
9184 "noinvol %d->%d\n", pmf, PM_DEVICE(dip),
9185 DEVI(dip)->devi_pm_noinvolpm,
9186 DEVI(dip)->devi_pm_noinvolpm - 1))
9187 ASSERT(DEVI(dip)->devi_pm_noinvolpm);
9188 PM_LOCK_DIP(dip);
9189 DEVI(dip)->devi_pm_noinvolpm--;
9190 if (req->bpni_wasvolpmd) {
9191 PMD(PMD_NOINVOL,
9192 ("%s: PM_BP_NOINVOL_REMDRV %s@%s(%s#%d) "
9193 "volpmd %d->%d\n", pmf, PM_DEVICE(dip),
9194 DEVI(dip)->devi_pm_volpmd,
9195 DEVI(dip)->devi_pm_volpmd - 1))
9197 * A power up could come in between and
9198 * clear the volpmd, if that's the case,
9199 * volpmd would be clear.
9201 if (DEVI(dip)->devi_pm_volpmd)
9202 DEVI(dip)->devi_pm_volpmd--;
9204 PM_UNLOCK_DIP(dip);
9205 break;
9207 case PM_BP_NOINVOL_CFB:
9208 PMD(PMD_NOINVOL,
9209 ("%s: PM_BP_NOIVOL_CFB %s@%s(%s#%d) noinvol %d->%d\n",
9210 pmf, PM_DEVICE(dip), DEVI(dip)->devi_pm_noinvolpm,
9211 DEVI(dip)->devi_pm_noinvolpm + 1))
9212 PM_LOCK_DIP(dip);
9213 DEVI(dip)->devi_pm_noinvolpm++;
9214 PM_UNLOCK_DIP(dip);
9215 break;
9217 case PM_BP_NOINVOL_POWER:
9218 PMD(PMD_NOINVOL,
9219 ("%s: PM_BP_NOIVOL_PWR %s@%s(%s#%d) volpmd %d->%d\n",
9220 pmf, PM_DEVICE(dip),
9221 DEVI(dip)->devi_pm_volpmd, DEVI(dip)->devi_pm_volpmd -
9222 req->bpni_volpmd))
9223 PM_LOCK_DIP(dip);
9224 DEVI(dip)->devi_pm_volpmd -= req->bpni_volpmd;
9225 PM_UNLOCK_DIP(dip);
9226 break;
9228 default:
9229 break;
9234 #ifdef DEBUG
9235 static int
9236 pm_desc_pwrchk_walk(dev_info_t *dip, void *arg)
9238 PMD_FUNC(pmf, "desc_pwrchk")
9239 pm_desc_pwrchk_t *pdpchk = (pm_desc_pwrchk_t *)arg;
9240 pm_info_t *info = PM_GET_PM_INFO(dip);
9241 int i;
9242 int curpwr, ce_level;
9244 if (!info)
9245 return (DDI_WALK_CONTINUE);
9247 PMD(PMD_SET, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
9248 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
9249 if ((curpwr = PM_CURPOWER(dip, i)) == 0)
9250 continue;
9251 /* E_FUNC_SET_NOT_USED */
9252 ce_level = (pdpchk->pdpc_par_involved == 0) ? CE_PANIC :
9253 CE_WARN;
9254 PMD(PMD_SET, ("%s: %s@%s(%s#%d) is powered off while desc "
9255 "%s@%s(%s#%d)[%d] is at %d\n", pmf,
9256 PM_DEVICE(pdpchk->pdpc_dip), PM_DEVICE(dip), i, curpwr))
9257 cmn_err(ce_level, "!device %s@%s(%s#%d) is powered on, "
9258 "while its ancestor, %s@%s(%s#%d), is powering off!",
9259 PM_DEVICE(dip), PM_DEVICE(pdpchk->pdpc_dip));
9261 return (DDI_WALK_CONTINUE);
9263 #endif
9266 * Record the fact that one thread is borrowing the lock on a device node.
9267 * Use is restricted to the case where the lending thread will block until
9268 * the borrowing thread (always curthread) completes.
9270 void
9271 pm_borrow_lock(kthread_t *lender)
9273 lock_loan_t *prev = &lock_loan_head;
9274 lock_loan_t *cur = (lock_loan_t *)kmem_zalloc(sizeof (*cur), KM_SLEEP);
9276 cur->pmlk_borrower = curthread;
9277 cur->pmlk_lender = lender;
9278 mutex_enter(&pm_loan_lock);
9279 cur->pmlk_next = prev->pmlk_next;
9280 prev->pmlk_next = cur;
9281 mutex_exit(&pm_loan_lock);
9285 * Return the borrowed lock. A thread can borrow only one.
9287 void
9288 pm_return_lock(void)
9290 lock_loan_t *cur;
9291 lock_loan_t *prev = &lock_loan_head;
9293 mutex_enter(&pm_loan_lock);
9294 ASSERT(prev->pmlk_next != NULL);
9295 for (cur = prev->pmlk_next; cur; prev = cur, cur = cur->pmlk_next)
9296 if (cur->pmlk_borrower == curthread)
9297 break;
9299 ASSERT(cur != NULL);
9300 prev->pmlk_next = cur->pmlk_next;
9301 mutex_exit(&pm_loan_lock);
9302 kmem_free(cur, sizeof (*cur));
9305 #if defined(__x86)
9307 #define CPR_RXR 0x1
9308 #define CPR_TXR 0x20
9309 #define CPR_DATAREG 0x3f8
9310 #define CPR_LSTAT 0x3fd
9311 #define CPR_INTRCTL 0x3f9
9313 char
9314 pm_getchar(void)
9316 while ((inb(CPR_LSTAT) & CPR_RXR) != CPR_RXR)
9317 drv_usecwait(10);
9319 return (inb(CPR_DATAREG));
9323 void
9324 pm_putchar(char c)
9326 while ((inb(CPR_LSTAT) & CPR_TXR) == 0)
9327 drv_usecwait(10);
9329 outb(CPR_DATAREG, c);
9332 void
9333 pm_printf(char *s)
9335 while (*s) {
9336 pm_putchar(*s++);
9340 #endif
9343 pm_ppm_searchlist(pm_searchargs_t *sp)
9345 power_req_t power_req;
9346 int result = 0;
9347 int ret;
9349 power_req.request_type = PMR_PPM_SEARCH_LIST;
9350 power_req.req.ppm_search_list_req.searchlist = sp;
9351 ASSERT(DEVI(ddi_root_node())->devi_pm_ppm);
9352 ret = pm_ctlops((dev_info_t *)DEVI(ddi_root_node())->devi_pm_ppm,
9353 ddi_root_node(), DDI_CTLOPS_POWER, &power_req, &result);
9354 PMD(PMD_SX, ("pm_ppm_searchlist returns %d, result %d\n",
9355 ret, result))
9356 return (result);