Merge commit '7e934d3acc051b7ee3ef0d11571fd1225800a607'
[unleashed.git] / kernel / os / sunpm.c
blobefbf0db789161f72e4ecb6aaebaad4e14dcf9192
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(8)
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(8) 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;
367 * on sparc these live in fillsysinfo.c
369 * If this variable is non-zero, cpr should return "not supported" when
370 * it is queried even though it would normally be supported on this platform.
372 int cpr_supported_override;
375 * Some platforms may need to support CPR even in the absence of
376 * having the correct platform id information. If this
377 * variable is non-zero, cpr should proceed even in the absence
378 * of otherwise being qualified.
380 int cpr_platform_enable = 0;
384 * pm_S3_enabled indicates that we believe the platform can support S3,
385 * which we get from pmconfig(8)
387 int pm_S3_enabled;
390 * This flag is true while processes are stopped for a checkpoint/resume.
391 * Controlling processes of direct pm'd devices are not available to
392 * participate in power level changes, so we bypass them when this is set.
394 static int pm_processes_stopped;
396 #ifdef DEBUG
399 * see include/sys/epm.h for PMD_* values
402 uint_t pm_debug = 0;
405 * If pm_divertdebug is set, then no prom_printf calls will be made by
406 * PMD(), which will prevent debug output from bringing up the console
407 * frame buffer. Clearing this variable before setting pm_debug will result
408 * in PMD output going to the console.
410 * pm_divertdebug is incremented in pm_set_power() if dip == cfb_dip to avoid
411 * deadlocks and decremented at the end of pm_set_power()
413 uint_t pm_divertdebug = 1;
414 volatile uint_t pm_debug_to_console = 0;
415 kmutex_t pm_debug_lock; /* protects pm_divertdebug */
417 void prdeps(char *);
418 #endif
420 /* Globals */
423 * List of recorded thresholds and dependencies
425 pm_thresh_rec_t *pm_thresh_head;
426 krwlock_t pm_thresh_rwlock;
428 pm_pdr_t *pm_dep_head;
429 static int pm_unresolved_deps = 0;
430 static int pm_prop_deps = 0;
433 * List of devices that exported no-involuntary-power-cycles property
435 pm_noinvol_t *pm_noinvol_head;
438 * Locks used in noinvol processing
440 krwlock_t pm_noinvol_rwlock;
441 kmutex_t pm_remdrv_lock;
443 int pm_default_idle_threshold = PM_DEFAULT_SYS_IDLENESS;
444 int pm_system_idle_threshold;
445 int pm_cpu_idle_threshold;
448 * By default nexus has 0 threshold, and depends on its children to keep it up
450 int pm_default_nexus_threshold = 0;
453 * Data structures shared with common/io/pm.c
455 kmutex_t pm_clone_lock;
456 kcondvar_t pm_clones_cv[PM_MAX_CLONE];
457 uint_t pm_poll_cnt[PM_MAX_CLONE]; /* count of events for poll */
458 unsigned char pm_interest[PM_MAX_CLONE];
459 struct pollhead pm_pollhead;
462 * Data structures shared with common/io/srn.c
464 kmutex_t srn_clone_lock; /* protects srn_signal, srn_inuse */
465 void (*srn_signal)(int type, int event);
466 int srn_inuse; /* stop srn detach */
468 extern int hz;
469 extern char *platform_module_list[];
472 * Wrappers for use in ddi_walk_devs
475 static int pm_set_dev_thr_walk(dev_info_t *, void *);
476 static int pm_restore_direct_lvl_walk(dev_info_t *, void *);
477 static int pm_save_direct_lvl_walk(dev_info_t *, void *);
478 static int pm_discard_dep_walk(dev_info_t *, void *);
479 #ifdef DEBUG
480 static int pm_desc_pwrchk_walk(dev_info_t *, void *);
481 #endif
484 * Routines for managing noinvol devices
486 int pm_noinvol_update(int, int, int, char *, dev_info_t *);
487 void pm_noinvol_update_node(dev_info_t *,
488 pm_bp_noinvol_t *req);
490 kmutex_t pm_rsvp_lock;
491 kmutex_t pm_compcnt_lock;
492 krwlock_t pm_pscc_direct_rwlock;
493 krwlock_t pm_pscc_interest_rwlock;
495 #define PSC_INTEREST 0 /* belongs to interest psc list */
496 #define PSC_DIRECT 1 /* belongs to direct psc list */
498 pscc_t *pm_pscc_interest;
499 pscc_t *pm_pscc_direct;
501 #define PM_MAJOR(dip) ddi_driver_major(dip)
502 #define PM_IS_NEXUS(dip) ((PM_MAJOR(dip) == DDI_MAJOR_T_NONE) ? 0 : \
503 NEXUS_DRV(devopsp[PM_MAJOR(dip)]))
504 #define POWERING_ON(old, new) ((old) == 0 && (new) != 0)
505 #define POWERING_OFF(old, new) ((old) != 0 && (new) == 0)
507 #define PM_INCR_NOTLOWEST(dip) { \
508 mutex_enter(&pm_compcnt_lock); \
509 if (!PM_IS_NEXUS(dip) || \
510 (DEVI(dip)->devi_pm_flags & (PMC_DEV_THRESH|PMC_COMP_THRESH))) {\
511 if (pm_comps_notlowest == 0) \
512 pm_ppm_notify_all_lowest(dip, PM_NOT_ALL_LOWEST);\
513 pm_comps_notlowest++; \
514 PMD(PMD_LEVEL, ("%s: %s@%s(%s#%d) incr notlowest->%d\n",\
515 pmf, PM_DEVICE(dip), pm_comps_notlowest)) \
517 mutex_exit(&pm_compcnt_lock); \
519 #define PM_DECR_NOTLOWEST(dip) { \
520 mutex_enter(&pm_compcnt_lock); \
521 if (!PM_IS_NEXUS(dip) || \
522 (DEVI(dip)->devi_pm_flags & (PMC_DEV_THRESH|PMC_COMP_THRESH))) {\
523 ASSERT(pm_comps_notlowest); \
524 pm_comps_notlowest--; \
525 PMD(PMD_LEVEL, ("%s: %s@%s(%s#%d) decr notlowest to " \
526 "%d\n", pmf, PM_DEVICE(dip), pm_comps_notlowest))\
527 if (pm_comps_notlowest == 0) \
528 pm_ppm_notify_all_lowest(dip, PM_ALL_LOWEST); \
530 mutex_exit(&pm_compcnt_lock); \
534 * console frame-buffer power-management is not enabled when
535 * debugging services are present. to override, set pm_cfb_override
536 * to non-zero.
538 uint_t pm_cfb_comps_off = 0; /* PM_LEVEL_UNKNOWN is considered on */
539 kmutex_t pm_cfb_lock;
540 int pm_cfb_enabled = 1; /* non-zero allows pm of console frame buffer */
541 #ifdef DEBUG
542 int pm_cfb_override = 1; /* non-zero allows pm of cfb with debuggers */
543 #else
544 int pm_cfb_override = 0; /* non-zero allows pm of cfb with debuggers */
545 #endif
547 static dev_info_t *cfb_dip = 0;
548 static dev_info_t *cfb_dip_detaching = 0;
549 uint_t cfb_inuse = 0;
550 static ddi_softintr_t pm_soft_id;
551 static boolean_t pm_soft_pending;
552 int pm_scans_disabled = 0;
555 * A structure to record the fact that one thread has borrowed a lock held
556 * by another thread. The context requires that the lender block on the
557 * completion of the borrower.
559 typedef struct lock_loan {
560 struct lock_loan *pmlk_next;
561 kthread_t *pmlk_borrower;
562 kthread_t *pmlk_lender;
563 dev_info_t *pmlk_dip;
564 } lock_loan_t;
565 static lock_loan_t lock_loan_head; /* list head is a dummy element */
567 #ifdef DEBUG
568 #ifdef PMDDEBUG
569 #define PMD_FUNC(func, name) char *(func) = (name);
570 #else /* !PMDDEBUG */
571 #define PMD_FUNC(func, name)
572 #endif /* PMDDEBUG */
573 #else /* !DEBUG */
574 #define PMD_FUNC(func, name)
575 #endif /* DEBUG */
579 * Must be called before first device (including pseudo) attach
581 void
582 pm_init_locks(void)
584 mutex_init(&pm_scan_lock, NULL, MUTEX_DRIVER, NULL);
585 mutex_init(&pm_rsvp_lock, NULL, MUTEX_DRIVER, NULL);
586 mutex_init(&pm_compcnt_lock, NULL, MUTEX_DRIVER, NULL);
587 mutex_init(&pm_dep_thread_lock, NULL, MUTEX_DRIVER, NULL);
588 mutex_init(&pm_remdrv_lock, NULL, MUTEX_DRIVER, NULL);
589 mutex_init(&pm_loan_lock, NULL, MUTEX_DRIVER, NULL);
590 rw_init(&pm_thresh_rwlock, NULL, RW_DEFAULT, NULL);
591 rw_init(&pm_noinvol_rwlock, NULL, RW_DEFAULT, NULL);
592 cv_init(&pm_dep_thread_cv, NULL, CV_DEFAULT, NULL);
595 static int pm_reset_timestamps(dev_info_t *, void *);
597 static boolean_t
598 pm_cpr_callb(void *arg, int code)
600 _NOTE(ARGUNUSED(arg))
601 static int auto_save;
602 static pm_cpupm_t cpupm_save;
604 switch (code) {
605 case CB_CODE_CPR_CHKPT:
607 * Cancel scan or wait for scan in progress to finish
608 * Other threads may be trying to restart the scan, so we
609 * have to keep at it unil it sticks
611 mutex_enter(&pm_scan_lock);
612 ASSERT(!pm_scans_disabled);
613 pm_scans_disabled = 1;
614 auto_save = autopm_enabled;
615 autopm_enabled = 0;
616 cpupm_save = cpupm;
617 cpupm = PM_CPUPM_NOTSET;
618 mutex_exit(&pm_scan_lock);
619 ddi_walk_devs(ddi_root_node(), pm_scan_stop_walk, NULL);
620 break;
622 case CB_CODE_CPR_RESUME:
623 ASSERT(!autopm_enabled);
624 ASSERT(cpupm == PM_CPUPM_NOTSET);
625 ASSERT(pm_scans_disabled);
626 pm_scans_disabled = 0;
628 * Call pm_reset_timestamps to reset timestamps of each
629 * device to the time when the system is resumed so that their
630 * idleness can be re-calculated. That's to avoid devices from
631 * being powered down right after resume if the system was in
632 * suspended mode long enough.
634 ddi_walk_devs(ddi_root_node(), pm_reset_timestamps, NULL);
636 autopm_enabled = auto_save;
637 cpupm = cpupm_save;
639 * If there is any auto-pm device, get the scanning
640 * going. Otherwise don't bother.
642 ddi_walk_devs(ddi_root_node(), pm_rescan_walk, NULL);
643 break;
645 return (B_TRUE);
649 * This callback routine is called when there is a system panic. This function
650 * exists for prototype matching.
652 static boolean_t
653 pm_panic_callb(void *arg, int code)
655 _NOTE(ARGUNUSED(arg, code))
656 void pm_cfb_check_and_powerup(void);
657 PMD(PMD_CFB, ("pm_panic_callb\n"))
658 pm_cfb_check_and_powerup();
659 return (B_TRUE);
662 static boolean_t
663 pm_halt_callb(void *arg, int code)
665 _NOTE(ARGUNUSED(arg, code))
666 return (B_TRUE);
669 static void pm_dep_thread(void);
672 * This needs to be called after the root and platform drivers are loaded
673 * and be single-threaded with respect to driver attach/detach
675 void
676 pm_init(void)
678 PMD_FUNC(pmf, "pm_init")
679 char **mod;
680 extern pri_t minclsyspri;
682 pm_comps_notlowest = 0;
683 pm_system_idle_threshold = pm_default_idle_threshold;
684 pm_cpu_idle_threshold = 0;
686 pm_cpr_cb_id = callb_add(pm_cpr_callb, NULL, CB_CL_CPR_PM, "pm_cpr");
687 pm_panic_cb_id = callb_add(pm_panic_callb, NULL, CB_CL_PANIC,
688 "pm_panic");
689 pm_halt_cb_id = callb_add(pm_halt_callb, NULL, CB_CL_HALT, "pm_halt");
692 * Create a thread to do dependency processing.
694 (void) thread_create(NULL, 0, (void (*)())pm_dep_thread, NULL, 0, &p0,
695 TS_RUN, minclsyspri);
698 * loadrootmodules already loaded these ppm drivers, now get them
699 * attached so they can claim the root drivers as they attach
701 for (mod = platform_module_list; *mod; mod++) {
702 if (i_ddi_attach_hw_nodes(*mod) != DDI_SUCCESS) {
703 cmn_err(CE_WARN, "!cannot load platform pm driver %s\n",
704 *mod);
705 } else {
706 PMD(PMD_DHR, ("%s: %s (%s)\n", pmf, *mod,
707 ddi_major_to_name(ddi_name_to_major(*mod))))
713 * pm_scan_init - create pm scan data structure. Called (if autopm or cpupm
714 * enabled) when device becomes power managed or after a failed detach and
715 * when autopm is started via PM_START_PM or PM_START_CPUPM ioctls, and after
716 * a CPR resume to get all the devices scanning again.
718 void
719 pm_scan_init(dev_info_t *dip)
721 PMD_FUNC(pmf, "scan_init")
722 pm_scan_t *scanp;
724 ASSERT(!PM_ISBC(dip));
726 PM_LOCK_DIP(dip);
727 scanp = PM_GET_PM_SCAN(dip);
728 if (!scanp) {
729 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): create scan data\n",
730 pmf, PM_DEVICE(dip)))
731 scanp = kmem_zalloc(sizeof (pm_scan_t), KM_SLEEP);
732 DEVI(dip)->devi_pm_scan = scanp;
733 } else if (scanp->ps_scan_flags & PM_SCAN_STOP) {
734 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): "
735 "clear PM_SCAN_STOP flag\n", pmf, PM_DEVICE(dip)))
736 scanp->ps_scan_flags &= ~PM_SCAN_STOP;
738 PM_UNLOCK_DIP(dip);
742 * pm_scan_fini - remove pm scan data structure when stopping pm on the device
744 void
745 pm_scan_fini(dev_info_t *dip)
747 PMD_FUNC(pmf, "scan_fini")
748 pm_scan_t *scanp;
750 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
751 ASSERT(!PM_ISBC(dip));
752 PM_LOCK_DIP(dip);
753 scanp = PM_GET_PM_SCAN(dip);
754 if (!scanp) {
755 PM_UNLOCK_DIP(dip);
756 return;
759 ASSERT(!scanp->ps_scan_id && !(scanp->ps_scan_flags &
760 (PM_SCANNING | PM_SCAN_DISPATCHED | PM_SCAN_AGAIN)));
762 kmem_free(scanp, sizeof (pm_scan_t));
763 DEVI(dip)->devi_pm_scan = NULL;
764 PM_UNLOCK_DIP(dip);
768 * Given a pointer to a component struct, return the current power level
769 * (struct contains index unless it is a continuous level).
770 * Located here in hopes of getting both this and dev_is_needed into the
771 * cache together
773 static int
774 cur_power(pm_component_t *cp)
776 if (cp->pmc_cur_pwr == PM_LEVEL_UNKNOWN)
777 return (cp->pmc_cur_pwr);
779 return (cp->pmc_comp.pmc_lvals[cp->pmc_cur_pwr]);
782 static char *
783 pm_decode_direction(int direction)
785 switch (direction) {
786 case PM_LEVEL_UPONLY:
787 return ("up");
789 case PM_LEVEL_EXACT:
790 return ("exact");
792 case PM_LEVEL_DOWNONLY:
793 return ("down");
795 default:
796 return ("INVALID DIRECTION");
800 char *
801 pm_decode_op(pm_bus_power_op_t op)
803 switch (op) {
804 case BUS_POWER_CHILD_PWRCHG:
805 return ("CHILD_PWRCHG");
806 case BUS_POWER_NEXUS_PWRUP:
807 return ("NEXUS_PWRUP");
808 case BUS_POWER_PRE_NOTIFICATION:
809 return ("PRE_NOTIFICATION");
810 case BUS_POWER_POST_NOTIFICATION:
811 return ("POST_NOTIFICATION");
812 case BUS_POWER_HAS_CHANGED:
813 return ("HAS_CHANGED");
814 case BUS_POWER_NOINVOL:
815 return ("NOINVOL");
816 default:
817 return ("UNKNOWN OP");
822 * Returns true if level is a possible (valid) power level for component
825 e_pm_valid_power(dev_info_t *dip, int cmpt, int level)
827 PMD_FUNC(pmf, "e_pm_valid_power")
828 pm_component_t *cp = PM_CP(dip, cmpt);
829 int i;
830 int *ip = cp->pmc_comp.pmc_lvals;
831 int limit = cp->pmc_comp.pmc_numlevels;
833 if (level < 0)
834 return (0);
835 for (i = 0; i < limit; i++) {
836 if (level == *ip++)
837 return (1);
839 #ifdef DEBUG
840 if (pm_debug & PMD_FAIL) {
841 ip = cp->pmc_comp.pmc_lvals;
843 for (i = 0; i < limit; i++)
844 PMD(PMD_FAIL, ("%s: index=%d, level=%d\n",
845 pmf, i, *ip++))
847 #endif
848 return (0);
851 static int pm_start(dev_info_t *dip);
853 * Returns true if device is pm'd (after calling pm_start if need be)
856 e_pm_valid_info(dev_info_t *dip, pm_info_t **infop)
858 pm_info_t *info;
861 * Check if the device is power managed if not.
862 * To make the common case (device is power managed already)
863 * fast, we check without the lock. If device is not already
864 * power managed, then we take the lock and the long route through
865 * go get it managed. Devices never go unmanaged until they
866 * detach.
868 info = PM_GET_PM_INFO(dip);
869 if (!info) {
870 if (!DEVI_IS_ATTACHING(dip)) {
871 return (0);
873 if (pm_start(dip) != DDI_SUCCESS) {
874 return (0);
876 info = PM_GET_PM_INFO(dip);
878 ASSERT(info);
879 if (infop != NULL)
880 *infop = info;
881 return (1);
885 e_pm_valid_comp(dev_info_t *dip, int cmpt, pm_component_t **cpp)
887 if (cmpt >= 0 && cmpt < PM_NUMCMPTS(dip)) {
888 if (cpp != NULL)
889 *cpp = PM_CP(dip, cmpt);
890 return (1);
891 } else {
892 return (0);
897 * Internal guts of ddi_dev_is_needed and pm_raise/lower_power
899 static int
900 dev_is_needed(dev_info_t *dip, int cmpt, int level, int direction)
902 PMD_FUNC(pmf, "din")
903 pm_component_t *cp;
904 char *pathbuf;
905 int result;
907 ASSERT(direction == PM_LEVEL_UPONLY || direction == PM_LEVEL_DOWNONLY);
908 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, cmpt, &cp) ||
909 !e_pm_valid_power(dip, cmpt, level))
910 return (DDI_FAILURE);
912 PMD(PMD_DIN, ("%s: %s@%s(%s#%d) cmpt=%d, dir=%s, new=%d, cur=%d\n",
913 pmf, PM_DEVICE(dip), cmpt, pm_decode_direction(direction),
914 level, cur_power(cp)))
916 if (pm_set_power(dip, cmpt, level, direction,
917 PM_CANBLOCK_BLOCK, 0, &result) != DDI_SUCCESS) {
918 if (direction == PM_LEVEL_UPONLY) {
919 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
920 (void) ddi_pathname(dip, pathbuf);
921 cmn_err(CE_WARN, "Device %s failed to power up.",
922 pathbuf);
923 kmem_free(pathbuf, MAXPATHLEN);
925 PMD(PMD_DIN | PMD_FAIL, ("%s: %s@%s(%s#%d) [%d] %s->%d failed, "
926 "errno %d\n", pmf, PM_DEVICE(dip), cmpt,
927 pm_decode_direction(direction), level, result))
928 return (DDI_FAILURE);
931 PMD(PMD_RESCAN | PMD_DIN, ("%s: pm_rescan %s@%s(%s#%d)\n", pmf,
932 PM_DEVICE(dip)))
933 pm_rescan(dip);
934 return (DDI_SUCCESS);
938 * We can get multiple pm_rescan() threads, if one of them discovers
939 * that no scan is running at the moment, it kicks it into action.
940 * Otherwise, it tells the current scanning thread to scan again when
941 * it is done by asserting the PM_SCAN_AGAIN flag. The PM_SCANNING and
942 * PM_SCAN_AGAIN flags are used to regulate scan, to make sure only one
943 * thread at a time runs the pm_scan_dev() code.
945 void
946 pm_rescan(void *arg)
948 PMD_FUNC(pmf, "rescan")
949 dev_info_t *dip = (dev_info_t *)arg;
950 pm_info_t *info;
951 pm_scan_t *scanp;
952 timeout_id_t scanid;
954 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
955 PM_LOCK_DIP(dip);
956 info = PM_GET_PM_INFO(dip);
957 scanp = PM_GET_PM_SCAN(dip);
958 if (pm_scans_disabled || !PM_SCANABLE(dip) || !info || !scanp ||
959 (scanp->ps_scan_flags & PM_SCAN_STOP)) {
960 PM_UNLOCK_DIP(dip);
961 return;
963 if (scanp->ps_scan_flags & PM_SCANNING) {
964 scanp->ps_scan_flags |= PM_SCAN_AGAIN;
965 PM_UNLOCK_DIP(dip);
966 return;
967 } else if (scanp->ps_scan_id) {
968 scanid = scanp->ps_scan_id;
969 scanp->ps_scan_id = 0;
970 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): cancel timeout scanid %lx\n",
971 pmf, PM_DEVICE(dip), (ulong_t)scanid))
972 PM_UNLOCK_DIP(dip);
973 (void) untimeout(scanid);
974 PM_LOCK_DIP(dip);
978 * Dispatching pm_scan during attach time is risky due to the fact that
979 * attach might soon fail and dip dissolved, and panic may happen while
980 * attempting to stop scan. So schedule a pm_rescan instead.
981 * (Note that if either of the first two terms are true, taskq_dispatch
982 * will not be invoked).
984 * Multiple pm_scan dispatching is unecessary and costly to keep track
985 * of. The PM_SCAN_DISPATCHED flag is used between pm_rescan and pm_scan
986 * to regulate the dispatching.
988 * Scan is stopped before the device is detached (in pm_detaching())
989 * but it may get re-started during the post_detach processing if the
990 * driver fails to detach.
992 if (DEVI_IS_ATTACHING(dip) ||
993 (scanp->ps_scan_flags & PM_SCAN_DISPATCHED) ||
994 !taskq_dispatch(system_taskq, pm_scan, (void *)dip, TQ_NOSLEEP)) {
995 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): attaching, pm_scan already "
996 "dispatched or dispatching failed\n", pmf, PM_DEVICE(dip)))
997 if (scanp->ps_scan_id) {
998 scanid = scanp->ps_scan_id;
999 scanp->ps_scan_id = 0;
1000 PM_UNLOCK_DIP(dip);
1001 (void) untimeout(scanid);
1002 PM_LOCK_DIP(dip);
1003 if (scanp->ps_scan_id) {
1004 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): a competing "
1005 "thread scheduled pm_rescan, scanid %lx\n",
1006 pmf, PM_DEVICE(dip),
1007 (ulong_t)scanp->ps_scan_id))
1008 PM_UNLOCK_DIP(dip);
1009 return;
1012 scanp->ps_scan_id = timeout(pm_rescan, (void *)dip,
1013 (scanp->ps_idle_down ? pm_id_ticks :
1014 (PM_MIN_SCAN(dip) * hz)));
1015 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): scheduled next pm_rescan, "
1016 "scanid %lx\n", pmf, PM_DEVICE(dip),
1017 (ulong_t)scanp->ps_scan_id))
1018 } else {
1019 PMD(PMD_SCAN, ("%s: dispatched pm_scan for %s@%s(%s#%d)\n",
1020 pmf, PM_DEVICE(dip)))
1021 scanp->ps_scan_flags |= PM_SCAN_DISPATCHED;
1023 PM_UNLOCK_DIP(dip);
1026 void
1027 pm_scan(void *arg)
1029 PMD_FUNC(pmf, "scan")
1030 dev_info_t *dip = (dev_info_t *)arg;
1031 pm_scan_t *scanp;
1032 time_t nextscan;
1034 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
1036 PM_LOCK_DIP(dip);
1037 scanp = PM_GET_PM_SCAN(dip);
1038 ASSERT(scanp && PM_GET_PM_INFO(dip));
1040 if (pm_scans_disabled || !PM_SCANABLE(dip) ||
1041 (scanp->ps_scan_flags & PM_SCAN_STOP)) {
1042 scanp->ps_scan_flags &= ~(PM_SCAN_AGAIN | PM_SCAN_DISPATCHED);
1043 PM_UNLOCK_DIP(dip);
1044 return;
1047 if (scanp->ps_idle_down) {
1049 * make sure we remember idledown was in affect until
1050 * we've completed the scan
1052 PMID_SET_SCANS(scanp->ps_idle_down)
1053 PMD(PMD_IDLEDOWN, ("%s: %s@%s(%s#%d): idledown starts "
1054 "(pmid %x)\n", pmf, PM_DEVICE(dip), scanp->ps_idle_down))
1057 /* possible having two threads running pm_scan() */
1058 if (scanp->ps_scan_flags & PM_SCANNING) {
1059 scanp->ps_scan_flags |= PM_SCAN_AGAIN;
1060 PMD(PMD_SCAN, ("%s: scanning, will scan %s@%s(%s#%d) again\n",
1061 pmf, PM_DEVICE(dip)))
1062 scanp->ps_scan_flags &= ~PM_SCAN_DISPATCHED;
1063 PM_UNLOCK_DIP(dip);
1064 return;
1067 scanp->ps_scan_flags |= PM_SCANNING;
1068 scanp->ps_scan_flags &= ~PM_SCAN_DISPATCHED;
1069 do {
1070 scanp->ps_scan_flags &= ~PM_SCAN_AGAIN;
1071 PM_UNLOCK_DIP(dip);
1072 nextscan = pm_scan_dev(dip);
1073 PM_LOCK_DIP(dip);
1074 } while (scanp->ps_scan_flags & PM_SCAN_AGAIN);
1076 ASSERT(scanp->ps_scan_flags & PM_SCANNING);
1077 scanp->ps_scan_flags &= ~PM_SCANNING;
1079 if (scanp->ps_idle_down) {
1080 scanp->ps_idle_down &= ~PMID_SCANS;
1081 PMD(PMD_IDLEDOWN, ("%s: %s@%s(%s#%d): idledown ends "
1082 "(pmid %x)\n", pmf, PM_DEVICE(dip), scanp->ps_idle_down))
1085 /* schedule for next idle check */
1086 if (nextscan != LONG_MAX) {
1087 if (nextscan > (LONG_MAX / hz))
1088 nextscan = (LONG_MAX - 1) / hz;
1089 if (scanp->ps_scan_id) {
1090 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): while scanning "
1091 "another rescan scheduled scanid(%lx)\n", pmf,
1092 PM_DEVICE(dip), (ulong_t)scanp->ps_scan_id))
1093 PM_UNLOCK_DIP(dip);
1094 return;
1095 } else if (!(scanp->ps_scan_flags & PM_SCAN_STOP)) {
1096 scanp->ps_scan_id = timeout(pm_rescan, (void *)dip,
1097 (clock_t)(nextscan * hz));
1098 PMD(PMD_SCAN, ("%s: nextscan for %s@%s(%s#%d) in "
1099 "%lx sec, scanid(%lx) \n", pmf, PM_DEVICE(dip),
1100 (ulong_t)nextscan, (ulong_t)scanp->ps_scan_id))
1103 PM_UNLOCK_DIP(dip);
1106 void
1107 pm_get_timestamps(dev_info_t *dip, time_t *valuep)
1109 int components = PM_NUMCMPTS(dip);
1110 int i;
1112 ASSERT(components > 0);
1113 PM_LOCK_BUSY(dip); /* so we get a consistent view */
1114 for (i = 0; i < components; i++) {
1115 valuep[i] = PM_CP(dip, i)->pmc_timestamp;
1117 PM_UNLOCK_BUSY(dip);
1121 * Returns true if device needs to be kept up because it exported the
1122 * "no-involuntary-power-cycles" property or we're pretending it did (console
1123 * fb case) or it is an ancestor of such a device and has used up the "one
1124 * free cycle" allowed when all such leaf nodes have voluntarily powered down
1125 * upon detach
1128 pm_noinvol(dev_info_t *dip)
1130 PMD_FUNC(pmf, "noinvol")
1133 * This doesn't change over the life of a driver, so no locking needed
1135 if (PM_IS_CFB(dip)) {
1136 PMD(PMD_NOINVOL | PMD_CFB, ("%s: inhibits CFB %s@%s(%s#%d)\n",
1137 pmf, PM_DEVICE(dip)))
1138 return (1);
1141 * Not an issue if no such kids
1143 if (DEVI(dip)->devi_pm_noinvolpm == 0) {
1144 #ifdef DEBUG
1145 if (DEVI(dip)->devi_pm_volpmd != 0) {
1146 dev_info_t *pdip = dip;
1147 do {
1148 PMD(PMD_NOINVOL, ("%s: %s@%s(%s#%d) noinvol %d "
1149 "volpmd %d\n", pmf, PM_DEVICE(pdip),
1150 DEVI(pdip)->devi_pm_noinvolpm,
1151 DEVI(pdip)->devi_pm_volpmd))
1152 pdip = ddi_get_parent(pdip);
1153 } while (pdip);
1155 #endif
1156 ASSERT(DEVI(dip)->devi_pm_volpmd == 0);
1157 return (0);
1161 * Since we now maintain the counts correct at every node, we no longer
1162 * need to look up the tree. An ancestor cannot use up the free cycle
1163 * without the children getting their counts adjusted.
1166 #ifdef DEBUG
1167 if (DEVI(dip)->devi_pm_noinvolpm != DEVI(dip)->devi_pm_volpmd)
1168 PMD(PMD_NOINVOL, ("%s: (%d != %d) inhibits %s@%s(%s#%d)\n", pmf,
1169 DEVI(dip)->devi_pm_noinvolpm, DEVI(dip)->devi_pm_volpmd,
1170 PM_DEVICE(dip)))
1171 #endif
1172 return (DEVI(dip)->devi_pm_noinvolpm != DEVI(dip)->devi_pm_volpmd);
1175 static int cur_threshold(dev_info_t *, int);
1176 static int pm_next_lower_power(pm_component_t *, int);
1179 * This function performs the actual scanning of the device.
1180 * It attempts to power off the indicated device's components if they have
1181 * been idle and other restrictions are met.
1182 * pm_scan_dev calculates and returns when the next scan should happen for
1183 * this device.
1185 time_t
1186 pm_scan_dev(dev_info_t *dip)
1188 PMD_FUNC(pmf, "scan_dev")
1189 pm_scan_t *scanp;
1190 time_t *timestamp, idletime, now, thresh;
1191 time_t timeleft = 0;
1192 #ifdef PMDDEBUG
1193 int curpwr;
1194 #endif
1195 int i, nxtpwr, pwrndx, unused;
1196 size_t size;
1197 pm_component_t *cp;
1198 dev_info_t *pdip = ddi_get_parent(dip);
1199 int circ;
1200 clock_t min_scan = pm_default_min_scan;
1203 * skip attaching device
1205 if (DEVI_IS_ATTACHING(dip)) {
1206 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) is attaching, timeleft(%lx)\n",
1207 pmf, PM_DEVICE(dip), min_scan))
1208 return (min_scan);
1211 PM_LOCK_DIP(dip);
1212 scanp = PM_GET_PM_SCAN(dip);
1213 min_scan = PM_MIN_SCAN(dip);
1214 ASSERT(scanp && PM_GET_PM_INFO(dip));
1216 PMD(PMD_SCAN, ("%s: [BEGIN %s@%s(%s#%d)]\n", pmf, PM_DEVICE(dip)))
1217 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): kuc is %d\n", pmf, PM_DEVICE(dip),
1218 PM_KUC(dip)))
1220 /* no scan under the following conditions */
1221 if (pm_scans_disabled || !PM_SCANABLE(dip) ||
1222 (scanp->ps_scan_flags & PM_SCAN_STOP) ||
1223 (PM_KUC(dip) != 0) ||
1224 PM_ISDIRECT(dip) || pm_noinvol(dip)) {
1225 PM_UNLOCK_DIP(dip);
1226 PMD(PMD_SCAN, ("%s: [END, %s@%s(%s#%d)] no scan, "
1227 "scan_disabled(%d), apm_enabled(%d), cpupm(%d), "
1228 "kuc(%d), %s directpm, %s pm_noinvol\n",
1229 pmf, PM_DEVICE(dip), pm_scans_disabled, autopm_enabled,
1230 cpupm, PM_KUC(dip),
1231 PM_ISDIRECT(dip) ? "is" : "is not",
1232 pm_noinvol(dip) ? "is" : "is not"))
1233 return (LONG_MAX);
1235 PM_UNLOCK_DIP(dip);
1237 if (!ndi_devi_tryenter(pdip, &circ)) {
1238 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) can't hold pdip",
1239 pmf, PM_DEVICE(pdip)))
1240 return ((time_t)1);
1242 now = gethrestime_sec();
1243 size = PM_NUMCMPTS(dip) * sizeof (time_t);
1244 timestamp = kmem_alloc(size, KM_SLEEP);
1245 pm_get_timestamps(dip, timestamp);
1248 * Since we removed support for backwards compatible devices,
1249 * (see big comment at top of file)
1250 * it is no longer required to deal with component 0 last.
1252 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
1254 * If already off (an optimization, perhaps)
1256 cp = PM_CP(dip, i);
1257 pwrndx = cp->pmc_cur_pwr;
1258 #ifdef PMDDEBUG
1259 curpwr = (pwrndx == PM_LEVEL_UNKNOWN) ?
1260 PM_LEVEL_UNKNOWN :
1261 cp->pmc_comp.pmc_lvals[pwrndx];
1262 #endif
1264 if (pwrndx == 0) {
1265 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d off or "
1266 "lowest\n", pmf, PM_DEVICE(dip), i))
1267 /* skip device if off or at its lowest */
1268 continue;
1271 thresh = cur_threshold(dip, i); /* comp i threshold */
1272 if ((timestamp[i] == 0) || (cp->pmc_busycount > 0)) {
1273 /* were busy or newly became busy by another thread */
1274 if (timeleft == 0)
1275 timeleft = max(thresh, min_scan);
1276 else
1277 timeleft = min(
1278 timeleft, max(thresh, min_scan));
1279 continue;
1282 idletime = now - timestamp[i]; /* idle time */
1283 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d idle time %lx\n",
1284 pmf, PM_DEVICE(dip), i, idletime))
1285 if (idletime >= thresh || PM_IS_PID(dip)) {
1286 nxtpwr = pm_next_lower_power(cp, pwrndx);
1287 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d, %d->%d\n",
1288 pmf, PM_DEVICE(dip), i, curpwr, nxtpwr))
1289 if (pm_set_power(dip, i, nxtpwr, PM_LEVEL_DOWNONLY,
1290 PM_CANBLOCK_FAIL, 1, &unused) != DDI_SUCCESS &&
1291 PM_CURPOWER(dip, i) != nxtpwr) {
1292 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d, "
1293 "%d->%d Failed\n", pmf, PM_DEVICE(dip),
1294 i, curpwr, nxtpwr))
1295 timeleft = min_scan;
1296 continue;
1297 } else {
1298 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d, "
1299 "%d->%d, GOOD curpwr %d\n", pmf,
1300 PM_DEVICE(dip), i, curpwr, nxtpwr,
1301 cur_power(cp)))
1303 if (nxtpwr == 0) /* component went off */
1304 continue;
1307 * scan to next lower level
1309 if (timeleft == 0)
1310 timeleft = max(
1311 1, cur_threshold(dip, i));
1312 else
1313 timeleft = min(timeleft,
1314 max(1, cur_threshold(dip, i)));
1315 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d, "
1316 "timeleft(%lx)\n", pmf, PM_DEVICE(dip),
1317 i, timeleft))
1319 } else { /* comp not idle long enough */
1320 if (timeleft == 0)
1321 timeleft = thresh - idletime;
1322 else
1323 timeleft = min(timeleft, (thresh - idletime));
1324 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d, timeleft="
1325 "%lx\n", pmf, PM_DEVICE(dip), i, timeleft))
1328 ndi_devi_exit(pdip, circ);
1329 kmem_free(timestamp, size);
1330 PMD(PMD_SCAN, ("%s: [END %s@%s(%s#%d)] timeleft(%lx)\n", pmf,
1331 PM_DEVICE(dip), timeleft))
1334 * if components are already at lowest level, timeleft is left 0
1336 return ((timeleft == 0) ? LONG_MAX : timeleft);
1340 * pm_scan_stop - cancel scheduled pm_rescan,
1341 * wait for termination of dispatched pm_scan thread
1342 * and active pm_scan_dev thread.
1344 void
1345 pm_scan_stop(dev_info_t *dip)
1347 PMD_FUNC(pmf, "scan_stop")
1348 pm_scan_t *scanp;
1349 timeout_id_t scanid;
1351 PMD(PMD_SCAN, ("%s: [BEGIN %s@%s(%s#%d)]\n", pmf, PM_DEVICE(dip)))
1352 PM_LOCK_DIP(dip);
1353 scanp = PM_GET_PM_SCAN(dip);
1354 if (!scanp) {
1355 PMD(PMD_SCAN, ("%s: [END %s@%s(%s#%d)] scan not initialized\n",
1356 pmf, PM_DEVICE(dip)))
1357 PM_UNLOCK_DIP(dip);
1358 return;
1360 scanp->ps_scan_flags |= PM_SCAN_STOP;
1362 /* cancel scheduled scan taskq */
1363 while (scanp->ps_scan_id) {
1364 scanid = scanp->ps_scan_id;
1365 scanp->ps_scan_id = 0;
1366 PM_UNLOCK_DIP(dip);
1367 (void) untimeout(scanid);
1368 PM_LOCK_DIP(dip);
1371 while (scanp->ps_scan_flags & (PM_SCANNING | PM_SCAN_DISPATCHED)) {
1372 PM_UNLOCK_DIP(dip);
1373 delay(1);
1374 PM_LOCK_DIP(dip);
1376 PM_UNLOCK_DIP(dip);
1377 PMD(PMD_SCAN, ("%s: [END %s@%s(%s#%d)]\n", pmf, PM_DEVICE(dip)))
1381 pm_scan_stop_walk(dev_info_t *dip, void *arg)
1383 _NOTE(ARGUNUSED(arg))
1385 if (!PM_GET_PM_SCAN(dip))
1386 return (DDI_WALK_CONTINUE);
1387 ASSERT(!PM_ISBC(dip));
1388 pm_scan_stop(dip);
1389 return (DDI_WALK_CONTINUE);
1393 * Converts a power level value to its index
1395 static int
1396 power_val_to_index(pm_component_t *cp, int val)
1398 int limit, i, *ip;
1400 ASSERT(val != PM_LEVEL_UPONLY && val != PM_LEVEL_DOWNONLY &&
1401 val != PM_LEVEL_EXACT);
1402 /* convert power value into index (i) */
1403 limit = cp->pmc_comp.pmc_numlevels;
1404 ip = cp->pmc_comp.pmc_lvals;
1405 for (i = 0; i < limit; i++)
1406 if (val == *ip++)
1407 return (i);
1408 return (-1);
1412 * Converts a numeric power level to a printable string
1414 static char *
1415 power_val_to_string(pm_component_t *cp, int val)
1417 int index;
1419 if (val == PM_LEVEL_UPONLY)
1420 return ("<UPONLY>");
1422 if (val == PM_LEVEL_UNKNOWN ||
1423 (index = power_val_to_index(cp, val)) == -1)
1424 return ("<LEVEL_UNKNOWN>");
1426 return (cp->pmc_comp.pmc_lnames[index]);
1430 * Return true if this node has been claimed by a ppm.
1432 static int
1433 pm_ppm_claimed(dev_info_t *dip)
1435 return (PPM(dip) != NULL);
1439 * A node which was voluntarily power managed has just used up its "free cycle"
1440 * and need is volpmd field cleared, and the same done to all its descendents
1442 static void
1443 pm_clear_volpm_dip(dev_info_t *dip)
1445 PMD_FUNC(pmf, "clear_volpm_dip")
1447 if (dip == NULL)
1448 return;
1449 PMD(PMD_NOINVOL, ("%s: clear volpm from %s@%s(%s#%d)\n", pmf,
1450 PM_DEVICE(dip)))
1451 DEVI(dip)->devi_pm_volpmd = 0;
1452 for (dip = ddi_get_child(dip); dip; dip = ddi_get_next_sibling(dip)) {
1453 pm_clear_volpm_dip(dip);
1458 * A node which was voluntarily power managed has used up the "free cycles"
1459 * for the subtree that it is the root of. Scan through the list of detached
1460 * nodes and adjust the counts of any that are descendents of the node.
1462 static void
1463 pm_clear_volpm_list(dev_info_t *dip)
1465 PMD_FUNC(pmf, "clear_volpm_list")
1466 char *pathbuf;
1467 size_t len;
1468 pm_noinvol_t *ip;
1470 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1471 (void) ddi_pathname(dip, pathbuf);
1472 len = strlen(pathbuf);
1473 PMD(PMD_NOINVOL, ("%s: clear volpm list %s\n", pmf, pathbuf))
1474 rw_enter(&pm_noinvol_rwlock, RW_WRITER);
1475 for (ip = pm_noinvol_head; ip; ip = ip->ni_next) {
1476 PMD(PMD_NOINVOL, ("%s: clear volpm: ni_path %s\n", pmf,
1477 ip->ni_path))
1478 if (strncmp(pathbuf, ip->ni_path, len) == 0 &&
1479 ip->ni_path[len] == '/') {
1480 PMD(PMD_NOINVOL, ("%s: clear volpm: %s\n", pmf,
1481 ip->ni_path))
1482 ip->ni_volpmd = 0;
1483 ip->ni_wasvolpmd = 0;
1486 kmem_free(pathbuf, MAXPATHLEN);
1487 rw_exit(&pm_noinvol_rwlock);
1491 * Powers a device, suspending or resuming the driver if it is a backward
1492 * compatible device, calling into ppm to change power level.
1493 * Called with the component's power lock held.
1495 static int
1496 power_dev(dev_info_t *dip, int comp, int level, int old_level,
1497 pm_canblock_t canblock, pm_ppm_devlist_t **devlist)
1499 PMD_FUNC(pmf, "power_dev")
1500 power_req_t power_req;
1501 int power_op_ret; /* DDI_SUCCESS or DDI_FAILURE */
1502 int resume_needed = 0;
1503 int suspended = 0;
1504 int result;
1505 #ifdef PMDDEBUG
1506 struct pm_component *cp = PM_CP(dip, comp);
1507 #endif
1508 int bc = PM_ISBC(dip);
1509 int pm_all_components_off(dev_info_t *);
1510 int clearvolpmd = 0;
1511 char pathbuf[MAXNAMELEN];
1512 #ifdef PMDDEBUG
1513 char *ppmname, *ppmaddr;
1514 #endif
1516 * If this is comp 0 of a backwards compat device and we are
1517 * going to take the power away, we need to detach it with
1518 * DDI_PM_SUSPEND command.
1520 if (bc && comp == 0 && POWERING_OFF(old_level, level)) {
1521 if (devi_detach(dip, DDI_PM_SUSPEND) != DDI_SUCCESS) {
1522 /* We could not suspend before turning cmpt zero off */
1523 PMD(PMD_ERROR, ("%s: could not suspend %s@%s(%s#%d)\n",
1524 pmf, PM_DEVICE(dip)))
1525 return (DDI_FAILURE);
1526 } else {
1527 DEVI(dip)->devi_pm_flags |= PMC_SUSPENDED;
1528 suspended++;
1531 power_req.request_type = PMR_PPM_SET_POWER;
1532 power_req.req.ppm_set_power_req.who = dip;
1533 power_req.req.ppm_set_power_req.cmpt = comp;
1534 power_req.req.ppm_set_power_req.old_level = old_level;
1535 power_req.req.ppm_set_power_req.new_level = level;
1536 power_req.req.ppm_set_power_req.canblock = canblock;
1537 power_req.req.ppm_set_power_req.cookie = NULL;
1538 #ifdef PMDDEBUG
1539 if (pm_ppm_claimed(dip)) {
1540 ppmname = PM_NAME(PPM(dip));
1541 ppmaddr = PM_ADDR(PPM(dip));
1543 } else {
1544 ppmname = "noppm";
1545 ppmaddr = "0";
1547 PMD(PMD_PPM, ("%s: %s@%s(%s#%d):%s[%d] %s (%d) -> %s (%d) via %s@%s\n",
1548 pmf, PM_DEVICE(dip), cp->pmc_comp.pmc_name, comp,
1549 power_val_to_string(cp, old_level), old_level,
1550 power_val_to_string(cp, level), level, ppmname, ppmaddr))
1551 #endif
1553 * If non-bc noinvolpm device is turning first comp on, or noinvolpm
1554 * bc device comp 0 is powering on, then we count it as a power cycle
1555 * against its voluntary count.
1557 if (DEVI(dip)->devi_pm_volpmd &&
1558 (!bc && pm_all_components_off(dip) && level != 0) ||
1559 (bc && comp == 0 && POWERING_ON(old_level, level)))
1560 clearvolpmd = 1;
1561 if ((power_op_ret = pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER,
1562 &power_req, &result)) == DDI_SUCCESS) {
1564 * Now do involuntary pm accounting; If we've just cycled power
1565 * on a voluntarily pm'd node, and by inference on its entire
1566 * subtree, we need to set the subtree (including those nodes
1567 * already detached) volpmd counts to 0, and subtract out the
1568 * value of the current node's volpmd count from the ancestors
1570 if (clearvolpmd) {
1571 int volpmd = DEVI(dip)->devi_pm_volpmd;
1572 pm_clear_volpm_dip(dip);
1573 pm_clear_volpm_list(dip);
1574 if (volpmd) {
1575 (void) ddi_pathname(dip, pathbuf);
1576 (void) pm_noinvol_update(PM_BP_NOINVOL_POWER,
1577 volpmd, 0, pathbuf, dip);
1580 } else {
1581 PMD(PMD_FAIL, ("%s: can't set comp %d (%s) of %s@%s(%s#%d) "
1582 "to level %d (%s)\n", pmf, comp, cp->pmc_comp.pmc_name,
1583 PM_DEVICE(dip), level, power_val_to_string(cp, level)))
1586 * If some other devices were also powered up (e.g. other cpus in
1587 * the same domain) return a pointer to that list
1589 if (devlist) {
1590 *devlist = (pm_ppm_devlist_t *)
1591 power_req.req.ppm_set_power_req.cookie;
1594 * We will have to resume the device if the device is backwards compat
1595 * device and either of the following is true:
1596 * -This is comp 0 and we have successfully powered it up
1597 * -This is comp 0 and we have failed to power it down. Resume is
1598 * needed because we have suspended it above
1601 if (bc && comp == 0) {
1602 ASSERT(PM_ISDIRECT(dip) || DEVI_IS_DETACHING(dip));
1603 if (power_op_ret == DDI_SUCCESS) {
1604 if (POWERING_ON(old_level, level)) {
1606 * It must be either suspended or resumed
1607 * via pm_power_has_changed path
1609 ASSERT((DEVI(dip)->devi_pm_flags &
1610 PMC_SUSPENDED) ||
1611 (PM_CP(dip, comp)->pmc_flags &
1612 PM_PHC_WHILE_SET_POWER));
1614 resume_needed = suspended;
1616 } else {
1617 if (POWERING_OFF(old_level, level)) {
1619 * It must be either suspended or resumed
1620 * via pm_power_has_changed path
1622 ASSERT((DEVI(dip)->devi_pm_flags &
1623 PMC_SUSPENDED) ||
1624 (PM_CP(dip, comp)->pmc_flags &
1625 PM_PHC_WHILE_SET_POWER));
1627 resume_needed = suspended;
1631 if (resume_needed) {
1632 ASSERT(DEVI(dip)->devi_pm_flags & PMC_SUSPENDED);
1633 /* ppm is not interested in DDI_PM_RESUME */
1634 if ((power_op_ret = devi_attach(dip, DDI_PM_RESUME)) ==
1635 DDI_SUCCESS) {
1636 DEVI(dip)->devi_pm_flags &= ~PMC_SUSPENDED;
1637 } else
1638 cmn_err(CE_WARN, "!pm: Can't resume %s@%s(%s#%d)",
1639 PM_DEVICE(dip));
1641 return (power_op_ret);
1645 * Return true if we are the owner or a borrower of the devi lock. See
1646 * pm_lock_power_single() about borrowing the lock.
1648 static int
1649 pm_devi_lock_held(dev_info_t *dip)
1651 lock_loan_t *cur;
1653 if (DEVI_BUSY_OWNED(dip))
1654 return (1);
1656 /* return false if no locks borrowed */
1657 if (lock_loan_head.pmlk_next == NULL)
1658 return (0);
1660 mutex_enter(&pm_loan_lock);
1661 /* see if our thread is registered as a lock borrower. */
1662 for (cur = lock_loan_head.pmlk_next; cur; cur = cur->pmlk_next)
1663 if (cur->pmlk_borrower == curthread)
1664 break;
1665 mutex_exit(&pm_loan_lock);
1667 return (cur != NULL && cur->pmlk_lender == DEVI(dip)->devi_busy_thread);
1671 * pm_set_power: adjusts power level of device. Assumes device is power
1672 * manageable & component exists.
1674 * Cases which require us to bring up devices we keep up ("wekeepups") for
1675 * backwards compatible devices:
1676 * component 0 is off and we're bringing it up from 0
1677 * bring up wekeepup first
1678 * and recursively when component 0 is off and we bring some other
1679 * component up from 0
1680 * For devices which are not backward compatible, our dependency notion is much
1681 * simpler. Unless all components are off, then wekeeps must be on.
1682 * We don't treat component 0 differently.
1683 * Canblock tells how to deal with a direct pm'd device.
1684 * Scan arg tells us if we were called from scan, in which case we don't need
1685 * to go back to the root node and walk down to change power.
1688 pm_set_power(dev_info_t *dip, int comp, int level, int direction,
1689 pm_canblock_t canblock, int scan, int *retp)
1691 PMD_FUNC(pmf, "set_power")
1692 char *pathbuf;
1693 pm_bp_child_pwrchg_t bpc;
1694 pm_sp_misc_t pspm;
1695 int ret = DDI_SUCCESS;
1696 int unused = DDI_SUCCESS;
1697 dev_info_t *pdip = ddi_get_parent(dip);
1699 #ifdef DEBUG
1700 int diverted = 0;
1703 * This prevents operations on the console from calling prom_printf and
1704 * either deadlocking or bringing up the console because of debug
1705 * output
1707 if (dip == cfb_dip) {
1708 diverted++;
1709 mutex_enter(&pm_debug_lock);
1710 pm_divertdebug++;
1711 mutex_exit(&pm_debug_lock);
1713 #endif
1714 ASSERT(direction == PM_LEVEL_UPONLY || direction == PM_LEVEL_DOWNONLY ||
1715 direction == PM_LEVEL_EXACT);
1716 PMD(PMD_SET, ("%s: %s@%s(%s#%d), comp=%d, dir=%s, new=%d\n",
1717 pmf, PM_DEVICE(dip), comp, pm_decode_direction(direction), level))
1718 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1719 (void) ddi_pathname(dip, pathbuf);
1720 bpc.bpc_dip = dip;
1721 bpc.bpc_path = pathbuf;
1722 bpc.bpc_comp = comp;
1723 bpc.bpc_olevel = PM_CURPOWER(dip, comp);
1724 bpc.bpc_nlevel = level;
1725 pspm.pspm_direction = direction;
1726 pspm.pspm_errnop = retp;
1727 pspm.pspm_canblock = canblock;
1728 pspm.pspm_scan = scan;
1729 bpc.bpc_private = &pspm;
1732 * If a config operation is being done (we've locked the parent) or
1733 * we already hold the power lock (we've locked the node)
1734 * then we can operate directly on the node because we have already
1735 * brought up all the ancestors, otherwise, we have to go back to the
1736 * top of the tree.
1738 if (pm_devi_lock_held(pdip) || pm_devi_lock_held(dip))
1739 ret = pm_busop_set_power(dip, NULL, BUS_POWER_CHILD_PWRCHG,
1740 (void *)&bpc, (void *)&unused);
1741 else
1742 ret = pm_busop_bus_power(ddi_root_node(), NULL,
1743 BUS_POWER_CHILD_PWRCHG, (void *)&bpc, (void *)&unused);
1744 #ifdef DEBUG
1745 if (ret != DDI_SUCCESS || *retp != DDI_SUCCESS) {
1746 PMD(PMD_ERROR, ("%s: %s@%s(%s#%d) can't change power, ret=%d, "
1747 "errno=%d\n", pmf, PM_DEVICE(dip), ret, *retp))
1749 if (diverted) {
1750 mutex_enter(&pm_debug_lock);
1751 pm_divertdebug--;
1752 mutex_exit(&pm_debug_lock);
1754 #endif
1755 kmem_free(pathbuf, MAXPATHLEN);
1756 return (ret);
1760 * If holddip is set, then if a dip is found we return with the node held.
1762 * This code uses the same locking scheme as e_ddi_hold_devi_by_path
1763 * (resolve_pathname), but it does not drive attach.
1765 dev_info_t *
1766 pm_name_to_dip(char *pathname, int holddip)
1768 struct pathname pn;
1769 char *component;
1770 dev_info_t *parent, *child;
1771 int circ;
1773 if ((pathname == NULL) || (*pathname != '/'))
1774 return (NULL);
1776 /* setup pathname and allocate component */
1777 if (pn_get(pathname, UIO_SYSSPACE, &pn))
1778 return (NULL);
1779 component = kmem_alloc(MAXNAMELEN, KM_SLEEP);
1781 /* start at top, process '/' component */
1782 parent = child = ddi_root_node();
1783 ndi_hold_devi(parent);
1784 pn_skipslash(&pn);
1785 ASSERT(i_ddi_devi_attached(parent));
1787 /* process components of pathname */
1788 while (pn_pathleft(&pn)) {
1789 (void) pn_getcomponent(&pn, component);
1791 /* enter parent and search for component child */
1792 ndi_devi_enter(parent, &circ);
1793 child = ndi_devi_findchild(parent, component);
1794 if ((child == NULL) || !i_ddi_devi_attached(child)) {
1795 child = NULL;
1796 ndi_devi_exit(parent, circ);
1797 ndi_rele_devi(parent);
1798 goto out;
1801 /* attached child found, hold child and release parent */
1802 ndi_hold_devi(child);
1803 ndi_devi_exit(parent, circ);
1804 ndi_rele_devi(parent);
1806 /* child becomes parent, and process next component */
1807 parent = child;
1808 pn_skipslash(&pn);
1810 /* loop with active ndi_devi_hold of child->parent */
1813 out:
1814 pn_free(&pn);
1815 kmem_free(component, MAXNAMELEN);
1817 /* if we are not asked to return with hold, drop current hold */
1818 if (child && !holddip)
1819 ndi_rele_devi(child);
1820 return (child);
1824 * Search for a dependency and mark it unsatisfied
1826 static void
1827 pm_unsatisfy(char *keeper, char *kept)
1829 PMD_FUNC(pmf, "unsatisfy")
1830 pm_pdr_t *dp;
1832 PMD(PMD_KEEPS, ("%s: keeper=%s, kept=%s\n", pmf, keeper, kept))
1833 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
1834 if (!dp->pdr_isprop) {
1835 if (strcmp(dp->pdr_keeper, keeper) == 0 &&
1836 (dp->pdr_kept_count > 0) &&
1837 strcmp(dp->pdr_kept_paths[0], kept) == 0) {
1838 if (dp->pdr_satisfied) {
1839 dp->pdr_satisfied = 0;
1840 pm_unresolved_deps++;
1841 PMD(PMD_KEEPS, ("%s: clear satisfied, "
1842 "pm_unresolved_deps now %d\n", pmf,
1843 pm_unresolved_deps))
1851 * Device dip is being un power managed, it keeps up count other devices.
1852 * We need to release any hold we have on the kept devices, and also
1853 * mark the dependency no longer satisfied.
1855 static void
1856 pm_unkeeps(int count, char *keeper, char **keptpaths, int pwr)
1858 PMD_FUNC(pmf, "unkeeps")
1859 int i, j;
1860 dev_info_t *kept;
1861 dev_info_t *dip;
1862 struct pm_component *cp;
1863 int keeper_on = 0, circ;
1865 PMD(PMD_KEEPS, ("%s: count=%d, keeper=%s, keptpaths=%p\n", pmf, count,
1866 keeper, (void *)keptpaths))
1868 * Try to grab keeper. Keeper may have gone away by now,
1869 * in this case, used the passed in value pwr
1871 dip = pm_name_to_dip(keeper, 1);
1872 for (i = 0; i < count; i++) {
1873 /* Release power hold */
1874 kept = pm_name_to_dip(keptpaths[i], 1);
1875 if (kept) {
1876 PMD(PMD_KEEPS, ("%s: %s@%s(%s#%d)[%d]\n", pmf,
1877 PM_DEVICE(kept), i))
1879 * We need to check if we skipped a bringup here
1880 * because we could have failed the bringup
1881 * (ie DIRECT PM device) and have
1882 * not increment the count.
1884 if ((dip != NULL) && (PM_GET_PM_INFO(dip) != NULL)) {
1885 keeper_on = 0;
1886 PM_LOCK_POWER(dip, &circ);
1887 for (j = 0; j < PM_NUMCMPTS(dip); j++) {
1888 cp = &DEVI(dip)->devi_pm_components[j];
1889 if (cur_power(cp)) {
1890 keeper_on++;
1891 break;
1894 if (keeper_on && (PM_SKBU(kept) == 0)) {
1895 pm_rele_power(kept);
1896 DEVI(kept)->devi_pm_flags
1897 &= ~PMC_SKIP_BRINGUP;
1899 PM_UNLOCK_POWER(dip, circ);
1900 } else if (pwr) {
1901 if (PM_SKBU(kept) == 0) {
1902 pm_rele_power(kept);
1903 DEVI(kept)->devi_pm_flags
1904 &= ~PMC_SKIP_BRINGUP;
1907 ddi_release_devi(kept);
1910 * mark this dependency not satisfied
1912 pm_unsatisfy(keeper, keptpaths[i]);
1914 if (dip)
1915 ddi_release_devi(dip);
1919 * Device kept is being un power managed, it is kept up by keeper.
1920 * We need to mark the dependency no longer satisfied.
1922 static void
1923 pm_unkepts(char *kept, char *keeper)
1925 PMD_FUNC(pmf, "unkepts")
1926 PMD(PMD_KEEPS, ("%s: kept=%s, keeper=%s\n", pmf, kept, keeper))
1927 ASSERT(keeper != NULL);
1929 * mark this dependency not satisfied
1931 pm_unsatisfy(keeper, kept);
1935 * Removes dependency information and hold on the kepts, if the path is a
1936 * path of a keeper.
1938 static void
1939 pm_free_keeper(char *path, int pwr)
1941 pm_pdr_t *dp;
1942 int i;
1943 size_t length;
1945 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
1946 if (strcmp(dp->pdr_keeper, path) != 0)
1947 continue;
1949 * Remove all our kept holds and the dependency records,
1950 * then free up the kept lists.
1952 pm_unkeeps(dp->pdr_kept_count, path, dp->pdr_kept_paths, pwr);
1953 if (dp->pdr_kept_count) {
1954 for (i = 0; i < dp->pdr_kept_count; i++) {
1955 length = strlen(dp->pdr_kept_paths[i]);
1956 kmem_free(dp->pdr_kept_paths[i], length + 1);
1958 kmem_free(dp->pdr_kept_paths,
1959 dp->pdr_kept_count * sizeof (char **));
1960 dp->pdr_kept_paths = NULL;
1961 dp->pdr_kept_count = 0;
1967 * Removes the device represented by path from the list of kepts, if the
1968 * path is a path of a kept
1970 static void
1971 pm_free_kept(char *path)
1973 pm_pdr_t *dp;
1974 int i;
1975 int j, count;
1976 size_t length;
1977 char **paths;
1979 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
1980 if (dp->pdr_kept_count == 0)
1981 continue;
1982 count = dp->pdr_kept_count;
1983 /* Remove this device from the kept path lists */
1984 for (i = 0; i < count; i++) {
1985 if (strcmp(dp->pdr_kept_paths[i], path) == 0) {
1986 pm_unkepts(path, dp->pdr_keeper);
1987 length = strlen(dp->pdr_kept_paths[i]) + 1;
1988 kmem_free(dp->pdr_kept_paths[i], length);
1989 dp->pdr_kept_paths[i] = NULL;
1990 dp->pdr_kept_count--;
1993 /* Compact the kept paths array */
1994 if (dp->pdr_kept_count) {
1995 length = dp->pdr_kept_count * sizeof (char **);
1996 paths = kmem_zalloc(length, KM_SLEEP);
1997 j = 0;
1998 for (i = 0; i < count; i++) {
1999 if (dp->pdr_kept_paths[i] != NULL) {
2000 paths[j] = dp->pdr_kept_paths[i];
2001 j++;
2004 ASSERT(j == dp->pdr_kept_count);
2006 /* Now free the old array and point to the new one */
2007 kmem_free(dp->pdr_kept_paths, count * sizeof (char **));
2008 if (dp->pdr_kept_count)
2009 dp->pdr_kept_paths = paths;
2010 else
2011 dp->pdr_kept_paths = NULL;
2016 * Free the dependency information for a device.
2018 void
2019 pm_free_keeps(char *path, int pwr)
2021 PMD_FUNC(pmf, "free_keeps")
2023 #ifdef DEBUG
2024 int doprdeps = 0;
2025 void prdeps(char *);
2027 PMD(PMD_KEEPS, ("%s: %s\n", pmf, path))
2028 if (pm_debug & PMD_KEEPS) {
2029 doprdeps = 1;
2030 prdeps("pm_free_keeps before");
2032 #endif
2034 * First assume we are a keeper and remove all our kepts.
2036 pm_free_keeper(path, pwr);
2038 * Now assume we a kept device, and remove all our records.
2040 pm_free_kept(path);
2041 #ifdef DEBUG
2042 if (doprdeps) {
2043 prdeps("pm_free_keeps after");
2045 #endif
2048 static int
2049 pm_is_kept(char *path)
2051 pm_pdr_t *dp;
2052 int i;
2054 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
2055 if (dp->pdr_kept_count == 0)
2056 continue;
2057 for (i = 0; i < dp->pdr_kept_count; i++) {
2058 if (strcmp(dp->pdr_kept_paths[i], path) == 0)
2059 return (1);
2062 return (0);
2065 static void
2066 e_pm_hold_rele_power(dev_info_t *dip, int cnt)
2068 PMD_FUNC(pmf, "hold_rele_power")
2069 int circ;
2071 if ((dip == NULL) ||
2072 (PM_GET_PM_INFO(dip) == NULL) || PM_ISBC(dip))
2073 return;
2075 PM_LOCK_POWER(dip, &circ);
2076 ASSERT(cnt >= 0 && PM_KUC(dip) >= 0 || cnt < 0 && PM_KUC(dip) > 0);
2077 PMD(PMD_KIDSUP, ("%s: kidsupcnt for %s@%s(%s#%d) %d->%d\n", pmf,
2078 PM_DEVICE(dip), PM_KUC(dip), (PM_KUC(dip) + cnt)))
2080 PM_KUC(dip) += cnt;
2082 ASSERT(PM_KUC(dip) >= 0);
2083 PM_UNLOCK_POWER(dip, circ);
2085 if (cnt < 0 && PM_KUC(dip) == 0)
2086 pm_rescan(dip);
2089 #define MAX_PPM_HANDLERS 4
2091 kmutex_t ppm_lock; /* in case we ever do multi-threaded startup */
2093 struct ppm_callbacks {
2094 int (*ppmc_func)(dev_info_t *);
2095 dev_info_t *ppmc_dip;
2096 } ppm_callbacks[MAX_PPM_HANDLERS + 1];
2100 * This routine calls into all the registered ppms to notify them
2101 * that either all components of power-managed devices are at their
2102 * lowest levels or no longer all are at their lowest levels.
2104 static void
2105 pm_ppm_notify_all_lowest(dev_info_t *dip, int mode)
2107 struct ppm_callbacks *ppmcp;
2108 power_req_t power_req;
2109 int result = 0;
2111 power_req.request_type = PMR_PPM_ALL_LOWEST;
2112 power_req.req.ppm_all_lowest_req.mode = mode;
2113 mutex_enter(&ppm_lock);
2114 for (ppmcp = ppm_callbacks; ppmcp->ppmc_func; ppmcp++)
2115 (void) pm_ctlops((dev_info_t *)ppmcp->ppmc_dip, dip,
2116 DDI_CTLOPS_POWER, &power_req, &result);
2117 mutex_exit(&ppm_lock);
2118 if (mode == PM_ALL_LOWEST) {
2119 if (autoS3_enabled) {
2120 PMD(PMD_SX, ("pm_ppm_notify_all_lowest triggering "
2121 "autos3\n"))
2122 mutex_enter(&srn_clone_lock);
2123 if (srn_signal) {
2124 srn_inuse++;
2125 PMD(PMD_SX, ("(*srn_signal)(AUTOSX, 3)\n"))
2126 (*srn_signal)(SRN_TYPE_AUTOSX, 3);
2127 srn_inuse--;
2128 } else {
2129 PMD(PMD_SX, ("srn_signal NULL\n"))
2131 mutex_exit(&srn_clone_lock);
2132 } else {
2133 PMD(PMD_SX, ("pm_ppm_notify_all_lowest autos3 "
2134 "disabled\n"));
2139 static void
2140 pm_set_pm_info(dev_info_t *dip, void *value)
2142 DEVI(dip)->devi_pm_info = value;
2145 pm_rsvp_t *pm_blocked_list;
2148 * Look up an entry in the blocked list by dip and component
2150 static pm_rsvp_t *
2151 pm_rsvp_lookup(dev_info_t *dip, int comp)
2153 pm_rsvp_t *p;
2154 ASSERT(MUTEX_HELD(&pm_rsvp_lock));
2155 for (p = pm_blocked_list; p; p = p->pr_next)
2156 if (p->pr_dip == dip && p->pr_comp == comp) {
2157 return (p);
2159 return (NULL);
2163 * Called when a device which is direct power managed (or the parent or
2164 * dependent of such a device) changes power, or when a pm clone is closed
2165 * that was direct power managing a device. This call results in pm_blocked()
2166 * (below) returning.
2168 void
2169 pm_proceed(dev_info_t *dip, int cmd, int comp, int newlevel)
2171 PMD_FUNC(pmf, "proceed")
2172 pm_rsvp_t *found = NULL;
2173 pm_rsvp_t *p;
2175 mutex_enter(&pm_rsvp_lock);
2176 switch (cmd) {
2178 * we're giving up control, let any pending op continue
2180 case PMP_RELEASE:
2181 for (p = pm_blocked_list; p; p = p->pr_next) {
2182 if (dip == p->pr_dip) {
2183 p->pr_retval = PMP_RELEASE;
2184 PMD(PMD_DPM, ("%s: RELEASE %s@%s(%s#%d)\n",
2185 pmf, PM_DEVICE(dip)))
2186 cv_signal(&p->pr_cv);
2189 break;
2192 * process has done PM_SET_CURRENT_POWER; let a matching request
2193 * succeed and a non-matching request for the same device fail
2195 case PMP_SETPOWER:
2196 found = pm_rsvp_lookup(dip, comp);
2197 if (!found) /* if driver not waiting */
2198 break;
2200 * This cannot be pm_lower_power, since that can only happen
2201 * during detach or probe
2203 if (found->pr_newlevel <= newlevel) {
2204 found->pr_retval = PMP_SUCCEED;
2205 PMD(PMD_DPM, ("%s: SUCCEED %s@%s(%s#%d)\n", pmf,
2206 PM_DEVICE(dip)))
2207 } else {
2208 found->pr_retval = PMP_FAIL;
2209 PMD(PMD_DPM, ("%s: FAIL %s@%s(%s#%d)\n", pmf,
2210 PM_DEVICE(dip)))
2212 cv_signal(&found->pr_cv);
2213 break;
2215 default:
2216 panic("pm_proceed unknown cmd %d", cmd);
2218 mutex_exit(&pm_rsvp_lock);
2222 * This routine dispatches new work to the dependency thread. Caller must
2223 * be prepared to block for memory if necessary.
2225 void
2226 pm_dispatch_to_dep_thread(int cmd, char *keeper, char *kept, int wait,
2227 int *res, int cached_pwr)
2229 pm_dep_wk_t *new_work;
2231 new_work = kmem_zalloc(sizeof (pm_dep_wk_t), KM_SLEEP);
2232 new_work->pdw_type = cmd;
2233 new_work->pdw_wait = wait;
2234 new_work->pdw_done = 0;
2235 new_work->pdw_ret = 0;
2236 new_work->pdw_pwr = cached_pwr;
2237 cv_init(&new_work->pdw_cv, NULL, CV_DEFAULT, NULL);
2238 if (keeper != NULL) {
2239 new_work->pdw_keeper = kmem_zalloc(strlen(keeper) + 1,
2240 KM_SLEEP);
2241 (void) strcpy(new_work->pdw_keeper, keeper);
2243 if (kept != NULL) {
2244 new_work->pdw_kept = kmem_zalloc(strlen(kept) + 1, KM_SLEEP);
2245 (void) strcpy(new_work->pdw_kept, kept);
2247 mutex_enter(&pm_dep_thread_lock);
2248 if (pm_dep_thread_workq == NULL) {
2249 pm_dep_thread_workq = new_work;
2250 pm_dep_thread_tail = new_work;
2251 new_work->pdw_next = NULL;
2252 } else {
2253 pm_dep_thread_tail->pdw_next = new_work;
2254 pm_dep_thread_tail = new_work;
2255 new_work->pdw_next = NULL;
2257 cv_signal(&pm_dep_thread_cv);
2258 /* If caller asked for it, wait till it is done. */
2259 if (wait) {
2260 while (!new_work->pdw_done)
2261 cv_wait(&new_work->pdw_cv, &pm_dep_thread_lock);
2263 * Pass return status, if any, back.
2265 if (res != NULL)
2266 *res = new_work->pdw_ret;
2268 * If we asked to wait, it is our job to free the request
2269 * structure.
2271 if (new_work->pdw_keeper)
2272 kmem_free(new_work->pdw_keeper,
2273 strlen(new_work->pdw_keeper) + 1);
2274 if (new_work->pdw_kept)
2275 kmem_free(new_work->pdw_kept,
2276 strlen(new_work->pdw_kept) + 1);
2277 kmem_free(new_work, sizeof (pm_dep_wk_t));
2279 mutex_exit(&pm_dep_thread_lock);
2283 * Release the pm resource for this device.
2285 void
2286 pm_rem_info(dev_info_t *dip)
2288 PMD_FUNC(pmf, "rem_info")
2289 int i, count = 0;
2290 pm_info_t *info = PM_GET_PM_INFO(dip);
2291 dev_info_t *pdip = ddi_get_parent(dip);
2292 char *pathbuf;
2293 int work_type = PM_DEP_WK_DETACH;
2295 ASSERT(info);
2297 ASSERT(!PM_IAM_LOCKING_DIP(dip));
2298 if (PM_ISDIRECT(dip)) {
2299 info->pmi_dev_pm_state &= ~PM_DIRECT;
2300 ASSERT(info->pmi_clone);
2301 info->pmi_clone = 0;
2302 pm_proceed(dip, PMP_RELEASE, -1, -1);
2304 ASSERT(!PM_GET_PM_SCAN(dip));
2307 * Now adjust parent's kidsupcnt. BC nodes we check only comp 0,
2308 * Others we check all components. BC node that has already
2309 * called pm_destroy_components() has zero component count.
2310 * Parents that get notification are not adjusted because their
2311 * kidsupcnt is always 0 (or 1 during configuration).
2313 PMD(PMD_KEEPS, ("%s: %s@%s(%s#%d) has %d components\n", pmf,
2314 PM_DEVICE(dip), PM_NUMCMPTS(dip)))
2316 /* node is detached, so we can examine power without locking */
2317 if (PM_ISBC(dip)) {
2318 count = (PM_CURPOWER(dip, 0) != 0);
2319 } else {
2320 for (i = 0; i < PM_NUMCMPTS(dip); i++)
2321 count += (PM_CURPOWER(dip, i) != 0);
2324 if (PM_NUMCMPTS(dip) && pdip && !PM_WANTS_NOTIFICATION(pdip))
2325 e_pm_hold_rele_power(pdip, -count);
2327 /* Schedule a request to clean up dependency records */
2328 pathbuf = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
2329 (void) ddi_pathname(dip, pathbuf);
2330 pm_dispatch_to_dep_thread(work_type, pathbuf, pathbuf,
2331 PM_DEP_NOWAIT, NULL, (count > 0));
2332 kmem_free(pathbuf, MAXPATHLEN);
2335 * Adjust the pm_comps_notlowest count since this device is
2336 * not being power-managed anymore.
2338 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
2339 pm_component_t *cp = PM_CP(dip, i);
2340 if (cp->pmc_cur_pwr != 0)
2341 PM_DECR_NOTLOWEST(dip)
2344 * Once we clear the info pointer, it looks like it is not power
2345 * managed to everybody else.
2347 pm_set_pm_info(dip, NULL);
2348 kmem_free(info, sizeof (pm_info_t));
2352 pm_get_norm_pwrs(dev_info_t *dip, int **valuep, size_t *length)
2354 int components = PM_NUMCMPTS(dip);
2355 int *bufp;
2356 size_t size;
2357 int i;
2359 if (components <= 0) {
2360 cmn_err(CE_NOTE, "!pm: %s@%s(%s#%d) has no components, "
2361 "can't get normal power values\n", PM_DEVICE(dip));
2362 return (DDI_FAILURE);
2363 } else {
2364 size = components * sizeof (int);
2365 bufp = kmem_alloc(size, KM_SLEEP);
2366 for (i = 0; i < components; i++) {
2367 bufp[i] = pm_get_normal_power(dip, i);
2370 *length = size;
2371 *valuep = bufp;
2372 return (DDI_SUCCESS);
2375 static int
2376 pm_reset_timestamps(dev_info_t *dip, void *arg)
2378 _NOTE(ARGUNUSED(arg))
2380 int components;
2381 int i;
2383 if (!PM_GET_PM_INFO(dip))
2384 return (DDI_WALK_CONTINUE);
2385 components = PM_NUMCMPTS(dip);
2386 ASSERT(components > 0);
2387 PM_LOCK_BUSY(dip);
2388 for (i = 0; i < components; i++) {
2389 struct pm_component *cp;
2391 * If the component was not marked as busy,
2392 * reset its timestamp to now.
2394 cp = PM_CP(dip, i);
2395 if (cp->pmc_timestamp)
2396 cp->pmc_timestamp = gethrestime_sec();
2398 PM_UNLOCK_BUSY(dip);
2399 return (DDI_WALK_CONTINUE);
2403 * Convert a power level to an index into the levels array (or
2404 * just PM_LEVEL_UNKNOWN in that special case).
2406 static int
2407 pm_level_to_index(dev_info_t *dip, pm_component_t *cp, int level)
2409 PMD_FUNC(pmf, "level_to_index")
2410 int i;
2411 int limit = cp->pmc_comp.pmc_numlevels;
2412 int *ip = cp->pmc_comp.pmc_lvals;
2414 if (level == PM_LEVEL_UNKNOWN)
2415 return (level);
2417 for (i = 0; i < limit; i++) {
2418 if (level == *ip++) {
2419 PMD(PMD_LEVEL, ("%s: %s@%s(%s#%d)[%d] to %x\n",
2420 pmf, PM_DEVICE(dip),
2421 (int)(cp - DEVI(dip)->devi_pm_components), level))
2422 return (i);
2425 panic("pm_level_to_index: level %d not found for device "
2426 "%s@%s(%s#%d)", level, PM_DEVICE(dip));
2427 /*NOTREACHED*/
2431 * Internal function to set current power level
2433 static void
2434 e_pm_set_cur_pwr(dev_info_t *dip, pm_component_t *cp, int level)
2436 PMD_FUNC(pmf, "set_cur_pwr")
2437 int curpwr = (cp->pmc_flags & PM_PHC_WHILE_SET_POWER ?
2438 cp->pmc_phc_pwr : cp->pmc_cur_pwr);
2441 * Nothing to adjust if current & new levels are the same.
2443 if (curpwr != PM_LEVEL_UNKNOWN &&
2444 level == cp->pmc_comp.pmc_lvals[curpwr])
2445 return;
2448 * Keep the count for comps doing transition to/from lowest
2449 * level.
2451 if (curpwr == 0) {
2452 PM_INCR_NOTLOWEST(dip);
2453 } else if (level == cp->pmc_comp.pmc_lvals[0]) {
2454 PM_DECR_NOTLOWEST(dip);
2456 cp->pmc_phc_pwr = PM_LEVEL_UNKNOWN;
2457 cp->pmc_cur_pwr = pm_level_to_index(dip, cp, level);
2460 static int pm_phc_impl(dev_info_t *, int, int, int);
2463 * This is the default method of setting the power of a device if no ppm
2464 * driver has claimed it.
2467 pm_power(dev_info_t *dip, int comp, int level)
2469 PMD_FUNC(pmf, "power")
2470 struct dev_ops *ops;
2471 int (*fn)(dev_info_t *, int, int);
2472 struct pm_component *cp = PM_CP(dip, comp);
2473 int retval;
2474 pm_info_t *info = PM_GET_PM_INFO(dip);
2476 PMD(PMD_KIDSUP, ("%s: %s@%s(%s#%d), comp=%d, level=%d\n", pmf,
2477 PM_DEVICE(dip), comp, level))
2478 if (!(ops = ddi_get_driver(dip))) {
2479 PMD(PMD_FAIL, ("%s: %s@%s(%s#%d) has no ops\n", pmf,
2480 PM_DEVICE(dip)))
2481 return (DDI_FAILURE);
2483 if ((ops->devo_rev < 2) || !(fn = ops->devo_power)) {
2484 PMD(PMD_FAIL, ("%s: %s%s\n", pmf,
2485 (ops->devo_rev < 2 ? " wrong devo_rev" : ""),
2486 (!fn ? " devo_power NULL" : "")))
2487 return (DDI_FAILURE);
2489 cp->pmc_flags |= PM_POWER_OP;
2490 retval = (*fn)(dip, comp, level);
2491 cp->pmc_flags &= ~PM_POWER_OP;
2492 if (retval == DDI_SUCCESS) {
2493 e_pm_set_cur_pwr(dip, PM_CP(dip, comp), level);
2494 return (DDI_SUCCESS);
2498 * If pm_power_has_changed() detected a deadlock with pm_power() it
2499 * updated only the power level of the component. If our attempt to
2500 * set the device new to a power level above has failed we sync the
2501 * total power state via phc code now.
2503 if (cp->pmc_flags & PM_PHC_WHILE_SET_POWER) {
2504 int phc_lvl =
2505 cp->pmc_comp.pmc_lvals[cp->pmc_cur_pwr];
2507 ASSERT(info);
2508 (void) pm_phc_impl(dip, comp, phc_lvl, 0);
2509 PMD(PMD_PHC, ("%s: phc %s@%s(%s#%d) comp=%d level=%d\n",
2510 pmf, PM_DEVICE(dip), comp, phc_lvl))
2513 PMD(PMD_FAIL, ("%s: can't set comp=%d (%s) of %s@%s(%s#%d) to "
2514 "level=%d (%s)\n", pmf, comp, cp->pmc_comp.pmc_name, PM_DEVICE(dip),
2515 level, power_val_to_string(cp, level)));
2516 return (DDI_FAILURE);
2520 pm_unmanage(dev_info_t *dip)
2522 PMD_FUNC(pmf, "unmanage")
2523 power_req_t power_req;
2524 int result, retval = 0;
2526 ASSERT(!PM_IAM_LOCKING_DIP(dip));
2527 PMD(PMD_REMDEV | PMD_KIDSUP, ("%s: %s@%s(%s#%d)\n", pmf,
2528 PM_DEVICE(dip)))
2529 power_req.request_type = PMR_PPM_UNMANAGE;
2530 power_req.req.ppm_config_req.who = dip;
2531 if (pm_ppm_claimed(dip))
2532 retval = pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER,
2533 &power_req, &result);
2534 #ifdef DEBUG
2535 else
2536 retval = pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER,
2537 &power_req, &result);
2538 #endif
2539 ASSERT(retval == DDI_SUCCESS);
2540 pm_rem_info(dip);
2541 return (retval);
2545 pm_raise_power(dev_info_t *dip, int comp, int level)
2547 if (level < 0)
2548 return (DDI_FAILURE);
2549 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, comp, NULL) ||
2550 !e_pm_valid_power(dip, comp, level))
2551 return (DDI_FAILURE);
2553 return (dev_is_needed(dip, comp, level, PM_LEVEL_UPONLY));
2557 pm_lower_power(dev_info_t *dip, int comp, int level)
2559 PMD_FUNC(pmf, "pm_lower_power")
2561 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, comp, NULL) ||
2562 !e_pm_valid_power(dip, comp, level)) {
2563 PMD(PMD_FAIL, ("%s: validation checks failed for %s@%s(%s#%d) "
2564 "comp=%d level=%d\n", pmf, PM_DEVICE(dip), comp, level))
2565 return (DDI_FAILURE);
2568 if (!DEVI_IS_DETACHING(dip)) {
2569 PMD(PMD_FAIL, ("%s: %s@%s(%s#%d) not detaching\n",
2570 pmf, PM_DEVICE(dip)))
2571 return (DDI_FAILURE);
2575 * If we don't care about saving power, or we're treating this node
2576 * specially, then this is a no-op
2578 if (!PM_SCANABLE(dip) || pm_noinvol(dip)) {
2579 PMD(PMD_FAIL, ("%s: %s@%s(%s#%d) %s%s%s%s\n",
2580 pmf, PM_DEVICE(dip),
2581 !autopm_enabled ? "!autopm_enabled " : "",
2582 !PM_POLLING_CPUPM ? "!cpupm_polling " : "",
2583 PM_CPUPM_DISABLED ? "cpupm_disabled " : "",
2584 pm_noinvol(dip) ? "pm_noinvol()" : ""))
2585 return (DDI_SUCCESS);
2588 if (dev_is_needed(dip, comp, level, PM_LEVEL_DOWNONLY) != DDI_SUCCESS) {
2589 PMD(PMD_FAIL, ("%s: %s@%s(%s#%d) dev_is_needed failed\n", pmf,
2590 PM_DEVICE(dip)))
2591 return (DDI_FAILURE);
2593 return (DDI_SUCCESS);
2597 * Find the entries struct for a given dip in the blocked list, return it locked
2599 static psce_t *
2600 pm_psc_dip_to_direct(dev_info_t *dip, pscc_t **psccp)
2602 pscc_t *p;
2603 psce_t *psce;
2605 rw_enter(&pm_pscc_direct_rwlock, RW_READER);
2606 for (p = pm_pscc_direct; p; p = p->pscc_next) {
2607 if (p->pscc_dip == dip) {
2608 *psccp = p;
2609 psce = p->pscc_entries;
2610 mutex_enter(&psce->psce_lock);
2611 ASSERT(psce);
2612 rw_exit(&pm_pscc_direct_rwlock);
2613 return (psce);
2616 rw_exit(&pm_pscc_direct_rwlock);
2617 panic("sunpm: no entry for dip %p in direct list", (void *)dip);
2618 /*NOTREACHED*/
2622 * Write an entry indicating a power level change (to be passed to a process
2623 * later) in the given psce.
2624 * If we were called in the path that brings up the console fb in the
2625 * case of entering the prom, we don't want to sleep. If the alloc fails, then
2626 * we create a record that has a size of -1, a physaddr of NULL, and that
2627 * has the overflow flag set.
2629 static int
2630 psc_entry(ushort_t event, psce_t *psce, dev_info_t *dip, int comp, int new,
2631 int old, int which, pm_canblock_t canblock)
2633 char buf[MAXNAMELEN];
2634 pm_state_change_t *p;
2635 size_t size;
2636 caddr_t physpath = NULL;
2637 int overrun = 0;
2639 ASSERT(MUTEX_HELD(&psce->psce_lock));
2640 (void) ddi_pathname(dip, buf);
2641 size = strlen(buf) + 1;
2642 p = psce->psce_in;
2643 if (canblock == PM_CANBLOCK_BYPASS) {
2644 physpath = kmem_alloc(size, KM_NOSLEEP);
2645 if (physpath == NULL) {
2647 * mark current entry as overrun
2649 p->flags |= PSC_EVENT_LOST;
2650 size = (size_t)-1;
2652 } else
2653 physpath = kmem_alloc(size, KM_SLEEP);
2654 if (p->size) { /* overflow; mark the next entry */
2655 if (p->size != (size_t)-1)
2656 kmem_free(p->physpath, p->size);
2657 ASSERT(psce->psce_out == p);
2658 if (p == psce->psce_last) {
2659 psce->psce_first->flags |= PSC_EVENT_LOST;
2660 psce->psce_out = psce->psce_first;
2661 } else {
2662 (p + 1)->flags |= PSC_EVENT_LOST;
2663 psce->psce_out = (p + 1);
2665 overrun++;
2666 } else if (physpath == NULL) { /* alloc failed, mark this entry */
2667 p->flags |= PSC_EVENT_LOST;
2668 p->size = 0;
2669 p->physpath = NULL;
2671 if (which == PSC_INTEREST) {
2672 mutex_enter(&pm_compcnt_lock);
2673 if (pm_comps_notlowest == 0)
2674 p->flags |= PSC_ALL_LOWEST;
2675 else
2676 p->flags &= ~PSC_ALL_LOWEST;
2677 mutex_exit(&pm_compcnt_lock);
2679 p->event = event;
2680 p->timestamp = gethrestime_sec();
2681 p->component = comp;
2682 p->old_level = old;
2683 p->new_level = new;
2684 p->physpath = physpath;
2685 p->size = size;
2686 if (physpath != NULL)
2687 (void) strcpy(p->physpath, buf);
2688 if (p == psce->psce_last)
2689 psce->psce_in = psce->psce_first;
2690 else
2691 psce->psce_in = ++p;
2692 mutex_exit(&psce->psce_lock);
2693 return (overrun);
2697 * Find the next entry on the interest list. We keep a pointer to the item we
2698 * last returned in the user's cooke. Returns a locked entries struct.
2700 static psce_t *
2701 psc_interest(void **cookie, pscc_t **psccp)
2703 pscc_t *pscc;
2704 pscc_t **cookiep = (pscc_t **)cookie;
2706 if (*cookiep == NULL)
2707 pscc = pm_pscc_interest;
2708 else
2709 pscc = (*cookiep)->pscc_next;
2710 if (pscc) {
2711 *cookiep = pscc;
2712 *psccp = pscc;
2713 mutex_enter(&pscc->pscc_entries->psce_lock);
2714 return (pscc->pscc_entries);
2715 } else {
2716 return (NULL);
2721 * Create an entry for a process to pick up indicating a power level change.
2723 static void
2724 pm_enqueue_notify(ushort_t cmd, dev_info_t *dip, int comp,
2725 int newlevel, int oldlevel, pm_canblock_t canblock)
2727 PMD_FUNC(pmf, "enqueue_notify")
2728 pscc_t *pscc;
2729 psce_t *psce;
2730 void *cookie = NULL;
2731 int overrun;
2733 ASSERT(MUTEX_HELD(&pm_rsvp_lock));
2734 switch (cmd) {
2735 case PSC_PENDING_CHANGE: /* only for controlling process */
2736 PMD(PMD_DPM, ("%s: PENDING %s@%s(%s#%d), comp %d, %d -> %d\n",
2737 pmf, PM_DEVICE(dip), comp, oldlevel, newlevel))
2738 psce = pm_psc_dip_to_direct(dip, &pscc);
2739 ASSERT(psce);
2740 PMD(PMD_IOCTL, ("%s: PENDING: %s@%s(%s#%d) pm_poll_cnt[%d] "
2741 "%d\n", pmf, PM_DEVICE(dip), pscc->pscc_clone,
2742 pm_poll_cnt[pscc->pscc_clone]))
2743 overrun = psc_entry(cmd, psce, dip, comp, newlevel, oldlevel,
2744 PSC_DIRECT, canblock);
2745 PMD(PMD_DPM, ("%s: sig %d\n", pmf, pscc->pscc_clone))
2746 mutex_enter(&pm_clone_lock);
2747 if (!overrun)
2748 pm_poll_cnt[pscc->pscc_clone]++;
2749 cv_signal(&pm_clones_cv[pscc->pscc_clone]);
2750 pollwakeup(&pm_pollhead, (POLLRDNORM | POLLIN));
2751 mutex_exit(&pm_clone_lock);
2752 break;
2753 case PSC_HAS_CHANGED:
2754 PMD(PMD_DPM, ("%s: HAS %s@%s(%s#%d), comp %d, %d -> %d\n",
2755 pmf, PM_DEVICE(dip), comp, oldlevel, newlevel))
2756 if (PM_ISDIRECT(dip) && canblock != PM_CANBLOCK_BYPASS) {
2757 psce = pm_psc_dip_to_direct(dip, &pscc);
2758 PMD(PMD_IOCTL, ("%s: HAS: %s@%s(%s#%d) pm_poll_cnt[%d] "
2759 "%d\n", pmf, PM_DEVICE(dip), pscc->pscc_clone,
2760 pm_poll_cnt[pscc->pscc_clone]))
2761 overrun = psc_entry(cmd, psce, dip, comp, newlevel,
2762 oldlevel, PSC_DIRECT, canblock);
2763 PMD(PMD_DPM, ("%s: sig %d\n", pmf, pscc->pscc_clone))
2764 mutex_enter(&pm_clone_lock);
2765 if (!overrun)
2766 pm_poll_cnt[pscc->pscc_clone]++;
2767 cv_signal(&pm_clones_cv[pscc->pscc_clone]);
2768 pollwakeup(&pm_pollhead, (POLLRDNORM | POLLIN));
2769 mutex_exit(&pm_clone_lock);
2771 mutex_enter(&pm_clone_lock);
2772 rw_enter(&pm_pscc_interest_rwlock, RW_READER);
2773 while ((psce = psc_interest(&cookie, &pscc)) != NULL) {
2774 (void) psc_entry(cmd, psce, dip, comp, newlevel,
2775 oldlevel, PSC_INTEREST, canblock);
2776 cv_signal(&pm_clones_cv[pscc->pscc_clone]);
2778 rw_exit(&pm_pscc_interest_rwlock);
2779 mutex_exit(&pm_clone_lock);
2780 break;
2781 #ifdef DEBUG
2782 default:
2783 ASSERT(0);
2784 #endif
2788 static void
2789 pm_enqueue_notify_others(pm_ppm_devlist_t **listp, pm_canblock_t canblock)
2791 if (listp) {
2792 pm_ppm_devlist_t *p, *next = NULL;
2794 for (p = *listp; p; p = next) {
2795 next = p->ppd_next;
2796 pm_enqueue_notify(PSC_HAS_CHANGED, p->ppd_who,
2797 p->ppd_cmpt, p->ppd_new_level, p->ppd_old_level,
2798 canblock);
2799 kmem_free(p, sizeof (pm_ppm_devlist_t));
2801 *listp = NULL;
2806 * Try to get the power locks of the parent node and target (child)
2807 * node. Return true if successful (with both locks held) or false
2808 * (with no locks held).
2810 static int
2811 pm_try_parent_child_locks(dev_info_t *pdip,
2812 dev_info_t *dip, int *pcircp, int *circp)
2814 if (ndi_devi_tryenter(pdip, pcircp))
2815 if (PM_TRY_LOCK_POWER(dip, circp)) {
2816 return (1);
2817 } else {
2818 ndi_devi_exit(pdip, *pcircp);
2820 return (0);
2824 * Determine if the power lock owner is blocked by current thread.
2825 * returns :
2826 * 1 - If the thread owning the effective power lock (the first lock on
2827 * which a thread blocks when it does PM_LOCK_POWER) is blocked by
2828 * a mutex held by the current thread.
2830 * 0 - otherwise
2832 * Note : This function is called by pm_power_has_changed to determine whether
2833 * it is executing in parallel with pm_set_power.
2835 static int
2836 pm_blocked_by_us(dev_info_t *dip)
2838 power_req_t power_req;
2839 kthread_t *owner;
2840 int result;
2841 kmutex_t *mp;
2842 dev_info_t *ppm = (dev_info_t *)DEVI(dip)->devi_pm_ppm;
2844 power_req.request_type = PMR_PPM_POWER_LOCK_OWNER;
2845 power_req.req.ppm_power_lock_owner_req.who = dip;
2846 if (pm_ctlops(ppm, dip, DDI_CTLOPS_POWER, &power_req, &result) !=
2847 DDI_SUCCESS) {
2849 * It is assumed that if the device is claimed by ppm, ppm
2850 * will always implement this request type and it'll always
2851 * return success. We panic here, if it fails.
2853 panic("pm: Can't determine power lock owner of %s@%s(%s#%d)\n",
2854 PM_DEVICE(dip));
2855 /*NOTREACHED*/
2858 if ((owner = power_req.req.ppm_power_lock_owner_req.owner) != NULL &&
2859 owner->t_state == TS_SLEEP &&
2860 owner->t_sobj_ops &&
2861 SOBJ_TYPE(owner->t_sobj_ops) == SOBJ_MUTEX &&
2862 (mp = (kmutex_t *)owner->t_wchan) &&
2863 mutex_owner(mp) == curthread)
2864 return (1);
2866 return (0);
2870 * Notify parent which wants to hear about a child's power changes.
2872 static void
2873 pm_notify_parent(dev_info_t *dip,
2874 dev_info_t *pdip, int comp, int old_level, int level)
2876 pm_bp_has_changed_t bphc;
2877 pm_sp_misc_t pspm;
2878 char *pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
2879 int result = DDI_SUCCESS;
2881 bphc.bphc_dip = dip;
2882 bphc.bphc_path = ddi_pathname(dip, pathbuf);
2883 bphc.bphc_comp = comp;
2884 bphc.bphc_olevel = old_level;
2885 bphc.bphc_nlevel = level;
2886 pspm.pspm_canblock = PM_CANBLOCK_BLOCK;
2887 pspm.pspm_scan = 0;
2888 bphc.bphc_private = &pspm;
2889 (void) (*PM_BUS_POWER_FUNC(pdip))(pdip, NULL,
2890 BUS_POWER_HAS_CHANGED, (void *)&bphc, (void *)&result);
2891 kmem_free(pathbuf, MAXPATHLEN);
2895 * Check if we need to resume a BC device, and make the attach call as required.
2897 static int
2898 pm_check_and_resume(dev_info_t *dip, int comp, int old_level, int level)
2900 int ret = DDI_SUCCESS;
2902 if (PM_ISBC(dip) && comp == 0 && old_level == 0 && level != 0) {
2903 ASSERT(DEVI(dip)->devi_pm_flags & PMC_SUSPENDED);
2904 /* ppm is not interested in DDI_PM_RESUME */
2905 if ((ret = devi_attach(dip, DDI_PM_RESUME)) != DDI_SUCCESS)
2906 /* XXX Should we mark it resumed, */
2907 /* even though it failed? */
2908 cmn_err(CE_WARN, "!pm: Can't resume %s@%s",
2909 PM_NAME(dip), PM_ADDR(dip));
2910 DEVI(dip)->devi_pm_flags &= ~PMC_SUSPENDED;
2913 return (ret);
2917 * Tests outside the lock to see if we should bother to enqueue an entry
2918 * for any watching process. If yes, then caller will take the lock and
2919 * do the full protocol
2921 static int
2922 pm_watchers()
2924 if (pm_processes_stopped)
2925 return (0);
2926 return (pm_pscc_direct || pm_pscc_interest);
2929 static int pm_phc_impl(dev_info_t *, int, int, int);
2932 * A driver is reporting that the power of one of its device's components
2933 * has changed. Update the power state accordingly.
2936 pm_power_has_changed(dev_info_t *dip, int comp, int level)
2938 PMD_FUNC(pmf, "pm_power_has_changed")
2939 int ret;
2940 dev_info_t *pdip = ddi_get_parent(dip);
2941 struct pm_component *cp;
2942 int blocked, circ, pcirc, old_level;
2944 if (level < 0) {
2945 PMD(PMD_FAIL, ("%s: %s@%s(%s#%d): bad level=%d\n", pmf,
2946 PM_DEVICE(dip), level))
2947 return (DDI_FAILURE);
2950 PMD(PMD_KIDSUP | PMD_DEP, ("%s: %s@%s(%s#%d), comp=%d, level=%d\n", pmf,
2951 PM_DEVICE(dip), comp, level))
2953 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, comp, &cp) ||
2954 !e_pm_valid_power(dip, comp, level))
2955 return (DDI_FAILURE);
2958 * A driver thread calling pm_power_has_changed and another thread
2959 * calling pm_set_power can deadlock. The problem is not resolvable
2960 * by changing lock order, so we use pm_blocked_by_us() to detect
2961 * this specific deadlock. If we can't get the lock immediately
2962 * and we are deadlocked, just update the component's level, do
2963 * notifications, and return. We intend to update the total power
2964 * state later (if the other thread fails to set power to the
2965 * desired level). If we were called because of a power change on a
2966 * component that isn't involved in a set_power op, update all state
2967 * immediately.
2969 cp = PM_CP(dip, comp);
2970 while (!pm_try_parent_child_locks(pdip, dip, &pcirc, &circ)) {
2971 if (((blocked = pm_blocked_by_us(dip)) != 0) &&
2972 (cp->pmc_flags & PM_POWER_OP)) {
2973 if (pm_watchers()) {
2974 mutex_enter(&pm_rsvp_lock);
2975 pm_enqueue_notify(PSC_HAS_CHANGED, dip, comp,
2976 level, cur_power(cp), PM_CANBLOCK_BLOCK);
2977 mutex_exit(&pm_rsvp_lock);
2979 if (pdip && PM_WANTS_NOTIFICATION(pdip))
2980 pm_notify_parent(dip,
2981 pdip, comp, cur_power(cp), level);
2982 (void) pm_check_and_resume(dip,
2983 comp, cur_power(cp), level);
2986 * Stash the old power index, update curpwr, and flag
2987 * that the total power state needs to be synched.
2989 cp->pmc_flags |= PM_PHC_WHILE_SET_POWER;
2991 * Several pm_power_has_changed calls could arrive
2992 * while the set power path remains blocked. Keep the
2993 * oldest old power and the newest new power of any
2994 * sequence of phc calls which arrive during deadlock.
2996 if (cp->pmc_phc_pwr == PM_LEVEL_UNKNOWN)
2997 cp->pmc_phc_pwr = cp->pmc_cur_pwr;
2998 cp->pmc_cur_pwr =
2999 pm_level_to_index(dip, cp, level);
3000 PMD(PMD_PHC, ("%s: deadlock for %s@%s(%s#%d), comp=%d, "
3001 "level=%d\n", pmf, PM_DEVICE(dip), comp, level))
3002 return (DDI_SUCCESS);
3003 } else
3004 if (blocked) { /* blocked, but different cmpt? */
3005 if (!ndi_devi_tryenter(pdip, &pcirc)) {
3006 cmn_err(CE_NOTE,
3007 "!pm: parent kuc not updated due "
3008 "to possible deadlock.\n");
3009 return (pm_phc_impl(dip,
3010 comp, level, 1));
3012 old_level = cur_power(cp);
3013 if (pdip && !PM_WANTS_NOTIFICATION(pdip) &&
3014 (!PM_ISBC(dip) || comp == 0) &&
3015 POWERING_ON(old_level, level))
3016 pm_hold_power(pdip);
3017 ret = pm_phc_impl(dip, comp, level, 1);
3018 if (pdip && !PM_WANTS_NOTIFICATION(pdip)) {
3019 if ((!PM_ISBC(dip) ||
3020 comp == 0) && level == 0 &&
3021 old_level != PM_LEVEL_UNKNOWN)
3022 pm_rele_power(pdip);
3024 ndi_devi_exit(pdip, pcirc);
3025 /* child lock not held: deadlock */
3026 return (ret);
3028 delay(1);
3029 PMD(PMD_PHC, ("%s: try lock again\n", pmf))
3032 /* non-deadlock case */
3033 old_level = cur_power(cp);
3034 if (pdip && !PM_WANTS_NOTIFICATION(pdip) &&
3035 (!PM_ISBC(dip) || comp == 0) && POWERING_ON(old_level, level))
3036 pm_hold_power(pdip);
3037 ret = pm_phc_impl(dip, comp, level, 1);
3038 if (pdip && !PM_WANTS_NOTIFICATION(pdip)) {
3039 if ((!PM_ISBC(dip) || comp == 0) && level == 0 &&
3040 old_level != PM_LEVEL_UNKNOWN)
3041 pm_rele_power(pdip);
3043 PM_UNLOCK_POWER(dip, circ);
3044 ndi_devi_exit(pdip, pcirc);
3045 return (ret);
3049 * Account for power changes to a component of the the console frame buffer.
3050 * If lowering power from full (or "unkown", which is treatd as full)
3051 * we will increment the "components off" count of the fb device.
3052 * Subsequent lowering of the same component doesn't affect the count. If
3053 * raising a component back to full power, we will decrement the count.
3055 * Return: the increment value for pm_cfb_comps_off (-1, 0, or 1)
3057 static int
3058 calc_cfb_comps_incr(dev_info_t *dip, int cmpt, int old, int new)
3060 struct pm_component *cp = PM_CP(dip, cmpt);
3061 int on = (old == PM_LEVEL_UNKNOWN || old == cp->pmc_norm_pwr);
3062 int want_normal = (new == cp->pmc_norm_pwr);
3063 int incr = 0;
3065 if (on && !want_normal)
3066 incr = 1;
3067 else if (!on && want_normal)
3068 incr = -1;
3069 return (incr);
3073 * Adjust the count of console frame buffer components < full power.
3075 static void
3076 update_comps_off(int incr, dev_info_t *dip)
3078 mutex_enter(&pm_cfb_lock);
3079 pm_cfb_comps_off += incr;
3080 ASSERT(pm_cfb_comps_off <= PM_NUMCMPTS(dip));
3081 mutex_exit(&pm_cfb_lock);
3085 * Update the power state in the framework (via the ppm). The 'notify'
3086 * argument tells whether to notify watchers. Power lock is already held.
3088 static int
3089 pm_phc_impl(dev_info_t *dip, int comp, int level, int notify)
3091 PMD_FUNC(pmf, "phc_impl")
3092 power_req_t power_req;
3093 int i, dodeps = 0;
3094 dev_info_t *pdip = ddi_get_parent(dip);
3095 int result;
3096 int old_level;
3097 struct pm_component *cp;
3098 int incr = 0;
3099 dev_info_t *ppm = (dev_info_t *)DEVI(dip)->devi_pm_ppm;
3100 int work_type = 0;
3101 char *pathbuf;
3103 /* Must use "official" power level for this test. */
3104 cp = PM_CP(dip, comp);
3105 old_level = (cp->pmc_flags & PM_PHC_WHILE_SET_POWER ?
3106 cp->pmc_phc_pwr : cp->pmc_cur_pwr);
3107 if (old_level != PM_LEVEL_UNKNOWN)
3108 old_level = cp->pmc_comp.pmc_lvals[old_level];
3110 if (level == old_level) {
3111 PMD(PMD_SET, ("%s: %s@%s(%s#%d), comp=%d is already at "
3112 "level=%d\n", pmf, PM_DEVICE(dip), comp, level))
3113 return (DDI_SUCCESS);
3117 * Tell ppm about this.
3119 power_req.request_type = PMR_PPM_POWER_CHANGE_NOTIFY;
3120 power_req.req.ppm_notify_level_req.who = dip;
3121 power_req.req.ppm_notify_level_req.cmpt = comp;
3122 power_req.req.ppm_notify_level_req.new_level = level;
3123 power_req.req.ppm_notify_level_req.old_level = old_level;
3124 if (pm_ctlops(ppm, dip, DDI_CTLOPS_POWER, &power_req,
3125 &result) == DDI_FAILURE) {
3126 PMD(PMD_FAIL, ("%s: pm_ctlops %s@%s(%s#%d) to %d failed\n",
3127 pmf, PM_DEVICE(dip), level))
3128 return (DDI_FAILURE);
3131 if (PM_IS_CFB(dip)) {
3132 incr = calc_cfb_comps_incr(dip, comp, old_level, level);
3134 if (incr) {
3135 update_comps_off(incr, dip);
3136 PMD(PMD_CFB, ("%s: %s@%s(%s#%d) comp=%d %d->%d "
3137 "cfb_comps_off->%d\n", pmf, PM_DEVICE(dip),
3138 comp, old_level, level, pm_cfb_comps_off))
3141 e_pm_set_cur_pwr(dip, PM_CP(dip, comp), level);
3142 result = DDI_SUCCESS;
3144 if (notify) {
3145 if (pdip && PM_WANTS_NOTIFICATION(pdip))
3146 pm_notify_parent(dip, pdip, comp, old_level, level);
3147 (void) pm_check_and_resume(dip, comp, old_level, level);
3151 * Decrement the dependency kidsup count if we turn a device
3152 * off.
3154 if (POWERING_OFF(old_level, level)) {
3155 dodeps = 1;
3156 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
3157 cp = PM_CP(dip, i);
3158 if (cur_power(cp)) {
3159 dodeps = 0;
3160 break;
3163 if (dodeps)
3164 work_type = PM_DEP_WK_POWER_OFF;
3168 * Increment if we turn it on. Check to see
3169 * if other comps are already on, if so,
3170 * dont increment.
3172 if (POWERING_ON(old_level, level)) {
3173 dodeps = 1;
3174 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
3175 cp = PM_CP(dip, i);
3176 if (comp == i)
3177 continue;
3178 /* -1 also treated as 0 in this case */
3179 if (cur_power(cp) > 0) {
3180 dodeps = 0;
3181 break;
3184 if (dodeps)
3185 work_type = PM_DEP_WK_POWER_ON;
3188 if (dodeps) {
3189 pathbuf = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
3190 (void) ddi_pathname(dip, pathbuf);
3191 pm_dispatch_to_dep_thread(work_type, pathbuf, NULL,
3192 PM_DEP_NOWAIT, NULL, 0);
3193 kmem_free(pathbuf, MAXPATHLEN);
3196 if (notify && (level != old_level) && pm_watchers()) {
3197 mutex_enter(&pm_rsvp_lock);
3198 pm_enqueue_notify(PSC_HAS_CHANGED, dip, comp, level, old_level,
3199 PM_CANBLOCK_BLOCK);
3200 mutex_exit(&pm_rsvp_lock);
3203 PMD(PMD_RESCAN, ("%s: %s@%s(%s#%d): pm_rescan\n", pmf, PM_DEVICE(dip)))
3204 pm_rescan(dip);
3205 return (DDI_SUCCESS);
3209 * This function is called at startup time to notify pm of the existence
3210 * of any platform power managers for this platform. As a result of
3211 * this registration, each function provided will be called each time
3212 * a device node is attached, until one returns true, and it must claim the
3213 * device node (by returning non-zero) if it wants to be involved in the
3214 * node's power management. If it does claim the node, then it will
3215 * subsequently be notified of attach and detach events.
3220 pm_register_ppm(int (*func)(dev_info_t *), dev_info_t *dip)
3222 PMD_FUNC(pmf, "register_ppm")
3223 struct ppm_callbacks *ppmcp;
3224 pm_component_t *cp;
3225 int i, pwr, result, circ;
3226 power_req_t power_req;
3227 struct ppm_notify_level_req *p = &power_req.req.ppm_notify_level_req;
3228 void pm_ppm_claim(dev_info_t *);
3230 mutex_enter(&ppm_lock);
3231 ppmcp = ppm_callbacks;
3232 for (i = 0; i < MAX_PPM_HANDLERS; i++, ppmcp++) {
3233 if (ppmcp->ppmc_func == NULL) {
3234 ppmcp->ppmc_func = func;
3235 ppmcp->ppmc_dip = dip;
3236 break;
3239 mutex_exit(&ppm_lock);
3241 if (i >= MAX_PPM_HANDLERS)
3242 return (DDI_FAILURE);
3243 while ((dip = ddi_get_parent(dip)) != NULL) {
3244 if (dip != ddi_root_node() && PM_GET_PM_INFO(dip) == NULL)
3245 continue;
3246 pm_ppm_claim(dip);
3247 /* don't bother with the not power-manageable nodes */
3248 if (pm_ppm_claimed(dip) && PM_GET_PM_INFO(dip)) {
3250 * Tell ppm about this.
3252 power_req.request_type = PMR_PPM_POWER_CHANGE_NOTIFY;
3253 p->old_level = PM_LEVEL_UNKNOWN;
3254 p->who = dip;
3255 PM_LOCK_POWER(dip, &circ);
3256 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
3257 cp = PM_CP(dip, i);
3258 pwr = cp->pmc_cur_pwr;
3259 if (pwr != PM_LEVEL_UNKNOWN) {
3260 p->cmpt = i;
3261 p->new_level = cur_power(cp);
3262 p->old_level = PM_LEVEL_UNKNOWN;
3263 if (pm_ctlops(PPM(dip), dip,
3264 DDI_CTLOPS_POWER, &power_req,
3265 &result) == DDI_FAILURE) {
3266 PMD(PMD_FAIL, ("%s: pc "
3267 "%s@%s(%s#%d) to %d "
3268 "fails\n", pmf,
3269 PM_DEVICE(dip), pwr))
3273 PM_UNLOCK_POWER(dip, circ);
3276 return (DDI_SUCCESS);
3280 * Call the ppm's that have registered and adjust the devinfo struct as
3281 * appropriate. First one to claim it gets it. The sets of devices claimed
3282 * by each ppm are assumed to be disjoint.
3284 void
3285 pm_ppm_claim(dev_info_t *dip)
3287 struct ppm_callbacks *ppmcp;
3289 if (PPM(dip)) {
3290 return;
3292 mutex_enter(&ppm_lock);
3293 for (ppmcp = ppm_callbacks; ppmcp->ppmc_func; ppmcp++) {
3294 if ((*ppmcp->ppmc_func)(dip)) {
3295 DEVI(dip)->devi_pm_ppm =
3296 (struct dev_info *)ppmcp->ppmc_dip;
3297 mutex_exit(&ppm_lock);
3298 return;
3301 mutex_exit(&ppm_lock);
3305 * Node is being detached so stop autopm until we see if it succeeds, in which
3306 * case pm_stop will be called. For backwards compatible devices we bring the
3307 * device up to full power on the assumption the detach will succeed.
3309 void
3310 pm_detaching(dev_info_t *dip)
3312 PMD_FUNC(pmf, "detaching")
3313 pm_info_t *info = PM_GET_PM_INFO(dip);
3314 int iscons;
3316 PMD(PMD_REMDEV, ("%s: %s@%s(%s#%d), %d comps\n", pmf, PM_DEVICE(dip),
3317 PM_NUMCMPTS(dip)))
3318 if (info == NULL)
3319 return;
3320 ASSERT(DEVI_IS_DETACHING(dip));
3321 PM_LOCK_DIP(dip);
3322 info->pmi_dev_pm_state |= PM_DETACHING;
3323 PM_UNLOCK_DIP(dip);
3324 if (!PM_ISBC(dip))
3325 pm_scan_stop(dip);
3328 * console and old-style devices get brought up when detaching.
3330 iscons = PM_IS_CFB(dip);
3331 if (iscons || PM_ISBC(dip)) {
3332 (void) pm_all_to_normal(dip, PM_CANBLOCK_BYPASS);
3333 if (iscons) {
3334 mutex_enter(&pm_cfb_lock);
3335 while (cfb_inuse) {
3336 mutex_exit(&pm_cfb_lock);
3337 PMD(PMD_CFB, ("%s: delay; cfb_inuse\n", pmf))
3338 delay(1);
3339 mutex_enter(&pm_cfb_lock);
3341 ASSERT(cfb_dip_detaching == NULL);
3342 ASSERT(cfb_dip);
3343 cfb_dip_detaching = cfb_dip; /* case detach fails */
3344 cfb_dip = NULL;
3345 mutex_exit(&pm_cfb_lock);
3351 * Node failed to detach. If it used to be autopm'd, make it so again.
3353 void
3354 pm_detach_failed(dev_info_t *dip)
3356 PMD_FUNC(pmf, "detach_failed")
3357 pm_info_t *info = PM_GET_PM_INFO(dip);
3358 int pm_all_at_normal(dev_info_t *);
3360 if (info == NULL)
3361 return;
3362 ASSERT(DEVI_IS_DETACHING(dip));
3363 if (info->pmi_dev_pm_state & PM_DETACHING) {
3364 info->pmi_dev_pm_state &= ~PM_DETACHING;
3365 if (info->pmi_dev_pm_state & PM_ALLNORM_DEFERRED) {
3366 /* Make sure the operation is still needed */
3367 if (!pm_all_at_normal(dip)) {
3368 if (pm_all_to_normal(dip,
3369 PM_CANBLOCK_FAIL) != DDI_SUCCESS) {
3370 PMD(PMD_ERROR, ("%s: could not bring "
3371 "%s@%s(%s#%d) to normal\n", pmf,
3372 PM_DEVICE(dip)))
3375 info->pmi_dev_pm_state &= ~PM_ALLNORM_DEFERRED;
3378 if (!PM_ISBC(dip)) {
3379 mutex_enter(&pm_scan_lock);
3380 if (PM_SCANABLE(dip))
3381 pm_scan_init(dip);
3382 mutex_exit(&pm_scan_lock);
3383 pm_rescan(dip);
3387 /* generic Backwards Compatible component */
3388 static char *bc_names[] = {"off", "on"};
3390 static pm_comp_t bc_comp = {"unknown", 2, NULL, NULL, &bc_names[0]};
3392 static void
3393 e_pm_default_levels(dev_info_t *dip, pm_component_t *cp, int norm)
3395 pm_comp_t *pmc;
3396 pmc = &cp->pmc_comp;
3397 pmc->pmc_numlevels = 2;
3398 pmc->pmc_lvals[0] = 0;
3399 pmc->pmc_lvals[1] = norm;
3400 e_pm_set_cur_pwr(dip, cp, norm);
3403 static void
3404 e_pm_default_components(dev_info_t *dip, int cmpts)
3406 int i;
3407 pm_component_t *p = DEVI(dip)->devi_pm_components;
3409 p = DEVI(dip)->devi_pm_components;
3410 for (i = 0; i < cmpts; i++, p++) {
3411 p->pmc_comp = bc_comp; /* struct assignment */
3412 p->pmc_comp.pmc_lvals = kmem_zalloc(2 * sizeof (int),
3413 KM_SLEEP);
3414 p->pmc_comp.pmc_thresh = kmem_alloc(2 * sizeof (int),
3415 KM_SLEEP);
3416 p->pmc_comp.pmc_numlevels = 2;
3417 p->pmc_comp.pmc_thresh[0] = INT_MAX;
3418 p->pmc_comp.pmc_thresh[1] = INT_MAX;
3423 * Called from functions that require components to exist already to allow
3424 * for their creation by parsing the pm-components property.
3425 * Device will not be power managed as a result of this call
3426 * No locking needed because we're single threaded by the ndi_devi_enter
3427 * done while attaching, and the device isn't visible until after it has
3428 * attached
3431 pm_premanage(dev_info_t *dip, int style)
3433 PMD_FUNC(pmf, "premanage")
3434 pm_comp_t *pcp, *compp;
3435 int cmpts, i, norm, error;
3436 pm_component_t *p = DEVI(dip)->devi_pm_components;
3437 pm_comp_t *pm_autoconfig(dev_info_t *, int *);
3439 ASSERT(!PM_IAM_LOCKING_DIP(dip));
3441 * If this dip has already been processed, don't mess with it
3443 if (DEVI(dip)->devi_pm_flags & PMC_COMPONENTS_DONE)
3444 return (DDI_SUCCESS);
3445 if (DEVI(dip)->devi_pm_flags & PMC_COMPONENTS_FAILED) {
3446 return (DDI_FAILURE);
3449 * Look up pm-components property and create components accordingly
3450 * If that fails, fall back to backwards compatibility
3452 if ((compp = pm_autoconfig(dip, &error)) == NULL) {
3454 * If error is set, the property existed but was not well formed
3456 if (error || (style == PM_STYLE_NEW)) {
3457 DEVI(dip)->devi_pm_flags |= PMC_COMPONENTS_FAILED;
3458 return (DDI_FAILURE);
3461 * If they don't have the pm-components property, then we
3462 * want the old "no pm until PM_SET_DEVICE_THRESHOLDS ioctl"
3463 * behavior driver must have called pm_create_components, and
3464 * we need to flesh out dummy components
3466 if ((cmpts = PM_NUMCMPTS(dip)) == 0) {
3468 * Not really failure, but we don't want the
3469 * caller to treat it as success
3471 return (DDI_FAILURE);
3473 DEVI(dip)->devi_pm_flags |= PMC_BC;
3474 e_pm_default_components(dip, cmpts);
3475 for (i = 0; i < cmpts; i++) {
3477 * if normal power not set yet, we don't really know
3478 * what *ANY* of the power values are. If normal
3479 * power is set, then we assume for this backwards
3480 * compatible case that the values are 0, normal power.
3482 norm = pm_get_normal_power(dip, i);
3483 if (norm == (uint_t)-1) {
3484 PMD(PMD_ERROR, ("%s: %s@%s(%s#%d)[%d]\n", pmf,
3485 PM_DEVICE(dip), i))
3486 return (DDI_FAILURE);
3489 * Components of BC devices start at their normal power,
3490 * so count them to be not at their lowest power.
3492 PM_INCR_NOTLOWEST(dip);
3493 e_pm_default_levels(dip, PM_CP(dip, i), norm);
3495 } else {
3497 * e_pm_create_components was called from pm_autoconfig(), it
3498 * creates components with no descriptions (or known levels)
3500 cmpts = PM_NUMCMPTS(dip);
3501 ASSERT(cmpts != 0);
3502 pcp = compp;
3503 p = DEVI(dip)->devi_pm_components;
3504 for (i = 0; i < cmpts; i++, p++) {
3505 p->pmc_comp = *pcp++; /* struct assignment */
3506 ASSERT(PM_CP(dip, i)->pmc_cur_pwr == 0);
3507 e_pm_set_cur_pwr(dip, PM_CP(dip, i), PM_LEVEL_UNKNOWN);
3509 if (DEVI(dip)->devi_pm_flags & PMC_CPU_THRESH)
3510 pm_set_device_threshold(dip, pm_cpu_idle_threshold,
3511 PMC_CPU_THRESH);
3512 else
3513 pm_set_device_threshold(dip, pm_system_idle_threshold,
3514 PMC_DEF_THRESH);
3515 kmem_free(compp, cmpts * sizeof (pm_comp_t));
3517 return (DDI_SUCCESS);
3521 * Called from during or after the device's attach to let us know it is ready
3522 * to play autopm. Look up the pm model and manage the device accordingly.
3523 * Returns system call errno value.
3524 * If DDI_ATTACH and DDI_DETACH were in same namespace, this would be
3525 * a little cleaner
3527 * Called with dip lock held, return with dip lock unheld.
3531 e_pm_manage(dev_info_t *dip, int style)
3533 PMD_FUNC(pmf, "e_manage")
3534 pm_info_t *info;
3535 dev_info_t *pdip = ddi_get_parent(dip);
3536 int pm_thresh_specd(dev_info_t *);
3537 int count;
3538 char *pathbuf;
3540 if (pm_premanage(dip, style) != DDI_SUCCESS) {
3541 return (DDI_FAILURE);
3543 PMD(PMD_KIDSUP, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
3544 ASSERT(PM_GET_PM_INFO(dip) == NULL);
3545 info = kmem_zalloc(sizeof (pm_info_t), KM_SLEEP);
3548 * Now set up parent's kidsupcnt. BC nodes are assumed to start
3549 * out at their normal power, so they are "up", others start out
3550 * unknown, which is effectively "up". Parent which want notification
3551 * get kidsupcnt of 0 always.
3553 count = (PM_ISBC(dip)) ? 1 : PM_NUMCMPTS(dip);
3554 if (count && pdip && !PM_WANTS_NOTIFICATION(pdip))
3555 e_pm_hold_rele_power(pdip, count);
3557 pm_set_pm_info(dip, info);
3559 * Apply any recorded thresholds
3561 (void) pm_thresh_specd(dip);
3564 * Do dependency processing.
3566 pathbuf = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
3567 (void) ddi_pathname(dip, pathbuf);
3568 pm_dispatch_to_dep_thread(PM_DEP_WK_ATTACH, pathbuf, pathbuf,
3569 PM_DEP_NOWAIT, NULL, 0);
3570 kmem_free(pathbuf, MAXPATHLEN);
3572 if (!PM_ISBC(dip)) {
3573 mutex_enter(&pm_scan_lock);
3574 if (PM_SCANABLE(dip)) {
3575 pm_scan_init(dip);
3576 mutex_exit(&pm_scan_lock);
3577 pm_rescan(dip);
3578 } else {
3579 mutex_exit(&pm_scan_lock);
3582 return (0);
3586 * This is the obsolete exported interface for a driver to find out its
3587 * "normal" (max) power.
3588 * We only get components destroyed while no power management is
3589 * going on (and the device is detached), so we don't need a mutex here
3592 pm_get_normal_power(dev_info_t *dip, int comp)
3595 if (comp >= 0 && comp < PM_NUMCMPTS(dip)) {
3596 return (PM_CP(dip, comp)->pmc_norm_pwr);
3598 return (DDI_FAILURE);
3602 * Fetches the current power level. Return DDI_SUCCESS or DDI_FAILURE.
3605 pm_get_current_power(dev_info_t *dip, int comp, int *levelp)
3607 if (comp >= 0 && comp < PM_NUMCMPTS(dip)) {
3608 *levelp = PM_CURPOWER(dip, comp);
3609 return (DDI_SUCCESS);
3611 return (DDI_FAILURE);
3615 * Returns current threshold of indicated component
3617 static int
3618 cur_threshold(dev_info_t *dip, int comp)
3620 pm_component_t *cp = PM_CP(dip, comp);
3621 int pwr;
3623 if (PM_ISBC(dip)) {
3625 * backwards compatible nodes only have one threshold
3627 return (cp->pmc_comp.pmc_thresh[1]);
3629 pwr = cp->pmc_cur_pwr;
3630 if (pwr == PM_LEVEL_UNKNOWN) {
3631 int thresh;
3632 if (DEVI(dip)->devi_pm_flags & PMC_NEXDEF_THRESH)
3633 thresh = pm_default_nexus_threshold;
3634 else if (DEVI(dip)->devi_pm_flags & PMC_CPU_THRESH)
3635 thresh = pm_cpu_idle_threshold;
3636 else
3637 thresh = pm_system_idle_threshold;
3638 return (thresh);
3640 ASSERT(cp->pmc_comp.pmc_thresh);
3641 return (cp->pmc_comp.pmc_thresh[pwr]);
3645 * Compute next lower component power level given power index.
3647 static int
3648 pm_next_lower_power(pm_component_t *cp, int pwrndx)
3650 int nxt_pwr;
3652 if (pwrndx == PM_LEVEL_UNKNOWN) {
3653 nxt_pwr = cp->pmc_comp.pmc_lvals[0];
3654 } else {
3655 pwrndx--;
3656 ASSERT(pwrndx >= 0);
3657 nxt_pwr = cp->pmc_comp.pmc_lvals[pwrndx];
3659 return (nxt_pwr);
3663 * Update the maxpower (normal) power of a component. Note that the
3664 * component's power level is only changed if it's current power level
3665 * is higher than the new max power.
3668 pm_update_maxpower(dev_info_t *dip, int comp, int level)
3670 PMD_FUNC(pmf, "update_maxpower")
3671 int old;
3672 int result;
3674 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, comp, NULL) ||
3675 !e_pm_valid_power(dip, comp, level)) {
3676 PMD(PMD_FAIL, ("%s: validation checks failed for %s@%s(%s#%d) "
3677 "comp=%d level=%d\n", pmf, PM_DEVICE(dip), comp, level))
3678 return (DDI_FAILURE);
3680 old = e_pm_get_max_power(dip, comp);
3681 e_pm_set_max_power(dip, comp, level);
3683 if (pm_set_power(dip, comp, level, PM_LEVEL_DOWNONLY,
3684 PM_CANBLOCK_BLOCK, 0, &result) != DDI_SUCCESS) {
3685 e_pm_set_max_power(dip, comp, old);
3686 PMD(PMD_FAIL, ("%s: %s@%s(%s#%d) pm_set_power failed\n", pmf,
3687 PM_DEVICE(dip)))
3688 return (DDI_FAILURE);
3690 return (DDI_SUCCESS);
3694 * Bring all components of device to normal power
3697 pm_all_to_normal(dev_info_t *dip, pm_canblock_t canblock)
3699 PMD_FUNC(pmf, "all_to_normal")
3700 int *normal;
3701 int i, ncomps, result;
3702 size_t size;
3703 int changefailed = 0;
3705 PMD(PMD_ALLNORM, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
3706 ASSERT(PM_GET_PM_INFO(dip));
3707 if (pm_get_norm_pwrs(dip, &normal, &size) != DDI_SUCCESS) {
3708 PMD(PMD_ALLNORM, ("%s: can't get norm pwrs for "
3709 "%s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
3710 return (DDI_FAILURE);
3712 ncomps = PM_NUMCMPTS(dip);
3713 for (i = 0; i < ncomps; i++) {
3714 if (pm_set_power(dip, i, normal[i],
3715 PM_LEVEL_UPONLY, canblock, 0, &result) != DDI_SUCCESS) {
3716 changefailed++;
3717 PMD(PMD_ALLNORM | PMD_FAIL, ("%s: failed to set "
3718 "%s@%s(%s#%d)[%d] to %d, errno %d\n", pmf,
3719 PM_DEVICE(dip), i, normal[i], result))
3722 kmem_free(normal, size);
3723 if (changefailed) {
3724 PMD(PMD_FAIL, ("%s: failed to set %d comps %s@%s(%s#%d) "
3725 "to full power\n", pmf, changefailed, PM_DEVICE(dip)))
3726 return (DDI_FAILURE);
3728 return (DDI_SUCCESS);
3732 * Returns true if all components of device are at normal power
3735 pm_all_at_normal(dev_info_t *dip)
3737 PMD_FUNC(pmf, "all_at_normal")
3738 int *normal;
3739 int i;
3740 size_t size;
3742 PMD(PMD_ALLNORM, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
3743 if (pm_get_norm_pwrs(dip, &normal, &size) != DDI_SUCCESS) {
3744 PMD(PMD_ALLNORM, ("%s: can't get normal power\n", pmf))
3745 return (DDI_FAILURE);
3747 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
3748 int current = PM_CURPOWER(dip, i);
3749 if (normal[i] > current) {
3750 PMD(PMD_ALLNORM, ("%s: %s@%s(%s#%d) comp=%d, "
3751 "norm=%d, cur=%d\n", pmf, PM_DEVICE(dip), i,
3752 normal[i], current))
3753 break;
3756 kmem_free(normal, size);
3757 if (i != PM_NUMCMPTS(dip)) {
3758 return (0);
3760 return (1);
3763 static void bring_pmdep_up(dev_info_t *, int);
3765 static void
3766 bring_wekeeps_up(char *keeper)
3768 PMD_FUNC(pmf, "bring_wekeeps_up")
3769 int i;
3770 pm_pdr_t *dp;
3771 pm_info_t *wku_info;
3772 char *kept_path;
3773 dev_info_t *kept;
3775 if (panicstr) {
3776 return;
3779 * We process the request even if the keeper detaches because
3780 * detach processing expects this to increment kidsupcnt of kept.
3782 PMD(PMD_BRING, ("%s: keeper= %s\n", pmf, keeper))
3783 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
3784 if (strcmp(dp->pdr_keeper, keeper) != 0)
3785 continue;
3786 for (i = 0; i < dp->pdr_kept_count; i++) {
3787 kept_path = dp->pdr_kept_paths[i];
3788 if (kept_path == NULL)
3789 continue;
3790 ASSERT(kept_path[0] != '\0');
3791 if ((kept = pm_name_to_dip(kept_path, 1)) == NULL)
3792 continue;
3793 wku_info = PM_GET_PM_INFO(kept);
3794 if (wku_info == NULL) {
3795 if (kept)
3796 ddi_release_devi(kept);
3797 continue;
3800 * Don't mess with it if it is being detached, it isn't
3801 * safe to call its power entry point
3803 if (wku_info->pmi_dev_pm_state & PM_DETACHING) {
3804 if (kept)
3805 ddi_release_devi(kept);
3806 continue;
3808 bring_pmdep_up(kept, 1);
3809 ddi_release_devi(kept);
3815 * Bring up the 'kept' device passed as argument
3817 static void
3818 bring_pmdep_up(dev_info_t *kept_dip, int hold)
3820 PMD_FUNC(pmf, "bring_pmdep_up")
3821 int is_all_at_normal = 0;
3824 * If the kept device has been unmanaged, do nothing.
3826 if (!PM_GET_PM_INFO(kept_dip))
3827 return;
3829 /* Just ignore DIRECT PM device till they are released. */
3830 if (!pm_processes_stopped && PM_ISDIRECT(kept_dip) &&
3831 !(is_all_at_normal = pm_all_at_normal(kept_dip))) {
3832 PMD(PMD_BRING, ("%s: can't bring up PM_DIRECT %s@%s(%s#%d) "
3833 "controlling process did something else\n", pmf,
3834 PM_DEVICE(kept_dip)))
3835 DEVI(kept_dip)->devi_pm_flags |= PMC_SKIP_BRINGUP;
3836 return;
3838 /* if we got here the keeper had a transition from OFF->ON */
3839 if (hold)
3840 pm_hold_power(kept_dip);
3842 if (!is_all_at_normal)
3843 (void) pm_all_to_normal(kept_dip, PM_CANBLOCK_FAIL);
3847 * A bunch of stuff that belongs only to the next routine (or two)
3850 static const char namestr[] = "NAME=";
3851 static const int nameln = sizeof (namestr) - 1;
3852 static const char pmcompstr[] = "pm-components";
3854 struct pm_comp_pkg {
3855 pm_comp_t *comp;
3856 struct pm_comp_pkg *next;
3859 #define isdigit(ch) ((ch) >= '0' && (ch) <= '9')
3861 #define isxdigit(ch) (isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \
3862 ((ch) >= 'A' && (ch) <= 'F'))
3865 * Rather than duplicate this code ...
3866 * (this code excerpted from the function that follows it)
3868 #define FINISH_COMP { \
3869 ASSERT(compp); \
3870 compp->pmc_lnames_sz = size; \
3871 tp = compp->pmc_lname_buf = kmem_alloc(size, KM_SLEEP); \
3872 compp->pmc_numlevels = level; \
3873 compp->pmc_lnames = kmem_alloc(level * sizeof (char *), KM_SLEEP); \
3874 compp->pmc_lvals = kmem_alloc(level * sizeof (int), KM_SLEEP); \
3875 compp->pmc_thresh = kmem_alloc(level * sizeof (int), KM_SLEEP); \
3876 /* copy string out of prop array into buffer */ \
3877 for (j = 0; j < level; j++) { \
3878 compp->pmc_thresh[j] = INT_MAX; /* only [0] sticks */ \
3879 compp->pmc_lvals[j] = lvals[j]; \
3880 (void) strcpy(tp, lnames[j]); \
3881 compp->pmc_lnames[j] = tp; \
3882 tp += lszs[j]; \
3884 ASSERT(tp > compp->pmc_lname_buf && tp <= \
3885 compp->pmc_lname_buf + compp->pmc_lnames_sz); \
3889 * Create (empty) component data structures.
3891 static void
3892 e_pm_create_components(dev_info_t *dip, int num_components)
3894 struct pm_component *compp, *ocompp;
3895 int i, size = 0;
3897 ASSERT(!PM_IAM_LOCKING_DIP(dip));
3898 ASSERT(!DEVI(dip)->devi_pm_components);
3899 ASSERT(!(DEVI(dip)->devi_pm_flags & PMC_COMPONENTS_DONE));
3900 size = sizeof (struct pm_component) * num_components;
3902 compp = kmem_zalloc(size, KM_SLEEP);
3903 ocompp = compp;
3904 DEVI(dip)->devi_pm_comp_size = size;
3905 DEVI(dip)->devi_pm_num_components = num_components;
3906 PM_LOCK_BUSY(dip);
3907 for (i = 0; i < num_components; i++) {
3908 compp->pmc_timestamp = gethrestime_sec();
3909 compp->pmc_norm_pwr = (uint_t)-1;
3910 compp++;
3912 PM_UNLOCK_BUSY(dip);
3913 DEVI(dip)->devi_pm_components = ocompp;
3914 DEVI(dip)->devi_pm_flags |= PMC_COMPONENTS_DONE;
3918 * Parse hex or decimal value from char string
3920 static char *
3921 pm_parsenum(char *cp, int *valp)
3923 int ch, offset;
3924 char numbuf[256];
3925 char *np = numbuf;
3926 int value = 0;
3928 ch = *cp++;
3929 if (isdigit(ch)) {
3930 if (ch == '0') {
3931 if ((ch = *cp++) == 'x' || ch == 'X') {
3932 ch = *cp++;
3933 while (isxdigit(ch)) {
3934 *np++ = (char)ch;
3935 ch = *cp++;
3937 *np = 0;
3938 cp--;
3939 goto hexval;
3940 } else {
3941 goto digit;
3943 } else {
3944 digit:
3945 while (isdigit(ch)) {
3946 *np++ = (char)ch;
3947 ch = *cp++;
3949 *np = 0;
3950 cp--;
3951 goto decval;
3953 } else
3954 return (NULL);
3956 hexval:
3957 for (np = numbuf; *np; np++) {
3958 if (*np >= 'a' && *np <= 'f')
3959 offset = 'a' - 10;
3960 else if (*np >= 'A' && *np <= 'F')
3961 offset = 'A' - 10;
3962 else if (*np >= '0' && *np <= '9')
3963 offset = '0';
3964 value *= 16;
3965 value += *np - offset;
3967 *valp = value;
3968 return (cp);
3970 decval:
3971 offset = '0';
3972 for (np = numbuf; *np; np++) {
3973 value *= 10;
3974 value += *np - offset;
3976 *valp = value;
3977 return (cp);
3981 * Set max (previously documented as "normal") power.
3983 static void
3984 e_pm_set_max_power(dev_info_t *dip, int component_number, int level)
3986 PM_CP(dip, component_number)->pmc_norm_pwr = level;
3990 * Get max (previously documented as "normal") power.
3992 static int
3993 e_pm_get_max_power(dev_info_t *dip, int component_number)
3995 return (PM_CP(dip, component_number)->pmc_norm_pwr);
3999 * Internal routine for destroying components
4000 * It is called even when there might not be any, so it must be forgiving.
4002 static void
4003 e_pm_destroy_components(dev_info_t *dip)
4005 int i;
4006 struct pm_component *cp;
4008 ASSERT(!PM_IAM_LOCKING_DIP(dip));
4009 if (PM_NUMCMPTS(dip) == 0)
4010 return;
4011 cp = DEVI(dip)->devi_pm_components;
4012 ASSERT(cp);
4013 for (i = 0; i < PM_NUMCMPTS(dip); i++, cp++) {
4014 int nlevels = cp->pmc_comp.pmc_numlevels;
4015 kmem_free(cp->pmc_comp.pmc_lvals, nlevels * sizeof (int));
4016 kmem_free(cp->pmc_comp.pmc_thresh, nlevels * sizeof (int));
4018 * For BC nodes, the rest is static in bc_comp, so skip it
4020 if (PM_ISBC(dip))
4021 continue;
4022 kmem_free(cp->pmc_comp.pmc_name, cp->pmc_comp.pmc_name_sz);
4023 kmem_free(cp->pmc_comp.pmc_lnames, nlevels * sizeof (char *));
4024 kmem_free(cp->pmc_comp.pmc_lname_buf,
4025 cp->pmc_comp.pmc_lnames_sz);
4027 kmem_free(DEVI(dip)->devi_pm_components, DEVI(dip)->devi_pm_comp_size);
4028 DEVI(dip)->devi_pm_components = NULL;
4029 DEVI(dip)->devi_pm_num_components = 0;
4030 DEVI(dip)->devi_pm_flags &=
4031 ~(PMC_COMPONENTS_DONE | PMC_COMPONENTS_FAILED);
4035 * Read the pm-components property (if there is one) and use it to set up
4036 * components. Returns a pointer to an array of component structures if
4037 * pm-components found and successfully parsed, else returns NULL.
4038 * Sets error return *errp to true to indicate a failure (as opposed to no
4039 * property being present).
4041 pm_comp_t *
4042 pm_autoconfig(dev_info_t *dip, int *errp)
4044 PMD_FUNC(pmf, "autoconfig")
4045 uint_t nelems;
4046 char **pp;
4047 pm_comp_t *compp = NULL;
4048 int i, j, level, components = 0;
4049 size_t size = 0;
4050 struct pm_comp_pkg *p, *ptail;
4051 struct pm_comp_pkg *phead = NULL;
4052 int *lvals = NULL;
4053 int *lszs = NULL;
4054 int *np = NULL;
4055 int npi = 0;
4056 char **lnames = NULL;
4057 char *cp, *tp;
4058 pm_comp_t *ret = NULL;
4060 ASSERT(!PM_IAM_LOCKING_DIP(dip));
4061 *errp = 0; /* assume success */
4062 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
4063 (char *)pmcompstr, &pp, &nelems) != DDI_PROP_SUCCESS) {
4064 return (NULL);
4067 if (nelems < 3) { /* need at least one name and two levels */
4068 goto errout;
4072 * pm_create_components is no longer allowed
4074 if (PM_NUMCMPTS(dip) != 0) {
4075 PMD(PMD_ERROR, ("%s: %s@%s(%s#%d) has %d comps\n",
4076 pmf, PM_DEVICE(dip), PM_NUMCMPTS(dip)))
4077 goto errout;
4080 lvals = kmem_alloc(nelems * sizeof (int), KM_SLEEP);
4081 lszs = kmem_alloc(nelems * sizeof (int), KM_SLEEP);
4082 lnames = kmem_alloc(nelems * sizeof (char *), KM_SLEEP);
4083 np = kmem_alloc(nelems * sizeof (int), KM_SLEEP);
4085 level = 0;
4086 phead = NULL;
4087 for (i = 0; i < nelems; i++) {
4088 cp = pp[i];
4089 if (!isdigit(*cp)) { /* must be name */
4090 if (strncmp(cp, namestr, nameln) != 0) {
4091 goto errout;
4093 if (i != 0) {
4094 if (level == 0) { /* no level spec'd */
4095 PMD(PMD_ERROR, ("%s: no level spec'd\n",
4096 pmf))
4097 goto errout;
4099 np[npi++] = lvals[level - 1];
4100 /* finish up previous component levels */
4101 FINISH_COMP;
4103 cp += nameln;
4104 if (!*cp) {
4105 PMD(PMD_ERROR, ("%s: nsa\n", pmf))
4106 goto errout;
4108 p = kmem_zalloc(sizeof (*phead), KM_SLEEP);
4109 if (phead == NULL) {
4110 phead = ptail = p;
4111 } else {
4112 ptail->next = p;
4113 ptail = p;
4115 compp = p->comp = kmem_zalloc(sizeof (pm_comp_t),
4116 KM_SLEEP);
4117 compp->pmc_name_sz = strlen(cp) + 1;
4118 compp->pmc_name = kmem_zalloc(compp->pmc_name_sz,
4119 KM_SLEEP);
4120 (void) strncpy(compp->pmc_name, cp, compp->pmc_name_sz);
4121 components++;
4122 level = 0;
4123 } else { /* better be power level <num>=<name> */
4124 #ifdef DEBUG
4125 tp = cp;
4126 #endif
4127 if (i == 0 ||
4128 (cp = pm_parsenum(cp, &lvals[level])) == NULL) {
4129 PMD(PMD_ERROR, ("%s: parsenum(%s)\n", pmf, tp))
4130 goto errout;
4132 #ifdef DEBUG
4133 tp = cp;
4134 #endif
4135 if (*cp++ != '=' || !*cp) {
4136 PMD(PMD_ERROR, ("%s: ex =, got %s\n", pmf, tp))
4137 goto errout;
4140 lszs[level] = strlen(cp) + 1;
4141 size += lszs[level];
4142 lnames[level] = cp; /* points into prop string */
4143 level++;
4146 np[npi++] = lvals[level - 1];
4147 if (level == 0) { /* ended with a name */
4148 PMD(PMD_ERROR, ("%s: ewn\n", pmf))
4149 goto errout;
4151 FINISH_COMP;
4155 * Now we have a list of components--we have to return instead an
4156 * array of them, but we can just copy the top level and leave
4157 * the rest as is
4159 (void) e_pm_create_components(dip, components);
4160 for (i = 0; i < components; i++)
4161 e_pm_set_max_power(dip, i, np[i]);
4163 ret = kmem_zalloc(components * sizeof (pm_comp_t), KM_SLEEP);
4164 for (i = 0, p = phead; i < components; i++) {
4165 ASSERT(p);
4167 * Now sanity-check values: levels must be monotonically
4168 * increasing
4170 if (p->comp->pmc_numlevels < 2) {
4171 PMD(PMD_ERROR, ("%s: comp %s of %s@%s(%s#%d) only %d "
4172 "levels\n", pmf,
4173 p->comp->pmc_name, PM_DEVICE(dip),
4174 p->comp->pmc_numlevels))
4175 goto errout;
4177 for (j = 0; j < p->comp->pmc_numlevels; j++) {
4178 if ((p->comp->pmc_lvals[j] < 0) || ((j > 0) &&
4179 (p->comp->pmc_lvals[j] <=
4180 p->comp->pmc_lvals[j - 1]))) {
4181 PMD(PMD_ERROR, ("%s: comp %s of %s@%s(%s#%d) "
4182 "not mono. incr, %d follows %d\n", pmf,
4183 p->comp->pmc_name, PM_DEVICE(dip),
4184 p->comp->pmc_lvals[j],
4185 p->comp->pmc_lvals[j - 1]))
4186 goto errout;
4189 ret[i] = *p->comp; /* struct assignment */
4190 for (j = 0; j < i; j++) {
4192 * Test for unique component names
4194 if (strcmp(ret[j].pmc_name, ret[i].pmc_name) == 0) {
4195 PMD(PMD_ERROR, ("%s: %s of %s@%s(%s#%d) not "
4196 "unique\n", pmf, ret[j].pmc_name,
4197 PM_DEVICE(dip)))
4198 goto errout;
4201 ptail = p;
4202 p = p->next;
4203 phead = p; /* errout depends on phead making sense */
4204 kmem_free(ptail->comp, sizeof (*ptail->comp));
4205 kmem_free(ptail, sizeof (*ptail));
4207 out:
4208 ddi_prop_free(pp);
4209 if (lvals)
4210 kmem_free(lvals, nelems * sizeof (int));
4211 if (lszs)
4212 kmem_free(lszs, nelems * sizeof (int));
4213 if (lnames)
4214 kmem_free(lnames, nelems * sizeof (char *));
4215 if (np)
4216 kmem_free(np, nelems * sizeof (int));
4217 return (ret);
4219 errout:
4220 e_pm_destroy_components(dip);
4221 *errp = 1; /* signal failure */
4222 cmn_err(CE_CONT, "!pm: %s property ", pmcompstr);
4223 for (i = 0; i < nelems - 1; i++)
4224 cmn_err(CE_CONT, "!'%s', ", pp[i]);
4225 if (nelems != 0)
4226 cmn_err(CE_CONT, "!'%s'", pp[nelems - 1]);
4227 cmn_err(CE_CONT, "! for %s@%s(%s#%d) is ill-formed.\n", PM_DEVICE(dip));
4228 for (p = phead; p; ) {
4229 pm_comp_t *pp;
4230 int n;
4232 ptail = p;
4234 * Free component data structures
4236 pp = p->comp;
4237 n = pp->pmc_numlevels;
4238 if (pp->pmc_name_sz) {
4239 kmem_free(pp->pmc_name, pp->pmc_name_sz);
4241 if (pp->pmc_lnames_sz) {
4242 kmem_free(pp->pmc_lname_buf, pp->pmc_lnames_sz);
4244 if (pp->pmc_lnames) {
4245 kmem_free(pp->pmc_lnames, n * (sizeof (char *)));
4247 if (pp->pmc_thresh) {
4248 kmem_free(pp->pmc_thresh, n * (sizeof (int)));
4250 if (pp->pmc_lvals) {
4251 kmem_free(pp->pmc_lvals, n * (sizeof (int)));
4253 p = ptail->next;
4254 kmem_free(ptail, sizeof (*ptail));
4256 if (ret != NULL)
4257 kmem_free(ret, components * sizeof (pm_comp_t));
4258 ret = NULL;
4259 goto out;
4263 * Set threshold values for a devices components by dividing the target
4264 * threshold (base) by the number of transitions and assign each transition
4265 * that threshold. This will get the entire device down in the target time if
4266 * all components are idle and even if there are dependencies among components.
4268 * Devices may well get powered all the way down before the target time, but
4269 * at least the EPA will be happy.
4271 void
4272 pm_set_device_threshold(dev_info_t *dip, int base, int flag)
4274 PMD_FUNC(pmf, "set_device_threshold")
4275 int target_threshold = (base * 95) / 100;
4276 int level, comp; /* loop counters */
4277 int transitions = 0;
4278 int ncomp = PM_NUMCMPTS(dip);
4279 int thresh;
4280 int remainder;
4281 pm_comp_t *pmc;
4282 int i, circ;
4284 ASSERT(!PM_IAM_LOCKING_DIP(dip));
4285 PM_LOCK_DIP(dip);
4287 * First we handle the easy one. If we're setting the default
4288 * threshold for a node with children, then we set it to the
4289 * default nexus threshold (currently 0) and mark it as default
4290 * nexus threshold instead
4292 if (PM_IS_NEXUS(dip)) {
4293 if (flag == PMC_DEF_THRESH) {
4294 PMD(PMD_THRESH, ("%s: [%s@%s(%s#%d) NEXDEF]\n", pmf,
4295 PM_DEVICE(dip)))
4296 thresh = pm_default_nexus_threshold;
4297 for (comp = 0; comp < ncomp; comp++) {
4298 pmc = &PM_CP(dip, comp)->pmc_comp;
4299 for (level = 1; level < pmc->pmc_numlevels;
4300 level++) {
4301 pmc->pmc_thresh[level] = thresh;
4304 DEVI(dip)->devi_pm_dev_thresh =
4305 pm_default_nexus_threshold;
4307 * If the nexus node is being reconfigured back to
4308 * the default threshold, adjust the notlowest count.
4310 if (DEVI(dip)->devi_pm_flags &
4311 (PMC_DEV_THRESH|PMC_COMP_THRESH)) {
4312 PM_LOCK_POWER(dip, &circ);
4313 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
4314 if (PM_CURPOWER(dip, i) == 0)
4315 continue;
4316 mutex_enter(&pm_compcnt_lock);
4317 ASSERT(pm_comps_notlowest);
4318 pm_comps_notlowest--;
4319 PMD(PMD_LEVEL, ("%s: %s@%s(%s#%d) decr "
4320 "notlowest to %d\n", pmf,
4321 PM_DEVICE(dip), pm_comps_notlowest))
4322 if (pm_comps_notlowest == 0)
4323 pm_ppm_notify_all_lowest(dip,
4324 PM_ALL_LOWEST);
4325 mutex_exit(&pm_compcnt_lock);
4327 PM_UNLOCK_POWER(dip, circ);
4329 DEVI(dip)->devi_pm_flags &= PMC_THRESH_NONE;
4330 DEVI(dip)->devi_pm_flags |= PMC_NEXDEF_THRESH;
4331 PM_UNLOCK_DIP(dip);
4332 return;
4333 } else if (DEVI(dip)->devi_pm_flags & PMC_NEXDEF_THRESH) {
4335 * If the nexus node is being configured for a
4336 * non-default threshold, include that node in
4337 * the notlowest accounting.
4339 PM_LOCK_POWER(dip, &circ);
4340 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
4341 if (PM_CURPOWER(dip, i) == 0)
4342 continue;
4343 mutex_enter(&pm_compcnt_lock);
4344 if (pm_comps_notlowest == 0)
4345 pm_ppm_notify_all_lowest(dip,
4346 PM_NOT_ALL_LOWEST);
4347 pm_comps_notlowest++;
4348 PMD(PMD_LEVEL, ("%s: %s@%s(%s#%d) incr "
4349 "notlowest to %d\n", pmf,
4350 PM_DEVICE(dip), pm_comps_notlowest))
4351 mutex_exit(&pm_compcnt_lock);
4353 PM_UNLOCK_POWER(dip, circ);
4357 * Compute the total number of transitions for all components
4358 * of the device. Distribute the threshold evenly over them
4360 for (comp = 0; comp < ncomp; comp++) {
4361 pmc = &PM_CP(dip, comp)->pmc_comp;
4362 ASSERT(pmc->pmc_numlevels > 1);
4363 transitions += pmc->pmc_numlevels - 1;
4365 ASSERT(transitions);
4366 thresh = target_threshold / transitions;
4368 for (comp = 0; comp < ncomp; comp++) {
4369 pmc = &PM_CP(dip, comp)->pmc_comp;
4370 for (level = 1; level < pmc->pmc_numlevels; level++) {
4371 pmc->pmc_thresh[level] = thresh;
4375 #ifdef DEBUG
4376 for (comp = 0; comp < ncomp; comp++) {
4377 pmc = &PM_CP(dip, comp)->pmc_comp;
4378 for (level = 1; level < pmc->pmc_numlevels; level++) {
4379 PMD(PMD_THRESH, ("%s: thresh before %s@%s(%s#%d) "
4380 "comp=%d, level=%d, %d\n", pmf, PM_DEVICE(dip),
4381 comp, level, pmc->pmc_thresh[level]))
4384 #endif
4386 * Distribute any remainder till they are all gone
4388 remainder = target_threshold - thresh * transitions;
4389 level = 1;
4390 #ifdef DEBUG
4391 PMD(PMD_THRESH, ("%s: remainder=%d target_threshold=%d thresh=%d "
4392 "trans=%d\n", pmf, remainder, target_threshold, thresh,
4393 transitions))
4394 #endif
4395 while (remainder > 0) {
4396 comp = 0;
4397 while (remainder && (comp < ncomp)) {
4398 pmc = &PM_CP(dip, comp)->pmc_comp;
4399 if (level < pmc->pmc_numlevels) {
4400 pmc->pmc_thresh[level] += 1;
4401 remainder--;
4403 comp++;
4405 level++;
4407 #ifdef DEBUG
4408 for (comp = 0; comp < ncomp; comp++) {
4409 pmc = &PM_CP(dip, comp)->pmc_comp;
4410 for (level = 1; level < pmc->pmc_numlevels; level++) {
4411 PMD(PMD_THRESH, ("%s: thresh after %s@%s(%s#%d) "
4412 "comp=%d level=%d, %d\n", pmf, PM_DEVICE(dip),
4413 comp, level, pmc->pmc_thresh[level]))
4416 #endif
4417 ASSERT(PM_IAM_LOCKING_DIP(dip));
4418 DEVI(dip)->devi_pm_dev_thresh = base;
4419 DEVI(dip)->devi_pm_flags &= PMC_THRESH_NONE;
4420 DEVI(dip)->devi_pm_flags |= flag;
4421 PM_UNLOCK_DIP(dip);
4425 * Called when there is no old-style platform power management driver
4427 static int
4428 ddi_no_platform_power(power_req_t *req)
4430 _NOTE(ARGUNUSED(req))
4431 return (DDI_FAILURE);
4435 * This function calls the entry point supplied by the platform-specific
4436 * pm driver to bring the device component 'pm_cmpt' to power level 'pm_level'.
4437 * The use of global for getting the function name from platform-specific
4438 * pm driver is not ideal, but it is simple and efficient.
4439 * The previous property lookup was being done in the idle loop on swift
4440 * systems without pmc chips and hurt deskbench performance as well as
4441 * violating scheduler locking rules
4443 int (*pm_platform_power)(power_req_t *) = ddi_no_platform_power;
4446 * Old obsolete interface for a device to request a power change (but only
4447 * an increase in power)
4450 ddi_dev_is_needed(dev_info_t *dip, int cmpt, int level)
4452 return (pm_raise_power(dip, cmpt, level));
4456 * The old obsolete interface to platform power management. Only used by
4457 * Gypsy platform and APM on X86.
4460 ddi_power(dev_info_t *dip, int pm_cmpt, int pm_level)
4462 power_req_t request;
4464 request.request_type = PMR_SET_POWER;
4465 request.req.set_power_req.who = dip;
4466 request.req.set_power_req.cmpt = pm_cmpt;
4467 request.req.set_power_req.level = pm_level;
4468 return (ddi_ctlops(dip, dip, DDI_CTLOPS_POWER, &request, NULL));
4472 * A driver can invoke this from its detach routine when DDI_SUSPEND is
4473 * passed. Returns true if subsequent processing could result in power being
4474 * removed from the device. The arg is not currently used because it is
4475 * implicit in the operation of cpr/DR.
4478 ddi_removing_power(dev_info_t *dip)
4480 _NOTE(ARGUNUSED(dip))
4481 return (pm_powering_down);
4485 * Returns true if a device indicates that its parent handles suspend/resume
4486 * processing for it.
4489 e_ddi_parental_suspend_resume(dev_info_t *dip)
4491 return (DEVI(dip)->devi_pm_flags & PMC_PARENTAL_SR);
4495 * Called for devices which indicate that their parent does suspend/resume
4496 * handling for them
4499 e_ddi_suspend(dev_info_t *dip, ddi_detach_cmd_t cmd)
4501 power_req_t request;
4502 request.request_type = PMR_SUSPEND;
4503 request.req.suspend_req.who = dip;
4504 request.req.suspend_req.cmd = cmd;
4505 return (ddi_ctlops(dip, dip, DDI_CTLOPS_POWER, &request, NULL));
4509 * Called for devices which indicate that their parent does suspend/resume
4510 * handling for them
4513 e_ddi_resume(dev_info_t *dip, ddi_attach_cmd_t cmd)
4515 power_req_t request;
4516 request.request_type = PMR_RESUME;
4517 request.req.resume_req.who = dip;
4518 request.req.resume_req.cmd = cmd;
4519 return (ddi_ctlops(dip, dip, DDI_CTLOPS_POWER, &request, NULL));
4523 * Old obsolete exported interface for drivers to create components.
4524 * This is now handled by exporting the pm-components property.
4527 pm_create_components(dev_info_t *dip, int num_components)
4529 PMD_FUNC(pmf, "pm_create_components")
4531 if (num_components < 1)
4532 return (DDI_FAILURE);
4534 if (!DEVI_IS_ATTACHING(dip)) {
4535 return (DDI_FAILURE);
4538 /* don't need to lock dip because attach is single threaded */
4539 if (DEVI(dip)->devi_pm_components) {
4540 PMD(PMD_ERROR, ("%s: %s@%s(%s#%d) already has %d\n", pmf,
4541 PM_DEVICE(dip), PM_NUMCMPTS(dip)))
4542 return (DDI_FAILURE);
4544 e_pm_create_components(dip, num_components);
4545 DEVI(dip)->devi_pm_flags |= PMC_BC;
4546 e_pm_default_components(dip, num_components);
4547 return (DDI_SUCCESS);
4551 * Obsolete interface previously called by drivers to destroy their components
4552 * at detach time. This is now done automatically. However, we need to keep
4553 * this for the old drivers.
4555 void
4556 pm_destroy_components(dev_info_t *dip)
4558 PMD_FUNC(pmf, "pm_destroy_components")
4559 dev_info_t *pdip = ddi_get_parent(dip);
4561 PMD(PMD_REMDEV | PMD_KIDSUP, ("%s: %s@%s(%s#%d)\n", pmf,
4562 PM_DEVICE(dip)))
4563 ASSERT(DEVI_IS_DETACHING(dip));
4564 #ifdef DEBUG
4565 if (!PM_ISBC(dip))
4566 cmn_err(CE_WARN, "!driver exporting pm-components property "
4567 "(%s@%s) calls pm_destroy_components", PM_NAME(dip),
4568 PM_ADDR(dip));
4569 #endif
4571 * We ignore this unless this is an old-style driver, except for
4572 * printing the message above
4574 if (PM_NUMCMPTS(dip) == 0 || !PM_ISBC(dip)) {
4575 PMD(PMD_REMDEV, ("%s: ignore %s@%s(%s#%d)\n", pmf,
4576 PM_DEVICE(dip)))
4577 return;
4579 ASSERT(PM_GET_PM_INFO(dip));
4582 * pm_unmanage will clear info pointer later, after dealing with
4583 * dependencies
4585 ASSERT(!PM_GET_PM_SCAN(dip)); /* better be gone already */
4587 * Now adjust parent's kidsupcnt. We check only comp 0.
4588 * Parents that get notification are not adjusted because their
4589 * kidsupcnt is always 0 (or 1 during probe and attach).
4591 if ((PM_CURPOWER(dip, 0) != 0) && pdip && !PM_WANTS_NOTIFICATION(pdip))
4592 pm_rele_power(pdip);
4593 #ifdef DEBUG
4594 else {
4595 PMD(PMD_KIDSUP, ("%s: kuc stays %s@%s(%s#%d) comps gone\n",
4596 pmf, PM_DEVICE(dip)))
4598 #endif
4599 e_pm_destroy_components(dip);
4601 * Forget we ever knew anything about the components of this device
4603 DEVI(dip)->devi_pm_flags &=
4604 ~(PMC_BC | PMC_COMPONENTS_DONE | PMC_COMPONENTS_FAILED);
4608 * Exported interface for a driver to set a component busy.
4611 pm_busy_component(dev_info_t *dip, int cmpt)
4613 struct pm_component *cp;
4615 ASSERT(dip != NULL);
4616 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, cmpt, &cp))
4617 return (DDI_FAILURE);
4618 PM_LOCK_BUSY(dip);
4619 cp->pmc_busycount++;
4620 cp->pmc_timestamp = 0;
4621 PM_UNLOCK_BUSY(dip);
4622 return (DDI_SUCCESS);
4626 * Exported interface for a driver to set a component idle.
4629 pm_idle_component(dev_info_t *dip, int cmpt)
4631 PMD_FUNC(pmf, "pm_idle_component")
4632 struct pm_component *cp;
4633 pm_scan_t *scanp = PM_GET_PM_SCAN(dip);
4635 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, cmpt, &cp))
4636 return (DDI_FAILURE);
4638 PM_LOCK_BUSY(dip);
4639 if (cp->pmc_busycount) {
4640 if (--(cp->pmc_busycount) == 0)
4641 cp->pmc_timestamp = gethrestime_sec();
4642 } else {
4643 cp->pmc_timestamp = gethrestime_sec();
4646 PM_UNLOCK_BUSY(dip);
4649 * if device becomes idle during idle down period, try scan it down
4651 if (scanp && PM_IS_PID(dip)) {
4652 PMD(PMD_IDLEDOWN, ("%s: %s@%s(%s#%d) idle.\n", pmf,
4653 PM_DEVICE(dip)))
4654 pm_rescan(dip);
4655 return (DDI_SUCCESS);
4659 * handle scan not running with nexus threshold == 0
4662 if (PM_IS_NEXUS(dip) && (cp->pmc_busycount == 0)) {
4663 pm_rescan(dip);
4666 return (DDI_SUCCESS);
4670 * This is the old obsolete interface called by drivers to set their normal
4671 * power. Thus we can't fix its behavior or return a value.
4672 * This functionality is replaced by the pm-component property.
4673 * We'll only get components destroyed while no power management is
4674 * going on (and the device is detached), so we don't need a mutex here
4676 void
4677 pm_set_normal_power(dev_info_t *dip, int comp, int level)
4679 PMD_FUNC(pmf, "set_normal_power")
4680 #ifdef DEBUG
4681 if (!PM_ISBC(dip))
4682 cmn_err(CE_WARN, "!call to pm_set_normal_power() by %s@%s "
4683 "(driver exporting pm-components property) ignored",
4684 PM_NAME(dip), PM_ADDR(dip));
4685 #endif
4686 if (PM_ISBC(dip)) {
4687 PMD(PMD_NORM, ("%s: %s@%s(%s#%d) set normal power comp=%d, "
4688 "level=%d\n", pmf, PM_DEVICE(dip), comp, level))
4689 e_pm_set_max_power(dip, comp, level);
4690 e_pm_default_levels(dip, PM_CP(dip, comp), level);
4695 * Called on a successfully detached driver to free pm resources
4697 static void
4698 pm_stop(dev_info_t *dip)
4700 PMD_FUNC(pmf, "stop")
4701 dev_info_t *pdip = ddi_get_parent(dip);
4703 ASSERT(!PM_IAM_LOCKING_DIP(dip));
4704 /* stopping scan, destroy scan data structure */
4705 if (!PM_ISBC(dip)) {
4706 pm_scan_stop(dip);
4707 pm_scan_fini(dip);
4710 if (PM_GET_PM_INFO(dip) != NULL) {
4711 if (pm_unmanage(dip) == DDI_SUCCESS) {
4713 * Old style driver may have called
4714 * pm_destroy_components already, but just in case ...
4716 e_pm_destroy_components(dip);
4717 } else {
4718 PMD(PMD_FAIL, ("%s: can't pm_unmanage %s@%s(%s#%d)\n",
4719 pmf, PM_DEVICE(dip)))
4721 } else {
4722 if (PM_NUMCMPTS(dip))
4723 e_pm_destroy_components(dip);
4724 else {
4725 if (DEVI(dip)->devi_pm_flags & PMC_NOPMKID) {
4726 DEVI(dip)->devi_pm_flags &= ~PMC_NOPMKID;
4727 if (pdip && !PM_WANTS_NOTIFICATION(pdip)) {
4728 pm_rele_power(pdip);
4729 } else if (pdip &&
4730 MDI_VHCI(pdip) && MDI_CLIENT(dip)) {
4731 (void) mdi_power(pdip,
4732 MDI_PM_RELE_POWER,
4733 (void *)dip, NULL, 0);
4741 * The node is the subject of a reparse pm props ioctl. Throw away the old
4742 * info and start over.
4745 e_new_pm_props(dev_info_t *dip)
4747 if (PM_GET_PM_INFO(dip) != NULL) {
4748 pm_stop(dip);
4750 if (e_pm_manage(dip, PM_STYLE_NEW) != DDI_SUCCESS) {
4751 return (DDI_FAILURE);
4754 e_pm_props(dip);
4755 return (DDI_SUCCESS);
4759 * Device has been attached, so process its pm properties
4761 void
4762 e_pm_props(dev_info_t *dip)
4764 char *pp;
4765 int len;
4766 int flags = 0;
4767 int propflag = DDI_PROP_DONTPASS|DDI_PROP_CANSLEEP;
4770 * It doesn't matter if we do this more than once, we should always
4771 * get the same answers, and if not, then the last one in is the
4772 * best one.
4774 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, propflag, "pm-hardware-state",
4775 (caddr_t)&pp, &len) == DDI_PROP_SUCCESS) {
4776 if (strcmp(pp, "needs-suspend-resume") == 0) {
4777 flags = PMC_NEEDS_SR;
4778 } else if (strcmp(pp, "no-suspend-resume") == 0) {
4779 flags = PMC_NO_SR;
4780 } else if (strcmp(pp, "parental-suspend-resume") == 0) {
4781 flags = PMC_PARENTAL_SR;
4782 } else {
4783 cmn_err(CE_NOTE, "!device %s@%s has unrecognized "
4784 "%s property value '%s'", PM_NAME(dip),
4785 PM_ADDR(dip), "pm-hardware-state", pp);
4787 kmem_free(pp, len);
4790 * This next segment (PMC_WANTS_NOTIFY) is in
4791 * support of nexus drivers which will want to be involved in
4792 * (or at least notified of) their child node's power level transitions.
4793 * "pm-want-child-notification?" is defined by the parent.
4795 if (ddi_prop_exists(DDI_DEV_T_ANY, dip, propflag,
4796 "pm-want-child-notification?") && PM_HAS_BUS_POWER(dip))
4797 flags |= PMC_WANTS_NOTIFY;
4798 ASSERT(PM_HAS_BUS_POWER(dip) || !ddi_prop_exists(DDI_DEV_T_ANY,
4799 dip, propflag, "pm-want-child-notification?"));
4800 if (ddi_prop_exists(DDI_DEV_T_ANY, dip, propflag,
4801 "no-involuntary-power-cycles"))
4802 flags |= PMC_NO_INVOL;
4804 * Is the device a CPU device?
4806 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, propflag, "pm-class",
4807 (caddr_t)&pp, &len) == DDI_PROP_SUCCESS) {
4808 if (strcmp(pp, "CPU") == 0) {
4809 flags |= PMC_CPU_DEVICE;
4810 } else {
4811 cmn_err(CE_NOTE, "!device %s@%s has unrecognized "
4812 "%s property value '%s'", PM_NAME(dip),
4813 PM_ADDR(dip), "pm-class", pp);
4815 kmem_free(pp, len);
4817 /* devfs single threads us */
4818 DEVI(dip)->devi_pm_flags |= flags;
4822 * This is the DDI_CTLOPS_POWER handler that is used when there is no ppm
4823 * driver which has claimed a node.
4824 * Sets old_power in arg struct.
4826 static int
4827 pm_default_ctlops(dev_info_t *dip, dev_info_t *rdip,
4828 ddi_ctl_enum_t ctlop, void *arg, void *result)
4830 _NOTE(ARGUNUSED(dip))
4831 PMD_FUNC(pmf, "ctlops")
4832 power_req_t *reqp = (power_req_t *)arg;
4833 int retval;
4834 dev_info_t *target_dip;
4835 int new_level, old_level, cmpt;
4836 #ifdef PMDDEBUG
4837 char *format;
4838 #endif
4841 * The interface for doing the actual power level changes is now
4842 * through the DDI_CTLOPS_POWER bus_ctl, so that we can plug in
4843 * different platform-specific power control drivers.
4845 * This driver implements the "default" version of this interface.
4846 * If no ppm driver has been installed then this interface is called
4847 * instead.
4849 ASSERT(dip == NULL);
4850 switch (ctlop) {
4851 case DDI_CTLOPS_POWER:
4852 switch (reqp->request_type) {
4853 case PMR_PPM_SET_POWER:
4855 target_dip = reqp->req.ppm_set_power_req.who;
4856 ASSERT(target_dip == rdip);
4857 new_level = reqp->req.ppm_set_power_req.new_level;
4858 cmpt = reqp->req.ppm_set_power_req.cmpt;
4859 /* pass back old power for the PM_LEVEL_UNKNOWN case */
4860 old_level = PM_CURPOWER(target_dip, cmpt);
4861 reqp->req.ppm_set_power_req.old_level = old_level;
4862 retval = pm_power(target_dip, cmpt, new_level);
4863 PMD(PMD_PPM, ("%s: PPM_SET_POWER %s@%s(%s#%d)[%d] %d->"
4864 "%d %s\n", pmf, PM_DEVICE(target_dip), cmpt,
4865 old_level, new_level, (retval == DDI_SUCCESS ?
4866 "chd" : "no chg")))
4867 return (retval);
4870 case PMR_PPM_PRE_DETACH:
4871 case PMR_PPM_POST_DETACH:
4872 case PMR_PPM_PRE_ATTACH:
4873 case PMR_PPM_POST_ATTACH:
4874 case PMR_PPM_PRE_PROBE:
4875 case PMR_PPM_POST_PROBE:
4876 case PMR_PPM_PRE_RESUME:
4877 case PMR_PPM_INIT_CHILD:
4878 case PMR_PPM_UNINIT_CHILD:
4879 #ifdef PMDDEBUG
4880 switch (reqp->request_type) {
4881 case PMR_PPM_PRE_DETACH:
4882 format = "%s: PMR_PPM_PRE_DETACH "
4883 "%s@%s(%s#%d)\n";
4884 break;
4885 case PMR_PPM_POST_DETACH:
4886 format = "%s: PMR_PPM_POST_DETACH "
4887 "%s@%s(%s#%d) rets %d\n";
4888 break;
4889 case PMR_PPM_PRE_ATTACH:
4890 format = "%s: PMR_PPM_PRE_ATTACH "
4891 "%s@%s(%s#%d)\n";
4892 break;
4893 case PMR_PPM_POST_ATTACH:
4894 format = "%s: PMR_PPM_POST_ATTACH "
4895 "%s@%s(%s#%d) rets %d\n";
4896 break;
4897 case PMR_PPM_PRE_PROBE:
4898 format = "%s: PMR_PPM_PRE_PROBE "
4899 "%s@%s(%s#%d)\n";
4900 break;
4901 case PMR_PPM_POST_PROBE:
4902 format = "%s: PMR_PPM_POST_PROBE "
4903 "%s@%s(%s#%d) rets %d\n";
4904 break;
4905 case PMR_PPM_PRE_RESUME:
4906 format = "%s: PMR_PPM_PRE_RESUME "
4907 "%s@%s(%s#%d) rets %d\n";
4908 break;
4909 case PMR_PPM_INIT_CHILD:
4910 format = "%s: PMR_PPM_INIT_CHILD "
4911 "%s@%s(%s#%d)\n";
4912 break;
4913 case PMR_PPM_UNINIT_CHILD:
4914 format = "%s: PMR_PPM_UNINIT_CHILD "
4915 "%s@%s(%s#%d)\n";
4916 break;
4917 default:
4918 break;
4920 PMD(PMD_PPM, (format, pmf, PM_DEVICE(rdip),
4921 reqp->req.ppm_config_req.result))
4922 #endif
4923 return (DDI_SUCCESS);
4925 case PMR_PPM_POWER_CHANGE_NOTIFY:
4927 * Nothing for us to do
4929 ASSERT(reqp->req.ppm_notify_level_req.who == rdip);
4930 PMD(PMD_PPM, ("%s: PMR_PPM_POWER_CHANGE_NOTIFY "
4931 "%s@%s(%s#%d)[%d] %d->%d\n", pmf,
4932 PM_DEVICE(reqp->req.ppm_notify_level_req.who),
4933 reqp->req.ppm_notify_level_req.cmpt,
4934 PM_CURPOWER(reqp->req.ppm_notify_level_req.who,
4935 reqp->req.ppm_notify_level_req.cmpt),
4936 reqp->req.ppm_notify_level_req.new_level))
4937 return (DDI_SUCCESS);
4939 case PMR_PPM_UNMANAGE:
4940 PMD(PMD_PPM, ("%s: PMR_PPM_UNMANAGE %s@%s(%s#%d)\n",
4941 pmf, PM_DEVICE(rdip)))
4942 return (DDI_SUCCESS);
4944 case PMR_PPM_LOCK_POWER:
4945 pm_lock_power_single(reqp->req.ppm_lock_power_req.who,
4946 reqp->req.ppm_lock_power_req.circp);
4947 return (DDI_SUCCESS);
4949 case PMR_PPM_UNLOCK_POWER:
4950 pm_unlock_power_single(
4951 reqp->req.ppm_unlock_power_req.who,
4952 reqp->req.ppm_unlock_power_req.circ);
4953 return (DDI_SUCCESS);
4955 case PMR_PPM_TRY_LOCK_POWER:
4956 *(int *)result = pm_try_locking_power_single(
4957 reqp->req.ppm_lock_power_req.who,
4958 reqp->req.ppm_lock_power_req.circp);
4959 return (DDI_SUCCESS);
4961 case PMR_PPM_POWER_LOCK_OWNER:
4962 target_dip = reqp->req.ppm_power_lock_owner_req.who;
4963 ASSERT(target_dip == rdip);
4964 reqp->req.ppm_power_lock_owner_req.owner =
4965 DEVI(rdip)->devi_busy_thread;
4966 return (DDI_SUCCESS);
4967 default:
4968 PMD(PMD_ERROR, ("%s: default!\n", pmf))
4969 return (DDI_FAILURE);
4972 default:
4973 PMD(PMD_ERROR, ("%s: unknown\n", pmf))
4974 return (DDI_FAILURE);
4979 * We overload the bus_ctl ops here--perhaps we ought to have a distinct
4980 * power_ops struct for this functionality instead?
4981 * However, we only ever do this on a ppm driver.
4984 pm_ctlops(dev_info_t *d, dev_info_t *r, ddi_ctl_enum_t op, void *a, void *v)
4986 int (*fp)();
4988 /* if no ppm handler, call the default routine */
4989 if (d == NULL) {
4990 return (pm_default_ctlops(d, r, op, a, v));
4992 if (!d || !r)
4993 return (DDI_FAILURE);
4994 ASSERT(DEVI(d)->devi_ops && DEVI(d)->devi_ops->devo_bus_ops &&
4995 DEVI(d)->devi_ops->devo_bus_ops->bus_ctl);
4997 fp = DEVI(d)->devi_ops->devo_bus_ops->bus_ctl;
4998 return ((*fp)(d, r, op, a, v));
5002 * Called on a node when attach completes or the driver makes its first pm
5003 * call (whichever comes first).
5004 * In the attach case, device may not be power manageable at all.
5005 * Don't need to lock the dip because we're single threaded by the devfs code
5007 static int
5008 pm_start(dev_info_t *dip)
5010 PMD_FUNC(pmf, "start")
5011 int ret;
5012 dev_info_t *pdip = ddi_get_parent(dip);
5013 int e_pm_manage(dev_info_t *, int);
5014 void pm_noinvol_specd(dev_info_t *dip);
5016 e_pm_props(dip);
5017 pm_noinvol_specd(dip);
5019 * If this dip has already been processed, don't mess with it
5020 * (but decrement the speculative count we did above, as whatever
5021 * code put it under pm already will have dealt with it)
5023 if (PM_GET_PM_INFO(dip)) {
5024 PMD(PMD_KIDSUP, ("%s: pm already done for %s@%s(%s#%d)\n",
5025 pmf, PM_DEVICE(dip)))
5026 return (0);
5028 ret = e_pm_manage(dip, PM_STYLE_UNKNOWN);
5030 if (PM_GET_PM_INFO(dip) == NULL) {
5032 * keep the kidsupcount increment as is
5034 DEVI(dip)->devi_pm_flags |= PMC_NOPMKID;
5035 if (pdip && !PM_WANTS_NOTIFICATION(pdip)) {
5036 pm_hold_power(pdip);
5037 } else if (pdip && MDI_VHCI(pdip) && MDI_CLIENT(dip)) {
5038 (void) mdi_power(pdip, MDI_PM_HOLD_POWER,
5039 (void *)dip, NULL, 0);
5042 PMD(PMD_KIDSUP, ("%s: pm of %s@%s(%s#%d) failed, parent "
5043 "left up\n", pmf, PM_DEVICE(dip)))
5046 return (ret);
5050 * Keep a list of recorded thresholds. For now we just keep a list and
5051 * search it linearly. We don't expect too many entries. Can always hash it
5052 * later if we need to.
5054 void
5055 pm_record_thresh(pm_thresh_rec_t *rp)
5057 pm_thresh_rec_t *pptr, *ptr;
5059 ASSERT(*rp->ptr_physpath);
5060 rw_enter(&pm_thresh_rwlock, RW_WRITER);
5061 for (pptr = NULL, ptr = pm_thresh_head;
5062 ptr; pptr = ptr, ptr = ptr->ptr_next) {
5063 if (strcmp(rp->ptr_physpath, ptr->ptr_physpath) == 0) {
5064 /* replace this one */
5065 rp->ptr_next = ptr->ptr_next;
5066 if (pptr) {
5067 pptr->ptr_next = rp;
5068 } else {
5069 pm_thresh_head = rp;
5071 rw_exit(&pm_thresh_rwlock);
5072 kmem_free(ptr, ptr->ptr_size);
5073 return;
5075 continue;
5078 * There was not a match in the list, insert this one in front
5080 if (pm_thresh_head) {
5081 rp->ptr_next = pm_thresh_head;
5082 pm_thresh_head = rp;
5083 } else {
5084 rp->ptr_next = NULL;
5085 pm_thresh_head = rp;
5087 rw_exit(&pm_thresh_rwlock);
5091 * Create a new dependency record and hang a new dependency entry off of it
5093 pm_pdr_t *
5094 newpdr(char *kept, char *keeps, int isprop)
5096 size_t size = strlen(kept) + strlen(keeps) + 2 + sizeof (pm_pdr_t);
5097 pm_pdr_t *p = kmem_zalloc(size, KM_SLEEP);
5098 p->pdr_size = size;
5099 p->pdr_isprop = isprop;
5100 p->pdr_kept_paths = NULL;
5101 p->pdr_kept_count = 0;
5102 p->pdr_kept = (char *)((intptr_t)p + sizeof (pm_pdr_t));
5103 (void) strcpy(p->pdr_kept, kept);
5104 p->pdr_keeper = (char *)((intptr_t)p->pdr_kept + strlen(kept) + 1);
5105 (void) strcpy(p->pdr_keeper, keeps);
5106 ASSERT((intptr_t)p->pdr_keeper + strlen(p->pdr_keeper) + 1 <=
5107 (intptr_t)p + size);
5108 ASSERT((intptr_t)p->pdr_kept + strlen(p->pdr_kept) + 1 <=
5109 (intptr_t)p + size);
5110 return (p);
5114 * Keep a list of recorded dependencies. We only keep the
5115 * keeper -> kept list for simplification. At this point We do not
5116 * care about whether the devices are attached or not yet,
5117 * this would be done in pm_keeper() and pm_kept().
5118 * If a PM_RESET_PM happens, then we tear down and forget the dependencies,
5119 * and it is up to the user to issue the ioctl again if they want it
5120 * (e.g. pmconfig)
5121 * Returns true if dependency already exists in the list.
5124 pm_record_keeper(char *kept, char *keeper, int isprop)
5126 PMD_FUNC(pmf, "record_keeper")
5127 pm_pdr_t *npdr, *ppdr, *pdr;
5129 PMD(PMD_KEEPS, ("%s: %s, %s\n", pmf, kept, keeper))
5130 ASSERT(kept && keeper);
5131 #ifdef DEBUG
5132 if (pm_debug & PMD_KEEPS)
5133 prdeps("pm_record_keeper entry");
5134 #endif
5135 for (ppdr = NULL, pdr = pm_dep_head; pdr;
5136 ppdr = pdr, pdr = pdr->pdr_next) {
5137 PMD(PMD_KEEPS, ("%s: check %s, %s\n", pmf, pdr->pdr_kept,
5138 pdr->pdr_keeper))
5139 if (strcmp(kept, pdr->pdr_kept) == 0 &&
5140 strcmp(keeper, pdr->pdr_keeper) == 0) {
5141 PMD(PMD_KEEPS, ("%s: match\n", pmf))
5142 return (1);
5146 * We did not find any match, so we have to make an entry
5148 npdr = newpdr(kept, keeper, isprop);
5149 if (ppdr) {
5150 ASSERT(ppdr->pdr_next == NULL);
5151 ppdr->pdr_next = npdr;
5152 } else {
5153 ASSERT(pm_dep_head == NULL);
5154 pm_dep_head = npdr;
5156 #ifdef DEBUG
5157 if (pm_debug & PMD_KEEPS)
5158 prdeps("pm_record_keeper after new record");
5159 #endif
5160 if (!isprop)
5161 pm_unresolved_deps++;
5162 else
5163 pm_prop_deps++;
5164 return (0);
5168 * Look up this device in the set of devices we've seen ioctls for
5169 * to see if we are holding a threshold spec for it. If so, make it so.
5170 * At ioctl time, we were given the physical path of the device.
5173 pm_thresh_specd(dev_info_t *dip)
5175 void pm_apply_recorded_thresh(dev_info_t *, pm_thresh_rec_t *);
5176 char *path = 0;
5177 char pathbuf[MAXNAMELEN];
5178 pm_thresh_rec_t *rp;
5180 path = ddi_pathname(dip, pathbuf);
5182 rw_enter(&pm_thresh_rwlock, RW_READER);
5183 for (rp = pm_thresh_head; rp; rp = rp->ptr_next) {
5184 if (strcmp(rp->ptr_physpath, path) != 0)
5185 continue;
5186 pm_apply_recorded_thresh(dip, rp);
5187 rw_exit(&pm_thresh_rwlock);
5188 return (1);
5190 rw_exit(&pm_thresh_rwlock);
5191 return (0);
5194 static int
5195 pm_set_keeping(dev_info_t *keeper, dev_info_t *kept)
5197 PMD_FUNC(pmf, "set_keeping")
5198 int j, up = 0, circ;
5199 void prdeps(char *);
5201 PMD(PMD_KEEPS, ("%s: keeper=%s@%s(%s#%d), kept=%s@%s(%s#%d)\n", pmf,
5202 PM_DEVICE(keeper), PM_DEVICE(kept)))
5203 #ifdef DEBUG
5204 if (pm_debug & PMD_KEEPS)
5205 prdeps("Before PAD\n");
5206 #endif
5207 ASSERT(keeper != kept);
5208 if (PM_GET_PM_INFO(keeper) == NULL) {
5209 cmn_err(CE_CONT, "!device %s@%s(%s#%d) keeps up device "
5210 "%s@%s(%s#%d), but the former is not power managed",
5211 PM_DEVICE(keeper), PM_DEVICE(kept));
5212 PMD((PMD_FAIL | PMD_KEEPS), ("%s: keeper %s@%s(%s#%d) is not"
5213 "power managed\n", pmf, PM_DEVICE(keeper)))
5214 return (0);
5216 if (PM_GET_PM_INFO(kept) == NULL) {
5217 cmn_err(CE_CONT, "!device %s@%s(%s#%d) keeps up device "
5218 "%s@%s(%s#%d), but the latter is not power managed",
5219 PM_DEVICE(keeper), PM_DEVICE(kept));
5220 PMD((PMD_FAIL | PMD_KEEPS), ("%s: kept %s@%s(%s#%d) is not"
5221 "power managed\n", pmf, PM_DEVICE(kept)))
5222 return (0);
5225 PM_LOCK_POWER(keeper, &circ);
5226 for (j = 0; j < PM_NUMCMPTS(keeper); j++) {
5227 if (PM_CURPOWER(keeper, j)) {
5228 up++;
5229 break;
5232 if (up) {
5233 /* Bringup and maintain a hold on the kept */
5234 PMD(PMD_KEEPS, ("%s: place a hold on kept %s@%s(%s#%d)\n", pmf,
5235 PM_DEVICE(kept)))
5236 bring_pmdep_up(kept, 1);
5238 PM_UNLOCK_POWER(keeper, circ);
5239 #ifdef DEBUG
5240 if (pm_debug & PMD_KEEPS)
5241 prdeps("After PAD\n");
5242 #endif
5243 return (1);
5247 * Should this device keep up another device?
5248 * Look up this device in the set of devices we've seen ioctls for
5249 * to see if we are holding a dependency spec for it. If so, make it so.
5250 * Because we require the kept device to be attached already in order to
5251 * make the list entry (and hold it), we only need to look for keepers.
5252 * At ioctl time, we were given the physical path of the device.
5255 pm_keeper(char *keeper)
5257 PMD_FUNC(pmf, "keeper")
5258 int pm_apply_recorded_dep(dev_info_t *, pm_pdr_t *);
5259 dev_info_t *dip;
5260 pm_pdr_t *dp;
5261 dev_info_t *kept = NULL;
5262 int ret = 0;
5263 int i;
5265 if (!pm_unresolved_deps && !pm_prop_deps)
5266 return (0);
5267 ASSERT(keeper != NULL);
5268 dip = pm_name_to_dip(keeper, 1);
5269 if (dip == NULL)
5270 return (0);
5271 PMD(PMD_KEEPS, ("%s: keeper=%s\n", pmf, keeper))
5272 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
5273 if (!dp->pdr_isprop) {
5274 if (!pm_unresolved_deps)
5275 continue;
5276 PMD(PMD_KEEPS, ("%s: keeper %s\n", pmf, dp->pdr_keeper))
5277 if (dp->pdr_satisfied) {
5278 PMD(PMD_KEEPS, ("%s: satisfied\n", pmf))
5279 continue;
5281 if (strcmp(dp->pdr_keeper, keeper) == 0) {
5282 ret += pm_apply_recorded_dep(dip, dp);
5284 } else {
5285 if (strcmp(dp->pdr_keeper, keeper) != 0)
5286 continue;
5287 for (i = 0; i < dp->pdr_kept_count; i++) {
5288 if (dp->pdr_kept_paths[i] == NULL)
5289 continue;
5290 kept = pm_name_to_dip(dp->pdr_kept_paths[i], 1);
5291 if (kept == NULL)
5292 continue;
5293 ASSERT(ddi_prop_exists(DDI_DEV_T_ANY, kept,
5294 DDI_PROP_DONTPASS, dp->pdr_kept));
5295 PMD(PMD_KEEPS, ("%s: keeper=%s@%s(%s#%d), "
5296 "kept=%s@%s(%s#%d) keptcnt=%d\n",
5297 pmf, PM_DEVICE(dip), PM_DEVICE(kept),
5298 dp->pdr_kept_count))
5299 if (kept != dip) {
5300 ret += pm_set_keeping(dip, kept);
5302 ddi_release_devi(kept);
5307 ddi_release_devi(dip);
5308 return (ret);
5312 * Should this device be kept up by another device?
5313 * Look up all dependency recorded from PM_ADD_DEPENDENT and
5314 * PM_ADD_DEPENDENT_PROPERTY ioctls. Record down on the keeper's
5315 * kept device lists.
5317 static int
5318 pm_kept(char *keptp)
5320 PMD_FUNC(pmf, "kept")
5321 pm_pdr_t *dp;
5322 int found = 0;
5323 int ret = 0;
5324 dev_info_t *keeper;
5325 dev_info_t *kept;
5326 size_t length;
5327 int i;
5328 char **paths;
5329 char *path;
5331 ASSERT(keptp != NULL);
5332 kept = pm_name_to_dip(keptp, 1);
5333 if (kept == NULL)
5334 return (0);
5335 PMD(PMD_KEEPS, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(kept)))
5336 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
5337 if (dp->pdr_isprop) {
5338 PMD(PMD_KEEPS, ("%s: property %s\n", pmf, dp->pdr_kept))
5339 if (ddi_prop_exists(DDI_DEV_T_ANY, kept,
5340 DDI_PROP_DONTPASS, dp->pdr_kept)) {
5342 * Dont allow self dependency.
5344 if (strcmp(dp->pdr_keeper, keptp) == 0)
5345 continue;
5346 keeper = pm_name_to_dip(dp->pdr_keeper, 1);
5347 if (keeper == NULL)
5348 continue;
5349 PMD(PMD_KEEPS, ("%s: adding to kepts path list "
5350 "%p\n", pmf, (void *)kept))
5351 #ifdef DEBUG
5352 if (pm_debug & PMD_DEP)
5353 prdeps("Before Adding from pm_kept\n");
5354 #endif
5356 * Add ourselves to the dip list.
5358 if (dp->pdr_kept_count == 0) {
5359 length = strlen(keptp) + 1;
5360 path =
5361 kmem_alloc(length, KM_SLEEP);
5362 paths = kmem_alloc(sizeof (char **),
5363 KM_SLEEP);
5364 (void) strcpy(path, keptp);
5365 paths[0] = path;
5366 dp->pdr_kept_paths = paths;
5367 dp->pdr_kept_count++;
5368 } else {
5369 /* Check to see if already on list */
5370 for (i = 0; i < dp->pdr_kept_count;
5371 i++) {
5372 if (strcmp(keptp,
5373 dp->pdr_kept_paths[i])
5374 == 0) {
5375 found++;
5376 break;
5379 if (found) {
5380 ddi_release_devi(keeper);
5381 continue;
5383 length = dp->pdr_kept_count *
5384 sizeof (char **);
5385 paths = kmem_alloc(
5386 length + sizeof (char **),
5387 KM_SLEEP);
5388 if (dp->pdr_kept_count) {
5389 bcopy(dp->pdr_kept_paths,
5390 paths, length);
5391 kmem_free(dp->pdr_kept_paths,
5392 length);
5394 dp->pdr_kept_paths = paths;
5395 length = strlen(keptp) + 1;
5396 path =
5397 kmem_alloc(length, KM_SLEEP);
5398 (void) strcpy(path, keptp);
5399 dp->pdr_kept_paths[i] = path;
5400 dp->pdr_kept_count++;
5402 #ifdef DEBUG
5403 if (pm_debug & PMD_DEP)
5404 prdeps("After from pm_kept\n");
5405 #endif
5406 if (keeper) {
5407 ret += pm_set_keeping(keeper, kept);
5408 ddi_release_devi(keeper);
5411 } else {
5413 * pm_keeper would be called later to do
5414 * the actual pm_set_keeping.
5416 PMD(PMD_KEEPS, ("%s: adding to kepts path list %p\n",
5417 pmf, (void *)kept))
5418 #ifdef DEBUG
5419 if (pm_debug & PMD_DEP)
5420 prdeps("Before Adding from pm_kept\n");
5421 #endif
5422 if (strcmp(keptp, dp->pdr_kept) == 0) {
5423 if (dp->pdr_kept_paths == NULL) {
5424 length = strlen(keptp) + 1;
5425 path =
5426 kmem_alloc(length, KM_SLEEP);
5427 paths = kmem_alloc(sizeof (char **),
5428 KM_SLEEP);
5429 (void) strcpy(path, keptp);
5430 paths[0] = path;
5431 dp->pdr_kept_paths = paths;
5432 dp->pdr_kept_count++;
5435 #ifdef DEBUG
5436 if (pm_debug & PMD_DEP)
5437 prdeps("After from pm_kept\n");
5438 #endif
5441 ddi_release_devi(kept);
5442 return (ret);
5446 * Apply a recorded dependency. dp specifies the dependency, and
5447 * keeper is already known to be the device that keeps up the other (kept) one.
5448 * We have to the whole tree for the "kept" device, then apply
5449 * the dependency (which may already be applied).
5452 pm_apply_recorded_dep(dev_info_t *keeper, pm_pdr_t *dp)
5454 PMD_FUNC(pmf, "apply_recorded_dep")
5455 dev_info_t *kept = NULL;
5456 int ret = 0;
5457 char *keptp = NULL;
5460 * Device to Device dependency can only be 1 to 1.
5462 if (dp->pdr_kept_paths == NULL)
5463 return (0);
5464 keptp = dp->pdr_kept_paths[0];
5465 if (keptp == NULL)
5466 return (0);
5467 ASSERT(*keptp != '\0');
5468 kept = pm_name_to_dip(keptp, 1);
5469 if (kept == NULL)
5470 return (0);
5471 if (kept) {
5472 PMD(PMD_KEEPS, ("%s: keeper=%s, kept=%s\n", pmf,
5473 dp->pdr_keeper, keptp))
5474 if (pm_set_keeping(keeper, kept)) {
5475 ASSERT(dp->pdr_satisfied == 0);
5476 dp->pdr_satisfied = 1;
5477 ASSERT(pm_unresolved_deps);
5478 pm_unresolved_deps--;
5479 ret++;
5482 ddi_release_devi(kept);
5484 return (ret);
5488 * Called from common/io/pm.c
5491 pm_cur_power(pm_component_t *cp)
5493 return (cur_power(cp));
5497 * External interface to sanity-check a power level.
5500 pm_valid_power(dev_info_t *dip, int comp, int level)
5502 PMD_FUNC(pmf, "valid_power")
5504 if (comp >= 0 && comp < PM_NUMCMPTS(dip) && level >= 0)
5505 return (e_pm_valid_power(dip, comp, level));
5506 else {
5507 PMD(PMD_FAIL, ("%s: comp=%d, ncomp=%d, level=%d\n",
5508 pmf, comp, PM_NUMCMPTS(dip), level))
5509 return (0);
5514 * Called when a device that is direct power managed needs to change state.
5515 * This routine arranges to block the request until the process managing
5516 * the device makes the change (or some other incompatible change) or
5517 * the process closes /dev/pm.
5519 static int
5520 pm_block(dev_info_t *dip, int comp, int newpower, int oldpower)
5522 pm_rsvp_t *new = kmem_zalloc(sizeof (*new), KM_SLEEP);
5523 int ret = 0;
5524 void pm_dequeue_blocked(pm_rsvp_t *);
5525 void pm_enqueue_blocked(pm_rsvp_t *);
5527 ASSERT(!pm_processes_stopped);
5528 ASSERT(PM_IAM_LOCKING_DIP(dip));
5529 new->pr_dip = dip;
5530 new->pr_comp = comp;
5531 new->pr_newlevel = newpower;
5532 new->pr_oldlevel = oldpower;
5533 cv_init(&new->pr_cv, NULL, CV_DEFAULT, NULL);
5534 mutex_enter(&pm_rsvp_lock);
5535 pm_enqueue_blocked(new);
5536 pm_enqueue_notify(PSC_PENDING_CHANGE, dip, comp, newpower, oldpower,
5537 PM_CANBLOCK_BLOCK);
5538 PM_UNLOCK_DIP(dip);
5540 * truss may make the cv_wait_sig return prematurely
5542 while (ret == 0) {
5544 * Normally there will be no user context involved, but if
5545 * there is (e.g. we are here via an ioctl call to a driver)
5546 * then we should allow the process to abort the request,
5547 * or we get an unkillable process if the same thread does
5548 * PM_DIRECT_PM and pm_raise_power
5550 if (cv_wait_sig(&new->pr_cv, &pm_rsvp_lock) == 0) {
5551 ret = PMP_FAIL;
5552 } else {
5553 ret = new->pr_retval;
5556 pm_dequeue_blocked(new);
5557 mutex_exit(&pm_rsvp_lock);
5558 cv_destroy(&new->pr_cv);
5559 kmem_free(new, sizeof (*new));
5560 return (ret);
5564 * Returns true if the process is interested in power level changes (has issued
5565 * PM_GET_STATE_CHANGE ioctl).
5568 pm_interest_registered(int clone)
5570 ASSERT(clone >= 0 && clone < PM_MAX_CLONE - 1);
5571 return (pm_interest[clone]);
5574 static void pm_enqueue_pscc(pscc_t *, pscc_t **);
5577 * Process with clone has just done PM_DIRECT_PM on dip, or has asked to
5578 * watch all state transitions (dip == NULL). Set up data
5579 * structs to communicate with process about state changes.
5581 void
5582 pm_register_watcher(int clone, dev_info_t *dip)
5584 pscc_t *p;
5585 psce_t *psce;
5588 * We definitely need a control struct, then we have to search to see
5589 * there is already an entries struct (in the dip != NULL case).
5591 pscc_t *pscc = kmem_zalloc(sizeof (*pscc), KM_SLEEP);
5592 pscc->pscc_clone = clone;
5593 pscc->pscc_dip = dip;
5595 if (dip) {
5596 int found = 0;
5597 rw_enter(&pm_pscc_direct_rwlock, RW_WRITER);
5598 for (p = pm_pscc_direct; p; p = p->pscc_next) {
5600 * Already an entry for this clone, so just use it
5601 * for the new one (for the case where a single
5602 * process is watching multiple devices)
5604 if (p->pscc_clone == clone) {
5605 pscc->pscc_entries = p->pscc_entries;
5606 pscc->pscc_entries->psce_references++;
5607 found++;
5608 break;
5611 if (!found) { /* create a new one */
5612 psce = kmem_zalloc(sizeof (psce_t), KM_SLEEP);
5613 mutex_init(&psce->psce_lock, NULL, MUTEX_DEFAULT, NULL);
5614 psce->psce_first =
5615 kmem_zalloc(sizeof (pm_state_change_t) * PSCCOUNT,
5616 KM_SLEEP);
5617 psce->psce_in = psce->psce_out = psce->psce_first;
5618 psce->psce_last = &psce->psce_first[PSCCOUNT - 1];
5619 psce->psce_references = 1;
5620 pscc->pscc_entries = psce;
5622 pm_enqueue_pscc(pscc, &pm_pscc_direct);
5623 rw_exit(&pm_pscc_direct_rwlock);
5624 } else {
5625 ASSERT(!pm_interest_registered(clone));
5626 rw_enter(&pm_pscc_interest_rwlock, RW_WRITER);
5627 #ifdef DEBUG
5628 for (p = pm_pscc_interest; p; p = p->pscc_next) {
5630 * Should not be an entry for this clone!
5632 ASSERT(p->pscc_clone != clone);
5634 #endif
5635 psce = kmem_zalloc(sizeof (psce_t), KM_SLEEP);
5636 psce->psce_first = kmem_zalloc(sizeof (pm_state_change_t) *
5637 PSCCOUNT, KM_SLEEP);
5638 psce->psce_in = psce->psce_out = psce->psce_first;
5639 psce->psce_last = &psce->psce_first[PSCCOUNT - 1];
5640 psce->psce_references = 1;
5641 pscc->pscc_entries = psce;
5642 pm_enqueue_pscc(pscc, &pm_pscc_interest);
5643 pm_interest[clone] = 1;
5644 rw_exit(&pm_pscc_interest_rwlock);
5649 * Remove the given entry from the blocked list
5651 void
5652 pm_dequeue_blocked(pm_rsvp_t *p)
5654 ASSERT(MUTEX_HELD(&pm_rsvp_lock));
5655 if (pm_blocked_list == p) {
5656 ASSERT(p->pr_prev == NULL);
5657 if (p->pr_next != NULL)
5658 p->pr_next->pr_prev = NULL;
5659 pm_blocked_list = p->pr_next;
5660 } else {
5661 ASSERT(p->pr_prev != NULL);
5662 p->pr_prev->pr_next = p->pr_next;
5663 if (p->pr_next != NULL)
5664 p->pr_next->pr_prev = p->pr_prev;
5669 * Remove the given control struct from the given list
5671 static void
5672 pm_dequeue_pscc(pscc_t *p, pscc_t **list)
5674 if (*list == p) {
5675 ASSERT(p->pscc_prev == NULL);
5676 if (p->pscc_next != NULL)
5677 p->pscc_next->pscc_prev = NULL;
5678 *list = p->pscc_next;
5679 } else {
5680 ASSERT(p->pscc_prev != NULL);
5681 p->pscc_prev->pscc_next = p->pscc_next;
5682 if (p->pscc_next != NULL)
5683 p->pscc_next->pscc_prev = p->pscc_prev;
5688 * Stick the control struct specified on the front of the list
5690 static void
5691 pm_enqueue_pscc(pscc_t *p, pscc_t **list)
5693 pscc_t *h; /* entry at head of list */
5694 if ((h = *list) == NULL) {
5695 *list = p;
5696 ASSERT(p->pscc_next == NULL);
5697 ASSERT(p->pscc_prev == NULL);
5698 } else {
5699 p->pscc_next = h;
5700 ASSERT(h->pscc_prev == NULL);
5701 h->pscc_prev = p;
5702 ASSERT(p->pscc_prev == NULL);
5703 *list = p;
5708 * If dip is NULL, process is closing "clone" clean up all its registrations.
5709 * Otherwise only clean up those for dip because process is just giving up
5710 * control of a direct device.
5712 void
5713 pm_deregister_watcher(int clone, dev_info_t *dip)
5715 pscc_t *p, *pn;
5716 psce_t *psce;
5717 int found = 0;
5719 if (dip == NULL) {
5720 rw_enter(&pm_pscc_interest_rwlock, RW_WRITER);
5721 for (p = pm_pscc_interest; p; p = pn) {
5722 pn = p->pscc_next;
5723 if (p->pscc_clone == clone) {
5724 pm_dequeue_pscc(p, &pm_pscc_interest);
5725 psce = p->pscc_entries;
5726 ASSERT(psce->psce_references == 1);
5727 mutex_destroy(&psce->psce_lock);
5728 kmem_free(psce->psce_first,
5729 sizeof (pm_state_change_t) * PSCCOUNT);
5730 kmem_free(psce, sizeof (*psce));
5731 kmem_free(p, sizeof (*p));
5734 pm_interest[clone] = 0;
5735 rw_exit(&pm_pscc_interest_rwlock);
5737 found = 0;
5738 rw_enter(&pm_pscc_direct_rwlock, RW_WRITER);
5739 for (p = pm_pscc_direct; p; p = pn) {
5740 pn = p->pscc_next;
5741 if ((dip && p->pscc_dip == dip) ||
5742 (dip == NULL && clone == p->pscc_clone)) {
5743 ASSERT(clone == p->pscc_clone);
5744 found++;
5746 * Remove from control list
5748 pm_dequeue_pscc(p, &pm_pscc_direct);
5750 * If we're the last reference, free the
5751 * entries struct.
5753 psce = p->pscc_entries;
5754 ASSERT(psce);
5755 if (psce->psce_references == 1) {
5756 kmem_free(psce->psce_first,
5757 PSCCOUNT * sizeof (pm_state_change_t));
5758 kmem_free(psce, sizeof (*psce));
5759 } else {
5760 psce->psce_references--;
5762 kmem_free(p, sizeof (*p));
5765 ASSERT(dip == NULL || found);
5766 rw_exit(&pm_pscc_direct_rwlock);
5770 * Search the indicated list for an entry that matches clone, and return a
5771 * pointer to it. To be interesting, the entry must have something ready to
5772 * be passed up to the controlling process.
5773 * The returned entry will be locked upon return from this call.
5775 static psce_t *
5776 pm_psc_find_clone(int clone, pscc_t **list, krwlock_t *lock)
5778 pscc_t *p;
5779 psce_t *psce;
5780 rw_enter(lock, RW_READER);
5781 for (p = *list; p; p = p->pscc_next) {
5782 if (clone == p->pscc_clone) {
5783 psce = p->pscc_entries;
5784 mutex_enter(&psce->psce_lock);
5785 if (psce->psce_out->size) {
5786 rw_exit(lock);
5787 return (psce);
5788 } else {
5789 mutex_exit(&psce->psce_lock);
5793 rw_exit(lock);
5794 return (NULL);
5797 static psce_t *pm_psc_find_clone(int, pscc_t **, krwlock_t *);
5799 * Find an entry for a particular clone in the direct list.
5801 psce_t *
5802 pm_psc_clone_to_direct(int clone)
5804 return (pm_psc_find_clone(clone, &pm_pscc_direct,
5805 &pm_pscc_direct_rwlock));
5809 * Find an entry for a particular clone in the interest list.
5811 psce_t *
5812 pm_psc_clone_to_interest(int clone)
5814 return (pm_psc_find_clone(clone, &pm_pscc_interest,
5815 &pm_pscc_interest_rwlock));
5819 * Put the given entry at the head of the blocked list
5821 void
5822 pm_enqueue_blocked(pm_rsvp_t *p)
5824 ASSERT(MUTEX_HELD(&pm_rsvp_lock));
5825 ASSERT(p->pr_next == NULL);
5826 ASSERT(p->pr_prev == NULL);
5827 if (pm_blocked_list != NULL) {
5828 p->pr_next = pm_blocked_list;
5829 ASSERT(pm_blocked_list->pr_prev == NULL);
5830 pm_blocked_list->pr_prev = p;
5831 pm_blocked_list = p;
5832 } else {
5833 pm_blocked_list = p;
5838 * Sets every power managed device back to its default threshold
5840 void
5841 pm_all_to_default_thresholds(void)
5843 ddi_walk_devs(ddi_root_node(), pm_set_dev_thr_walk,
5844 (void *) &pm_system_idle_threshold);
5847 static int
5848 pm_set_dev_thr_walk(dev_info_t *dip, void *arg)
5850 int thr = (int)(*(int *)arg);
5852 if (!PM_GET_PM_INFO(dip))
5853 return (DDI_WALK_CONTINUE);
5854 pm_set_device_threshold(dip, thr, PMC_DEF_THRESH);
5855 return (DDI_WALK_CONTINUE);
5859 * Returns the current threshold value (in seconds) for the indicated component
5862 pm_current_threshold(dev_info_t *dip, int comp, int *threshp)
5864 if (comp < 0 || comp >= PM_NUMCMPTS(dip)) {
5865 return (DDI_FAILURE);
5866 } else {
5867 *threshp = cur_threshold(dip, comp);
5868 return (DDI_SUCCESS);
5873 * To be called when changing the power level of a component of a device.
5874 * On some platforms, changing power on one device may require that power
5875 * be changed on other, related devices in the same transaction. Thus, we
5876 * always pass this request to the platform power manager so that all the
5877 * affected devices will be locked.
5879 void
5880 pm_lock_power(dev_info_t *dip, int *circp)
5882 power_req_t power_req;
5883 int result;
5885 power_req.request_type = PMR_PPM_LOCK_POWER;
5886 power_req.req.ppm_lock_power_req.who = dip;
5887 power_req.req.ppm_lock_power_req.circp = circp;
5888 (void) pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER, &power_req, &result);
5892 * Release the lock (or locks) acquired to change the power of a device.
5893 * See comments for pm_lock_power.
5895 void
5896 pm_unlock_power(dev_info_t *dip, int circ)
5898 power_req_t power_req;
5899 int result;
5901 power_req.request_type = PMR_PPM_UNLOCK_POWER;
5902 power_req.req.ppm_unlock_power_req.who = dip;
5903 power_req.req.ppm_unlock_power_req.circ = circ;
5904 (void) pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER, &power_req, &result);
5909 * Attempt (without blocking) to acquire the lock(s) needed to change the
5910 * power of a component of a device. See comments for pm_lock_power.
5912 * Return: 1 if lock(s) acquired, 0 if not.
5915 pm_try_locking_power(dev_info_t *dip, int *circp)
5917 power_req_t power_req;
5918 int result;
5920 power_req.request_type = PMR_PPM_TRY_LOCK_POWER;
5921 power_req.req.ppm_lock_power_req.who = dip;
5922 power_req.req.ppm_lock_power_req.circp = circp;
5923 (void) pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER, &power_req, &result);
5924 return (result);
5929 * Lock power state of a device.
5931 * The implementation handles a special case where another thread may have
5932 * acquired the lock and created/launched this thread to do the work. If
5933 * the lock cannot be acquired immediately, we check to see if this thread
5934 * is registered as a borrower of the lock. If so, we may proceed without
5935 * the lock. This assumes that the lending thread blocks on the completion
5936 * of this thread.
5938 * Note 1: for use by ppm only.
5940 * Note 2: On failing to get the lock immediately, we search lock_loan list
5941 * for curthread (as borrower of the lock). On a hit, we check that the
5942 * lending thread already owns the lock we want. It is safe to compare
5943 * devi_busy_thread and thread id of the lender because in the == case (the
5944 * only one we care about) we know that the owner is blocked. Similarly,
5945 * If we find that curthread isn't registered as a lock borrower, it is safe
5946 * to use the blocking call (ndi_devi_enter) because we know that if we
5947 * weren't already listed as a borrower (upstream on the call stack) we won't
5948 * become one.
5950 void
5951 pm_lock_power_single(dev_info_t *dip, int *circp)
5953 lock_loan_t *cur;
5955 /* if the lock is available, we are done. */
5956 if (ndi_devi_tryenter(dip, circp))
5957 return;
5959 mutex_enter(&pm_loan_lock);
5960 /* see if our thread is registered as a lock borrower. */
5961 for (cur = lock_loan_head.pmlk_next; cur; cur = cur->pmlk_next)
5962 if (cur->pmlk_borrower == curthread)
5963 break;
5964 mutex_exit(&pm_loan_lock);
5966 /* if this thread not already registered, it is safe to block */
5967 if (cur == NULL)
5968 ndi_devi_enter(dip, circp);
5969 else {
5970 /* registered: does lender own the lock we want? */
5971 if (cur->pmlk_lender == DEVI(dip)->devi_busy_thread) {
5972 ASSERT(cur->pmlk_dip == NULL || cur->pmlk_dip == dip);
5973 cur->pmlk_dip = dip;
5974 } else /* no: just block for it */
5975 ndi_devi_enter(dip, circp);
5981 * Drop the lock on the device's power state. See comment for
5982 * pm_lock_power_single() for special implementation considerations.
5984 * Note: for use by ppm only.
5986 void
5987 pm_unlock_power_single(dev_info_t *dip, int circ)
5989 lock_loan_t *cur;
5991 /* optimization: mutex not needed to check empty list */
5992 if (lock_loan_head.pmlk_next == NULL) {
5993 ndi_devi_exit(dip, circ);
5994 return;
5997 mutex_enter(&pm_loan_lock);
5998 /* see if our thread is registered as a lock borrower. */
5999 for (cur = lock_loan_head.pmlk_next; cur; cur = cur->pmlk_next)
6000 if (cur->pmlk_borrower == curthread)
6001 break;
6002 mutex_exit(&pm_loan_lock);
6004 if (cur == NULL || cur->pmlk_dip != dip)
6005 /* we acquired the lock directly, so return it */
6006 ndi_devi_exit(dip, circ);
6010 * Try to take the lock for changing the power level of a component.
6012 * Note: for use by ppm only.
6015 pm_try_locking_power_single(dev_info_t *dip, int *circp)
6017 return (ndi_devi_tryenter(dip, circp));
6020 #ifdef DEBUG
6022 * The following are used only to print out data structures for debugging
6024 void
6025 prdeps(char *msg)
6028 pm_pdr_t *rp;
6029 int i;
6031 pm_log("pm_dep_head %s %p\n", msg, (void *)pm_dep_head);
6032 for (rp = pm_dep_head; rp; rp = rp->pdr_next) {
6033 pm_log("%p: %s keeper %s, kept %s, kept count %d, next %p\n",
6034 (void *)rp, (rp->pdr_isprop ? "property" : "device"),
6035 rp->pdr_keeper, rp->pdr_kept, rp->pdr_kept_count,
6036 (void *)rp->pdr_next);
6037 if (rp->pdr_kept_count != 0) {
6038 pm_log("kept list = ");
6039 i = 0;
6040 while (i < rp->pdr_kept_count) {
6041 pm_log("%s ", rp->pdr_kept_paths[i]);
6042 i++;
6044 pm_log("\n");
6049 void
6050 pr_noinvol(char *hdr)
6052 pm_noinvol_t *ip;
6054 pm_log("%s\n", hdr);
6055 rw_enter(&pm_noinvol_rwlock, RW_READER);
6056 for (ip = pm_noinvol_head; ip; ip = ip->ni_next)
6057 pm_log("\tmaj %d, flags %x, noinvolpm %d %s\n",
6058 ip->ni_major, ip->ni_flags, ip->ni_noinvolpm, ip->ni_path);
6059 rw_exit(&pm_noinvol_rwlock);
6061 #endif
6064 * Attempt to apply the thresholds indicated by rp to the node specified by
6065 * dip.
6067 void
6068 pm_apply_recorded_thresh(dev_info_t *dip, pm_thresh_rec_t *rp)
6070 PMD_FUNC(pmf, "apply_recorded_thresh")
6071 int i, j;
6072 int comps = PM_NUMCMPTS(dip);
6073 struct pm_component *cp;
6074 pm_pte_t *ep;
6075 int pm_valid_thresh(dev_info_t *, pm_thresh_rec_t *);
6077 PMD(PMD_THRESH, ("%s: part: %s@%s(%s#%d), rp %p, %s\n", pmf,
6078 PM_DEVICE(dip), (void *)rp, rp->ptr_physpath))
6079 PM_LOCK_DIP(dip);
6080 if (!PM_GET_PM_INFO(dip) || PM_ISBC(dip) || !pm_valid_thresh(dip, rp)) {
6081 PMD(PMD_FAIL, ("%s: part: %s@%s(%s#%d) PM_GET_PM_INFO %p\n",
6082 pmf, PM_DEVICE(dip), (void*)PM_GET_PM_INFO(dip)))
6083 PMD(PMD_FAIL, ("%s: part: %s@%s(%s#%d) PM_ISBC %d\n",
6084 pmf, PM_DEVICE(dip), PM_ISBC(dip)))
6085 PMD(PMD_FAIL, ("%s: part: %s@%s(%s#%d) pm_valid_thresh %d\n",
6086 pmf, PM_DEVICE(dip), pm_valid_thresh(dip, rp)))
6087 PM_UNLOCK_DIP(dip);
6088 return;
6091 ep = rp->ptr_entries;
6093 * Here we do the special case of a device threshold
6095 if (rp->ptr_numcomps == 0) { /* PM_SET_DEVICE_THRESHOLD product */
6096 ASSERT(ep && ep->pte_numthresh == 1);
6097 PMD(PMD_THRESH, ("%s: set dev thr %s@%s(%s#%d) to 0x%x\n",
6098 pmf, PM_DEVICE(dip), ep->pte_thresh[0]))
6099 PM_UNLOCK_DIP(dip);
6100 pm_set_device_threshold(dip, ep->pte_thresh[0], PMC_DEV_THRESH);
6101 if (PM_SCANABLE(dip))
6102 pm_rescan(dip);
6103 return;
6105 for (i = 0; i < comps; i++) {
6106 cp = PM_CP(dip, i);
6107 for (j = 0; j < ep->pte_numthresh; j++) {
6108 PMD(PMD_THRESH, ("%s: set thr %d for %s@%s(%s#%d)[%d] "
6109 "to %x\n", pmf, j, PM_DEVICE(dip),
6110 i, ep->pte_thresh[j]))
6111 cp->pmc_comp.pmc_thresh[j + 1] = ep->pte_thresh[j];
6113 ep++;
6115 DEVI(dip)->devi_pm_flags &= PMC_THRESH_NONE;
6116 DEVI(dip)->devi_pm_flags |= PMC_COMP_THRESH;
6117 PM_UNLOCK_DIP(dip);
6119 if (PM_SCANABLE(dip))
6120 pm_rescan(dip);
6124 * Returns true if the threshold specified by rp could be applied to dip
6125 * (that is, the number of components and transitions are the same)
6128 pm_valid_thresh(dev_info_t *dip, pm_thresh_rec_t *rp)
6130 PMD_FUNC(pmf, "valid_thresh")
6131 int comps, i;
6132 pm_component_t *cp;
6133 pm_pte_t *ep;
6135 if (!PM_GET_PM_INFO(dip) || PM_ISBC(dip)) {
6136 PMD(PMD_ERROR, ("%s: %s: no pm_info or BC\n", pmf,
6137 rp->ptr_physpath))
6138 return (0);
6141 * Special case: we represent the PM_SET_DEVICE_THRESHOLD case by
6142 * an entry with numcomps == 0, (since we don't know how many
6143 * components there are in advance). This is always a valid
6144 * spec.
6146 if (rp->ptr_numcomps == 0) {
6147 ASSERT(rp->ptr_entries && rp->ptr_entries->pte_numthresh == 1);
6148 return (1);
6150 if (rp->ptr_numcomps != (comps = PM_NUMCMPTS(dip))) {
6151 PMD(PMD_ERROR, ("%s: comp # mm (dip %d cmd %d) for %s\n",
6152 pmf, PM_NUMCMPTS(dip), rp->ptr_numcomps, rp->ptr_physpath))
6153 return (0);
6155 ep = rp->ptr_entries;
6156 for (i = 0; i < comps; i++) {
6157 cp = PM_CP(dip, i);
6158 if ((ep + i)->pte_numthresh !=
6159 cp->pmc_comp.pmc_numlevels - 1) {
6160 PMD(PMD_ERROR, ("%s: %s[%d]: thresh=%d, record=%d\n",
6161 pmf, rp->ptr_physpath, i,
6162 cp->pmc_comp.pmc_numlevels - 1,
6163 (ep + i)->pte_numthresh))
6164 return (0);
6167 return (1);
6171 * Remove any recorded threshold for device physpath
6172 * We know there will be at most one.
6174 void
6175 pm_unrecord_threshold(char *physpath)
6177 pm_thresh_rec_t *pptr, *ptr;
6179 rw_enter(&pm_thresh_rwlock, RW_WRITER);
6180 for (pptr = NULL, ptr = pm_thresh_head; ptr; ptr = ptr->ptr_next) {
6181 if (strcmp(physpath, ptr->ptr_physpath) == 0) {
6182 if (pptr) {
6183 pptr->ptr_next = ptr->ptr_next;
6184 } else {
6185 ASSERT(pm_thresh_head == ptr);
6186 pm_thresh_head = ptr->ptr_next;
6188 kmem_free(ptr, ptr->ptr_size);
6189 break;
6191 pptr = ptr;
6193 rw_exit(&pm_thresh_rwlock);
6197 * Discard all recorded thresholds. We are returning to the default pm state.
6199 void
6200 pm_discard_thresholds(void)
6202 pm_thresh_rec_t *rp;
6203 rw_enter(&pm_thresh_rwlock, RW_WRITER);
6204 while (pm_thresh_head) {
6205 rp = pm_thresh_head;
6206 pm_thresh_head = rp->ptr_next;
6207 kmem_free(rp, rp->ptr_size);
6209 rw_exit(&pm_thresh_rwlock);
6213 * Discard all recorded dependencies. We are returning to the default pm state.
6215 void
6216 pm_discard_dependencies(void)
6218 pm_pdr_t *rp;
6219 int i;
6220 size_t length;
6222 #ifdef DEBUG
6223 if (pm_debug & PMD_DEP)
6224 prdeps("Before discard\n");
6225 #endif
6226 ddi_walk_devs(ddi_root_node(), pm_discard_dep_walk, NULL);
6228 #ifdef DEBUG
6229 if (pm_debug & PMD_DEP)
6230 prdeps("After discard\n");
6231 #endif
6232 while (pm_dep_head) {
6233 rp = pm_dep_head;
6234 if (!rp->pdr_isprop) {
6235 ASSERT(rp->pdr_satisfied == 0);
6236 ASSERT(pm_unresolved_deps);
6237 pm_unresolved_deps--;
6238 } else {
6239 ASSERT(pm_prop_deps);
6240 pm_prop_deps--;
6242 pm_dep_head = rp->pdr_next;
6243 if (rp->pdr_kept_count) {
6244 for (i = 0; i < rp->pdr_kept_count; i++) {
6245 length = strlen(rp->pdr_kept_paths[i]) + 1;
6246 kmem_free(rp->pdr_kept_paths[i], length);
6248 kmem_free(rp->pdr_kept_paths,
6249 rp->pdr_kept_count * sizeof (char **));
6251 kmem_free(rp, rp->pdr_size);
6256 static int
6257 pm_discard_dep_walk(dev_info_t *dip, void *arg)
6259 _NOTE(ARGUNUSED(arg))
6260 char *pathbuf;
6262 if (PM_GET_PM_INFO(dip) == NULL)
6263 return (DDI_WALK_CONTINUE);
6264 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
6265 (void) ddi_pathname(dip, pathbuf);
6266 pm_free_keeper(pathbuf, 0);
6267 kmem_free(pathbuf, MAXPATHLEN);
6268 return (DDI_WALK_CONTINUE);
6271 static int
6272 pm_kept_walk(dev_info_t *dip, void *arg)
6274 _NOTE(ARGUNUSED(arg))
6275 char *pathbuf;
6277 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
6278 (void) ddi_pathname(dip, pathbuf);
6279 (void) pm_kept(pathbuf);
6280 kmem_free(pathbuf, MAXPATHLEN);
6282 return (DDI_WALK_CONTINUE);
6285 static int
6286 pm_keeper_walk(dev_info_t *dip, void *arg)
6288 _NOTE(ARGUNUSED(arg))
6289 char *pathbuf;
6291 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
6292 (void) ddi_pathname(dip, pathbuf);
6293 (void) pm_keeper(pathbuf);
6294 kmem_free(pathbuf, MAXPATHLEN);
6296 return (DDI_WALK_CONTINUE);
6299 static char *
6300 pdw_type_decode(int type)
6302 switch (type) {
6303 case PM_DEP_WK_POWER_ON:
6304 return ("power on");
6305 case PM_DEP_WK_POWER_OFF:
6306 return ("power off");
6307 case PM_DEP_WK_DETACH:
6308 return ("detach");
6309 case PM_DEP_WK_REMOVE_DEP:
6310 return ("remove dep");
6311 case PM_DEP_WK_BRINGUP_SELF:
6312 return ("bringup self");
6313 case PM_DEP_WK_RECORD_KEEPER:
6314 return ("add dependent");
6315 case PM_DEP_WK_RECORD_KEEPER_PROP:
6316 return ("add dependent property");
6317 case PM_DEP_WK_KEPT:
6318 return ("kept");
6319 case PM_DEP_WK_KEEPER:
6320 return ("keeper");
6321 case PM_DEP_WK_ATTACH:
6322 return ("attach");
6323 case PM_DEP_WK_CHECK_KEPT:
6324 return ("check kept");
6325 case PM_DEP_WK_CPR_SUSPEND:
6326 return ("suspend");
6327 case PM_DEP_WK_CPR_RESUME:
6328 return ("resume");
6329 default:
6330 return ("unknown");
6335 static void
6336 pm_rele_dep(char *keeper)
6338 PMD_FUNC(pmf, "rele_dep")
6339 pm_pdr_t *dp;
6340 char *kept_path = NULL;
6341 dev_info_t *kept = NULL;
6342 int count = 0;
6344 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
6345 if (strcmp(dp->pdr_keeper, keeper) != 0)
6346 continue;
6347 for (count = 0; count < dp->pdr_kept_count; count++) {
6348 kept_path = dp->pdr_kept_paths[count];
6349 if (kept_path == NULL)
6350 continue;
6351 kept = pm_name_to_dip(kept_path, 1);
6352 if (kept) {
6353 PMD(PMD_KEEPS, ("%s: release kept=%s@%s(%s#%d) "
6354 "of keeper=%s\n", pmf, PM_DEVICE(kept),
6355 keeper))
6356 ASSERT(DEVI(kept)->devi_pm_kidsupcnt > 0);
6357 pm_rele_power(kept);
6358 ddi_release_devi(kept);
6365 * Called when we are just released from direct PM. Bring ourself up
6366 * if our keeper is up since dependency is not honored while a kept
6367 * device is under direct PM.
6369 static void
6370 pm_bring_self_up(char *keptpath)
6372 PMD_FUNC(pmf, "bring_self_up")
6373 dev_info_t *kept;
6374 dev_info_t *keeper;
6375 pm_pdr_t *dp;
6376 int i, j;
6377 int up = 0, circ;
6379 kept = pm_name_to_dip(keptpath, 1);
6380 if (kept == NULL)
6381 return;
6382 PMD(PMD_KEEPS, ("%s: kept=%s@%s(%s#%d)\n", pmf, PM_DEVICE(kept)))
6383 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
6384 if (dp->pdr_kept_count == 0)
6385 continue;
6386 for (i = 0; i < dp->pdr_kept_count; i++) {
6387 if (strcmp(dp->pdr_kept_paths[i], keptpath) != 0)
6388 continue;
6389 keeper = pm_name_to_dip(dp->pdr_keeper, 1);
6390 if (keeper) {
6391 PMD(PMD_KEEPS, ("%s: keeper=%s@%s(%s#%d)\n",
6392 pmf, PM_DEVICE(keeper)))
6393 PM_LOCK_POWER(keeper, &circ);
6394 for (j = 0; j < PM_NUMCMPTS(keeper);
6395 j++) {
6396 if (PM_CURPOWER(keeper, j)) {
6397 PMD(PMD_KEEPS, ("%s: comp="
6398 "%d is up\n", pmf, j))
6399 up++;
6402 if (up) {
6403 if (PM_SKBU(kept))
6404 DEVI(kept)->devi_pm_flags &=
6405 ~PMC_SKIP_BRINGUP;
6406 bring_pmdep_up(kept, 1);
6408 PM_UNLOCK_POWER(keeper, circ);
6409 ddi_release_devi(keeper);
6413 ddi_release_devi(kept);
6416 static void
6417 pm_process_dep_request(pm_dep_wk_t *work)
6419 PMD_FUNC(pmf, "dep_req")
6420 int ret;
6422 PMD(PMD_DEP, ("%s: work=%s\n", pmf,
6423 pdw_type_decode(work->pdw_type)))
6424 PMD(PMD_DEP, ("%s: keeper=%s, kept=%s\n", pmf,
6425 (work->pdw_keeper ? work->pdw_keeper : "NULL"),
6426 (work->pdw_kept ? work->pdw_kept : "NULL")))
6428 switch (work->pdw_type) {
6429 case PM_DEP_WK_POWER_ON:
6430 /* Bring up the kept devices and put a hold on them */
6431 bring_wekeeps_up(work->pdw_keeper);
6432 break;
6433 case PM_DEP_WK_POWER_OFF:
6434 /* Release the kept devices */
6435 pm_rele_dep(work->pdw_keeper);
6436 break;
6437 case PM_DEP_WK_DETACH:
6438 pm_free_keeps(work->pdw_keeper, work->pdw_pwr);
6439 break;
6440 case PM_DEP_WK_REMOVE_DEP:
6441 pm_discard_dependencies();
6442 break;
6443 case PM_DEP_WK_BRINGUP_SELF:
6445 * We deferred satisfying our dependency till now, so satisfy
6446 * it again and bring ourselves up.
6448 pm_bring_self_up(work->pdw_kept);
6449 break;
6450 case PM_DEP_WK_RECORD_KEEPER:
6451 (void) pm_record_keeper(work->pdw_kept, work->pdw_keeper, 0);
6452 ddi_walk_devs(ddi_root_node(), pm_kept_walk, NULL);
6453 ddi_walk_devs(ddi_root_node(), pm_keeper_walk, NULL);
6454 break;
6455 case PM_DEP_WK_RECORD_KEEPER_PROP:
6456 (void) pm_record_keeper(work->pdw_kept, work->pdw_keeper, 1);
6457 ddi_walk_devs(ddi_root_node(), pm_keeper_walk, NULL);
6458 ddi_walk_devs(ddi_root_node(), pm_kept_walk, NULL);
6459 break;
6460 case PM_DEP_WK_KEPT:
6461 ret = pm_kept(work->pdw_kept);
6462 PMD(PMD_DEP, ("%s: PM_DEP_WK_KEPT: pm_kept returns %d\n", pmf,
6463 ret))
6464 break;
6465 case PM_DEP_WK_KEEPER:
6466 ret = pm_keeper(work->pdw_keeper);
6467 PMD(PMD_DEP, ("%s: PM_DEP_WK_KEEPER: pm_keeper returns %d\n",
6468 pmf, ret))
6469 break;
6470 case PM_DEP_WK_ATTACH:
6471 ret = pm_keeper(work->pdw_keeper);
6472 PMD(PMD_DEP, ("%s: PM_DEP_WK_ATTACH: pm_keeper returns %d\n",
6473 pmf, ret))
6474 ret = pm_kept(work->pdw_kept);
6475 PMD(PMD_DEP, ("%s: PM_DEP_WK_ATTACH: pm_kept returns %d\n",
6476 pmf, ret))
6477 break;
6478 case PM_DEP_WK_CHECK_KEPT:
6479 ret = pm_is_kept(work->pdw_kept);
6480 PMD(PMD_DEP, ("%s: PM_DEP_WK_CHECK_KEPT: kept=%s, ret=%d\n",
6481 pmf, work->pdw_kept, ret))
6482 break;
6483 case PM_DEP_WK_CPR_SUSPEND:
6484 pm_discard_dependencies();
6485 break;
6486 case PM_DEP_WK_CPR_RESUME:
6487 ddi_walk_devs(ddi_root_node(), pm_kept_walk, NULL);
6488 ddi_walk_devs(ddi_root_node(), pm_keeper_walk, NULL);
6489 break;
6490 default:
6491 ASSERT(0);
6492 break;
6495 * Free the work structure if the requester is not waiting
6496 * Otherwise it is the requester's responsiblity to free it.
6498 if (!work->pdw_wait) {
6499 if (work->pdw_keeper)
6500 kmem_free(work->pdw_keeper,
6501 strlen(work->pdw_keeper) + 1);
6502 if (work->pdw_kept)
6503 kmem_free(work->pdw_kept, strlen(work->pdw_kept) + 1);
6504 kmem_free(work, sizeof (pm_dep_wk_t));
6505 } else {
6507 * Notify requester if it is waiting for it.
6509 work->pdw_ret = ret;
6510 work->pdw_done = 1;
6511 cv_signal(&work->pdw_cv);
6516 * Process PM dependency requests.
6518 static void
6519 pm_dep_thread(void)
6521 pm_dep_wk_t *work;
6522 callb_cpr_t cprinfo;
6524 CALLB_CPR_INIT(&cprinfo, &pm_dep_thread_lock, callb_generic_cpr,
6525 "pm_dep_thread");
6526 for (;;) {
6527 mutex_enter(&pm_dep_thread_lock);
6528 if (pm_dep_thread_workq == NULL) {
6529 CALLB_CPR_SAFE_BEGIN(&cprinfo);
6530 cv_wait(&pm_dep_thread_cv, &pm_dep_thread_lock);
6531 CALLB_CPR_SAFE_END(&cprinfo, &pm_dep_thread_lock);
6533 work = pm_dep_thread_workq;
6534 pm_dep_thread_workq = work->pdw_next;
6535 if (pm_dep_thread_tail == work)
6536 pm_dep_thread_tail = work->pdw_next;
6537 mutex_exit(&pm_dep_thread_lock);
6538 pm_process_dep_request(work);
6541 /*NOTREACHED*/
6545 * Set the power level of the indicated device to unknown (if it is not a
6546 * backwards compatible device), as it has just been resumed, and it won't
6547 * know if the power was removed or not. Adjust parent's kidsupcnt if necessary.
6549 void
6550 pm_forget_power_level(dev_info_t *dip)
6552 dev_info_t *pdip = ddi_get_parent(dip);
6553 int i, count = 0;
6555 if (!PM_ISBC(dip)) {
6556 for (i = 0; i < PM_NUMCMPTS(dip); i++)
6557 count += (PM_CURPOWER(dip, i) == 0);
6559 if (count && pdip && !PM_WANTS_NOTIFICATION(pdip))
6560 e_pm_hold_rele_power(pdip, count);
6563 * Count this as a power cycle if we care
6565 if (DEVI(dip)->devi_pm_volpmd &&
6566 PM_CP(dip, 0)->pmc_cur_pwr == 0)
6567 DEVI(dip)->devi_pm_volpmd = 0;
6568 for (i = 0; i < PM_NUMCMPTS(dip); i++)
6569 e_pm_set_cur_pwr(dip, PM_CP(dip, i), PM_LEVEL_UNKNOWN);
6574 * This function advises the caller whether it should make a power-off
6575 * transition at this time or not. If the transition is not advised
6576 * at this time, the time that the next power-off transition can
6577 * be made from now is returned through "intervalp" pointer.
6578 * This function returns:
6580 * 1 power-off advised
6581 * 0 power-off not advised, intervalp will point to seconds from
6582 * now that a power-off is advised. If it is passed the number
6583 * of years that policy specifies the device should last,
6584 * a large number is returned as the time interval.
6585 * -1 error
6588 pm_trans_check(struct pm_trans_data *datap, time_t *intervalp)
6590 PMD_FUNC(pmf, "pm_trans_check")
6591 char dbuf[DC_SCSI_MFR_LEN];
6592 struct pm_scsi_cycles *scp;
6593 int service_years, service_weeks, full_years;
6594 time_t now, service_seconds, tdiff;
6595 time_t within_year, when_allowed;
6596 char *ptr;
6597 int lower_bound_cycles, upper_bound_cycles, cycles_allowed;
6598 int cycles_diff, cycles_over;
6599 struct pm_smart_count *smart_p;
6601 if (datap == NULL) {
6602 PMD(PMD_TCHECK, ("%s: NULL data pointer!\n", pmf))
6603 return (-1);
6606 if (datap->format == DC_SCSI_FORMAT) {
6608 * Power cycles of the scsi drives are distributed
6609 * over 5 years with the following percentage ratio:
6611 * 30%, 25%, 20%, 15%, and 10%
6613 * The power cycle quota for each year is distributed
6614 * linearly through out the year. The equation for
6615 * determining the expected cycles is:
6617 * e = a * (n / y)
6619 * e = expected cycles
6620 * a = allocated cycles for this year
6621 * n = number of seconds since beginning of this year
6622 * y = number of seconds in a year
6624 * Note that beginning of the year starts the day that
6625 * the drive has been put on service.
6627 * If the drive has passed its expected cycles, we
6628 * can determine when it can start to power cycle
6629 * again to keep it on track to meet the 5-year
6630 * life expectancy. The equation for determining
6631 * when to power cycle is:
6633 * w = y * (c / a)
6635 * w = when it can power cycle again
6636 * y = number of seconds in a year
6637 * c = current number of cycles
6638 * a = allocated cycles for the year
6641 char pcnt[DC_SCSI_NPY] = { 30, 55, 75, 90, 100 };
6643 scp = &datap->un.scsi_cycles;
6644 PMD(PMD_TCHECK, ("%s: format=%d, lifemax=%d, ncycles=%d, "
6645 "svc_date=%s, svc_flag=%d\n", pmf, datap->format,
6646 scp->lifemax, scp->ncycles, scp->svc_date, scp->flag))
6647 if (scp->ncycles < 0 || scp->flag != 0) {
6648 PMD(PMD_TCHECK, ("%s: ncycles < 0 || flag != 0\n", pmf))
6649 return (-1);
6652 if (scp->ncycles > scp->lifemax) {
6653 *intervalp = (LONG_MAX / hz);
6654 return (0);
6658 * convert service date to time_t
6660 bcopy(scp->svc_date, dbuf, DC_SCSI_YEAR_LEN);
6661 dbuf[DC_SCSI_YEAR_LEN] = '\0';
6662 ptr = dbuf;
6663 service_years = stoi(&ptr) - EPOCH_YEAR;
6664 bcopy(&scp->svc_date[DC_SCSI_YEAR_LEN], dbuf,
6665 DC_SCSI_WEEK_LEN);
6666 dbuf[DC_SCSI_WEEK_LEN] = '\0';
6669 * scsi standard does not specify WW data,
6670 * could be (00-51) or (01-52)
6672 ptr = dbuf;
6673 service_weeks = stoi(&ptr);
6674 if (service_years < 0 ||
6675 service_weeks < 0 || service_weeks > 52) {
6676 PMD(PMD_TCHECK, ("%s: service year %d and week %d\n",
6677 pmf, service_years, service_weeks))
6678 return (-1);
6682 * calculate service date in seconds-since-epoch,
6683 * adding one day for each leap-year.
6685 * (years-since-epoch + 2) fixes integer truncation,
6686 * example: (8) leap-years during [1972, 2000]
6687 * (2000 - 1970) = 30; and (30 + 2) / 4 = 8;
6689 service_seconds = (service_years * DC_SPY) +
6690 (service_weeks * DC_SPW) +
6691 (((service_years + 2) / 4) * DC_SPD);
6693 now = gethrestime_sec();
6695 * since the granularity of 'svc_date' is day not second,
6696 * 'now' should be rounded up to full day.
6698 now = ((now + DC_SPD -1) / DC_SPD) * DC_SPD;
6699 if (service_seconds > now) {
6700 PMD(PMD_TCHECK, ("%s: service date (%ld) later "
6701 "than now (%ld)!\n", pmf, service_seconds, now))
6702 return (-1);
6705 tdiff = now - service_seconds;
6706 PMD(PMD_TCHECK, ("%s: age is %ld sec\n", pmf, tdiff))
6709 * NOTE - Leap years are not considered in the calculations
6710 * below.
6712 full_years = (tdiff / DC_SPY);
6713 if ((full_years >= DC_SCSI_NPY) &&
6714 (scp->ncycles <= scp->lifemax))
6715 return (1);
6718 * Determine what is the normal cycle usage for the
6719 * device at the beginning and the end of this year.
6721 lower_bound_cycles = (!full_years) ? 0 :
6722 ((scp->lifemax * pcnt[full_years - 1]) / 100);
6723 upper_bound_cycles = (scp->lifemax * pcnt[full_years]) / 100;
6725 if (scp->ncycles <= lower_bound_cycles)
6726 return (1);
6729 * The linear slope that determines how many cycles
6730 * are allowed this year is number of seconds
6731 * passed this year over total number of seconds in a year.
6733 cycles_diff = (upper_bound_cycles - lower_bound_cycles);
6734 within_year = (tdiff % DC_SPY);
6735 cycles_allowed = lower_bound_cycles +
6736 (((uint64_t)cycles_diff * (uint64_t)within_year) / DC_SPY);
6737 PMD(PMD_TCHECK, ("%s: lived %d yrs and %ld secs\n", pmf,
6738 full_years, within_year))
6739 PMD(PMD_TCHECK, ("%s: # of cycles allowed %d\n", pmf,
6740 cycles_allowed))
6742 if (scp->ncycles <= cycles_allowed)
6743 return (1);
6746 * The transition is not advised now but we can
6747 * determine when the next transition can be made.
6749 * Depending on how many cycles the device has been
6750 * over-used, we may need to skip years with
6751 * different percentage quota in order to determine
6752 * when the next transition can be made.
6754 cycles_over = (scp->ncycles - lower_bound_cycles);
6755 while (cycles_over > cycles_diff) {
6756 full_years++;
6757 if (full_years >= DC_SCSI_NPY) {
6758 *intervalp = (LONG_MAX / hz);
6759 return (0);
6761 cycles_over -= cycles_diff;
6762 lower_bound_cycles = upper_bound_cycles;
6763 upper_bound_cycles =
6764 (scp->lifemax * pcnt[full_years]) / 100;
6765 cycles_diff = (upper_bound_cycles - lower_bound_cycles);
6769 * The linear slope that determines when the next transition
6770 * can be made is the relative position of used cycles within a
6771 * year over total number of cycles within that year.
6773 when_allowed = service_seconds + (full_years * DC_SPY) +
6774 (((uint64_t)DC_SPY * (uint64_t)cycles_over) / cycles_diff);
6775 *intervalp = (when_allowed - now);
6776 if (*intervalp > (LONG_MAX / hz))
6777 *intervalp = (LONG_MAX / hz);
6778 PMD(PMD_TCHECK, ("%s: no cycle is allowed in %ld secs\n", pmf,
6779 *intervalp))
6780 return (0);
6781 } else if (datap->format == DC_SMART_FORMAT) {
6783 * power cycles of SATA disks are reported from SMART
6784 * attributes.
6786 smart_p = &datap->un.smart_count;
6787 if (smart_p->consumed >= smart_p->allowed) {
6788 *intervalp = (LONG_MAX / hz);
6789 PMD(PMD_TCHECK, ("%s: exceeded lifemax cycles.\n", pmf))
6790 return (0);
6791 } else
6792 return (1);
6795 PMD(PMD_TCHECK, ("%s: unknown format!\n", pmf))
6796 return (-1);
6800 * Nexus drivers call into pm framework to indicate which child driver is about
6801 * to be installed. In some platforms, ppm may need to configure the hardware
6802 * for successful installation of a driver.
6805 pm_init_child(dev_info_t *dip)
6807 power_req_t power_req;
6809 ASSERT(ddi_binding_name(dip));
6810 ASSERT(ddi_get_name_addr(dip));
6811 pm_ppm_claim(dip);
6812 if (pm_ppm_claimed(dip)) { /* if ppm driver claims the node */
6813 power_req.request_type = PMR_PPM_INIT_CHILD;
6814 power_req.req.ppm_config_req.who = dip;
6815 ASSERT(PPM(dip) != NULL);
6816 return (pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER, &power_req,
6817 NULL));
6818 } else {
6819 #ifdef DEBUG
6820 /* pass it to the default handler so we can debug things */
6821 power_req.request_type = PMR_PPM_INIT_CHILD;
6822 power_req.req.ppm_config_req.who = dip;
6823 (void) pm_ctlops(NULL, dip,
6824 DDI_CTLOPS_POWER, &power_req, NULL);
6825 #endif
6827 return (DDI_SUCCESS);
6831 * Bring parent of a node that is about to be probed up to full power, and
6832 * arrange for it to stay up until pm_post_probe() or pm_post_attach() decide
6833 * it is time to let it go down again
6835 void
6836 pm_pre_probe(dev_info_t *dip, pm_ppm_cookie_t *cp)
6838 int result;
6839 power_req_t power_req;
6841 bzero(cp, sizeof (*cp));
6842 cp->ppc_dip = dip;
6844 pm_ppm_claim(dip);
6845 if (pm_ppm_claimed(dip)) { /* if ppm driver claims the node */
6846 power_req.request_type = PMR_PPM_PRE_PROBE;
6847 power_req.req.ppm_config_req.who = dip;
6848 ASSERT(PPM(dip) != NULL);
6849 (void) pm_ctlops(PPM(dip), dip,
6850 DDI_CTLOPS_POWER, &power_req, &result);
6851 cp->ppc_ppm = PPM(dip);
6852 } else {
6853 #ifdef DEBUG
6854 /* pass it to the default handler so we can debug things */
6855 power_req.request_type = PMR_PPM_PRE_PROBE;
6856 power_req.req.ppm_config_req.who = dip;
6857 (void) pm_ctlops(NULL, dip,
6858 DDI_CTLOPS_POWER, &power_req, &result);
6859 #endif
6860 cp->ppc_ppm = NULL;
6865 pm_pre_config(dev_info_t *dip, char *devnm)
6867 PMD_FUNC(pmf, "pre_config")
6868 int ret;
6870 if (MDI_VHCI(dip)) {
6871 PMD(PMD_SET, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
6872 ret = mdi_power(dip, MDI_PM_PRE_CONFIG, NULL, devnm, 0);
6873 return (ret == MDI_SUCCESS ? DDI_SUCCESS : DDI_FAILURE);
6874 } else if (!PM_GET_PM_INFO(dip))
6875 return (DDI_SUCCESS);
6877 PMD(PMD_SET, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
6878 pm_hold_power(dip);
6879 ret = pm_all_to_normal(dip, PM_CANBLOCK_BLOCK);
6880 if (ret != DDI_SUCCESS)
6881 pm_rele_power(dip);
6882 return (ret);
6886 * This routine is called by devfs during its walk to unconfigue a node.
6887 * If the call is due to auto mod_unloads and the dip is not at its
6888 * full power, we return DDI_FAILURE to terminate the walk, otherwise
6889 * return DDI_SUCCESS.
6892 pm_pre_unconfig(dev_info_t *dip, int flags, int *held, char *devnm)
6894 PMD_FUNC(pmf, "pre_unconfig")
6895 int ret;
6897 if (MDI_VHCI(dip)) {
6898 PMD(PMD_SET, ("%s: %s@%s(%s#%d), flags=%x\n", pmf,
6899 PM_DEVICE(dip), flags))
6900 ret = mdi_power(dip, MDI_PM_PRE_UNCONFIG, held, devnm, flags);
6901 return (ret == MDI_SUCCESS ? DDI_SUCCESS : DDI_FAILURE);
6902 } else if (!PM_GET_PM_INFO(dip))
6903 return (DDI_SUCCESS);
6905 PMD(PMD_SET, ("%s: %s@%s(%s#%d), flags=%x\n", pmf, PM_DEVICE(dip),
6906 flags))
6907 *held = 0;
6910 * If the dip is a leaf node, don't power it up.
6912 if (!ddi_get_child(dip))
6913 return (DDI_SUCCESS);
6916 * Do not power up the node if it is called due to auto-modunload.
6918 if ((flags & NDI_AUTODETACH) && !pm_all_at_normal(dip))
6919 return (DDI_FAILURE);
6921 pm_hold_power(dip);
6922 *held = 1;
6923 ret = pm_all_to_normal(dip, PM_CANBLOCK_BLOCK);
6924 if (ret != DDI_SUCCESS) {
6925 pm_rele_power(dip);
6926 *held = 0;
6928 return (ret);
6932 * Notify ppm of attach action. Parent is already held at full power by
6933 * probe action.
6935 void
6936 pm_pre_attach(dev_info_t *dip, pm_ppm_cookie_t *cp, ddi_attach_cmd_t cmd)
6938 static char *me = "pm_pre_attach";
6939 power_req_t power_req;
6940 int result;
6943 * Initialize and fill in the PPM cookie
6945 bzero(cp, sizeof (*cp));
6946 cp->ppc_cmd = (int)cmd;
6947 cp->ppc_ppm = PPM(dip);
6948 cp->ppc_dip = dip;
6951 * DDI_ATTACH and DDI_RESUME cmds need to call platform specific
6952 * Power Management stuff. DDI_RESUME also has to purge it's
6953 * powerlevel information.
6955 switch (cmd) {
6956 case DDI_ATTACH:
6957 if (cp->ppc_ppm) { /* if ppm driver claims the node */
6958 power_req.request_type = PMR_PPM_PRE_ATTACH;
6959 power_req.req.ppm_config_req.who = dip;
6960 ASSERT(PPM(dip));
6961 (void) pm_ctlops(cp->ppc_ppm, dip, DDI_CTLOPS_POWER,
6962 &power_req, &result);
6964 #ifdef DEBUG
6965 else {
6966 power_req.request_type = PMR_PPM_PRE_ATTACH;
6967 power_req.req.ppm_config_req.who = dip;
6968 (void) pm_ctlops(NULL, dip,
6969 DDI_CTLOPS_POWER, &power_req, &result);
6971 #endif
6972 break;
6973 case DDI_RESUME:
6974 pm_forget_power_level(dip);
6976 if (cp->ppc_ppm) { /* if ppm driver claims the node */
6977 power_req.request_type = PMR_PPM_PRE_RESUME;
6978 power_req.req.resume_req.who = cp->ppc_dip;
6979 power_req.req.resume_req.cmd =
6980 (ddi_attach_cmd_t)cp->ppc_cmd;
6981 ASSERT(PPM(cp->ppc_dip) == cp->ppc_ppm);
6982 (void) pm_ctlops(cp->ppc_ppm, cp->ppc_dip,
6983 DDI_CTLOPS_POWER, &power_req, &result);
6985 #ifdef DEBUG
6986 else {
6987 power_req.request_type = PMR_PPM_PRE_RESUME;
6988 power_req.req.resume_req.who = cp->ppc_dip;
6989 power_req.req.resume_req.cmd =
6990 (ddi_attach_cmd_t)cp->ppc_cmd;
6991 (void) pm_ctlops(NULL, cp->ppc_dip,
6992 DDI_CTLOPS_POWER, &power_req, &result);
6994 #endif
6995 break;
6997 case DDI_PM_RESUME:
6998 break;
7000 default:
7001 panic(me);
7006 * Nexus drivers call into pm framework to indicate which child driver is
7007 * being uninstalled. In some platforms, ppm may need to reconfigure the
7008 * hardware since the device driver is no longer installed.
7011 pm_uninit_child(dev_info_t *dip)
7013 power_req_t power_req;
7015 ASSERT(ddi_binding_name(dip));
7016 ASSERT(ddi_get_name_addr(dip));
7017 pm_ppm_claim(dip);
7018 if (pm_ppm_claimed(dip)) { /* if ppm driver claims the node */
7019 power_req.request_type = PMR_PPM_UNINIT_CHILD;
7020 power_req.req.ppm_config_req.who = dip;
7021 ASSERT(PPM(dip));
7022 return (pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER, &power_req,
7023 NULL));
7024 } else {
7025 #ifdef DEBUG
7026 /* pass it to the default handler so we can debug things */
7027 power_req.request_type = PMR_PPM_UNINIT_CHILD;
7028 power_req.req.ppm_config_req.who = dip;
7029 (void) pm_ctlops(NULL, dip, DDI_CTLOPS_POWER, &power_req, NULL);
7030 #endif
7032 return (DDI_SUCCESS);
7035 * Decrement kidsupcnt so scan can turn the parent back off if it is idle
7036 * Also notify ppm of result of probe if there is a ppm that cares
7038 void
7039 pm_post_probe(pm_ppm_cookie_t *cp, int ret, int probe_failed)
7041 _NOTE(ARGUNUSED(probe_failed))
7042 int result;
7043 power_req_t power_req;
7045 if (cp->ppc_ppm) { /* if ppm driver claims the node */
7046 power_req.request_type = PMR_PPM_POST_PROBE;
7047 power_req.req.ppm_config_req.who = cp->ppc_dip;
7048 power_req.req.ppm_config_req.result = ret;
7049 ASSERT(PPM(cp->ppc_dip) == cp->ppc_ppm);
7050 (void) pm_ctlops(cp->ppc_ppm, cp->ppc_dip, DDI_CTLOPS_POWER,
7051 &power_req, &result);
7053 #ifdef DEBUG
7054 else {
7055 power_req.request_type = PMR_PPM_POST_PROBE;
7056 power_req.req.ppm_config_req.who = cp->ppc_dip;
7057 power_req.req.ppm_config_req.result = ret;
7058 (void) pm_ctlops(NULL, cp->ppc_dip, DDI_CTLOPS_POWER,
7059 &power_req, &result);
7061 #endif
7064 void
7065 pm_post_config(dev_info_t *dip, char *devnm)
7067 PMD_FUNC(pmf, "post_config")
7069 if (MDI_VHCI(dip)) {
7070 PMD(PMD_SET, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
7071 (void) mdi_power(dip, MDI_PM_POST_CONFIG, NULL, devnm, 0);
7072 return;
7073 } else if (!PM_GET_PM_INFO(dip))
7074 return;
7076 PMD(PMD_SET, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
7077 pm_rele_power(dip);
7080 void
7081 pm_post_unconfig(dev_info_t *dip, int held, char *devnm)
7083 PMD_FUNC(pmf, "post_unconfig")
7085 if (MDI_VHCI(dip)) {
7086 PMD(PMD_SET, ("%s: %s@%s(%s#%d), held = %d\n", pmf,
7087 PM_DEVICE(dip), held))
7088 (void) mdi_power(dip, MDI_PM_POST_UNCONFIG, &held, devnm, 0);
7089 return;
7090 } else if (!PM_GET_PM_INFO(dip))
7091 return;
7093 PMD(PMD_SET, ("%s: %s@%s(%s#%d), held = %d\n", pmf, PM_DEVICE(dip),
7094 held))
7095 if (!held)
7096 return;
7098 * We have held power in pre_unconfig, release it here.
7100 pm_rele_power(dip);
7104 * Notify ppm of result of attach if there is a ppm that cares
7106 void
7107 pm_post_attach(pm_ppm_cookie_t *cp, int ret)
7109 int result;
7110 power_req_t power_req;
7111 dev_info_t *dip;
7113 if (cp->ppc_cmd != DDI_ATTACH)
7114 return;
7116 dip = cp->ppc_dip;
7118 if (ret == DDI_SUCCESS) {
7120 * Attach succeeded, so proceed to doing post-attach pm tasks
7122 if (PM_GET_PM_INFO(dip) == NULL)
7123 (void) pm_start(dip);
7124 } else {
7126 * Attach may have got pm started before failing
7128 pm_stop(dip);
7131 if (cp->ppc_ppm) { /* if ppm driver claims the node */
7132 power_req.request_type = PMR_PPM_POST_ATTACH;
7133 power_req.req.ppm_config_req.who = cp->ppc_dip;
7134 power_req.req.ppm_config_req.result = ret;
7135 ASSERT(PPM(cp->ppc_dip) == cp->ppc_ppm);
7136 (void) pm_ctlops(cp->ppc_ppm, cp->ppc_dip,
7137 DDI_CTLOPS_POWER, &power_req, &result);
7139 #ifdef DEBUG
7140 else {
7141 power_req.request_type = PMR_PPM_POST_ATTACH;
7142 power_req.req.ppm_config_req.who = cp->ppc_dip;
7143 power_req.req.ppm_config_req.result = ret;
7144 (void) pm_ctlops(NULL, cp->ppc_dip,
7145 DDI_CTLOPS_POWER, &power_req, &result);
7147 #endif
7151 * Notify ppm of attach action. Parent is already held at full power by
7152 * probe action.
7154 void
7155 pm_pre_detach(dev_info_t *dip, ddi_detach_cmd_t cmd, pm_ppm_cookie_t *cp)
7157 int result;
7158 power_req_t power_req;
7160 bzero(cp, sizeof (*cp));
7161 cp->ppc_dip = dip;
7162 cp->ppc_cmd = (int)cmd;
7164 switch (cmd) {
7165 case DDI_DETACH:
7166 pm_detaching(dip); /* suspend pm while detaching */
7167 if (pm_ppm_claimed(dip)) { /* if ppm driver claims node */
7168 power_req.request_type = PMR_PPM_PRE_DETACH;
7169 power_req.req.ppm_config_req.who = dip;
7170 ASSERT(PPM(dip));
7171 (void) pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER,
7172 &power_req, &result);
7173 cp->ppc_ppm = PPM(dip);
7174 } else {
7175 #ifdef DEBUG
7176 /* pass to the default handler so we can debug things */
7177 power_req.request_type = PMR_PPM_PRE_DETACH;
7178 power_req.req.ppm_config_req.who = dip;
7179 (void) pm_ctlops(NULL, dip,
7180 DDI_CTLOPS_POWER, &power_req, &result);
7181 #endif
7182 cp->ppc_ppm = NULL;
7184 break;
7186 default:
7187 break;
7192 * Dip is either a leaf node that exported "no-involuntary-power-cycles" prop.,
7193 * (if devi_pm_noinvol count is 0) or an ancestor of such a node. We need to
7194 * make an entry to record the details, which includes certain flag settings.
7196 static void
7197 pm_record_invol_path(char *path, int flags, int noinvolpm, int volpmd,
7198 int wasvolpmd, major_t major)
7200 PMD_FUNC(pmf, "record_invol_path")
7201 major_t pm_path_to_major(char *);
7202 size_t plen;
7203 pm_noinvol_t *ip, *np, *pp;
7204 pp = NULL;
7206 plen = strlen(path) + 1;
7207 np = kmem_zalloc(sizeof (*np), KM_SLEEP);
7208 np->ni_size = plen;
7209 np->ni_path = kmem_alloc(plen, KM_SLEEP);
7210 np->ni_noinvolpm = noinvolpm;
7211 np->ni_volpmd = volpmd;
7212 np->ni_wasvolpmd = wasvolpmd;
7213 np->ni_flags = flags;
7214 (void) strcpy(np->ni_path, path);
7216 * If we haven't actually seen the node attached, it is hard to figure
7217 * out its major. If we could hold the node by path, we would be much
7218 * happier here.
7220 if (major == DDI_MAJOR_T_NONE) {
7221 np->ni_major = pm_path_to_major(path);
7222 } else {
7223 np->ni_major = major;
7225 rw_enter(&pm_noinvol_rwlock, RW_WRITER);
7226 for (ip = pm_noinvol_head; ip; pp = ip, ip = ip->ni_next) {
7227 int comp = strcmp(path, ip->ni_path);
7228 if (comp < 0) {
7229 PMD(PMD_NOINVOL, ("%s: %s insert before %s\n",
7230 pmf, path, ip->ni_path))
7231 /* insert before current entry */
7232 np->ni_next = ip;
7233 if (pp) {
7234 pp->ni_next = np;
7235 } else {
7236 pm_noinvol_head = np;
7238 rw_exit(&pm_noinvol_rwlock);
7239 #ifdef DEBUG
7240 if (pm_debug & PMD_NOINVOL)
7241 pr_noinvol("record_invol_path exit0");
7242 #endif
7243 return;
7244 } else if (comp == 0) {
7245 panic("%s already in pm_noinvol list", path);
7249 * If we did not find an entry in the list that this should go before,
7250 * then it must go at the end
7252 if (pp) {
7253 PMD(PMD_NOINVOL, ("%s: %s append after %s\n", pmf, path,
7254 pp->ni_path))
7255 ASSERT(pp->ni_next == 0);
7256 pp->ni_next = np;
7257 } else {
7258 PMD(PMD_NOINVOL, ("%s: %s added to end-of-list\n", pmf, path))
7259 ASSERT(!pm_noinvol_head);
7260 pm_noinvol_head = np;
7262 rw_exit(&pm_noinvol_rwlock);
7263 #ifdef DEBUG
7264 if (pm_debug & PMD_NOINVOL)
7265 pr_noinvol("record_invol_path exit");
7266 #endif
7269 void
7270 pm_record_invol(dev_info_t *dip)
7272 char *pathbuf;
7273 int pm_all_components_off(dev_info_t *);
7274 int volpmd = (PM_NUMCMPTS(dip) > 0) && pm_all_components_off(dip);
7276 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
7277 (void) ddi_pathname(dip, pathbuf);
7279 pm_record_invol_path(pathbuf, (DEVI(dip)->devi_pm_flags &
7280 (PMC_NO_INVOL | PMC_CONSOLE_FB)), DEVI(dip)->devi_pm_noinvolpm,
7281 DEVI(dip)->devi_pm_volpmd, volpmd, PM_MAJOR(dip));
7284 * If this child's detach will be holding up its ancestors, then we
7285 * allow for an exception to that if all children of this type have
7286 * gone down voluntarily.
7287 * Now walk down the tree incrementing devi_pm_noinvolpm
7289 (void) pm_noinvol_update(PM_BP_NOINVOL_DETACH, 0, volpmd, pathbuf,
7290 dip);
7291 kmem_free(pathbuf, MAXPATHLEN);
7294 void
7295 pm_post_detach(pm_ppm_cookie_t *cp, int ret)
7297 dev_info_t *dip = cp->ppc_dip;
7298 int result;
7299 power_req_t power_req;
7301 switch (cp->ppc_cmd) {
7302 case DDI_DETACH:
7303 if (cp->ppc_ppm) { /* if ppm driver claims the node */
7304 power_req.request_type = PMR_PPM_POST_DETACH;
7305 power_req.req.ppm_config_req.who = cp->ppc_dip;
7306 power_req.req.ppm_config_req.result = ret;
7307 ASSERT(PPM(cp->ppc_dip) == cp->ppc_ppm);
7308 (void) pm_ctlops(cp->ppc_ppm, cp->ppc_dip,
7309 DDI_CTLOPS_POWER, &power_req, &result);
7311 #ifdef DEBUG
7312 else {
7313 power_req.request_type = PMR_PPM_POST_DETACH;
7314 power_req.req.ppm_config_req.who = cp->ppc_dip;
7315 power_req.req.ppm_config_req.result = ret;
7316 (void) pm_ctlops(NULL, cp->ppc_dip,
7317 DDI_CTLOPS_POWER, &power_req, &result);
7319 #endif
7320 if (ret == DDI_SUCCESS) {
7322 * For hotplug detach we assume it is *really* gone
7324 if (cp->ppc_cmd == DDI_DETACH &&
7325 ((DEVI(dip)->devi_pm_flags &
7326 (PMC_NO_INVOL | PMC_CONSOLE_FB)) ||
7327 DEVI(dip)->devi_pm_noinvolpm))
7328 pm_record_invol(dip);
7329 DEVI(dip)->devi_pm_flags &=
7330 ~(PMC_NO_INVOL | PMC_NOINVOL_DONE);
7333 * If console fb is detaching, then we don't need to
7334 * worry any more about it going off (pm_detaching has
7335 * brought up all components)
7337 if (PM_IS_CFB(dip)) {
7338 mutex_enter(&pm_cfb_lock);
7339 ASSERT(cfb_dip_detaching);
7340 ASSERT(cfb_dip == NULL);
7341 ASSERT(pm_cfb_comps_off == 0);
7342 cfb_dip_detaching = NULL;
7343 mutex_exit(&pm_cfb_lock);
7345 pm_stop(dip); /* make it permanent */
7346 } else {
7347 if (PM_IS_CFB(dip)) {
7348 mutex_enter(&pm_cfb_lock);
7349 ASSERT(cfb_dip_detaching);
7350 ASSERT(cfb_dip == NULL);
7351 ASSERT(pm_cfb_comps_off == 0);
7352 cfb_dip = cfb_dip_detaching;
7353 cfb_dip_detaching = NULL;
7354 mutex_exit(&pm_cfb_lock);
7356 pm_detach_failed(dip); /* resume power management */
7358 break;
7359 case DDI_PM_SUSPEND:
7360 break;
7361 case DDI_SUSPEND:
7362 break; /* legal, but nothing to do */
7363 default:
7364 #ifdef DEBUG
7365 panic("pm_post_detach: unrecognized cmd %d for detach",
7366 cp->ppc_cmd);
7367 /*NOTREACHED*/
7368 #else
7369 break;
7370 #endif
7375 * Called after vfs_mountroot has got the clock started to fix up timestamps
7376 * that were set when root bush drivers attached. hresttime was 0 then, so the
7377 * devices look busy but have a 0 busycnt
7380 pm_adjust_timestamps(dev_info_t *dip, void *arg)
7382 _NOTE(ARGUNUSED(arg))
7384 pm_info_t *info = PM_GET_PM_INFO(dip);
7385 struct pm_component *cp;
7386 int i;
7388 if (!info)
7389 return (DDI_WALK_CONTINUE);
7390 PM_LOCK_BUSY(dip);
7391 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
7392 cp = PM_CP(dip, i);
7393 if (cp->pmc_timestamp == 0 && cp->pmc_busycount == 0)
7394 cp->pmc_timestamp = gethrestime_sec();
7396 PM_UNLOCK_BUSY(dip);
7397 return (DDI_WALK_CONTINUE);
7401 * Called at attach time to see if the device being attached has a record in
7402 * the no involuntary power cycles list. If so, we do some bookkeeping on the
7403 * parents and set a flag in the dip
7405 void
7406 pm_noinvol_specd(dev_info_t *dip)
7408 PMD_FUNC(pmf, "noinvol_specd")
7409 char *pathbuf;
7410 pm_noinvol_t *ip, *pp = NULL;
7411 int wasvolpmd;
7412 int found = 0;
7414 if (DEVI(dip)->devi_pm_flags & PMC_NOINVOL_DONE)
7415 return;
7416 DEVI(dip)->devi_pm_flags |= PMC_NOINVOL_DONE;
7417 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
7418 (void) ddi_pathname(dip, pathbuf);
7420 PM_LOCK_DIP(dip);
7421 DEVI(dip)->devi_pm_volpmd = 0;
7422 DEVI(dip)->devi_pm_noinvolpm = 0;
7423 rw_enter(&pm_noinvol_rwlock, RW_READER);
7424 for (ip = pm_noinvol_head; ip; pp = ip, ip = ip->ni_next) {
7425 PMD(PMD_NOINVOL, ("%s: comparing '%s' to '%s'\n",
7426 pmf, pathbuf, ip->ni_path))
7427 if (strcmp(pathbuf, ip->ni_path) == 0) {
7428 found++;
7429 break;
7432 rw_exit(&pm_noinvol_rwlock);
7433 if (!found) {
7434 PM_UNLOCK_DIP(dip);
7435 kmem_free(pathbuf, MAXPATHLEN);
7436 return;
7438 rw_enter(&pm_noinvol_rwlock, RW_WRITER);
7439 pp = NULL;
7440 for (ip = pm_noinvol_head; ip; pp = ip, ip = ip->ni_next) {
7441 PMD(PMD_NOINVOL, ("%s: comparing '%s' to '%s'\n",
7442 pmf, pathbuf, ip->ni_path))
7443 if (strcmp(pathbuf, ip->ni_path) == 0) {
7444 ip->ni_flags &= ~PMC_DRIVER_REMOVED;
7445 DEVI(dip)->devi_pm_flags |= ip->ni_flags;
7447 * Handle special case of console fb
7449 if (PM_IS_CFB(dip)) {
7450 mutex_enter(&pm_cfb_lock);
7451 cfb_dip = dip;
7452 PMD(PMD_CFB, ("%s: %s@%s(%s#%d) setting "
7453 "cfb_dip\n", pmf, PM_DEVICE(dip)))
7454 mutex_exit(&pm_cfb_lock);
7456 DEVI(dip)->devi_pm_noinvolpm = ip->ni_noinvolpm;
7457 ASSERT((DEVI(dip)->devi_pm_flags &
7458 (PMC_NO_INVOL | PMC_CONSOLE_FB)) ||
7459 DEVI(dip)->devi_pm_noinvolpm);
7460 DEVI(dip)->devi_pm_volpmd = ip->ni_volpmd;
7461 PMD(PMD_NOINVOL, ("%s: noinvol=%d, volpmd=%d, "
7462 "wasvolpmd=%d, flags=%x, path=%s\n", pmf,
7463 ip->ni_noinvolpm, ip->ni_volpmd,
7464 ip->ni_wasvolpmd, ip->ni_flags, ip->ni_path))
7466 * free the entry in hopes the list will now be empty
7467 * and we won't have to search it any more until the
7468 * device detaches
7470 if (pp) {
7471 PMD(PMD_NOINVOL, ("%s: free %s, prev %s\n",
7472 pmf, ip->ni_path, pp->ni_path))
7473 pp->ni_next = ip->ni_next;
7474 } else {
7475 PMD(PMD_NOINVOL, ("%s: free %s head\n",
7476 pmf, ip->ni_path))
7477 ASSERT(pm_noinvol_head == ip);
7478 pm_noinvol_head = ip->ni_next;
7480 PM_UNLOCK_DIP(dip);
7481 wasvolpmd = ip->ni_wasvolpmd;
7482 rw_exit(&pm_noinvol_rwlock);
7483 kmem_free(ip->ni_path, ip->ni_size);
7484 kmem_free(ip, sizeof (*ip));
7486 * Now walk up the tree decrementing devi_pm_noinvolpm
7487 * (and volpmd if appropriate)
7489 (void) pm_noinvol_update(PM_BP_NOINVOL_ATTACH, 0,
7490 wasvolpmd, pathbuf, dip);
7491 #ifdef DEBUG
7492 if (pm_debug & PMD_NOINVOL)
7493 pr_noinvol("noinvol_specd exit");
7494 #endif
7495 kmem_free(pathbuf, MAXPATHLEN);
7496 return;
7499 kmem_free(pathbuf, MAXPATHLEN);
7500 rw_exit(&pm_noinvol_rwlock);
7501 PM_UNLOCK_DIP(dip);
7505 pm_all_components_off(dev_info_t *dip)
7507 int i;
7508 pm_component_t *cp;
7510 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
7511 cp = PM_CP(dip, i);
7512 if (cp->pmc_cur_pwr == PM_LEVEL_UNKNOWN ||
7513 cp->pmc_comp.pmc_lvals[cp->pmc_cur_pwr])
7514 return (0);
7516 return (1); /* all off */
7520 * Make sure that all "no involuntary power cycles" devices are attached.
7521 * Called before doing a cpr suspend to make sure the driver has a say about
7522 * the power cycle
7525 pm_reattach_noinvol(void)
7527 PMD_FUNC(pmf, "reattach_noinvol")
7528 pm_noinvol_t *ip;
7529 char *path;
7530 dev_info_t *dip;
7533 * Prevent the modunload thread from unloading any modules until we
7534 * have completely stopped all kernel threads.
7536 modunload_disable();
7537 for (ip = pm_noinvol_head; ip; ip = ip->ni_next) {
7539 * Forget we'v ever seen any entry
7541 ip->ni_persistent = 0;
7543 restart:
7544 rw_enter(&pm_noinvol_rwlock, RW_READER);
7545 for (ip = pm_noinvol_head; ip; ip = ip->ni_next) {
7546 #ifdef PMDDEBUG
7547 major_t maj;
7548 maj = ip->ni_major;
7549 #endif
7550 path = ip->ni_path;
7551 if (path != NULL && !(ip->ni_flags & PMC_DRIVER_REMOVED)) {
7552 if (ip->ni_persistent) {
7554 * If we weren't able to make this entry
7555 * go away, then we give up, as
7556 * holding/attaching the driver ought to have
7557 * resulted in this entry being deleted
7559 PMD(PMD_NOINVOL, ("%s: can't reattach %s "
7560 "(%s|%d)\n", pmf, ip->ni_path,
7561 ddi_major_to_name(maj), (int)maj))
7562 cmn_err(CE_WARN, "cpr: unable to reattach %s ",
7563 ip->ni_path);
7564 modunload_enable();
7565 rw_exit(&pm_noinvol_rwlock);
7566 return (0);
7568 ip->ni_persistent++;
7569 rw_exit(&pm_noinvol_rwlock);
7570 PMD(PMD_NOINVOL, ("%s: holding %s\n", pmf, path))
7571 dip = e_ddi_hold_devi_by_path(path, 0);
7572 if (dip == NULL) {
7573 PMD(PMD_NOINVOL, ("%s: can't hold (%s|%d)\n",
7574 pmf, path, (int)maj))
7575 cmn_err(CE_WARN, "cpr: unable to hold %s "
7576 "driver", path);
7577 modunload_enable();
7578 return (0);
7579 } else {
7580 PMD(PMD_DHR, ("%s: release %s\n", pmf, path))
7582 * Since the modunload thread is stopped, we
7583 * don't have to keep the driver held, which
7584 * saves a ton of bookkeeping
7586 ddi_release_devi(dip);
7587 goto restart;
7589 } else {
7590 PMD(PMD_NOINVOL, ("%s: skip %s; unknown major\n",
7591 pmf, ip->ni_path))
7592 continue;
7595 rw_exit(&pm_noinvol_rwlock);
7596 return (1);
7599 void
7600 pm_reattach_noinvol_fini(void)
7602 modunload_enable();
7606 * Display pm support code
7611 * console frame-buffer power-mgmt gets enabled when debugging
7612 * services are not present or console fbpm override is set
7614 void
7615 pm_cfb_setup(const char *stdout_path)
7617 PMD_FUNC(pmf, "cfb_setup")
7618 extern int obpdebug;
7619 char *devname;
7620 dev_info_t *dip;
7621 int devname_len;
7622 extern dev_info_t *fbdip;
7625 * By virtue of this function being called (from consconfig),
7626 * we know stdout is a framebuffer.
7628 stdout_is_framebuffer = 1;
7630 if (obpdebug || (boothowto & RB_DEBUG)) {
7631 if (pm_cfb_override == 0) {
7633 * Console is frame buffer, but we want to suppress
7634 * pm on it because of debugging setup
7636 pm_cfb_enabled = 0;
7637 cmn_err(CE_NOTE, "Kernel debugger present: disabling "
7638 "console power management.");
7640 * however, we still need to know which is the console
7641 * fb in order to suppress pm on it
7643 } else {
7644 cmn_err(CE_WARN, "Kernel debugger present: see "
7645 "kmdb(8) for interaction with power management.");
7648 #ifdef DEBUG
7650 * IF console is fb and is power managed, don't do prom_printfs from
7651 * pm debug macro
7653 if (pm_cfb_enabled && !pm_debug_to_console) {
7654 if (pm_debug)
7655 prom_printf("pm debug output will be to log only\n");
7656 pm_divertdebug++;
7658 #endif
7659 devname = i_ddi_strdup((char *)stdout_path, KM_SLEEP);
7660 devname_len = strlen(devname) + 1;
7661 PMD(PMD_CFB, ("%s: stripped %s\n", pmf, devname))
7662 /* if the driver is attached */
7663 if ((dip = fbdip) != NULL) {
7664 PMD(PMD_CFB, ("%s: attached: %s@%s(%s#%d)\n", pmf,
7665 PM_DEVICE(dip)))
7667 * We set up here as if the driver were power manageable in case
7668 * we get a later attach of a pm'able driver (which would result
7669 * in a panic later)
7671 cfb_dip = dip;
7672 DEVI(dip)->devi_pm_flags |= (PMC_CONSOLE_FB | PMC_NO_INVOL);
7673 PMD(PMD_CFB, ("%s: cfb_dip -> %s@%s(%s#%d)\n", pmf,
7674 PM_DEVICE(dip)))
7675 #ifdef DEBUG
7676 if (!(PM_GET_PM_INFO(dip) != NULL && PM_NUMCMPTS(dip))) {
7677 PMD(PMD_CFB, ("%s: %s@%s(%s#%d) not power-managed\n",
7678 pmf, PM_DEVICE(dip)))
7680 #endif
7681 } else {
7682 char *ep;
7683 PMD(PMD_CFB, ("%s: pntd %s failed\n", pmf, devname))
7684 pm_record_invol_path(devname,
7685 (PMC_CONSOLE_FB | PMC_NO_INVOL), 1, 0, 0,
7686 DDI_MAJOR_T_NONE);
7687 for (ep = strrchr(devname, '/'); ep != devname;
7688 ep = strrchr(devname, '/')) {
7689 PMD(PMD_CFB, ("%s: devname %s\n", pmf, devname))
7690 *ep = '\0';
7691 dip = pm_name_to_dip(devname, 0);
7692 if (dip != NULL) {
7694 * Walk up the tree incrementing
7695 * devi_pm_noinvolpm
7697 (void) pm_noinvol_update(PM_BP_NOINVOL_CFB,
7698 0, 0, devname, dip);
7699 break;
7700 } else {
7701 pm_record_invol_path(devname,
7702 PMC_NO_INVOL, 1, 0, 0, DDI_MAJOR_T_NONE);
7706 kmem_free(devname, devname_len);
7709 void
7710 pm_cfb_rele(void)
7712 mutex_enter(&pm_cfb_lock);
7714 * this call isn't using the console any more, it is ok to take it
7715 * down if the count goes to 0
7717 cfb_inuse--;
7718 mutex_exit(&pm_cfb_lock);
7722 * software interrupt handler for fbpm; this function exists because we can't
7723 * bring up the frame buffer power from above lock level. So if we need to,
7724 * we instead schedule a softint that runs this routine and takes us into
7725 * debug_enter (a bit delayed from the original request, but avoiding a panic).
7727 static uint_t
7728 pm_cfb_softint(caddr_t int_handler_arg)
7730 _NOTE(ARGUNUSED(int_handler_arg))
7731 int rval = DDI_INTR_UNCLAIMED;
7733 mutex_enter(&pm_cfb_lock);
7734 if (pm_soft_pending) {
7735 mutex_exit(&pm_cfb_lock);
7736 debug_enter(NULL);
7737 /* acquired in debug_enter before calling pm_cfb_trigger */
7738 pm_cfb_rele();
7739 mutex_enter(&pm_cfb_lock);
7740 pm_soft_pending = B_FALSE;
7741 mutex_exit(&pm_cfb_lock);
7742 rval = DDI_INTR_CLAIMED;
7743 } else
7744 mutex_exit(&pm_cfb_lock);
7746 return (rval);
7749 void
7750 pm_cfb_setup_intr(void)
7752 PMD_FUNC(pmf, "cfb_setup_intr")
7753 extern void prom_set_outfuncs(void (*)(void), void (*)(void));
7754 void pm_cfb_check_and_powerup(void);
7756 mutex_init(&pm_cfb_lock, NULL, MUTEX_SPIN, (void *)ipltospl(SPL8));
7757 #ifdef PMDDEBUG
7758 mutex_init(&pm_debug_lock, NULL, MUTEX_SPIN, (void *)ipltospl(SPL8));
7759 #endif
7761 if (!stdout_is_framebuffer) {
7762 PMD(PMD_CFB, ("%s: console not fb\n", pmf))
7763 return;
7767 * setup software interrupt handler
7769 if (ddi_add_softintr(ddi_root_node(), DDI_SOFTINT_HIGH, &pm_soft_id,
7770 NULL, NULL, pm_cfb_softint, NULL) != DDI_SUCCESS)
7771 panic("pm: unable to register soft intr.");
7773 prom_set_outfuncs(pm_cfb_check_and_powerup, pm_cfb_rele);
7777 * Checks to see if it is safe to write to the console wrt power management
7778 * (i.e. if the console is a framebuffer, then it must be at full power)
7779 * returns 1 when power is off (power-up is needed)
7780 * returns 0 when power is on (power-up not needed)
7783 pm_cfb_check_and_hold(void)
7786 * cfb_dip is set iff console is a power manageable frame buffer
7787 * device
7789 extern int modrootloaded;
7791 mutex_enter(&pm_cfb_lock);
7792 cfb_inuse++;
7793 ASSERT(cfb_inuse); /* wrap? */
7794 if (modrootloaded && cfb_dip) {
7796 * don't power down the frame buffer, the prom is using it
7798 if (pm_cfb_comps_off) {
7799 mutex_exit(&pm_cfb_lock);
7800 return (1);
7803 mutex_exit(&pm_cfb_lock);
7804 return (0);
7808 * turn on cfb power (which is known to be off).
7809 * Must be called below lock level!
7811 void
7812 pm_cfb_powerup(void)
7814 pm_info_t *info;
7815 int norm;
7816 int ccount, ci;
7817 int unused;
7818 #ifdef DEBUG
7820 * Can't reenter prom_prekern, so suppress pm debug messages
7821 * (still go to circular buffer).
7823 mutex_enter(&pm_debug_lock);
7824 pm_divertdebug++;
7825 mutex_exit(&pm_debug_lock);
7826 #endif
7827 info = PM_GET_PM_INFO(cfb_dip);
7828 ASSERT(info);
7830 ccount = PM_NUMCMPTS(cfb_dip);
7831 for (ci = 0; ci < ccount; ci++) {
7832 norm = pm_get_normal_power(cfb_dip, ci);
7833 (void) pm_set_power(cfb_dip, ci, norm, PM_LEVEL_UPONLY,
7834 PM_CANBLOCK_BYPASS, 0, &unused);
7836 #ifdef DEBUG
7837 mutex_enter(&pm_debug_lock);
7838 pm_divertdebug--;
7839 mutex_exit(&pm_debug_lock);
7840 #endif
7844 * Check if the console framebuffer is powered up. If not power it up.
7845 * Note: Calling pm_cfb_check_and_hold has put a hold on the power state which
7846 * must be released by calling pm_cfb_rele when the console fb operation
7847 * is completed.
7849 void
7850 pm_cfb_check_and_powerup(void)
7852 if (pm_cfb_check_and_hold())
7853 pm_cfb_powerup();
7857 * Trigger a low level interrupt to power up console frame buffer.
7859 void
7860 pm_cfb_trigger(void)
7862 if (cfb_dip == NULL)
7863 return;
7865 mutex_enter(&pm_cfb_lock);
7867 * If the machine appears to be hung, pulling the keyboard connector of
7868 * the console will cause a high level interrupt and go to debug_enter.
7869 * But, if the fb is powered down, this routine will be called to bring
7870 * it up (by generating a softint to do the work). If a second attempt
7871 * at triggering this softint happens before the first one completes,
7872 * we panic as softints are most likely not being handled.
7874 if (pm_soft_pending) {
7875 panicstr = "pm_cfb_trigger: failed to enter the debugger";
7876 panic(panicstr); /* does a power up at any intr level */
7877 /* NOTREACHED */
7879 pm_soft_pending = B_TRUE;
7880 mutex_exit(&pm_cfb_lock);
7881 ddi_trigger_softintr(pm_soft_id);
7884 static major_t i_path_to_major(char *, char *);
7886 major_t
7887 pm_path_to_major(char *path)
7889 PMD_FUNC(pmf, "path_to_major")
7890 char *np, *ap, *bp;
7891 major_t ret;
7892 size_t len;
7894 PMD(PMD_NOINVOL, ("%s: %s\n", pmf, path))
7896 np = strrchr(path, '/');
7897 if (np != NULL)
7898 np++;
7899 else
7900 np = path;
7901 len = strlen(np) + 1;
7902 bp = kmem_alloc(len, KM_SLEEP);
7903 (void) strcpy(bp, np);
7904 if ((ap = strchr(bp, '@')) != NULL) {
7905 *ap = '\0';
7907 PMD(PMD_NOINVOL, ("%s: %d\n", pmf, ddi_name_to_major(np)))
7908 ret = i_path_to_major(path, np);
7909 kmem_free(bp, len);
7910 return (ret);
7913 #ifdef DEBUG
7914 #ifndef sparc
7915 clock_t pt_sleep = 1;
7916 #endif
7918 char *pm_msgp;
7919 char *pm_bufend;
7920 char *pm_msgbuf = NULL;
7921 int pm_logpages = 0x100;
7922 #include <sys/sunldi.h>
7923 #include <sys/uio.h>
7924 clock_t pm_log_sleep = 1000;
7925 int pm_extra_cr = 1;
7926 volatile int pm_tty = 1;
7928 #define PMLOGPGS pm_logpages
7930 #if defined(__x86)
7931 void pm_printf(char *s);
7932 #endif
7934 /*PRINTFLIKE1*/
7935 void
7936 pm_log(const char *fmt, ...)
7938 va_list adx;
7939 size_t size;
7941 mutex_enter(&pm_debug_lock);
7942 if (pm_msgbuf == NULL) {
7943 pm_msgbuf = kmem_zalloc(mmu_ptob(PMLOGPGS), KM_SLEEP);
7944 pm_bufend = pm_msgbuf + mmu_ptob(PMLOGPGS) - 1;
7945 pm_msgp = pm_msgbuf;
7947 va_start(adx, fmt);
7948 size = vsnprintf(NULL, 0, fmt, adx) + 1;
7949 va_end(adx);
7950 va_start(adx, fmt);
7951 if (size > (pm_bufend - pm_msgp)) { /* wraps */
7952 bzero(pm_msgp, pm_bufend - pm_msgp);
7953 (void) vsnprintf(pm_msgbuf, size, fmt, adx);
7954 if (!pm_divertdebug)
7955 prom_printf("%s", pm_msgp);
7956 #if defined(__x86)
7957 if (pm_tty) {
7958 pm_printf(pm_msgp);
7959 if (pm_extra_cr)
7960 pm_printf("\r");
7962 #endif
7963 pm_msgp = pm_msgbuf + size;
7964 } else {
7965 (void) vsnprintf(pm_msgp, size, fmt, adx);
7966 #if defined(__x86)
7967 if (pm_tty) {
7968 pm_printf(pm_msgp);
7969 if (pm_extra_cr)
7970 pm_printf("\r");
7972 #endif
7973 if (!pm_divertdebug)
7974 prom_printf("%s", pm_msgp);
7975 pm_msgp += size;
7977 va_end(adx);
7978 mutex_exit(&pm_debug_lock);
7979 drv_usecwait((clock_t)pm_log_sleep);
7981 #endif /* DEBUG */
7984 * We want to save the state of any directly pm'd devices over the suspend/
7985 * resume process so that we can put them back the way the controlling
7986 * process left them.
7988 void
7989 pm_save_direct_levels(void)
7991 pm_processes_stopped = 1;
7992 ddi_walk_devs(ddi_root_node(), pm_save_direct_lvl_walk, 0);
7995 static int
7996 pm_save_direct_lvl_walk(dev_info_t *dip, void *arg)
7998 _NOTE(ARGUNUSED(arg))
7999 int i;
8000 int *ip;
8001 pm_info_t *info = PM_GET_PM_INFO(dip);
8003 if (!info)
8004 return (DDI_WALK_CONTINUE);
8006 if (PM_ISDIRECT(dip) && !PM_ISBC(dip)) {
8007 if (PM_NUMCMPTS(dip) > 2) {
8008 info->pmi_lp = kmem_alloc(PM_NUMCMPTS(dip) *
8009 sizeof (int), KM_SLEEP);
8010 ip = info->pmi_lp;
8011 } else {
8012 ip = info->pmi_levels;
8014 /* autopm and processes are stopped, ok not to lock power */
8015 for (i = 0; i < PM_NUMCMPTS(dip); i++)
8016 *ip++ = PM_CURPOWER(dip, i);
8018 * There is a small window between stopping the
8019 * processes and setting pm_processes_stopped where
8020 * a driver could get hung up in a pm_raise_power()
8021 * call. Free any such driver now.
8023 pm_proceed(dip, PMP_RELEASE, -1, -1);
8026 return (DDI_WALK_CONTINUE);
8029 void
8030 pm_restore_direct_levels(void)
8033 * If cpr didn't call pm_save_direct_levels, (because stopping user
8034 * threads failed) then we don't want to try to restore them
8036 if (!pm_processes_stopped)
8037 return;
8039 ddi_walk_devs(ddi_root_node(), pm_restore_direct_lvl_walk, 0);
8040 pm_processes_stopped = 0;
8043 static int
8044 pm_restore_direct_lvl_walk(dev_info_t *dip, void *arg)
8046 _NOTE(ARGUNUSED(arg))
8047 PMD_FUNC(pmf, "restore_direct_lvl_walk")
8048 int i, nc, result;
8049 int *ip;
8051 pm_info_t *info = PM_GET_PM_INFO(dip);
8052 if (!info)
8053 return (DDI_WALK_CONTINUE);
8055 if (PM_ISDIRECT(dip) && !PM_ISBC(dip)) {
8056 if ((nc = PM_NUMCMPTS(dip)) > 2) {
8057 ip = &info->pmi_lp[nc - 1];
8058 } else {
8059 ip = &info->pmi_levels[nc - 1];
8062 * Because fb drivers fail attempts to turn off the
8063 * fb when the monitor is on, but treat a request to
8064 * turn on the monitor as a request to turn on the
8065 * fb too, we process components in descending order
8066 * Because autopm is disabled and processes aren't
8067 * running, it is ok to examine current power outside
8068 * of the power lock
8070 for (i = nc - 1; i >= 0; i--, ip--) {
8071 if (PM_CURPOWER(dip, i) == *ip)
8072 continue;
8073 if (pm_set_power(dip, i, *ip, PM_LEVEL_EXACT,
8074 PM_CANBLOCK_BYPASS, 0, &result) != DDI_SUCCESS) {
8075 cmn_err(CE_WARN, "cpr: unable "
8076 "to restore power level of "
8077 "component %d of directly "
8078 "power manged device %s@%s"
8079 " to %d",
8080 i, PM_NAME(dip),
8081 PM_ADDR(dip), *ip);
8082 PMD(PMD_FAIL, ("%s: failed to restore "
8083 "%s@%s(%s#%d)[%d] exact(%d)->%d, "
8084 "errno %d\n", pmf, PM_DEVICE(dip), i,
8085 PM_CURPOWER(dip, i), *ip, result))
8088 if (nc > 2) {
8089 kmem_free(info->pmi_lp, nc * sizeof (int));
8090 info->pmi_lp = NULL;
8093 return (DDI_WALK_CONTINUE);
8097 * Stolen from the bootdev module
8098 * attempt to convert a path to a major number
8100 static major_t
8101 i_path_to_major(char *path, char *leaf_name)
8103 extern major_t path_to_major(char *pathname);
8104 major_t maj;
8106 if ((maj = path_to_major(path)) == DDI_MAJOR_T_NONE) {
8107 maj = ddi_name_to_major(leaf_name);
8110 return (maj);
8113 static void i_pm_driver_removed(major_t major);
8116 * When user calls rem_drv, we need to forget no-involuntary-power-cycles state
8117 * An entry in the list means that the device is detached, so we need to
8118 * adjust its ancestors as if they had just seen this attach, and any detached
8119 * ancestors need to have their list entries adjusted.
8121 void
8122 pm_driver_removed(major_t major)
8126 * Serialize removal of drivers. This is to keep ancestors of
8127 * a node that is being deleted from getting deleted and added back
8128 * with different counters.
8130 mutex_enter(&pm_remdrv_lock);
8131 i_pm_driver_removed(major);
8132 mutex_exit(&pm_remdrv_lock);
8135 static void adjust_ancestors(char *, int);
8136 static int pm_is_noinvol_ancestor(pm_noinvol_t *);
8137 static void pm_noinvol_process_ancestors(char *);
8140 * This routine is called recursively by pm_noinvol_process_ancestors()
8142 static void
8143 i_pm_driver_removed(major_t major)
8145 PMD_FUNC(pmf, "driver_removed")
8146 pm_noinvol_t *ip, *pp = NULL;
8147 int wasvolpmd;
8148 ASSERT(major != DDI_MAJOR_T_NONE);
8149 PMD(PMD_NOINVOL, ("%s: %s\n", pmf, ddi_major_to_name(major)))
8150 again:
8151 rw_enter(&pm_noinvol_rwlock, RW_WRITER);
8152 for (ip = pm_noinvol_head; ip; pp = ip, ip = ip->ni_next) {
8153 if (major != ip->ni_major)
8154 continue;
8156 * If it is an ancestor of no-invol node, which is
8157 * not removed, skip it. This is to cover the case of
8158 * ancestor removed without removing its descendants.
8160 if (pm_is_noinvol_ancestor(ip)) {
8161 ip->ni_flags |= PMC_DRIVER_REMOVED;
8162 continue;
8164 wasvolpmd = ip->ni_wasvolpmd;
8166 * remove the entry from the list
8168 if (pp) {
8169 PMD(PMD_NOINVOL, ("%s: freeing %s, prev is %s\n",
8170 pmf, ip->ni_path, pp->ni_path))
8171 pp->ni_next = ip->ni_next;
8172 } else {
8173 PMD(PMD_NOINVOL, ("%s: free %s head\n", pmf,
8174 ip->ni_path))
8175 ASSERT(pm_noinvol_head == ip);
8176 pm_noinvol_head = ip->ni_next;
8178 rw_exit(&pm_noinvol_rwlock);
8179 adjust_ancestors(ip->ni_path, wasvolpmd);
8181 * Had an ancestor been removed before this node, it would have
8182 * been skipped. Adjust the no-invol counters for such skipped
8183 * ancestors.
8185 pm_noinvol_process_ancestors(ip->ni_path);
8186 kmem_free(ip->ni_path, ip->ni_size);
8187 kmem_free(ip, sizeof (*ip));
8188 goto again;
8190 rw_exit(&pm_noinvol_rwlock);
8194 * returns 1, if *aip is a ancestor of a no-invol node
8195 * 0, otherwise
8197 static int
8198 pm_is_noinvol_ancestor(pm_noinvol_t *aip)
8200 pm_noinvol_t *ip;
8202 ASSERT(strlen(aip->ni_path) != 0);
8203 for (ip = pm_noinvol_head; ip; ip = ip->ni_next) {
8204 if (ip == aip)
8205 continue;
8207 * To be an ancestor, the path must be an initial substring of
8208 * the descendent, and end just before a '/' in the
8209 * descendent's path.
8211 if ((strstr(ip->ni_path, aip->ni_path) == ip->ni_path) &&
8212 (ip->ni_path[strlen(aip->ni_path)] == '/'))
8213 return (1);
8215 return (0);
8219 * scan through the pm_noinvolpm list adjusting ancestors of the current
8220 * node; Modifies string *path.
8222 static void
8223 adjust_ancestors(char *path, int wasvolpmd)
8225 PMD_FUNC(pmf, "adjust_ancestors")
8226 char *cp;
8227 pm_noinvol_t *lp;
8228 pm_noinvol_t *pp = NULL;
8229 major_t locked = DDI_MAJOR_T_NONE;
8230 dev_info_t *dip;
8231 char *pathbuf;
8232 size_t pathbuflen = strlen(path) + 1;
8235 * First we look up the ancestor's dip. If we find it, then we
8236 * adjust counts up the tree
8238 PMD(PMD_NOINVOL, ("%s: %s wasvolpmd %d\n", pmf, path, wasvolpmd))
8239 pathbuf = kmem_alloc(pathbuflen, KM_SLEEP);
8240 (void) strcpy(pathbuf, path);
8241 cp = strrchr(pathbuf, '/');
8242 if (cp == NULL) {
8243 /* if no ancestors, then nothing to do */
8244 kmem_free(pathbuf, pathbuflen);
8245 return;
8247 *cp = '\0';
8248 dip = pm_name_to_dip(pathbuf, 1);
8249 if (dip != NULL) {
8250 locked = PM_MAJOR(dip);
8252 (void) pm_noinvol_update(PM_BP_NOINVOL_REMDRV, 0, wasvolpmd,
8253 path, dip);
8255 if (locked != DDI_MAJOR_T_NONE)
8256 ddi_release_devi(dip);
8257 } else {
8258 char *apath;
8259 size_t len = strlen(pathbuf) + 1;
8260 int lock_held = 1;
8263 * Now check for ancestors that exist only in the list
8265 apath = kmem_alloc(len, KM_SLEEP);
8266 (void) strcpy(apath, pathbuf);
8267 rw_enter(&pm_noinvol_rwlock, RW_WRITER);
8268 for (lp = pm_noinvol_head; lp; pp = lp, lp = lp->ni_next) {
8270 * This can only happen once. Since we have to drop
8271 * the lock, we need to extract the relevant info.
8273 if (strcmp(pathbuf, lp->ni_path) == 0) {
8274 PMD(PMD_NOINVOL, ("%s: %s no %d -> %d\n", pmf,
8275 lp->ni_path, lp->ni_noinvolpm,
8276 lp->ni_noinvolpm - 1))
8277 lp->ni_noinvolpm--;
8278 if (wasvolpmd && lp->ni_volpmd) {
8279 PMD(PMD_NOINVOL, ("%s: %s vol %d -> "
8280 "%d\n", pmf, lp->ni_path,
8281 lp->ni_volpmd, lp->ni_volpmd - 1))
8282 lp->ni_volpmd--;
8285 * remove the entry from the list, if there
8286 * are no more no-invol descendants and node
8287 * itself is not a no-invol node.
8289 if (!(lp->ni_noinvolpm ||
8290 (lp->ni_flags & PMC_NO_INVOL))) {
8291 ASSERT(lp->ni_volpmd == 0);
8292 if (pp) {
8293 PMD(PMD_NOINVOL, ("%s: freeing "
8294 "%s, prev is %s\n", pmf,
8295 lp->ni_path, pp->ni_path))
8296 pp->ni_next = lp->ni_next;
8297 } else {
8298 PMD(PMD_NOINVOL, ("%s: free %s "
8299 "head\n", pmf, lp->ni_path))
8300 ASSERT(pm_noinvol_head == lp);
8301 pm_noinvol_head = lp->ni_next;
8303 lock_held = 0;
8304 rw_exit(&pm_noinvol_rwlock);
8305 adjust_ancestors(apath, wasvolpmd);
8306 /* restore apath */
8307 (void) strcpy(apath, pathbuf);
8308 kmem_free(lp->ni_path, lp->ni_size);
8309 kmem_free(lp, sizeof (*lp));
8311 break;
8314 if (lock_held)
8315 rw_exit(&pm_noinvol_rwlock);
8316 adjust_ancestors(apath, wasvolpmd);
8317 kmem_free(apath, len);
8319 kmem_free(pathbuf, pathbuflen);
8323 * Do no-invol processing for any ancestors i.e. adjust counters of ancestors,
8324 * which were skipped even though their drivers were removed.
8326 static void
8327 pm_noinvol_process_ancestors(char *path)
8329 pm_noinvol_t *lp;
8331 rw_enter(&pm_noinvol_rwlock, RW_READER);
8332 for (lp = pm_noinvol_head; lp; lp = lp->ni_next) {
8333 if (strstr(path, lp->ni_path) &&
8334 (lp->ni_flags & PMC_DRIVER_REMOVED)) {
8335 rw_exit(&pm_noinvol_rwlock);
8336 i_pm_driver_removed(lp->ni_major);
8337 return;
8340 rw_exit(&pm_noinvol_rwlock);
8344 * Returns true if (detached) device needs to be kept up because it exported the
8345 * "no-involuntary-power-cycles" property or we're pretending it did (console
8346 * fb case) or it is an ancestor of such a device and has used up the "one
8347 * free cycle" allowed when all such leaf nodes have voluntarily powered down
8348 * upon detach. In any event, we need an exact hit on the path or we return
8349 * false.
8352 pm_noinvol_detached(char *path)
8354 PMD_FUNC(pmf, "noinvol_detached")
8355 pm_noinvol_t *ip;
8356 int ret = 0;
8358 rw_enter(&pm_noinvol_rwlock, RW_READER);
8359 for (ip = pm_noinvol_head; ip; ip = ip->ni_next) {
8360 if (strcmp(path, ip->ni_path) == 0) {
8361 if (ip->ni_flags & PMC_CONSOLE_FB) {
8362 PMD(PMD_NOINVOL | PMD_CFB, ("%s: inhibits CFB "
8363 "%s\n", pmf, path))
8364 ret = 1;
8365 break;
8367 #ifdef DEBUG
8368 if (ip->ni_noinvolpm != ip->ni_volpmd)
8369 PMD(PMD_NOINVOL, ("%s: (%d != %d) inhibits %s"
8370 "\n", pmf, ip->ni_noinvolpm, ip->ni_volpmd,
8371 path))
8372 #endif
8373 ret = (ip->ni_noinvolpm != ip->ni_volpmd);
8374 break;
8377 rw_exit(&pm_noinvol_rwlock);
8378 return (ret);
8382 pm_is_cfb(dev_info_t *dip)
8384 return (dip == cfb_dip);
8387 #ifdef DEBUG
8389 * Return true if all components of the console frame buffer are at
8390 * "normal" power, i.e., fully on. For the case where the console is not
8391 * a framebuffer, we also return true
8394 pm_cfb_is_up(void)
8396 return (pm_cfb_comps_off == 0);
8398 #endif
8401 * Preventing scan from powering down the node by incrementing the
8402 * kidsupcnt.
8404 void
8405 pm_hold_power(dev_info_t *dip)
8407 e_pm_hold_rele_power(dip, 1);
8411 * Releasing the hold by decrementing the kidsupcnt allowing scan
8412 * to power down the node if all conditions are met.
8414 void
8415 pm_rele_power(dev_info_t *dip)
8417 e_pm_hold_rele_power(dip, -1);
8421 * A wrapper of pm_all_to_normal() to power up a dip
8422 * to its normal level
8425 pm_powerup(dev_info_t *dip)
8427 PMD_FUNC(pmf, "pm_powerup")
8429 PMD(PMD_ALLNORM, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
8430 ASSERT(!(servicing_interrupt()));
8433 * in case this node is not already participating pm
8435 if (!PM_GET_PM_INFO(dip)) {
8436 if (!DEVI_IS_ATTACHING(dip))
8437 return (DDI_SUCCESS);
8438 if (pm_start(dip) != DDI_SUCCESS)
8439 return (DDI_FAILURE);
8440 if (!PM_GET_PM_INFO(dip))
8441 return (DDI_SUCCESS);
8444 return (pm_all_to_normal(dip, PM_CANBLOCK_BLOCK));
8448 pm_rescan_walk(dev_info_t *dip, void *arg)
8450 _NOTE(ARGUNUSED(arg))
8452 if (!PM_GET_PM_INFO(dip) || PM_ISBC(dip))
8453 return (DDI_WALK_CONTINUE);
8456 * Currently pm_cpr_callb/resume code is the only caller
8457 * and it needs to make sure that stopped scan get
8458 * reactivated. Otherwise, rescan walk needn't reactive
8459 * stopped scan.
8461 pm_scan_init(dip);
8463 (void) pm_rescan(dip);
8464 return (DDI_WALK_CONTINUE);
8467 static dev_info_t *
8468 pm_get_next_descendent(dev_info_t *dip, dev_info_t *tdip)
8470 dev_info_t *wdip, *pdip;
8472 for (wdip = tdip; wdip != dip; wdip = pdip) {
8473 pdip = ddi_get_parent(wdip);
8474 if (pdip == dip)
8475 return (wdip);
8477 return (NULL);
8481 pm_busop_bus_power(dev_info_t *dip, void *impl_arg, pm_bus_power_op_t op,
8482 void *arg, void *result)
8484 PMD_FUNC(pmf, "bp_bus_power")
8485 dev_info_t *cdip;
8486 pm_info_t *cinfo;
8487 pm_bp_child_pwrchg_t *bpc;
8488 pm_sp_misc_t *pspm;
8489 pm_bp_nexus_pwrup_t *bpn;
8490 pm_bp_child_pwrchg_t new_bpc;
8491 pm_bp_noinvol_t *bpi;
8492 dev_info_t *tdip;
8493 char *pathbuf;
8494 int ret = DDI_SUCCESS;
8495 int errno = 0;
8496 pm_component_t *cp;
8498 PMD(PMD_SET, ("%s: %s@%s(%s#%d) %s\n", pmf, PM_DEVICE(dip),
8499 pm_decode_op(op)))
8500 switch (op) {
8501 case BUS_POWER_CHILD_PWRCHG:
8502 bpc = (pm_bp_child_pwrchg_t *)arg;
8503 pspm = (pm_sp_misc_t *)bpc->bpc_private;
8504 tdip = bpc->bpc_dip;
8505 cdip = pm_get_next_descendent(dip, tdip);
8506 cinfo = PM_GET_PM_INFO(cdip);
8507 if (cdip != tdip) {
8509 * If the node is an involved parent, it needs to
8510 * power up the node as it is needed. There is nothing
8511 * else the framework can do here.
8513 if (PM_WANTS_NOTIFICATION(cdip)) {
8514 PMD(PMD_SET, ("%s: call bus_power for "
8515 "%s@%s(%s#%d)\n", pmf, PM_DEVICE(cdip)))
8516 return ((*PM_BUS_POWER_FUNC(cdip))(cdip,
8517 impl_arg, op, arg, result));
8519 ASSERT(pspm->pspm_direction == PM_LEVEL_UPONLY ||
8520 pspm->pspm_direction == PM_LEVEL_DOWNONLY ||
8521 pspm->pspm_direction == PM_LEVEL_EXACT);
8523 * we presume that the parent needs to be up in
8524 * order for the child to change state (either
8525 * because it must already be on if the child is on
8526 * (and the pm_all_to_normal_nexus() will be a nop)
8527 * or because it will need to be on for the child
8528 * to come on; so we make the call regardless
8530 pm_hold_power(cdip);
8531 if (cinfo) {
8532 pm_canblock_t canblock = pspm->pspm_canblock;
8533 ret = pm_all_to_normal_nexus(cdip, canblock);
8534 if (ret != DDI_SUCCESS) {
8535 pm_rele_power(cdip);
8536 return (ret);
8539 PMD(PMD_SET, ("%s: walk down to %s@%s(%s#%d)\n", pmf,
8540 PM_DEVICE(cdip)))
8541 ret = pm_busop_bus_power(cdip, impl_arg, op, arg,
8542 result);
8543 pm_rele_power(cdip);
8544 } else {
8545 ret = pm_busop_set_power(cdip, impl_arg, op, arg,
8546 result);
8548 return (ret);
8550 case BUS_POWER_NEXUS_PWRUP:
8551 bpn = (pm_bp_nexus_pwrup_t *)arg;
8552 pspm = (pm_sp_misc_t *)bpn->bpn_private;
8554 if (!e_pm_valid_info(dip, NULL) ||
8555 !e_pm_valid_comp(dip, bpn->bpn_comp, &cp) ||
8556 !e_pm_valid_power(dip, bpn->bpn_comp, bpn->bpn_level)) {
8557 PMD(PMD_SET, ("%s: %s@%s(%s#%d) has no pm info; EIO\n",
8558 pmf, PM_DEVICE(dip)))
8559 *pspm->pspm_errnop = EIO;
8560 *(int *)result = DDI_FAILURE;
8561 return (DDI_FAILURE);
8564 ASSERT(bpn->bpn_dip == dip);
8565 PMD(PMD_SET, ("%s: nexus powerup for %s@%s(%s#%d)\n", pmf,
8566 PM_DEVICE(dip)))
8567 new_bpc.bpc_dip = dip;
8568 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
8569 new_bpc.bpc_path = ddi_pathname(dip, pathbuf);
8570 new_bpc.bpc_comp = bpn->bpn_comp;
8571 new_bpc.bpc_olevel = PM_CURPOWER(dip, bpn->bpn_comp);
8572 new_bpc.bpc_nlevel = bpn->bpn_level;
8573 new_bpc.bpc_private = bpn->bpn_private;
8574 ((pm_sp_misc_t *)(new_bpc.bpc_private))->pspm_direction =
8575 PM_LEVEL_UPONLY;
8576 ((pm_sp_misc_t *)(new_bpc.bpc_private))->pspm_errnop =
8577 &errno;
8578 ret = pm_busop_set_power(dip, impl_arg, BUS_POWER_CHILD_PWRCHG,
8579 (void *)&new_bpc, result);
8580 kmem_free(pathbuf, MAXPATHLEN);
8581 return (ret);
8583 case BUS_POWER_NOINVOL:
8584 bpi = (pm_bp_noinvol_t *)arg;
8585 tdip = bpi->bpni_dip;
8586 cdip = pm_get_next_descendent(dip, tdip);
8588 /* In case of rem_drv, the leaf node has been removed */
8589 if (cdip == NULL)
8590 return (DDI_SUCCESS);
8592 cinfo = PM_GET_PM_INFO(cdip);
8593 if (cdip != tdip) {
8594 if (PM_WANTS_NOTIFICATION(cdip)) {
8595 PMD(PMD_NOINVOL,
8596 ("%s: call bus_power for %s@%s(%s#%d)\n",
8597 pmf, PM_DEVICE(cdip)))
8598 ret = (*PM_BUS_POWER_FUNC(cdip))
8599 (cdip, NULL, op, arg, result);
8600 if ((cinfo) && (ret == DDI_SUCCESS))
8601 (void) pm_noinvol_update_node(cdip,
8602 bpi);
8603 return (ret);
8604 } else {
8605 PMD(PMD_NOINVOL,
8606 ("%s: walk down to %s@%s(%s#%d)\n", pmf,
8607 PM_DEVICE(cdip)))
8608 ret = pm_busop_bus_power(cdip, NULL, op,
8609 arg, result);
8611 * Update the current node.
8613 if ((cinfo) && (ret == DDI_SUCCESS))
8614 (void) pm_noinvol_update_node(cdip,
8615 bpi);
8616 return (ret);
8618 } else {
8620 * For attach, detach, power up:
8621 * Do nothing for leaf node since its
8622 * counts are already updated.
8623 * For CFB and driver removal, since the
8624 * path and the target dip passed in is up to and incl.
8625 * the immediate ancestor, need to do the update.
8627 PMD(PMD_NOINVOL, ("%s: target %s@%s(%s#%d) is "
8628 "reached\n", pmf, PM_DEVICE(cdip)))
8629 if (cinfo && ((bpi->bpni_cmd == PM_BP_NOINVOL_REMDRV) ||
8630 (bpi->bpni_cmd == PM_BP_NOINVOL_CFB)))
8631 (void) pm_noinvol_update_node(cdip, bpi);
8632 return (DDI_SUCCESS);
8635 default:
8636 PMD(PMD_SET, ("%s: operation %d is not supported!\n", pmf, op))
8637 return (DDI_FAILURE);
8641 static int
8642 pm_busop_set_power(dev_info_t *dip, void *impl_arg, pm_bus_power_op_t op,
8643 void *arg, void *resultp)
8645 _NOTE(ARGUNUSED(impl_arg))
8646 PMD_FUNC(pmf, "bp_set_power")
8647 pm_ppm_devlist_t *devl = NULL;
8648 int clevel, circ;
8649 #ifdef DEBUG
8650 int circ_db, ccirc_db;
8651 #endif
8652 int ret = DDI_SUCCESS;
8653 dev_info_t *cdip;
8654 pm_bp_child_pwrchg_t *bpc = (pm_bp_child_pwrchg_t *)arg;
8655 pm_sp_misc_t *pspm = (pm_sp_misc_t *)bpc->bpc_private;
8656 pm_canblock_t canblock = pspm->pspm_canblock;
8657 int scan = pspm->pspm_scan;
8658 int comp = bpc->bpc_comp;
8659 int olevel = bpc->bpc_olevel;
8660 int nlevel = bpc->bpc_nlevel;
8661 int comps_off_incr = 0;
8662 dev_info_t *pdip = ddi_get_parent(dip);
8663 int dodeps;
8664 int direction = pspm->pspm_direction;
8665 int *errnop = pspm->pspm_errnop;
8666 #ifdef PMDDEBUG
8667 char *dir = pm_decode_direction(direction);
8668 #endif
8669 int *iresp = (int *)resultp;
8670 time_t idletime, thresh;
8671 pm_component_t *cp = PM_CP(dip, comp);
8672 int work_type;
8674 *iresp = DDI_SUCCESS;
8675 *errnop = 0;
8676 ASSERT(op == BUS_POWER_CHILD_PWRCHG);
8677 PMD(PMD_SET, ("%s: %s@%s(%s#%d) %s\n", pmf, PM_DEVICE(dip),
8678 pm_decode_op(op)))
8681 * The following set of conditions indicate we are here to handle a
8682 * driver's pm_[raise|lower]_power request, but the device is being
8683 * power managed (PM_DIRECT_PM) by a user process. For that case
8684 * we want to pm_block and pass a status back to the caller based
8685 * on whether the controlling process's next activity on the device
8686 * matches the current request or not. This distinction tells
8687 * downstream functions to avoid calling into a driver or changing
8688 * the framework's power state. To actually block, we need:
8690 * PM_ISDIRECT(dip)
8691 * no reason to block unless a process is directly controlling dev
8692 * direction != PM_LEVEL_EXACT
8693 * EXACT is used by controlling proc's PM_SET_CURRENT_POWER ioctl
8694 * !pm_processes_stopped
8695 * don't block if controlling proc already be stopped for cpr
8696 * canblock != PM_CANBLOCK_BYPASS
8697 * our caller must not have explicitly prevented blocking
8699 if (direction != PM_LEVEL_EXACT && canblock != PM_CANBLOCK_BYPASS) {
8700 PM_LOCK_DIP(dip);
8701 while (PM_ISDIRECT(dip) && !pm_processes_stopped) {
8702 /* releases dip lock */
8703 ret = pm_busop_match_request(dip, bpc);
8704 if (ret == EAGAIN) {
8705 PM_LOCK_DIP(dip);
8706 continue;
8708 return (*iresp = ret);
8710 PM_UNLOCK_DIP(dip);
8712 /* BC device is never scanned, so power will stick until we are done */
8713 if (PM_ISBC(dip) && comp != 0 && nlevel != 0 &&
8714 direction != PM_LEVEL_DOWNONLY) {
8715 int nrmpwr0 = pm_get_normal_power(dip, 0);
8716 if (pm_set_power(dip, 0, nrmpwr0, direction,
8717 canblock, 0, resultp) != DDI_SUCCESS) {
8718 /* *resultp set by pm_set_power */
8719 return (DDI_FAILURE);
8722 if (PM_WANTS_NOTIFICATION(pdip)) {
8723 PMD(PMD_SET, ("%s: pre_notify %s@%s(%s#%d) for child "
8724 "%s@%s(%s#%d)\n", pmf, PM_DEVICE(pdip), PM_DEVICE(dip)))
8725 ret = (*PM_BUS_POWER_FUNC(pdip))(pdip, NULL,
8726 BUS_POWER_PRE_NOTIFICATION, bpc, resultp);
8727 if (ret != DDI_SUCCESS) {
8728 PMD(PMD_SET, ("%s: failed to pre_notify %s@%s(%s#%d)\n",
8729 pmf, PM_DEVICE(pdip)))
8730 return (DDI_FAILURE);
8732 } else {
8734 * Since we don't know what the actual power level is,
8735 * we place a power hold on the parent no matter what
8736 * component and level is changing.
8738 pm_hold_power(pdip);
8740 PM_LOCK_POWER(dip, &circ);
8741 clevel = PM_CURPOWER(dip, comp);
8743 * It's possible that a call was made to pm_update_maxpower()
8744 * on another thread before we took the lock above. So, we need to
8745 * make sure that this request isn't processed after the
8746 * change of power executed on behalf of pm_update_maxpower().
8748 if (nlevel > pm_get_normal_power(dip, comp)) {
8749 PMD(PMD_SET, ("%s: requested level is higher than normal.\n",
8750 pmf))
8751 ret = DDI_FAILURE;
8752 *iresp = DDI_FAILURE;
8753 goto post_notify;
8755 PMD(PMD_SET, ("%s: %s@%s(%s#%d), cmp=%d, olvl=%d, nlvl=%d, clvl=%d, "
8756 "dir=%s\n", pmf, PM_DEVICE(dip), comp, bpc->bpc_olevel, nlevel,
8757 clevel, dir))
8758 switch (direction) {
8759 case PM_LEVEL_UPONLY:
8760 /* Powering up */
8761 if (clevel >= nlevel) {
8762 PMD(PMD_SET, ("%s: current level is already "
8763 "at or above the requested level.\n", pmf))
8764 *iresp = DDI_SUCCESS;
8765 ret = DDI_SUCCESS;
8766 goto post_notify;
8768 break;
8769 case PM_LEVEL_EXACT:
8770 /* specific level request */
8771 if (clevel == nlevel && !PM_ISBC(dip)) {
8772 PMD(PMD_SET, ("%s: current level is already "
8773 "at the requested level.\n", pmf))
8774 *iresp = DDI_SUCCESS;
8775 ret = DDI_SUCCESS;
8776 goto post_notify;
8777 } else if (PM_IS_CFB(dip) && (nlevel < clevel)) {
8778 PMD(PMD_CFB, ("%s: powerdown of console\n", pmf))
8779 if (!pm_cfb_enabled) {
8780 PMD(PMD_ERROR | PMD_CFB,
8781 ("%s: !pm_cfb_enabled, fails\n", pmf))
8782 *errnop = EINVAL;
8783 *iresp = DDI_FAILURE;
8784 ret = DDI_FAILURE;
8785 goto post_notify;
8787 mutex_enter(&pm_cfb_lock);
8788 while (cfb_inuse) {
8789 mutex_exit(&pm_cfb_lock);
8790 if (delay_sig(1) == EINTR) {
8791 ret = DDI_FAILURE;
8792 *iresp = DDI_FAILURE;
8793 *errnop = EINTR;
8794 goto post_notify;
8796 mutex_enter(&pm_cfb_lock);
8798 mutex_exit(&pm_cfb_lock);
8800 break;
8801 case PM_LEVEL_DOWNONLY:
8802 /* Powering down */
8803 thresh = cur_threshold(dip, comp);
8804 idletime = gethrestime_sec() - cp->pmc_timestamp;
8805 if (scan && ((PM_KUC(dip) != 0) ||
8806 (cp->pmc_busycount > 0) ||
8807 ((idletime < thresh) && !PM_IS_PID(dip)))) {
8808 #ifdef DEBUG
8809 if (DEVI(dip)->devi_pm_kidsupcnt != 0)
8810 PMD(PMD_SET, ("%s: scan failed: "
8811 "kidsupcnt != 0\n", pmf))
8812 if (cp->pmc_busycount > 0)
8813 PMD(PMD_SET, ("%s: scan failed: "
8814 "device become busy\n", pmf))
8815 if (idletime < thresh)
8816 PMD(PMD_SET, ("%s: scan failed: device "
8817 "hasn't been idle long enough\n", pmf))
8818 #endif
8819 *iresp = DDI_FAILURE;
8820 *errnop = EBUSY;
8821 ret = DDI_FAILURE;
8822 goto post_notify;
8823 } else if (clevel != PM_LEVEL_UNKNOWN && clevel <= nlevel) {
8824 PMD(PMD_SET, ("%s: current level is already at "
8825 "or below the requested level.\n", pmf))
8826 *iresp = DDI_SUCCESS;
8827 ret = DDI_SUCCESS;
8828 goto post_notify;
8830 break;
8833 if (PM_IS_CFB(dip) && (comps_off_incr =
8834 calc_cfb_comps_incr(dip, comp, clevel, nlevel)) > 0) {
8836 * Pre-adjust pm_cfb_comps_off if lowering a console fb
8837 * component from full power. Remember that we tried to
8838 * lower power in case it fails and we need to back out
8839 * the adjustment.
8841 update_comps_off(comps_off_incr, dip);
8842 PMD(PMD_CFB, ("%s: %s@%s(%s#%d)[%d] %d->%d cfb_comps_off->%d\n",
8843 pmf, PM_DEVICE(dip), comp, clevel, nlevel,
8844 pm_cfb_comps_off))
8847 if ((*iresp = power_dev(dip,
8848 comp, nlevel, clevel, canblock, &devl)) == DDI_SUCCESS) {
8849 #ifdef DEBUG
8851 * All descendents of this node should already be powered off.
8853 if (PM_CURPOWER(dip, comp) == 0) {
8854 pm_desc_pwrchk_t pdpchk;
8855 pdpchk.pdpc_dip = dip;
8856 pdpchk.pdpc_par_involved = PM_WANTS_NOTIFICATION(dip);
8857 ndi_devi_enter(dip, &circ_db);
8858 for (cdip = ddi_get_child(dip); cdip != NULL;
8859 cdip = ddi_get_next_sibling(cdip)) {
8860 ndi_devi_enter(cdip, &ccirc_db);
8861 ddi_walk_devs(cdip, pm_desc_pwrchk_walk,
8862 (void *)&pdpchk);
8863 ndi_devi_exit(cdip, ccirc_db);
8865 ndi_devi_exit(dip, circ_db);
8867 #endif
8869 * Post-adjust pm_cfb_comps_off if we brought an fb component
8870 * back up to full power.
8872 if (PM_IS_CFB(dip) && comps_off_incr < 0) {
8873 update_comps_off(comps_off_incr, dip);
8874 PMD(PMD_CFB, ("%s: %s@%s(%s#%d)[%d] %d->%d "
8875 "cfb_comps_off->%d\n", pmf, PM_DEVICE(dip),
8876 comp, clevel, nlevel, pm_cfb_comps_off))
8878 dodeps = 0;
8879 if (POWERING_OFF(clevel, nlevel)) {
8880 if (PM_ISBC(dip)) {
8881 dodeps = (comp == 0);
8882 } else {
8883 int i;
8884 dodeps = 1;
8885 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
8886 /* if some component still on */
8887 if (PM_CURPOWER(dip, i)) {
8888 dodeps = 0;
8889 break;
8893 if (dodeps)
8894 work_type = PM_DEP_WK_POWER_OFF;
8895 } else if (POWERING_ON(clevel, nlevel)) {
8896 if (PM_ISBC(dip)) {
8897 dodeps = (comp == 0);
8898 } else {
8899 int i;
8900 dodeps = 1;
8901 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
8902 if (i == comp)
8903 continue;
8904 if (PM_CURPOWER(dip, i) > 0) {
8905 dodeps = 0;
8906 break;
8910 if (dodeps)
8911 work_type = PM_DEP_WK_POWER_ON;
8914 if (dodeps) {
8915 char *pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
8917 (void) ddi_pathname(dip, pathbuf);
8918 pm_dispatch_to_dep_thread(work_type, pathbuf, NULL,
8919 PM_DEP_NOWAIT, NULL, 0);
8920 kmem_free(pathbuf, MAXPATHLEN);
8922 if ((PM_CURPOWER(dip, comp) == nlevel) && pm_watchers()) {
8923 int old;
8925 /* If old power cached during deadlock, use it. */
8926 old = (cp->pmc_flags & PM_PHC_WHILE_SET_POWER ?
8927 cp->pmc_phc_pwr : olevel);
8928 mutex_enter(&pm_rsvp_lock);
8929 pm_enqueue_notify(PSC_HAS_CHANGED, dip, comp, nlevel,
8930 old, canblock);
8931 pm_enqueue_notify_others(&devl, canblock);
8932 mutex_exit(&pm_rsvp_lock);
8933 } else {
8934 pm_ppm_devlist_t *p;
8935 pm_ppm_devlist_t *next;
8936 for (p = devl; p != NULL; p = next) {
8937 next = p->ppd_next;
8938 kmem_free(p, sizeof (pm_ppm_devlist_t));
8940 devl = NULL;
8944 * If we are coming from a scan, don't do it again,
8945 * else we can have infinite loops.
8947 if (!scan)
8948 pm_rescan(dip);
8949 } else {
8950 /* if we incremented pm_comps_off_count, but failed */
8951 if (comps_off_incr > 0) {
8952 update_comps_off(-comps_off_incr, dip);
8953 PMD(PMD_CFB, ("%s: %s@%s(%s#%d)[%d] %d->%d "
8954 "cfb_comps_off->%d\n", pmf, PM_DEVICE(dip),
8955 comp, clevel, nlevel, pm_cfb_comps_off))
8957 *errnop = EIO;
8960 post_notify:
8962 * This thread may have been in deadlock with pm_power_has_changed.
8963 * Before releasing power lock, clear the flag which marks this
8964 * condition.
8966 cp->pmc_flags &= ~PM_PHC_WHILE_SET_POWER;
8969 * Update the old power level in the bus power structure with the
8970 * actual power level before the transition was made to the new level.
8971 * Some involved parents depend on this information to keep track of
8972 * their children's power transition.
8974 if (*iresp != DDI_FAILURE)
8975 bpc->bpc_olevel = clevel;
8977 if (PM_WANTS_NOTIFICATION(pdip)) {
8978 ret = (*PM_BUS_POWER_FUNC(pdip))(pdip, NULL,
8979 BUS_POWER_POST_NOTIFICATION, bpc, resultp);
8980 PM_UNLOCK_POWER(dip, circ);
8981 PMD(PMD_SET, ("%s: post_notify %s@%s(%s#%d) for "
8982 "child %s@%s(%s#%d), ret=%d\n", pmf, PM_DEVICE(pdip),
8983 PM_DEVICE(dip), ret))
8984 } else {
8985 nlevel = cur_power(cp); /* in case phc deadlock updated pwr */
8986 PM_UNLOCK_POWER(dip, circ);
8988 * Now that we know what power transition has occurred
8989 * (if any), release the power hold. Leave the hold
8990 * in effect in the case of OFF->ON transition.
8992 if (!(clevel == 0 && nlevel > 0 &&
8993 (!PM_ISBC(dip) || comp == 0)))
8994 pm_rele_power(pdip);
8996 * If the power transition was an ON->OFF transition,
8997 * remove the power hold from the parent.
8999 if ((clevel > 0 || clevel == PM_LEVEL_UNKNOWN) &&
9000 nlevel == 0 && (!PM_ISBC(dip) || comp == 0))
9001 pm_rele_power(pdip);
9003 if (*iresp != DDI_SUCCESS || ret != DDI_SUCCESS)
9004 return (DDI_FAILURE);
9005 else
9006 return (DDI_SUCCESS);
9010 * If an app (SunVTS or Xsun) has taken control, then block until it
9011 * gives it up or makes the requested power level change, unless
9012 * we have other instructions about blocking. Returns DDI_SUCCESS,
9013 * DDI_FAILURE or EAGAIN (owner released device from directpm).
9015 static int
9016 pm_busop_match_request(dev_info_t *dip, void *arg)
9018 PMD_FUNC(pmf, "bp_match_request")
9019 pm_bp_child_pwrchg_t *bpc = (pm_bp_child_pwrchg_t *)arg;
9020 pm_sp_misc_t *pspm = (pm_sp_misc_t *)bpc->bpc_private;
9021 int comp = bpc->bpc_comp;
9022 int nlevel = bpc->bpc_nlevel;
9023 pm_canblock_t canblock = pspm->pspm_canblock;
9024 int direction = pspm->pspm_direction;
9025 int clevel, circ;
9027 ASSERT(PM_IAM_LOCKING_DIP(dip));
9028 PM_LOCK_POWER(dip, &circ);
9029 clevel = PM_CURPOWER(dip, comp);
9030 PMD(PMD_SET, ("%s: %s@%s(%s#%d), cmp=%d, nlvl=%d, clvl=%d\n",
9031 pmf, PM_DEVICE(dip), comp, nlevel, clevel))
9032 if (direction == PM_LEVEL_UPONLY) {
9033 if (clevel >= nlevel) {
9034 PM_UNLOCK_POWER(dip, circ);
9035 PM_UNLOCK_DIP(dip);
9036 return (DDI_SUCCESS);
9038 } else if (clevel == nlevel) {
9039 PM_UNLOCK_POWER(dip, circ);
9040 PM_UNLOCK_DIP(dip);
9041 return (DDI_SUCCESS);
9043 if (canblock == PM_CANBLOCK_FAIL) {
9044 PM_UNLOCK_POWER(dip, circ);
9045 PM_UNLOCK_DIP(dip);
9046 return (DDI_FAILURE);
9048 if (canblock == PM_CANBLOCK_BLOCK) {
9050 * To avoid a deadlock, we must not hold the
9051 * power lock when we pm_block.
9053 PM_UNLOCK_POWER(dip, circ);
9054 PMD(PMD_SET, ("%s: blocking\n", pmf))
9055 /* pm_block releases dip lock */
9056 switch (pm_block(dip, comp, nlevel, clevel)) {
9057 case PMP_RELEASE:
9058 return (EAGAIN);
9059 case PMP_SUCCEED:
9060 return (DDI_SUCCESS);
9061 case PMP_FAIL:
9062 return (DDI_FAILURE);
9064 } else {
9065 ASSERT(0);
9067 _NOTE(NOTREACHED);
9068 return (DDI_FAILURE); /* keep gcc happy */
9071 static int
9072 pm_all_to_normal_nexus(dev_info_t *dip, pm_canblock_t canblock)
9074 PMD_FUNC(pmf, "all_to_normal_nexus")
9075 int *normal;
9076 int i, ncomps;
9077 size_t size;
9078 int changefailed = 0;
9079 int ret, result = DDI_SUCCESS;
9080 pm_bp_nexus_pwrup_t bpn;
9081 pm_sp_misc_t pspm;
9083 ASSERT(PM_GET_PM_INFO(dip));
9084 PMD(PMD_ALLNORM, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
9085 if (pm_get_norm_pwrs(dip, &normal, &size) != DDI_SUCCESS) {
9086 PMD(PMD_ALLNORM, ("%s: can't get norm pwrs\n", pmf))
9087 return (DDI_FAILURE);
9089 ncomps = PM_NUMCMPTS(dip);
9090 for (i = 0; i < ncomps; i++) {
9091 bpn.bpn_dip = dip;
9092 bpn.bpn_comp = i;
9093 bpn.bpn_level = normal[i];
9094 pspm.pspm_canblock = canblock;
9095 pspm.pspm_scan = 0;
9096 bpn.bpn_private = &pspm;
9097 ret = pm_busop_bus_power(dip, NULL, BUS_POWER_NEXUS_PWRUP,
9098 (void *)&bpn, (void *)&result);
9099 if (ret != DDI_SUCCESS || result != DDI_SUCCESS) {
9100 PMD(PMD_FAIL | PMD_ALLNORM, ("%s: %s@%s(%s#%d)[%d] "
9101 "->%d failure result %d\n", pmf, PM_DEVICE(dip),
9102 i, normal[i], result))
9103 changefailed++;
9106 kmem_free(normal, size);
9107 if (changefailed) {
9108 PMD(PMD_FAIL, ("%s: failed to set %d comps %s@%s(%s#%d) "
9109 "full power\n", pmf, changefailed, PM_DEVICE(dip)))
9110 return (DDI_FAILURE);
9112 return (DDI_SUCCESS);
9116 pm_noinvol_update(int subcmd, int volpmd, int wasvolpmd, char *path,
9117 dev_info_t *tdip)
9119 PMD_FUNC(pmf, "noinvol_update")
9120 pm_bp_noinvol_t args;
9121 int ret;
9122 int result = DDI_SUCCESS;
9124 args.bpni_path = path;
9125 args.bpni_dip = tdip;
9126 args.bpni_cmd = subcmd;
9127 args.bpni_wasvolpmd = wasvolpmd;
9128 args.bpni_volpmd = volpmd;
9129 PMD(PMD_NOINVOL, ("%s: update for path %s tdip %p subcmd %d "
9130 "volpmd %d wasvolpmd %d\n", pmf,
9131 path, (void *)tdip, subcmd, wasvolpmd, volpmd))
9132 ret = pm_busop_bus_power(ddi_root_node(), NULL, BUS_POWER_NOINVOL,
9133 &args, &result);
9134 return (ret);
9137 void
9138 pm_noinvol_update_node(dev_info_t *dip, pm_bp_noinvol_t *req)
9140 PMD_FUNC(pmf, "noinvol_update_node")
9142 PMD(PMD_NOINVOL, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
9143 switch (req->bpni_cmd) {
9144 case PM_BP_NOINVOL_ATTACH:
9145 PMD(PMD_NOINVOL, ("%s: PM_PB_NOINVOL_ATTACH %s@%s(%s#%d) "
9146 "noinvol %d->%d\n", pmf, PM_DEVICE(dip),
9147 DEVI(dip)->devi_pm_noinvolpm,
9148 DEVI(dip)->devi_pm_noinvolpm - 1))
9149 ASSERT(DEVI(dip)->devi_pm_noinvolpm);
9150 PM_LOCK_DIP(dip);
9151 DEVI(dip)->devi_pm_noinvolpm--;
9152 if (req->bpni_wasvolpmd) {
9153 PMD(PMD_NOINVOL, ("%s: PM_BP_NOINVOL_ATTACH "
9154 "%s@%s(%s#%d) volpmd %d->%d\n", pmf,
9155 PM_DEVICE(dip), DEVI(dip)->devi_pm_volpmd,
9156 DEVI(dip)->devi_pm_volpmd - 1))
9157 if (DEVI(dip)->devi_pm_volpmd)
9158 DEVI(dip)->devi_pm_volpmd--;
9160 PM_UNLOCK_DIP(dip);
9161 break;
9163 case PM_BP_NOINVOL_DETACH:
9164 PMD(PMD_NOINVOL, ("%s: PM_BP_NOINVOL_DETACH %s@%s(%s#%d) "
9165 "noinvolpm %d->%d\n", pmf, PM_DEVICE(dip),
9166 DEVI(dip)->devi_pm_noinvolpm,
9167 DEVI(dip)->devi_pm_noinvolpm + 1))
9168 PM_LOCK_DIP(dip);
9169 DEVI(dip)->devi_pm_noinvolpm++;
9170 if (req->bpni_wasvolpmd) {
9171 PMD(PMD_NOINVOL, ("%s: PM_BP_NOINVOL_DETACH "
9172 "%s@%s(%s#%d) volpmd %d->%d\n", pmf,
9173 PM_DEVICE(dip), DEVI(dip)->devi_pm_volpmd,
9174 DEVI(dip)->devi_pm_volpmd + 1))
9175 DEVI(dip)->devi_pm_volpmd++;
9177 PM_UNLOCK_DIP(dip);
9178 break;
9180 case PM_BP_NOINVOL_REMDRV:
9181 PMD(PMD_NOINVOL, ("%s: PM_BP_NOINVOL_REMDRV %s@%s(%s#%d) "
9182 "noinvol %d->%d\n", pmf, PM_DEVICE(dip),
9183 DEVI(dip)->devi_pm_noinvolpm,
9184 DEVI(dip)->devi_pm_noinvolpm - 1))
9185 ASSERT(DEVI(dip)->devi_pm_noinvolpm);
9186 PM_LOCK_DIP(dip);
9187 DEVI(dip)->devi_pm_noinvolpm--;
9188 if (req->bpni_wasvolpmd) {
9189 PMD(PMD_NOINVOL,
9190 ("%s: PM_BP_NOINVOL_REMDRV %s@%s(%s#%d) "
9191 "volpmd %d->%d\n", pmf, PM_DEVICE(dip),
9192 DEVI(dip)->devi_pm_volpmd,
9193 DEVI(dip)->devi_pm_volpmd - 1))
9195 * A power up could come in between and
9196 * clear the volpmd, if that's the case,
9197 * volpmd would be clear.
9199 if (DEVI(dip)->devi_pm_volpmd)
9200 DEVI(dip)->devi_pm_volpmd--;
9202 PM_UNLOCK_DIP(dip);
9203 break;
9205 case PM_BP_NOINVOL_CFB:
9206 PMD(PMD_NOINVOL,
9207 ("%s: PM_BP_NOIVOL_CFB %s@%s(%s#%d) noinvol %d->%d\n",
9208 pmf, PM_DEVICE(dip), DEVI(dip)->devi_pm_noinvolpm,
9209 DEVI(dip)->devi_pm_noinvolpm + 1))
9210 PM_LOCK_DIP(dip);
9211 DEVI(dip)->devi_pm_noinvolpm++;
9212 PM_UNLOCK_DIP(dip);
9213 break;
9215 case PM_BP_NOINVOL_POWER:
9216 PMD(PMD_NOINVOL,
9217 ("%s: PM_BP_NOIVOL_PWR %s@%s(%s#%d) volpmd %d->%d\n",
9218 pmf, PM_DEVICE(dip),
9219 DEVI(dip)->devi_pm_volpmd, DEVI(dip)->devi_pm_volpmd -
9220 req->bpni_volpmd))
9221 PM_LOCK_DIP(dip);
9222 DEVI(dip)->devi_pm_volpmd -= req->bpni_volpmd;
9223 PM_UNLOCK_DIP(dip);
9224 break;
9226 default:
9227 break;
9232 #ifdef DEBUG
9233 static int
9234 pm_desc_pwrchk_walk(dev_info_t *dip, void *arg)
9236 PMD_FUNC(pmf, "desc_pwrchk")
9237 pm_desc_pwrchk_t *pdpchk = (pm_desc_pwrchk_t *)arg;
9238 pm_info_t *info = PM_GET_PM_INFO(dip);
9239 int i;
9240 int curpwr, ce_level;
9242 if (!info)
9243 return (DDI_WALK_CONTINUE);
9245 PMD(PMD_SET, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
9246 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
9247 if ((curpwr = PM_CURPOWER(dip, i)) == 0)
9248 continue;
9249 /* E_FUNC_SET_NOT_USED */
9250 ce_level = (pdpchk->pdpc_par_involved == 0) ? CE_PANIC :
9251 CE_WARN;
9252 PMD(PMD_SET, ("%s: %s@%s(%s#%d) is powered off while desc "
9253 "%s@%s(%s#%d)[%d] is at %d\n", pmf,
9254 PM_DEVICE(pdpchk->pdpc_dip), PM_DEVICE(dip), i, curpwr))
9255 cmn_err(ce_level, "!device %s@%s(%s#%d) is powered on, "
9256 "while its ancestor, %s@%s(%s#%d), is powering off!",
9257 PM_DEVICE(dip), PM_DEVICE(pdpchk->pdpc_dip));
9259 return (DDI_WALK_CONTINUE);
9261 #endif
9264 * Record the fact that one thread is borrowing the lock on a device node.
9265 * Use is restricted to the case where the lending thread will block until
9266 * the borrowing thread (always curthread) completes.
9268 void
9269 pm_borrow_lock(kthread_t *lender)
9271 lock_loan_t *prev = &lock_loan_head;
9272 lock_loan_t *cur = (lock_loan_t *)kmem_zalloc(sizeof (*cur), KM_SLEEP);
9274 cur->pmlk_borrower = curthread;
9275 cur->pmlk_lender = lender;
9276 mutex_enter(&pm_loan_lock);
9277 cur->pmlk_next = prev->pmlk_next;
9278 prev->pmlk_next = cur;
9279 mutex_exit(&pm_loan_lock);
9283 * Return the borrowed lock. A thread can borrow only one.
9285 void
9286 pm_return_lock(void)
9288 lock_loan_t *cur;
9289 lock_loan_t *prev = &lock_loan_head;
9291 mutex_enter(&pm_loan_lock);
9292 ASSERT(prev->pmlk_next != NULL);
9293 for (cur = prev->pmlk_next; cur; prev = cur, cur = cur->pmlk_next)
9294 if (cur->pmlk_borrower == curthread)
9295 break;
9297 ASSERT(cur != NULL);
9298 prev->pmlk_next = cur->pmlk_next;
9299 mutex_exit(&pm_loan_lock);
9300 kmem_free(cur, sizeof (*cur));
9303 #if defined(__x86)
9305 #define CPR_RXR 0x1
9306 #define CPR_TXR 0x20
9307 #define CPR_DATAREG 0x3f8
9308 #define CPR_LSTAT 0x3fd
9309 #define CPR_INTRCTL 0x3f9
9311 char
9312 pm_getchar(void)
9314 while ((inb(CPR_LSTAT) & CPR_RXR) != CPR_RXR)
9315 drv_usecwait(10);
9317 return (inb(CPR_DATAREG));
9321 void
9322 pm_putchar(char c)
9324 while ((inb(CPR_LSTAT) & CPR_TXR) == 0)
9325 drv_usecwait(10);
9327 outb(CPR_DATAREG, c);
9330 void
9331 pm_printf(char *s)
9333 while (*s) {
9334 pm_putchar(*s++);
9338 #endif
9341 pm_ppm_searchlist(pm_searchargs_t *sp)
9343 power_req_t power_req;
9344 int result = 0;
9345 int ret;
9347 power_req.request_type = PMR_PPM_SEARCH_LIST;
9348 power_req.req.ppm_search_list_req.searchlist = sp;
9349 ASSERT(DEVI(ddi_root_node())->devi_pm_ppm);
9350 ret = pm_ctlops((dev_info_t *)DEVI(ddi_root_node())->devi_pm_ppm,
9351 ddi_root_node(), DDI_CTLOPS_POWER, &power_req, &result);
9352 PMD(PMD_SX, ("pm_ppm_searchlist returns %d, result %d\n",
9353 ret, result))
9354 return (result);